blob: b0732671fadedaa0ea78a2e0a5fa975ccf0c645c [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/validationES2.h"
12#include "libANGLE/validationES3.h"
13#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040014#include "libANGLE/Display.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Texture.h"
16#include "libANGLE/Framebuffer.h"
17#include "libANGLE/FramebufferAttachment.h"
18#include "libANGLE/formatutils.h"
Geoff Langa8406172015-07-21 16:53:39 -040019#include "libANGLE/Image.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/Query.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050021#include "libANGLE/Program.h"
22#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050023#include "libANGLE/TransformFeedback.h"
24#include "libANGLE/VertexArray.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025
26#include "common/mathutil.h"
27#include "common/utilities.h"
28
Jamie Madille2e406c2016-06-02 13:04:10 -040029using namespace angle;
30
Geoff Lange8ebe7f2013-08-05 15:03:13 -040031namespace gl
32{
Jamie Madille79b1e12015-11-04 16:36:37 -050033const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum element index.";
34
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
Corentin Wallez92db6942016-12-09 13:10:36 -050037bool ValidateDrawAttribs(ValidationContext *context,
38 GLint primcount,
39 GLint maxVertex,
40 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040041{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070042 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040043 const gl::Program *program = state.getProgram();
44
Corentin Wallez327411e2016-12-09 11:09:17 -050045 bool webglCompatibility = context->getExtensions().webglCompatibility;
46
He Yunchaoced53ae2016-11-29 15:00:51 +080047 const VertexArray *vao = state.getVertexArray();
48 const auto &vertexAttribs = vao->getVertexAttributes();
49 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040050 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
51 {
52 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Jamie Madill63805b42015-08-25 13:17:39 -040053 if (program->isAttribLocationActive(attributeIndex) && attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040054 {
55 gl::Buffer *buffer = attrib.buffer.get();
56
57 if (buffer)
58 {
Corentin Wallez92db6942016-12-09 13:10:36 -050059 CheckedNumeric<GLint64> maxVertexElement = 0;
60 bool readsData = false;
61 if (attrib.divisor == 0)
Jamie Madill1ca74672015-07-21 15:14:11 -040062 {
Corentin Wallez92db6942016-12-09 13:10:36 -050063 readsData = vertexCount > 0;
Jamie Madill1ca74672015-07-21 15:14:11 -040064 maxVertexElement = static_cast<GLint64>(maxVertex);
65 }
Corentin Wallez92db6942016-12-09 13:10:36 -050066 else if (primcount > 0)
67 {
68 readsData = true;
69 maxVertexElement =
70 static_cast<GLint64>(primcount - 1) / static_cast<GLint64>(attrib.divisor);
71 }
Jamie Madill1ca74672015-07-21 15:14:11 -040072
73 // If we're drawing zero vertices, we have enough data.
Corentin Wallez92db6942016-12-09 13:10:36 -050074 if (readsData)
Jamie Madill1ca74672015-07-21 15:14:11 -040075 {
76 // Note: Last vertex element does not take the full stride!
Corentin Wallez92db6942016-12-09 13:10:36 -050077 CheckedNumeric<GLint64> attribStride = ComputeVertexAttributeStride(attrib);
78 CheckedNumeric<GLint64> attribSize = ComputeVertexAttributeTypeSize(attrib);
79 CheckedNumeric<GLint64> attribDataSize =
80 maxVertexElement * attribStride + attribSize;
81 CheckedNumeric<GLint64> maxOffset = attribDataSize + attrib.offset;
82
83 if (!maxOffset.IsValid())
84 {
85 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
86 return false;
87 }
Jamie Madill1ca74672015-07-21 15:14:11 -040088
89 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
90 // We can return INVALID_OPERATION if our vertex attribute does not have
91 // enough backing data.
Corentin Wallez92db6942016-12-09 13:10:36 -050092 if (maxOffset.ValueOrDie() > buffer->getSize())
Jamie Madill1ca74672015-07-21 15:14:11 -040093 {
Jamie Madill437fa652016-05-03 15:13:24 -040094 context->handleError(
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040095 Error(GL_INVALID_OPERATION,
96 "Vertex buffer is not big enough for the draw call"));
Jamie Madill1ca74672015-07-21 15:14:11 -040097 return false;
98 }
99 }
100 }
Corentin Wallez327411e2016-12-09 11:09:17 -0500101 else if (webglCompatibility)
102 {
103 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
104 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
105 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then
106 // calls to drawArrays or drawElements will generate an INVALID_OPERATION error.
107 context->handleError(
108 Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer."));
109 }
Jamie Madill1ca74672015-07-21 15:14:11 -0400110 else if (attrib.pointer == NULL)
111 {
112 // This is an application error that would normally result in a crash,
113 // but we catch it and return an error
Jamie Madill437fa652016-05-03 15:13:24 -0400114 context->handleError(Error(
Jamie Madill1ca74672015-07-21 15:14:11 -0400115 GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer."));
116 return false;
117 }
118 }
119 }
120
121 return true;
122}
123
Geoff Langf607c602016-09-21 11:46:48 -0400124bool ValidReadPixelsFormatType(ValidationContext *context,
125 GLenum framebufferComponentType,
126 GLenum format,
127 GLenum type)
128{
129 switch (framebufferComponentType)
130 {
131 case GL_UNSIGNED_NORMALIZED:
132 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
133 // ReadPixels with BGRA even if the extension is not present
134 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
135 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
136 type == GL_UNSIGNED_BYTE);
137
138 case GL_SIGNED_NORMALIZED:
139 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
140
141 case GL_INT:
142 return (format == GL_RGBA_INTEGER && type == GL_INT);
143
144 case GL_UNSIGNED_INT:
145 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
146
147 case GL_FLOAT:
148 return (format == GL_RGBA && type == GL_FLOAT);
149
150 default:
151 UNREACHABLE();
152 return false;
153 }
154}
155
Geoff Langf41a7152016-09-19 15:11:17 -0400156bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
Geoff Lang0550d032014-01-30 11:29:07 -0500157{
158 switch (cap)
159 {
Geoff Langf41a7152016-09-19 15:11:17 -0400160 // EXT_multisample_compatibility
161 case GL_MULTISAMPLE_EXT:
162 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
163 return context->getExtensions().multisampleCompatibility;
Sami Väisänen74c23472016-05-09 17:30:30 +0300164
Geoff Langf41a7152016-09-19 15:11:17 -0400165 case GL_CULL_FACE:
166 case GL_POLYGON_OFFSET_FILL:
167 case GL_SAMPLE_ALPHA_TO_COVERAGE:
168 case GL_SAMPLE_COVERAGE:
169 case GL_SCISSOR_TEST:
170 case GL_STENCIL_TEST:
171 case GL_DEPTH_TEST:
172 case GL_BLEND:
173 case GL_DITHER:
174 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -0500175
Geoff Langf41a7152016-09-19 15:11:17 -0400176 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
177 case GL_RASTERIZER_DISCARD:
178 return (context->getClientMajorVersion() >= 3);
Geoff Lang70d0f492015-12-10 17:45:46 -0500179
Geoff Langf41a7152016-09-19 15:11:17 -0400180 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
181 case GL_DEBUG_OUTPUT:
182 return context->getExtensions().debug;
Geoff Lang70d0f492015-12-10 17:45:46 -0500183
Geoff Langf41a7152016-09-19 15:11:17 -0400184 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
185 return queryOnly && context->getExtensions().bindGeneratesResource;
186
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700187 case GL_FRAMEBUFFER_SRGB_EXT:
188 return context->getExtensions().sRGBWriteControl;
189
Geoff Lang3b573612016-10-31 14:08:10 -0400190 case GL_SAMPLE_MASK:
Geoff Lang3b573612016-10-31 14:08:10 -0400191 return context->getClientVersion() >= Version(3, 1);
192
Geoff Langf41a7152016-09-19 15:11:17 -0400193 default:
194 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500195 }
196}
197
Geoff Lang62fce5b2016-09-30 10:46:35 -0400198bool ValidateReadPixelsBase(ValidationContext *context,
199 GLint x,
200 GLint y,
201 GLsizei width,
202 GLsizei height,
203 GLenum format,
204 GLenum type,
205 GLsizei bufSize,
206 GLsizei *length,
207 GLvoid *pixels)
208{
209 if (length != nullptr)
210 {
211 *length = 0;
212 }
213
214 if (width < 0 || height < 0)
215 {
216 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
217 return false;
218 }
219
220 auto readFramebuffer = context->getGLState().getReadFramebuffer();
221
222 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
223 {
224 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
225 return false;
226 }
227
228 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
229 {
230 context->handleError(Error(GL_INVALID_OPERATION));
231 return false;
232 }
233
234 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
235 ASSERT(framebuffer);
236
237 if (framebuffer->getReadBufferState() == GL_NONE)
238 {
239 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
240 return false;
241 }
242
243 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
244 if (!readBuffer)
245 {
246 context->handleError(Error(GL_INVALID_OPERATION));
247 return false;
248 }
249
250 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
251 GLenum currentType = framebuffer->getImplementationColorReadType();
252 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
253
254 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
255 bool validFormatTypeCombination =
256 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
257
258 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
259 {
260 context->handleError(Error(GL_INVALID_OPERATION));
261 return false;
262 }
263
264 // Check for pixel pack buffer related API errors
265 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
266 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
267 {
268 // ...the buffer object's data store is currently mapped.
269 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
270 return false;
271 }
272
273 // .. the data would be packed to the buffer object such that the memory writes required
274 // would exceed the data store size.
275 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
276 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
277 const gl::Extents size(width, height, 1);
278 const auto &pack = context->getGLState().getPackState();
279
280 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
281 if (endByteOrErr.isError())
282 {
283 context->handleError(endByteOrErr.getError());
284 return false;
285 }
286
287 size_t endByte = endByteOrErr.getResult();
288 if (bufSize >= 0)
289 {
290
291 if (static_cast<size_t>(bufSize) < endByte)
292 {
293 context->handleError(
294 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
295 return false;
296 }
297 }
298
299 if (pixelPackBuffer != nullptr)
300 {
301 CheckedNumeric<size_t> checkedEndByte(endByte);
302 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
303 checkedEndByte += checkedOffset;
304
305 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
306 {
307 // Overflow past the end of the buffer
308 context->handleError(
309 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
310 return false;
311 }
312 }
313
314 if (length != nullptr)
315 {
316 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
317 {
318 context->handleError(
319 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
320 return false;
321 }
322
323 *length = static_cast<GLsizei>(endByte);
324 }
325
326 return true;
327}
328
Geoff Lang740d9022016-10-07 11:20:52 -0400329bool ValidateGetRenderbufferParameterivBase(Context *context,
330 GLenum target,
331 GLenum pname,
332 GLsizei *length)
333{
334 if (length)
335 {
336 *length = 0;
337 }
338
339 if (target != GL_RENDERBUFFER)
340 {
341 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
342 return false;
343 }
344
345 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
346 if (renderbuffer == nullptr)
347 {
348 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
349 return false;
350 }
351
352 switch (pname)
353 {
354 case GL_RENDERBUFFER_WIDTH:
355 case GL_RENDERBUFFER_HEIGHT:
356 case GL_RENDERBUFFER_INTERNAL_FORMAT:
357 case GL_RENDERBUFFER_RED_SIZE:
358 case GL_RENDERBUFFER_GREEN_SIZE:
359 case GL_RENDERBUFFER_BLUE_SIZE:
360 case GL_RENDERBUFFER_ALPHA_SIZE:
361 case GL_RENDERBUFFER_DEPTH_SIZE:
362 case GL_RENDERBUFFER_STENCIL_SIZE:
363 break;
364
365 case GL_RENDERBUFFER_SAMPLES_ANGLE:
366 if (!context->getExtensions().framebufferMultisample)
367 {
368 context->handleError(
369 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
370 return false;
371 }
372 break;
373
374 default:
375 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
376 return false;
377 }
378
379 if (length)
380 {
381 *length = 1;
382 }
383 return true;
384}
385
Geoff Langd7d0ed32016-10-07 11:33:51 -0400386bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
387{
388 if (length)
389 {
390 *length = 0;
391 }
392
393 if (GetValidShader(context, shader) == nullptr)
394 {
395 return false;
396 }
397
398 switch (pname)
399 {
400 case GL_SHADER_TYPE:
401 case GL_DELETE_STATUS:
402 case GL_COMPILE_STATUS:
403 case GL_INFO_LOG_LENGTH:
404 case GL_SHADER_SOURCE_LENGTH:
405 break;
406
407 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
408 if (!context->getExtensions().translatedShaderSource)
409 {
410 context->handleError(
411 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
412 return false;
413 }
414 break;
415
416 default:
417 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
418 return false;
419 }
420
421 if (length)
422 {
423 *length = 1;
424 }
425 return true;
426}
427
Geoff Langc1984ed2016-10-07 12:41:00 -0400428bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
429{
430 if (length)
431 {
432 *length = 0;
433 }
434
435 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
436 {
437 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
438 return false;
439 }
440
441 if (context->getTargetTexture(target) == nullptr)
442 {
443 // Should only be possible for external textures
444 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
445 return false;
446 }
447
448 switch (pname)
449 {
450 case GL_TEXTURE_MAG_FILTER:
451 case GL_TEXTURE_MIN_FILTER:
452 case GL_TEXTURE_WRAP_S:
453 case GL_TEXTURE_WRAP_T:
454 break;
455
456 case GL_TEXTURE_USAGE_ANGLE:
457 if (!context->getExtensions().textureUsage)
458 {
459 context->handleError(
460 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
461 return false;
462 }
463 break;
464
465 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
466 if (!context->getExtensions().textureFilterAnisotropic)
467 {
468 context->handleError(
469 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
470 return false;
471 }
472 break;
473
474 case GL_TEXTURE_IMMUTABLE_FORMAT:
475 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
476 {
477 context->handleError(
478 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
479 return false;
480 }
481 break;
482
483 case GL_TEXTURE_WRAP_R:
484 case GL_TEXTURE_IMMUTABLE_LEVELS:
485 case GL_TEXTURE_SWIZZLE_R:
486 case GL_TEXTURE_SWIZZLE_G:
487 case GL_TEXTURE_SWIZZLE_B:
488 case GL_TEXTURE_SWIZZLE_A:
489 case GL_TEXTURE_BASE_LEVEL:
490 case GL_TEXTURE_MAX_LEVEL:
491 case GL_TEXTURE_MIN_LOD:
492 case GL_TEXTURE_MAX_LOD:
493 case GL_TEXTURE_COMPARE_MODE:
494 case GL_TEXTURE_COMPARE_FUNC:
495 if (context->getClientMajorVersion() < 3)
496 {
497 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
498 return false;
499 }
500 break;
501
Geoff Lang81c6b572016-10-19 14:07:52 -0700502 case GL_TEXTURE_SRGB_DECODE_EXT:
503 if (!context->getExtensions().textureSRGBDecode)
504 {
505 context->handleError(
506 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
507 return false;
508 }
509 break;
510
Geoff Langc1984ed2016-10-07 12:41:00 -0400511 default:
512 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
513 return false;
514 }
515
516 if (length)
517 {
518 *length = 1;
519 }
520 return true;
521}
522
523template <typename ParamType>
524bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
525{
526 switch (ConvertToGLenum(params[0]))
527 {
528 case GL_CLAMP_TO_EDGE:
529 break;
530
531 case GL_REPEAT:
532 case GL_MIRRORED_REPEAT:
533 if (isExternalTextureTarget)
534 {
535 // OES_EGL_image_external specifies this error.
536 context->handleError(Error(
537 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
538 return false;
539 }
540 break;
541
542 default:
543 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
544 return false;
545 }
546
547 return true;
548}
549
550template <typename ParamType>
551bool ValidateTextureMinFilterValue(Context *context,
552 ParamType *params,
553 bool isExternalTextureTarget)
554{
555 switch (ConvertToGLenum(params[0]))
556 {
557 case GL_NEAREST:
558 case GL_LINEAR:
559 break;
560
561 case GL_NEAREST_MIPMAP_NEAREST:
562 case GL_LINEAR_MIPMAP_NEAREST:
563 case GL_NEAREST_MIPMAP_LINEAR:
564 case GL_LINEAR_MIPMAP_LINEAR:
565 if (isExternalTextureTarget)
566 {
567 // OES_EGL_image_external specifies this error.
568 context->handleError(
569 Error(GL_INVALID_ENUM,
570 "external textures only support NEAREST and LINEAR filtering"));
571 return false;
572 }
573 break;
574
575 default:
576 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
577 return false;
578 }
579
580 return true;
581}
582
583template <typename ParamType>
584bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
585{
586 switch (ConvertToGLenum(params[0]))
587 {
588 case GL_NEAREST:
589 case GL_LINEAR:
590 break;
591
592 default:
593 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
594 return false;
595 }
596
597 return true;
598}
599
600template <typename ParamType>
601bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
602{
603 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
604 switch (ConvertToGLenum(params[0]))
605 {
606 case GL_NONE:
607 case GL_COMPARE_REF_TO_TEXTURE:
608 break;
609
610 default:
611 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
612 return false;
613 }
614
615 return true;
616}
617
618template <typename ParamType>
619bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
620{
621 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
622 switch (ConvertToGLenum(params[0]))
623 {
624 case GL_LEQUAL:
625 case GL_GEQUAL:
626 case GL_LESS:
627 case GL_GREATER:
628 case GL_EQUAL:
629 case GL_NOTEQUAL:
630 case GL_ALWAYS:
631 case GL_NEVER:
632 break;
633
634 default:
635 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
636 return false;
637 }
638
639 return true;
640}
641
642template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700643bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
644{
645 if (!context->getExtensions().textureSRGBDecode)
646 {
647 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
648 return false;
649 }
650
651 switch (ConvertToGLenum(params[0]))
652 {
653 case GL_DECODE_EXT:
654 case GL_SKIP_DECODE_EXT:
655 break;
656
657 default:
658 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
659 return false;
660 }
661
662 return true;
663}
664
665template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400666bool ValidateTexParameterBase(Context *context,
667 GLenum target,
668 GLenum pname,
669 GLsizei bufSize,
670 ParamType *params)
671{
672 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
673 {
674 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
675 return false;
676 }
677
678 if (context->getTargetTexture(target) == nullptr)
679 {
680 // Should only be possible for external textures
681 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
682 return false;
683 }
684
685 const GLsizei minBufSize = 1;
686 if (bufSize >= 0 && bufSize < minBufSize)
687 {
688 context->handleError(
689 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
690 return false;
691 }
692
693 switch (pname)
694 {
695 case GL_TEXTURE_WRAP_R:
696 case GL_TEXTURE_SWIZZLE_R:
697 case GL_TEXTURE_SWIZZLE_G:
698 case GL_TEXTURE_SWIZZLE_B:
699 case GL_TEXTURE_SWIZZLE_A:
700 case GL_TEXTURE_BASE_LEVEL:
701 case GL_TEXTURE_MAX_LEVEL:
702 case GL_TEXTURE_COMPARE_MODE:
703 case GL_TEXTURE_COMPARE_FUNC:
704 case GL_TEXTURE_MIN_LOD:
705 case GL_TEXTURE_MAX_LOD:
706 if (context->getClientMajorVersion() < 3)
707 {
708 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
709 return false;
710 }
711 if (target == GL_TEXTURE_EXTERNAL_OES &&
712 !context->getExtensions().eglImageExternalEssl3)
713 {
714 context->handleError(Error(GL_INVALID_ENUM,
715 "ES3 texture parameters are not available without "
716 "GL_OES_EGL_image_external_essl3."));
717 return false;
718 }
719 break;
720
721 default:
722 break;
723 }
724
725 switch (pname)
726 {
727 case GL_TEXTURE_WRAP_S:
728 case GL_TEXTURE_WRAP_T:
729 case GL_TEXTURE_WRAP_R:
730 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
731 {
732 return false;
733 }
734 break;
735
736 case GL_TEXTURE_MIN_FILTER:
737 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
738 {
739 return false;
740 }
741 break;
742
743 case GL_TEXTURE_MAG_FILTER:
744 if (!ValidateTextureMagFilterValue(context, params))
745 {
746 return false;
747 }
748 break;
749
750 case GL_TEXTURE_USAGE_ANGLE:
751 switch (ConvertToGLenum(params[0]))
752 {
753 case GL_NONE:
754 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
755 break;
756
757 default:
758 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
759 return false;
760 }
761 break;
762
763 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
764 if (!context->getExtensions().textureFilterAnisotropic)
765 {
766 context->handleError(
767 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
768 return false;
769 }
770
771 // we assume the parameter passed to this validation method is truncated, not rounded
772 if (params[0] < 1)
773 {
774 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
775 return false;
776 }
777 break;
778
779 case GL_TEXTURE_MIN_LOD:
780 case GL_TEXTURE_MAX_LOD:
781 // any value is permissible
782 break;
783
784 case GL_TEXTURE_COMPARE_MODE:
785 if (!ValidateTextureCompareModeValue(context, params))
786 {
787 return false;
788 }
789 break;
790
791 case GL_TEXTURE_COMPARE_FUNC:
792 if (!ValidateTextureCompareFuncValue(context, params))
793 {
794 return false;
795 }
796 break;
797
798 case GL_TEXTURE_SWIZZLE_R:
799 case GL_TEXTURE_SWIZZLE_G:
800 case GL_TEXTURE_SWIZZLE_B:
801 case GL_TEXTURE_SWIZZLE_A:
802 switch (ConvertToGLenum(params[0]))
803 {
804 case GL_RED:
805 case GL_GREEN:
806 case GL_BLUE:
807 case GL_ALPHA:
808 case GL_ZERO:
809 case GL_ONE:
810 break;
811
812 default:
813 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
814 return false;
815 }
816 break;
817
818 case GL_TEXTURE_BASE_LEVEL:
819 if (params[0] < 0)
820 {
821 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
822 return false;
823 }
824 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
825 {
826 context->handleError(
827 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
828 return false;
829 }
830 break;
831
832 case GL_TEXTURE_MAX_LEVEL:
833 if (params[0] < 0)
834 {
835 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
836 return false;
837 }
838 break;
839
Geoff Lang3b573612016-10-31 14:08:10 -0400840 case GL_DEPTH_STENCIL_TEXTURE_MODE:
841 if (context->getClientVersion() < Version(3, 1))
842 {
843 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
844 return false;
845 }
Geoff Lang9f090372016-12-02 10:20:43 -0500846 switch (ConvertToGLenum(params[0]))
847 {
848 case GL_DEPTH_COMPONENT:
849 case GL_STENCIL_INDEX:
850 break;
851
852 default:
853 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
854 return false;
855 }
Geoff Lang3b573612016-10-31 14:08:10 -0400856 break;
857
Geoff Lang81c6b572016-10-19 14:07:52 -0700858 case GL_TEXTURE_SRGB_DECODE_EXT:
859 if (!ValidateTextureSRGBDecodeValue(context, params))
860 {
861 return false;
862 }
863 break;
864
Geoff Langc1984ed2016-10-07 12:41:00 -0400865 default:
866 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
867 return false;
868 }
869
870 return true;
871}
872
873template <typename ParamType>
874bool ValidateSamplerParameterBase(Context *context,
875 GLuint sampler,
876 GLenum pname,
877 GLsizei bufSize,
878 ParamType *params)
879{
880 if (context->getClientMajorVersion() < 3)
881 {
882 context->handleError(
883 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
884 return false;
885 }
886
887 if (!context->isSampler(sampler))
888 {
889 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
890 return false;
891 }
892
893 const GLsizei minBufSize = 1;
894 if (bufSize >= 0 && bufSize < minBufSize)
895 {
896 context->handleError(
897 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
898 return false;
899 }
900
901 switch (pname)
902 {
903 case GL_TEXTURE_WRAP_S:
904 case GL_TEXTURE_WRAP_T:
905 case GL_TEXTURE_WRAP_R:
906 if (!ValidateTextureWrapModeValue(context, params, false))
907 {
908 return false;
909 }
910 break;
911
912 case GL_TEXTURE_MIN_FILTER:
913 if (!ValidateTextureMinFilterValue(context, params, false))
914 {
915 return false;
916 }
917 break;
918
919 case GL_TEXTURE_MAG_FILTER:
920 if (!ValidateTextureMagFilterValue(context, params))
921 {
922 return false;
923 }
924 break;
925
926 case GL_TEXTURE_MIN_LOD:
927 case GL_TEXTURE_MAX_LOD:
928 // any value is permissible
929 break;
930
931 case GL_TEXTURE_COMPARE_MODE:
932 if (!ValidateTextureCompareModeValue(context, params))
933 {
934 return false;
935 }
936 break;
937
938 case GL_TEXTURE_COMPARE_FUNC:
939 if (!ValidateTextureCompareFuncValue(context, params))
940 {
941 return false;
942 }
943 break;
944
Geoff Lang81c6b572016-10-19 14:07:52 -0700945 case GL_TEXTURE_SRGB_DECODE_EXT:
946 if (!ValidateTextureSRGBDecodeValue(context, params))
947 {
948 return false;
949 }
950 break;
951
Geoff Langc1984ed2016-10-07 12:41:00 -0400952 default:
953 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
954 return false;
955 }
956
957 return true;
958}
959
960bool ValidateGetSamplerParameterBase(Context *context,
961 GLuint sampler,
962 GLenum pname,
963 GLsizei *length)
964{
965 if (length)
966 {
967 *length = 0;
968 }
969
970 if (context->getClientMajorVersion() < 3)
971 {
972 context->handleError(
973 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
974 return false;
975 }
976
977 if (!context->isSampler(sampler))
978 {
979 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
980 return false;
981 }
982
983 switch (pname)
984 {
985 case GL_TEXTURE_WRAP_S:
986 case GL_TEXTURE_WRAP_T:
987 case GL_TEXTURE_WRAP_R:
988 case GL_TEXTURE_MIN_FILTER:
989 case GL_TEXTURE_MAG_FILTER:
990 case GL_TEXTURE_MIN_LOD:
991 case GL_TEXTURE_MAX_LOD:
992 case GL_TEXTURE_COMPARE_MODE:
993 case GL_TEXTURE_COMPARE_FUNC:
994 break;
995
Geoff Lang81c6b572016-10-19 14:07:52 -0700996 case GL_TEXTURE_SRGB_DECODE_EXT:
997 if (!context->getExtensions().textureSRGBDecode)
998 {
999 context->handleError(
1000 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
1001 return false;
1002 }
1003 break;
1004
Geoff Langc1984ed2016-10-07 12:41:00 -04001005 default:
1006 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1007 return false;
1008 }
1009
1010 if (length)
1011 {
1012 *length = 1;
1013 }
1014 return true;
1015}
1016
Geoff Lang0b031062016-10-13 14:30:04 -04001017bool ValidateGetVertexAttribBase(Context *context,
1018 GLuint index,
1019 GLenum pname,
1020 GLsizei *length,
1021 bool pointer,
1022 bool pureIntegerEntryPoint)
1023{
1024 if (length)
1025 {
1026 *length = 0;
1027 }
1028
1029 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
1030 {
1031 context->handleError(
1032 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1033 return false;
1034 }
1035
1036 if (index >= context->getCaps().maxVertexAttributes)
1037 {
1038 context->handleError(Error(
1039 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
1040 return false;
1041 }
1042
1043 if (pointer)
1044 {
1045 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1046 {
1047 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1048 return false;
1049 }
1050 }
1051 else
1052 {
1053 switch (pname)
1054 {
1055 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1056 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1057 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1058 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1059 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1060 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1061 case GL_CURRENT_VERTEX_ATTRIB:
1062 break;
1063
1064 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1065 static_assert(
1066 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1067 "ANGLE extension enums not equal to GL enums.");
1068 if (context->getClientMajorVersion() < 3 &&
1069 !context->getExtensions().instancedArrays)
1070 {
1071 context->handleError(Error(GL_INVALID_ENUM,
1072 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1073 "3.0 or GL_ANGLE_instanced_arrays."));
1074 return false;
1075 }
1076 break;
1077
1078 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1079 if (context->getClientMajorVersion() < 3)
1080 {
1081 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
1082 return false;
1083 }
1084 break;
1085
1086 default:
1087 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1088 return false;
1089 }
1090 }
1091
1092 if (length)
1093 {
1094 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1095 {
1096 *length = 4;
1097 }
1098 else
1099 {
1100 *length = 1;
1101 }
1102 }
1103
1104 return true;
1105}
1106
Geoff Lang6899b872016-10-14 11:30:13 -04001107bool ValidateGetActiveUniformBlockivBase(Context *context,
1108 GLuint program,
1109 GLuint uniformBlockIndex,
1110 GLenum pname,
1111 GLsizei *length)
1112{
1113 if (length)
1114 {
1115 *length = 0;
1116 }
1117
1118 if (context->getClientMajorVersion() < 3)
1119 {
1120 context->handleError(
1121 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1122 return false;
1123 }
1124
1125 Program *programObject = GetValidProgram(context, program);
1126 if (!programObject)
1127 {
1128 return false;
1129 }
1130
1131 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1132 {
1133 context->handleError(
1134 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1135 return false;
1136 }
1137
1138 switch (pname)
1139 {
1140 case GL_UNIFORM_BLOCK_BINDING:
1141 case GL_UNIFORM_BLOCK_DATA_SIZE:
1142 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1143 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1144 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1145 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1146 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1147 break;
1148
1149 default:
1150 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1151 return false;
1152 }
1153
1154 if (length)
1155 {
1156 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1157 {
1158 const UniformBlock &uniformBlock =
1159 programObject->getUniformBlockByIndex(uniformBlockIndex);
1160 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1161 }
1162 else
1163 {
1164 *length = 1;
1165 }
1166 }
1167
1168 return true;
1169}
1170
Geoff Langebebe1c2016-10-14 12:01:31 -04001171bool ValidateGetBufferParameterBase(ValidationContext *context,
1172 GLenum target,
1173 GLenum pname,
1174 bool pointerVersion,
1175 GLsizei *numParams)
1176{
1177 if (numParams)
1178 {
1179 *numParams = 0;
1180 }
1181
1182 if (!ValidBufferTarget(context, target))
1183 {
1184 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1185 return false;
1186 }
1187
1188 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1189 if (!buffer)
1190 {
1191 // A null buffer means that "0" is bound to the requested buffer target
1192 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1193 return false;
1194 }
1195
1196 const Extensions &extensions = context->getExtensions();
1197
1198 switch (pname)
1199 {
1200 case GL_BUFFER_USAGE:
1201 case GL_BUFFER_SIZE:
1202 break;
1203
1204 case GL_BUFFER_ACCESS_OES:
1205 if (!extensions.mapBuffer)
1206 {
1207 context->handleError(
1208 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_map_buffer."));
1209 return false;
1210 }
1211 break;
1212
1213 case GL_BUFFER_MAPPED:
1214 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1215 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1216 !extensions.mapBufferRange)
1217 {
1218 context->handleError(Error(
1219 GL_INVALID_ENUM,
1220 "pname requires OpenGL ES 3.0, GL_OES_map_buffer or GL_EXT_map_buffer_range."));
1221 return false;
1222 }
1223 break;
1224
1225 case GL_BUFFER_MAP_POINTER:
1226 if (!pointerVersion)
1227 {
1228 context->handleError(
1229 Error(GL_INVALID_ENUM,
1230 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1231 return false;
1232 }
1233 break;
1234
1235 case GL_BUFFER_ACCESS_FLAGS:
1236 case GL_BUFFER_MAP_OFFSET:
1237 case GL_BUFFER_MAP_LENGTH:
1238 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1239 {
1240 context->handleError(Error(
1241 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1242 return false;
1243 }
1244 break;
1245
1246 default:
1247 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1248 return false;
1249 }
1250
1251 // All buffer parameter queries return one value.
1252 if (numParams)
1253 {
1254 *numParams = 1;
1255 }
1256
1257 return true;
1258}
1259
Geoff Lang0a9661f2016-10-20 10:59:20 -07001260bool ValidateGetInternalFormativBase(Context *context,
1261 GLenum target,
1262 GLenum internalformat,
1263 GLenum pname,
1264 GLsizei bufSize,
1265 GLsizei *numParams)
1266{
1267 if (numParams)
1268 {
1269 *numParams = 0;
1270 }
1271
1272 if (context->getClientMajorVersion() < 3)
1273 {
1274 context->handleError(
1275 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1276 return false;
1277 }
1278
1279 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1280 if (!formatCaps.renderable)
1281 {
1282 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1283 return false;
1284 }
1285
1286 switch (target)
1287 {
1288 case GL_RENDERBUFFER:
1289 break;
1290
1291 default:
1292 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1293 return false;
1294 }
1295
1296 if (bufSize < 0)
1297 {
1298 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1299 return false;
1300 }
1301
1302 GLsizei maxWriteParams = 0;
1303 switch (pname)
1304 {
1305 case GL_NUM_SAMPLE_COUNTS:
1306 maxWriteParams = 1;
1307 break;
1308
1309 case GL_SAMPLES:
1310 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1311 break;
1312
1313 default:
1314 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1315 return false;
1316 }
1317
1318 if (numParams)
1319 {
1320 // glGetInternalFormativ will not overflow bufSize
1321 *numParams = std::min(bufSize, maxWriteParams);
1322 }
1323
1324 return true;
1325}
1326
Geoff Langf41a7152016-09-19 15:11:17 -04001327} // anonymous namespace
1328
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001329bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001330{
Jamie Madilld7460c72014-01-21 16:38:14 -05001331 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001332 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001333 case GL_TEXTURE_2D:
1334 case GL_TEXTURE_CUBE_MAP:
1335 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001336
He Yunchaoced53ae2016-11-29 15:00:51 +08001337 case GL_TEXTURE_3D:
1338 case GL_TEXTURE_2D_ARRAY:
1339 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001340
He Yunchaoced53ae2016-11-29 15:00:51 +08001341 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001342 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001343
He Yunchaoced53ae2016-11-29 15:00:51 +08001344 default:
1345 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001346 }
Jamie Madill35d15012013-10-07 10:46:37 -04001347}
1348
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001349bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1350{
1351 switch (target)
1352 {
1353 case GL_TEXTURE_2D:
1354 case GL_TEXTURE_CUBE_MAP:
1355 return true;
1356
1357 default:
1358 return false;
1359 }
1360}
1361
1362bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1363{
1364 switch (target)
1365 {
1366 case GL_TEXTURE_3D:
1367 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001368 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001369
1370 default:
1371 return false;
1372 }
1373}
1374
Ian Ewellbda75592016-04-18 17:25:54 -04001375// Most texture GL calls are not compatible with external textures, so we have a separate validation
1376// function for use in the GL calls that do
1377bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1378{
1379 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1380 (context->getExtensions().eglImageExternal ||
1381 context->getExtensions().eglStreamConsumerExternal);
1382}
1383
Shannon Woods4dfed832014-03-17 20:03:39 -04001384// This function differs from ValidTextureTarget in that the target must be
1385// usable as the destination of a 2D operation-- so a cube face is valid, but
1386// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001387// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001388bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001389{
1390 switch (target)
1391 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001392 case GL_TEXTURE_2D:
1393 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1394 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1395 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1396 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1397 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1398 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1399 return true;
1400 default:
1401 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001402 }
1403}
1404
1405bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1406{
1407 switch (target)
1408 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001409 case GL_TEXTURE_3D:
1410 case GL_TEXTURE_2D_ARRAY:
1411 return true;
1412 default:
1413 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001414 }
1415}
1416
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001417bool ValidFramebufferTarget(GLenum target)
1418{
He Yunchaoced53ae2016-11-29 15:00:51 +08001419 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1420 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001421 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001422
1423 switch (target)
1424 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001425 case GL_FRAMEBUFFER:
1426 return true;
1427 case GL_READ_FRAMEBUFFER:
1428 return true;
1429 case GL_DRAW_FRAMEBUFFER:
1430 return true;
1431 default:
1432 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001433 }
1434}
1435
Jamie Madill29639852016-09-02 15:00:09 -04001436bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001437{
1438 switch (target)
1439 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001440 case GL_ARRAY_BUFFER:
1441 case GL_ELEMENT_ARRAY_BUFFER:
1442 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001443
He Yunchaoced53ae2016-11-29 15:00:51 +08001444 case GL_PIXEL_PACK_BUFFER:
1445 case GL_PIXEL_UNPACK_BUFFER:
1446 return (context->getExtensions().pixelBufferObject ||
1447 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001448
He Yunchaoced53ae2016-11-29 15:00:51 +08001449 case GL_COPY_READ_BUFFER:
1450 case GL_COPY_WRITE_BUFFER:
1451 case GL_TRANSFORM_FEEDBACK_BUFFER:
1452 case GL_UNIFORM_BUFFER:
1453 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001454
He Yunchaoced53ae2016-11-29 15:00:51 +08001455 case GL_ATOMIC_COUNTER_BUFFER:
1456 case GL_SHADER_STORAGE_BUFFER:
1457 case GL_DRAW_INDIRECT_BUFFER:
1458 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001459 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001460
He Yunchaoced53ae2016-11-29 15:00:51 +08001461 default:
1462 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001463 }
1464}
1465
Jamie Madillc29968b2016-01-20 11:17:23 -05001466bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001467{
Jamie Madillc29968b2016-01-20 11:17:23 -05001468 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001469 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001470 switch (target)
1471 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001472 case GL_TEXTURE_2D:
1473 maxDimension = caps.max2DTextureSize;
1474 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001475 case GL_TEXTURE_CUBE_MAP:
1476 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1477 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1478 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1479 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1480 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1481 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1482 maxDimension = caps.maxCubeMapTextureSize;
1483 break;
1484 case GL_TEXTURE_3D:
1485 maxDimension = caps.max3DTextureSize;
1486 break;
1487 case GL_TEXTURE_2D_ARRAY:
1488 maxDimension = caps.max2DTextureSize;
1489 break;
1490 default:
1491 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001492 }
1493
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001494 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001495}
1496
Austin Kinross08528e12015-10-07 16:24:40 -07001497bool ValidImageSizeParameters(const Context *context,
1498 GLenum target,
1499 GLint level,
1500 GLsizei width,
1501 GLsizei height,
1502 GLsizei depth,
1503 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001504{
1505 if (level < 0 || width < 0 || height < 0 || depth < 0)
1506 {
1507 return false;
1508 }
1509
Austin Kinross08528e12015-10-07 16:24:40 -07001510 // TexSubImage parameters can be NPOT without textureNPOT extension,
1511 // as long as the destination texture is POT.
1512 if (!isSubImage && !context->getExtensions().textureNPOT &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001513 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001514 {
1515 return false;
1516 }
1517
1518 if (!ValidMipLevel(context, target, level))
1519 {
1520 return false;
1521 }
1522
1523 return true;
1524}
1525
Geoff Lang0d8b7242015-09-09 14:56:53 -04001526bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1527{
1528 // List of compressed format that require that the texture size is smaller than or a multiple of
1529 // the compressed block size.
1530 switch (internalFormat)
1531 {
1532 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1533 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1534 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1535 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001536 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001537 return true;
1538
1539 default:
1540 return false;
1541 }
1542}
1543
Jamie Madillc29968b2016-01-20 11:17:23 -05001544bool ValidCompressedImageSize(const ValidationContext *context,
1545 GLenum internalFormat,
1546 GLsizei width,
1547 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001548{
Geoff Lang5d601382014-07-22 15:14:06 -04001549 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1550 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001551 {
1552 return false;
1553 }
1554
Geoff Lang0d8b7242015-09-09 14:56:53 -04001555 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001556 {
1557 return false;
1558 }
1559
Geoff Lang0d8b7242015-09-09 14:56:53 -04001560 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1561 {
1562 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1563 width % formatInfo.compressedBlockWidth != 0) ||
1564 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1565 height % formatInfo.compressedBlockHeight != 0))
1566 {
1567 return false;
1568 }
1569 }
1570
Geoff Langd4f180b2013-09-24 13:57:44 -04001571 return true;
1572}
1573
Geoff Langff5b2d52016-09-07 11:32:23 -04001574bool ValidImageDataSize(ValidationContext *context,
1575 GLenum textureTarget,
1576 GLsizei width,
1577 GLsizei height,
1578 GLsizei depth,
1579 GLenum internalFormat,
1580 GLenum type,
1581 const GLvoid *pixels,
1582 GLsizei imageSize)
1583{
1584 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1585 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1586 {
1587 // Checks are not required
1588 return true;
1589 }
1590
1591 // ...the data would be unpacked from the buffer object such that the memory reads required
1592 // would exceed the data store size.
1593 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1594 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1595 const gl::Extents size(width, height, depth);
1596 const auto &unpack = context->getGLState().getUnpackState();
1597
1598 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1599 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1600 if (endByteOrErr.isError())
1601 {
1602 context->handleError(endByteOrErr.getError());
1603 return false;
1604 }
1605
1606 GLuint endByte = endByteOrErr.getResult();
1607
1608 if (pixelUnpackBuffer)
1609 {
1610 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1611 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1612 checkedEndByte += checkedOffset;
1613
1614 if (!checkedEndByte.IsValid() ||
1615 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1616 {
1617 // Overflow past the end of the buffer
1618 context->handleError(Error(GL_INVALID_OPERATION));
1619 return false;
1620 }
1621 }
1622 else
1623 {
1624 ASSERT(imageSize >= 0);
1625 if (pixels == nullptr && imageSize != 0)
1626 {
1627 context->handleError(
1628 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001629 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001630 }
1631
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001632 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001633 {
1634 context->handleError(
1635 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1636 return false;
1637 }
1638 }
1639
1640 return true;
1641}
1642
Geoff Lang37dde692014-01-31 16:34:54 -05001643bool ValidQueryType(const Context *context, GLenum queryType)
1644{
He Yunchaoced53ae2016-11-29 15:00:51 +08001645 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1646 "GL extension enums not equal.");
1647 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1648 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001649
1650 switch (queryType)
1651 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001652 case GL_ANY_SAMPLES_PASSED:
1653 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1654 return true;
1655 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1656 return (context->getClientMajorVersion() >= 3);
1657 case GL_TIME_ELAPSED_EXT:
1658 return context->getExtensions().disjointTimerQuery;
1659 case GL_COMMANDS_COMPLETED_CHROMIUM:
1660 return context->getExtensions().syncQuery;
1661 default:
1662 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001663 }
1664}
1665
Jamie Madillef300b12016-10-07 15:12:09 -04001666Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001667{
He Yunchaoced53ae2016-11-29 15:00:51 +08001668 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1669 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1670 // or program object and INVALID_OPERATION if the provided name identifies an object
1671 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001672
Dian Xiang769769a2015-09-09 15:20:08 -07001673 Program *validProgram = context->getProgram(id);
1674
1675 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001676 {
Dian Xiang769769a2015-09-09 15:20:08 -07001677 if (context->getShader(id))
1678 {
Jamie Madill437fa652016-05-03 15:13:24 -04001679 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001680 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1681 }
1682 else
1683 {
Jamie Madill437fa652016-05-03 15:13:24 -04001684 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001685 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001686 }
Dian Xiang769769a2015-09-09 15:20:08 -07001687
1688 return validProgram;
1689}
1690
Jamie Madillef300b12016-10-07 15:12:09 -04001691Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001692{
1693 // See ValidProgram for spec details.
1694
1695 Shader *validShader = context->getShader(id);
1696
1697 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001698 {
Dian Xiang769769a2015-09-09 15:20:08 -07001699 if (context->getProgram(id))
1700 {
Jamie Madill437fa652016-05-03 15:13:24 -04001701 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001702 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1703 }
1704 else
1705 {
Jamie Madill437fa652016-05-03 15:13:24 -04001706 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001707 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001708 }
Dian Xiang769769a2015-09-09 15:20:08 -07001709
1710 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001711}
1712
Geoff Langb1196682014-07-23 13:47:29 -04001713bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001714{
1715 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1716 {
1717 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1718
Geoff Langaae65a42014-05-26 12:43:44 -04001719 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001720 {
Jamie Madill437fa652016-05-03 15:13:24 -04001721 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001722 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001723 }
1724 }
1725 else
1726 {
1727 switch (attachment)
1728 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001729 case GL_DEPTH_ATTACHMENT:
1730 case GL_STENCIL_ATTACHMENT:
1731 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001732
He Yunchaoced53ae2016-11-29 15:00:51 +08001733 case GL_DEPTH_STENCIL_ATTACHMENT:
1734 if (!context->getExtensions().webglCompatibility &&
1735 context->getClientMajorVersion() < 3)
1736 {
1737 context->handleError(Error(GL_INVALID_ENUM));
1738 return false;
1739 }
1740 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001741
He Yunchaoced53ae2016-11-29 15:00:51 +08001742 default:
1743 context->handleError(Error(GL_INVALID_ENUM));
1744 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001745 }
1746 }
1747
1748 return true;
1749}
1750
He Yunchaoced53ae2016-11-29 15:00:51 +08001751bool ValidateRenderbufferStorageParametersBase(gl::Context *context,
1752 GLenum target,
1753 GLsizei samples,
1754 GLenum internalformat,
1755 GLsizei width,
1756 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001757{
1758 switch (target)
1759 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001760 case GL_RENDERBUFFER:
1761 break;
1762 default:
1763 context->handleError(Error(GL_INVALID_ENUM));
1764 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001765 }
1766
1767 if (width < 0 || height < 0 || samples < 0)
1768 {
Jamie Madill437fa652016-05-03 15:13:24 -04001769 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001770 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001771 }
1772
Geoff Langd87878e2014-09-19 15:42:59 -04001773 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1774 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001775 {
Jamie Madill437fa652016-05-03 15:13:24 -04001776 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001777 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001778 }
1779
1780 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1781 // 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 -08001782 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001783 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001784 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001785 {
Jamie Madill437fa652016-05-03 15:13:24 -04001786 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001787 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001788 }
1789
Geoff Langaae65a42014-05-26 12:43:44 -04001790 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001791 {
Jamie Madill437fa652016-05-03 15:13:24 -04001792 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001793 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001794 }
1795
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001796 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001797 if (handle == 0)
1798 {
Jamie Madill437fa652016-05-03 15:13:24 -04001799 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001800 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001801 }
1802
1803 return true;
1804}
1805
He Yunchaoced53ae2016-11-29 15:00:51 +08001806bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context,
1807 GLenum target,
1808 GLsizei samples,
1809 GLenum internalformat,
1810 GLsizei width,
1811 GLsizei height)
Corentin Walleze0902642014-11-04 12:32:15 -08001812{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001813 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001814
1815 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001816 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001817 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001818 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001819 {
Jamie Madill437fa652016-05-03 15:13:24 -04001820 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001821 return false;
1822 }
1823
1824 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1825 // the specified storage. This is different than ES 3.0 in which a sample number higher
1826 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001827 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001828 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001829 {
Geoff Langa4903b72015-03-02 16:02:48 -08001830 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1831 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1832 {
Jamie Madill437fa652016-05-03 15:13:24 -04001833 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001834 return false;
1835 }
Corentin Walleze0902642014-11-04 12:32:15 -08001836 }
1837
He Yunchaoced53ae2016-11-29 15:00:51 +08001838 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
1839 width, height);
Corentin Walleze0902642014-11-04 12:32:15 -08001840}
1841
He Yunchaoced53ae2016-11-29 15:00:51 +08001842bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1843 GLenum target,
1844 GLenum attachment,
1845 GLenum renderbuffertarget,
1846 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001847{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001848 if (!ValidFramebufferTarget(target))
1849 {
Jamie Madill437fa652016-05-03 15:13:24 -04001850 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001851 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001852 }
1853
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001854 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001855
Jamie Madill84115c92015-04-23 15:00:07 -04001856 ASSERT(framebuffer);
1857 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001858 {
Jamie Madill437fa652016-05-03 15:13:24 -04001859 context->handleError(
1860 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001861 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001862 }
1863
Jamie Madillb4472272014-07-03 10:38:55 -04001864 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001865 {
Jamie Madillb4472272014-07-03 10:38:55 -04001866 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001867 }
1868
Jamie Madillab9d82c2014-01-21 16:38:14 -05001869 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1870 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1871 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1872 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1873 if (renderbuffer != 0)
1874 {
1875 if (!context->getRenderbuffer(renderbuffer))
1876 {
Jamie Madill437fa652016-05-03 15:13:24 -04001877 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001878 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001879 }
1880 }
1881
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001882 return true;
1883}
1884
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001885bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001886 GLint srcX0,
1887 GLint srcY0,
1888 GLint srcX1,
1889 GLint srcY1,
1890 GLint dstX0,
1891 GLint dstY0,
1892 GLint dstX1,
1893 GLint dstY1,
1894 GLbitfield mask,
1895 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001896{
1897 switch (filter)
1898 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001899 case GL_NEAREST:
1900 break;
1901 case GL_LINEAR:
1902 break;
1903 default:
1904 context->handleError(Error(GL_INVALID_ENUM));
1905 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001906 }
1907
1908 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1909 {
Jamie Madill437fa652016-05-03 15:13:24 -04001910 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001911 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001912 }
1913
1914 if (mask == 0)
1915 {
1916 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1917 // buffers are copied.
1918 return false;
1919 }
1920
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001921 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1922 // color buffer, leaving only nearest being unfiltered from above
1923 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1924 {
Jamie Madill437fa652016-05-03 15:13:24 -04001925 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001926 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001927 }
1928
Jamie Madill51f40ec2016-06-15 14:06:00 -04001929 const auto &glState = context->getGLState();
1930 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1931 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001932
1933 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001934 {
Jamie Madill437fa652016-05-03 15:13:24 -04001935 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001936 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001937 }
1938
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001939 if (readFramebuffer->id() == drawFramebuffer->id())
1940 {
1941 context->handleError(Error(GL_INVALID_OPERATION));
1942 return false;
1943 }
1944
Jamie Madill51f40ec2016-06-15 14:06:00 -04001945 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001946 {
Jamie Madill437fa652016-05-03 15:13:24 -04001947 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001948 return false;
1949 }
1950
Jamie Madill51f40ec2016-06-15 14:06:00 -04001951 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001952 {
Jamie Madill437fa652016-05-03 15:13:24 -04001953 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001954 return false;
1955 }
1956
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001957 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001958 {
Jamie Madill437fa652016-05-03 15:13:24 -04001959 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001960 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001961 }
1962
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001963 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1964
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001965 if (mask & GL_COLOR_BUFFER_BIT)
1966 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001967 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1968 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001969 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001970
1971 if (readColorBuffer && drawColorBuffer)
1972 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001973 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001974
Geoff Langa15472a2015-08-11 11:48:03 -04001975 for (size_t drawbufferIdx = 0;
1976 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001977 {
Geoff Langa15472a2015-08-11 11:48:03 -04001978 const FramebufferAttachment *attachment =
1979 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1980 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001981 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001982 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001983
Geoff Langb2f3d052013-08-13 12:49:27 -04001984 // The GL ES 3.0.2 spec (pg 193) states that:
1985 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001986 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1987 // as well
1988 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1989 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001990 // Changes with EXT_color_buffer_float:
1991 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001992 GLenum readComponentType = readFormat.info->componentType;
1993 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001994 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001995 readComponentType == GL_SIGNED_NORMALIZED);
1996 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1997 drawComponentType == GL_SIGNED_NORMALIZED);
1998
1999 if (extensions.colorBufferFloat)
2000 {
2001 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2002 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2003
2004 if (readFixedOrFloat != drawFixedOrFloat)
2005 {
Jamie Madill437fa652016-05-03 15:13:24 -04002006 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002007 "If the read buffer contains fixed-point or "
2008 "floating-point values, the draw buffer "
2009 "must as well."));
2010 return false;
2011 }
2012 }
2013 else if (readFixedPoint != drawFixedPoint)
2014 {
Jamie Madill437fa652016-05-03 15:13:24 -04002015 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002016 "If the read buffer contains fixed-point "
2017 "values, the draw buffer must as well."));
2018 return false;
2019 }
2020
2021 if (readComponentType == GL_UNSIGNED_INT &&
2022 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002023 {
Jamie Madill437fa652016-05-03 15:13:24 -04002024 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002025 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002026 }
2027
Jamie Madill6163c752015-12-07 16:32:59 -05002028 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002029 {
Jamie Madill437fa652016-05-03 15:13:24 -04002030 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002031 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002032 }
2033
Jamie Madilla3944d42016-07-22 22:13:26 -04002034 if (readColorBuffer->getSamples() > 0 &&
2035 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002036 {
Jamie Madill437fa652016-05-03 15:13:24 -04002037 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002038 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002039 }
2040 }
2041 }
2042
Jamie Madilla3944d42016-07-22 22:13:26 -04002043 if ((readFormat.info->componentType == GL_INT ||
2044 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2045 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002046 {
Jamie Madill437fa652016-05-03 15:13:24 -04002047 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002048 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002049 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002050 }
2051 }
2052
He Yunchaoced53ae2016-11-29 15:00:51 +08002053 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002054 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2055 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002056 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002057 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002058 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002059 const gl::FramebufferAttachment *readBuffer =
2060 readFramebuffer->getAttachment(attachments[i]);
2061 const gl::FramebufferAttachment *drawBuffer =
2062 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002063
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002064 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002065 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002066 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002067 {
Jamie Madill437fa652016-05-03 15:13:24 -04002068 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002069 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002070 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002071
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002072 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002073 {
Jamie Madill437fa652016-05-03 15:13:24 -04002074 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002075 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002076 }
2077 }
2078 }
2079 }
2080
2081 return true;
2082}
2083
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002084bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002085 GLint x,
2086 GLint y,
2087 GLsizei width,
2088 GLsizei height,
2089 GLenum format,
2090 GLenum type,
2091 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002092{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002093 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2094}
2095
2096bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2097 GLint x,
2098 GLint y,
2099 GLsizei width,
2100 GLsizei height,
2101 GLenum format,
2102 GLenum type,
2103 GLsizei bufSize,
2104 GLsizei *length,
2105 GLvoid *pixels)
2106{
2107 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002108 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002109 return false;
2110 }
2111
Geoff Lang62fce5b2016-09-30 10:46:35 -04002112 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2113 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002114 {
Geoff Langb1196682014-07-23 13:47:29 -04002115 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002116 }
2117
Geoff Lang62fce5b2016-09-30 10:46:35 -04002118 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002119 {
Geoff Langb1196682014-07-23 13:47:29 -04002120 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002121 }
2122
Jamie Madillc29968b2016-01-20 11:17:23 -05002123 return true;
2124}
2125
2126bool ValidateReadnPixelsEXT(Context *context,
2127 GLint x,
2128 GLint y,
2129 GLsizei width,
2130 GLsizei height,
2131 GLenum format,
2132 GLenum type,
2133 GLsizei bufSize,
2134 GLvoid *pixels)
2135{
2136 if (bufSize < 0)
2137 {
Jamie Madill437fa652016-05-03 15:13:24 -04002138 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002139 return false;
2140 }
2141
Geoff Lang62fce5b2016-09-30 10:46:35 -04002142 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2143 pixels);
2144}
Jamie Madill26e91952014-03-05 15:01:27 -05002145
Geoff Lang62fce5b2016-09-30 10:46:35 -04002146bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2147 GLint x,
2148 GLint y,
2149 GLsizei width,
2150 GLsizei height,
2151 GLenum format,
2152 GLenum type,
2153 GLsizei bufSize,
2154 GLsizei *length,
2155 GLvoid *data)
2156{
2157 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002158 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002159 return false;
2160 }
2161
Geoff Lang62fce5b2016-09-30 10:46:35 -04002162 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002163 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002164 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002165 }
2166
Geoff Lang62fce5b2016-09-30 10:46:35 -04002167 if (!ValidateRobustBufferSize(context, bufSize, *length))
2168 {
2169 return false;
2170 }
2171
2172 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002173}
2174
Olli Etuaho41997e72016-03-10 13:38:39 +02002175bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002176{
2177 if (!context->getExtensions().occlusionQueryBoolean &&
2178 !context->getExtensions().disjointTimerQuery)
2179 {
Jamie Madill437fa652016-05-03 15:13:24 -04002180 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002181 return false;
2182 }
2183
Olli Etuaho41997e72016-03-10 13:38:39 +02002184 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002185}
2186
Olli Etuaho41997e72016-03-10 13:38:39 +02002187bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002188{
2189 if (!context->getExtensions().occlusionQueryBoolean &&
2190 !context->getExtensions().disjointTimerQuery)
2191 {
Jamie Madill437fa652016-05-03 15:13:24 -04002192 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002193 return false;
2194 }
2195
Olli Etuaho41997e72016-03-10 13:38:39 +02002196 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002197}
2198
2199bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002200{
2201 if (!ValidQueryType(context, target))
2202 {
Jamie Madill437fa652016-05-03 15:13:24 -04002203 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002204 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002205 }
2206
2207 if (id == 0)
2208 {
Jamie Madill437fa652016-05-03 15:13:24 -04002209 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002210 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002211 }
2212
2213 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2214 // of zero, if the active query object name for <target> is non-zero (for the
2215 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2216 // the active query for either target is non-zero), if <id> is the name of an
2217 // existing query object whose type does not match <target>, or if <id> is the
2218 // active query object name for any query type, the error INVALID_OPERATION is
2219 // generated.
2220
2221 // Ensure no other queries are active
2222 // NOTE: If other queries than occlusion are supported, we will need to check
2223 // separately that:
2224 // a) The query ID passed is not the current active query for any target/type
2225 // b) There are no active queries for the requested target (and in the case
2226 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2227 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002228
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002229 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002230 {
Jamie Madill437fa652016-05-03 15:13:24 -04002231 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002232 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002233 }
2234
2235 Query *queryObject = context->getQuery(id, true, target);
2236
2237 // check that name was obtained with glGenQueries
2238 if (!queryObject)
2239 {
Jamie Madill437fa652016-05-03 15:13:24 -04002240 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002241 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002242 }
2243
2244 // check for type mismatch
2245 if (queryObject->getType() != target)
2246 {
Jamie Madill437fa652016-05-03 15:13:24 -04002247 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002248 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002249 }
2250
2251 return true;
2252}
2253
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002254bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2255{
2256 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002257 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002258 {
Jamie Madill437fa652016-05-03 15:13:24 -04002259 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002260 return false;
2261 }
2262
2263 return ValidateBeginQueryBase(context, target, id);
2264}
2265
2266bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002267{
2268 if (!ValidQueryType(context, target))
2269 {
Jamie Madill437fa652016-05-03 15:13:24 -04002270 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002271 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002272 }
2273
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002274 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002275
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002276 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002277 {
Jamie Madill437fa652016-05-03 15:13:24 -04002278 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002279 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002280 }
2281
Jamie Madill45c785d2014-05-13 14:09:34 -04002282 return true;
2283}
2284
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002285bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2286{
2287 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002288 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002289 {
Jamie Madill437fa652016-05-03 15:13:24 -04002290 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002291 return false;
2292 }
2293
2294 return ValidateEndQueryBase(context, target);
2295}
2296
2297bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2298{
2299 if (!context->getExtensions().disjointTimerQuery)
2300 {
Jamie Madill437fa652016-05-03 15:13:24 -04002301 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002302 return false;
2303 }
2304
2305 if (target != GL_TIMESTAMP_EXT)
2306 {
Jamie Madill437fa652016-05-03 15:13:24 -04002307 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002308 return false;
2309 }
2310
2311 Query *queryObject = context->getQuery(id, true, target);
2312 if (queryObject == nullptr)
2313 {
Jamie Madill437fa652016-05-03 15:13:24 -04002314 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002315 return false;
2316 }
2317
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002318 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002319 {
Jamie Madill437fa652016-05-03 15:13:24 -04002320 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002321 return false;
2322 }
2323
2324 return true;
2325}
2326
Geoff Lang2186c382016-10-14 10:54:54 -04002327bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002328{
Geoff Lang2186c382016-10-14 10:54:54 -04002329 if (numParams)
2330 {
2331 *numParams = 0;
2332 }
2333
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002334 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2335 {
Jamie Madill437fa652016-05-03 15:13:24 -04002336 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002337 return false;
2338 }
2339
2340 switch (pname)
2341 {
2342 case GL_CURRENT_QUERY_EXT:
2343 if (target == GL_TIMESTAMP_EXT)
2344 {
Jamie Madill437fa652016-05-03 15:13:24 -04002345 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002346 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2347 return false;
2348 }
2349 break;
2350 case GL_QUERY_COUNTER_BITS_EXT:
2351 if (!context->getExtensions().disjointTimerQuery ||
2352 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2353 {
Jamie Madill437fa652016-05-03 15:13:24 -04002354 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002355 return false;
2356 }
2357 break;
2358 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002359 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002360 return false;
2361 }
2362
Geoff Lang2186c382016-10-14 10:54:54 -04002363 if (numParams)
2364 {
2365 // All queries return only one value
2366 *numParams = 1;
2367 }
2368
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002369 return true;
2370}
2371
2372bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2373{
2374 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002375 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002376 {
Jamie Madill437fa652016-05-03 15:13:24 -04002377 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002378 return false;
2379 }
2380
Geoff Lang2186c382016-10-14 10:54:54 -04002381 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002382}
2383
Geoff Lang2186c382016-10-14 10:54:54 -04002384bool ValidateGetQueryivRobustANGLE(Context *context,
2385 GLenum target,
2386 GLenum pname,
2387 GLsizei bufSize,
2388 GLsizei *length,
2389 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002390{
Geoff Lang2186c382016-10-14 10:54:54 -04002391 if (!ValidateRobustEntryPoint(context, bufSize))
2392 {
2393 return false;
2394 }
2395
2396 if (!ValidateGetQueryivBase(context, target, pname, length))
2397 {
2398 return false;
2399 }
2400
2401 if (!ValidateRobustBufferSize(context, bufSize, *length))
2402 {
2403 return false;
2404 }
2405
2406 return true;
2407}
2408
2409bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2410{
2411 if (numParams)
2412 {
2413 *numParams = 0;
2414 }
2415
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002416 Query *queryObject = context->getQuery(id, false, GL_NONE);
2417
2418 if (!queryObject)
2419 {
Jamie Madill437fa652016-05-03 15:13:24 -04002420 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002421 return false;
2422 }
2423
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002424 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002425 {
Jamie Madill437fa652016-05-03 15:13:24 -04002426 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002427 return false;
2428 }
2429
2430 switch (pname)
2431 {
2432 case GL_QUERY_RESULT_EXT:
2433 case GL_QUERY_RESULT_AVAILABLE_EXT:
2434 break;
2435
2436 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002437 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002438 return false;
2439 }
2440
Geoff Lang2186c382016-10-14 10:54:54 -04002441 if (numParams)
2442 {
2443 *numParams = 1;
2444 }
2445
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002446 return true;
2447}
2448
2449bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2450{
2451 if (!context->getExtensions().disjointTimerQuery)
2452 {
Jamie Madill437fa652016-05-03 15:13:24 -04002453 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002454 return false;
2455 }
Geoff Lang2186c382016-10-14 10:54:54 -04002456 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2457}
2458
2459bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2460 GLuint id,
2461 GLenum pname,
2462 GLsizei bufSize,
2463 GLsizei *length,
2464 GLint *params)
2465{
2466 if (!context->getExtensions().disjointTimerQuery)
2467 {
2468 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2469 return false;
2470 }
2471
2472 if (!ValidateRobustEntryPoint(context, bufSize))
2473 {
2474 return false;
2475 }
2476
2477 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2478 {
2479 return false;
2480 }
2481
2482 if (!ValidateRobustBufferSize(context, bufSize, *length))
2483 {
2484 return false;
2485 }
2486
2487 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002488}
2489
2490bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2491{
2492 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002493 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002494 {
Jamie Madill437fa652016-05-03 15:13:24 -04002495 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002496 return false;
2497 }
Geoff Lang2186c382016-10-14 10:54:54 -04002498 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2499}
2500
2501bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2502 GLuint id,
2503 GLenum pname,
2504 GLsizei bufSize,
2505 GLsizei *length,
2506 GLuint *params)
2507{
2508 if (!context->getExtensions().disjointTimerQuery &&
2509 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2510 {
2511 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2512 return false;
2513 }
2514
2515 if (!ValidateRobustEntryPoint(context, bufSize))
2516 {
2517 return false;
2518 }
2519
2520 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2521 {
2522 return false;
2523 }
2524
2525 if (!ValidateRobustBufferSize(context, bufSize, *length))
2526 {
2527 return false;
2528 }
2529
2530 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002531}
2532
2533bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2534{
2535 if (!context->getExtensions().disjointTimerQuery)
2536 {
Jamie Madill437fa652016-05-03 15:13:24 -04002537 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002538 return false;
2539 }
Geoff Lang2186c382016-10-14 10:54:54 -04002540 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2541}
2542
2543bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2544 GLuint id,
2545 GLenum pname,
2546 GLsizei bufSize,
2547 GLsizei *length,
2548 GLint64 *params)
2549{
2550 if (!context->getExtensions().disjointTimerQuery)
2551 {
2552 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2553 return false;
2554 }
2555
2556 if (!ValidateRobustEntryPoint(context, bufSize))
2557 {
2558 return false;
2559 }
2560
2561 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2562 {
2563 return false;
2564 }
2565
2566 if (!ValidateRobustBufferSize(context, bufSize, *length))
2567 {
2568 return false;
2569 }
2570
2571 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002572}
2573
2574bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2575{
2576 if (!context->getExtensions().disjointTimerQuery)
2577 {
Jamie Madill437fa652016-05-03 15:13:24 -04002578 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002579 return false;
2580 }
Geoff Lang2186c382016-10-14 10:54:54 -04002581 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2582}
2583
2584bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2585 GLuint id,
2586 GLenum pname,
2587 GLsizei bufSize,
2588 GLsizei *length,
2589 GLuint64 *params)
2590{
2591 if (!context->getExtensions().disjointTimerQuery)
2592 {
2593 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2594 return false;
2595 }
2596
2597 if (!ValidateRobustEntryPoint(context, bufSize))
2598 {
2599 return false;
2600 }
2601
2602 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2603 {
2604 return false;
2605 }
2606
2607 if (!ValidateRobustBufferSize(context, bufSize, *length))
2608 {
2609 return false;
2610 }
2611
2612 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002613}
2614
Jamie Madill62d31cb2015-09-11 13:25:51 -04002615static bool ValidateUniformCommonBase(gl::Context *context,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002616 gl::Program *program,
Jamie Madill62d31cb2015-09-11 13:25:51 -04002617 GLenum targetUniformType,
2618 GLint location,
2619 GLsizei count,
2620 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002621{
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002622 // TODO(Jiajia): Add image uniform check in future.
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002623 if (count < 0)
2624 {
Jamie Madill437fa652016-05-03 15:13:24 -04002625 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002626 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002627 }
2628
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002629 if (!program || !program->isLinked())
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002630 {
Jamie Madill437fa652016-05-03 15:13:24 -04002631 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002632 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002633 }
2634
Geoff Langd8605522016-04-13 10:19:12 -04002635 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002636 {
2637 // Silently ignore the uniform command
2638 return false;
2639 }
2640
Geoff Lang7dd2e102014-11-10 15:19:26 -05002641 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04002642 {
Jamie Madill437fa652016-05-03 15:13:24 -04002643 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002644 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002645 }
2646
Jamie Madill62d31cb2015-09-11 13:25:51 -04002647 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04002648
2649 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002650 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002651 {
Jamie Madill437fa652016-05-03 15:13:24 -04002652 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002653 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002654 }
2655
Jamie Madill62d31cb2015-09-11 13:25:51 -04002656 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002657 return true;
2658}
2659
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002660bool ValidateProgramUniform(gl::Context *context,
2661 GLenum uniformType,
2662 GLuint program,
2663 GLint location,
2664 GLsizei count)
2665{
2666 // Check for ES31 program uniform entry points
2667 if (context->getClientVersion() < Version(3, 1))
2668 {
2669 context->handleError(Error(GL_INVALID_OPERATION));
2670 return false;
2671 }
2672
2673 const LinkedUniform *uniform = nullptr;
2674 gl::Program *programObject = GetValidProgram(context, program);
2675 if (!ValidateUniformCommonBase(context, programObject, uniformType, location, count, &uniform))
2676 {
2677 return false;
2678 }
2679
2680 GLenum targetBoolType = VariableBoolVectorType(uniformType);
2681 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
2682 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2683 {
2684 context->handleError(Error(GL_INVALID_OPERATION));
2685 return false;
2686 }
2687
2688 return true;
2689}
2690
2691bool ValidateProgramUniformMatrix(gl::Context *context,
2692 GLenum matrixType,
2693 GLuint program,
2694 GLint location,
2695 GLsizei count,
2696 GLboolean transpose)
2697{
2698 // Check for ES31 program uniform entry points
2699 if (context->getClientVersion() < Version(3, 1))
2700 {
2701 context->handleError(Error(GL_INVALID_OPERATION));
2702 return false;
2703 }
2704
2705 const LinkedUniform *uniform = nullptr;
2706 gl::Program *programObject = GetValidProgram(context, program);
2707 if (!ValidateUniformCommonBase(context, programObject, matrixType, location, count, &uniform))
2708 {
2709 return false;
2710 }
2711
2712 if (uniform->type != matrixType)
2713 {
2714 context->handleError(Error(GL_INVALID_OPERATION));
2715 return false;
2716 }
2717
2718 return true;
2719}
2720
Jamie Madillaa981bd2014-05-20 10:55:55 -04002721bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2722{
2723 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002724 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2725 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002726 {
Jamie Madill437fa652016-05-03 15:13:24 -04002727 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002728 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002729 }
2730
Jamie Madill62d31cb2015-09-11 13:25:51 -04002731 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002732 gl::Program *program = context->getGLState().getProgram();
2733 if (!ValidateUniformCommonBase(context, program, uniformType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002734 {
2735 return false;
2736 }
2737
He Yunchaoced53ae2016-11-29 15:00:51 +08002738 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002739 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002740 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2741 {
Jamie Madill437fa652016-05-03 15:13:24 -04002742 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002743 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002744 }
2745
2746 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002747}
2748
He Yunchaoced53ae2016-11-29 15:00:51 +08002749bool ValidateUniformMatrix(gl::Context *context,
2750 GLenum matrixType,
2751 GLint location,
2752 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002753 GLboolean transpose)
2754{
2755 // Check for ES3 uniform entry points
2756 int rows = VariableRowCount(matrixType);
2757 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002758 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002759 {
Jamie Madill437fa652016-05-03 15:13:24 -04002760 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002761 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002762 }
2763
Martin Radev1be913c2016-07-11 17:59:16 +03002764 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002765 {
Jamie Madill437fa652016-05-03 15:13:24 -04002766 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002767 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002768 }
2769
Jamie Madill62d31cb2015-09-11 13:25:51 -04002770 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002771 gl::Program *program = context->getGLState().getProgram();
2772 if (!ValidateUniformCommonBase(context, program, matrixType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002773 {
2774 return false;
2775 }
2776
2777 if (uniform->type != matrixType)
2778 {
Jamie Madill437fa652016-05-03 15:13:24 -04002779 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002780 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002781 }
2782
2783 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002784}
2785
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002786bool ValidateStateQuery(ValidationContext *context,
2787 GLenum pname,
2788 GLenum *nativeType,
2789 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002790{
2791 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2792 {
Jamie Madill437fa652016-05-03 15:13:24 -04002793 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002794 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002795 }
2796
Jamie Madill0af26e12015-03-05 19:54:33 -05002797 const Caps &caps = context->getCaps();
2798
Jamie Madill893ab082014-05-16 16:56:10 -04002799 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2800 {
2801 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2802
Jamie Madill0af26e12015-03-05 19:54:33 -05002803 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002804 {
Jamie Madill437fa652016-05-03 15:13:24 -04002805 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002806 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002807 }
2808 }
2809
2810 switch (pname)
2811 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002812 case GL_TEXTURE_BINDING_2D:
2813 case GL_TEXTURE_BINDING_CUBE_MAP:
2814 case GL_TEXTURE_BINDING_3D:
2815 case GL_TEXTURE_BINDING_2D_ARRAY:
2816 break;
2817 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2818 if (!context->getExtensions().eglStreamConsumerExternal &&
2819 !context->getExtensions().eglImageExternal)
2820 {
2821 context->handleError(Error(GL_INVALID_ENUM,
2822 "Neither NV_EGL_stream_consumer_external nor "
2823 "GL_OES_EGL_image_external extensions enabled"));
2824 return false;
2825 }
2826 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002827
He Yunchaoced53ae2016-11-29 15:00:51 +08002828 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2829 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002830 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002831 if (context->getGLState().getReadFramebuffer()->checkStatus(
2832 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002833 {
Jamie Madill437fa652016-05-03 15:13:24 -04002834 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002835 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002836 }
2837
Jamie Madill51f40ec2016-06-15 14:06:00 -04002838 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2839 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002840
2841 if (framebuffer->getReadBufferState() == GL_NONE)
2842 {
2843 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2844 return false;
2845 }
2846
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002847 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002848 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002849 {
Jamie Madill437fa652016-05-03 15:13:24 -04002850 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002851 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002852 }
2853 }
2854 break;
2855
He Yunchaoced53ae2016-11-29 15:00:51 +08002856 default:
2857 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002858 }
2859
2860 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002861 if (*numParams == 0)
2862 {
2863 return false;
2864 }
2865
2866 return true;
2867}
2868
2869bool ValidateRobustStateQuery(ValidationContext *context,
2870 GLenum pname,
2871 GLsizei bufSize,
2872 GLenum *nativeType,
2873 unsigned int *numParams)
2874{
2875 if (!ValidateRobustEntryPoint(context, bufSize))
2876 {
2877 return false;
2878 }
2879
2880 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2881 {
2882 return false;
2883 }
2884
2885 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002886 {
2887 return false;
2888 }
2889
2890 return true;
2891}
2892
Jamie Madillc29968b2016-01-20 11:17:23 -05002893bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2894 GLenum target,
2895 GLint level,
2896 GLenum internalformat,
2897 bool isSubImage,
2898 GLint xoffset,
2899 GLint yoffset,
2900 GLint zoffset,
2901 GLint x,
2902 GLint y,
2903 GLsizei width,
2904 GLsizei height,
2905 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002906 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002907{
Jamie Madill560a8d82014-05-21 13:06:20 -04002908 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2909 {
Jamie Madill437fa652016-05-03 15:13:24 -04002910 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002911 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002912 }
2913
He Yunchaoced53ae2016-11-29 15:00:51 +08002914 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2915 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002916 {
Jamie Madill437fa652016-05-03 15:13:24 -04002917 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002918 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002919 }
2920
2921 if (border != 0)
2922 {
Jamie Madill437fa652016-05-03 15:13:24 -04002923 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002924 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002925 }
2926
2927 if (!ValidMipLevel(context, target, level))
2928 {
Jamie Madill437fa652016-05-03 15:13:24 -04002929 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002930 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002931 }
2932
Jamie Madill51f40ec2016-06-15 14:06:00 -04002933 const auto &state = context->getGLState();
2934 auto readFramebuffer = state.getReadFramebuffer();
2935 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002936 {
Jamie Madill437fa652016-05-03 15:13:24 -04002937 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002938 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002939 }
2940
Jamie Madill51f40ec2016-06-15 14:06:00 -04002941 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002942 {
Jamie Madill437fa652016-05-03 15:13:24 -04002943 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002944 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002945 }
2946
Martin Radev138064f2016-07-15 12:03:41 +03002947 if (readFramebuffer->getReadBufferState() == GL_NONE)
2948 {
2949 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2950 return false;
2951 }
2952
Geoff Langaae65a42014-05-26 12:43:44 -04002953 const gl::Caps &caps = context->getCaps();
2954
Geoff Langaae65a42014-05-26 12:43:44 -04002955 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002956 switch (target)
2957 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002958 case GL_TEXTURE_2D:
2959 maxDimension = caps.max2DTextureSize;
2960 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002961
He Yunchaoced53ae2016-11-29 15:00:51 +08002962 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2963 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2964 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2965 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2966 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2967 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2968 maxDimension = caps.maxCubeMapTextureSize;
2969 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002970
He Yunchaoced53ae2016-11-29 15:00:51 +08002971 case GL_TEXTURE_2D_ARRAY:
2972 maxDimension = caps.max2DTextureSize;
2973 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002974
He Yunchaoced53ae2016-11-29 15:00:51 +08002975 case GL_TEXTURE_3D:
2976 maxDimension = caps.max3DTextureSize;
2977 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002978
He Yunchaoced53ae2016-11-29 15:00:51 +08002979 default:
2980 context->handleError(Error(GL_INVALID_ENUM));
2981 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002982 }
2983
Jamie Madillc29968b2016-01-20 11:17:23 -05002984 gl::Texture *texture =
2985 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002986 if (!texture)
2987 {
Jamie Madill437fa652016-05-03 15:13:24 -04002988 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002989 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002990 }
2991
Geoff Lang69cce582015-09-17 13:20:36 -04002992 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002993 {
Jamie Madill437fa652016-05-03 15:13:24 -04002994 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002995 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002996 }
2997
Geoff Lang5d601382014-07-22 15:14:06 -04002998 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
2999
3000 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003001 {
Jamie Madill437fa652016-05-03 15:13:24 -04003002 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003003 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003004 }
3005
Geoff Langa9be0dc2014-12-17 12:34:40 -05003006 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003007 {
Jamie Madill437fa652016-05-03 15:13:24 -04003008 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003009 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003010 }
3011
3012 if (isSubImage)
3013 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003014 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3015 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3016 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003017 {
Jamie Madill437fa652016-05-03 15:13:24 -04003018 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003019 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003020 }
3021 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003022 else
3023 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003024 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003025 {
Jamie Madill437fa652016-05-03 15:13:24 -04003026 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003027 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003028 }
3029
Geoff Langeb66a6e2016-10-31 13:06:12 -04003030 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003031 {
Jamie Madill437fa652016-05-03 15:13:24 -04003032 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003033 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003034 }
3035
3036 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003037 if (static_cast<int>(width) > maxLevelDimension ||
3038 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003039 {
Jamie Madill437fa652016-05-03 15:13:24 -04003040 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003041 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003042 }
3043 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003044
Jamie Madill0c8abca2016-07-22 20:21:26 -04003045 if (textureFormatOut)
3046 {
3047 *textureFormatOut = texture->getFormat(target, level);
3048 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003049 return true;
3050}
3051
Jamie Madillf25855c2015-11-03 11:06:18 -05003052static bool ValidateDrawBase(ValidationContext *context,
3053 GLenum mode,
3054 GLsizei count,
3055 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003056{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003057 switch (mode)
3058 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003059 case GL_POINTS:
3060 case GL_LINES:
3061 case GL_LINE_LOOP:
3062 case GL_LINE_STRIP:
3063 case GL_TRIANGLES:
3064 case GL_TRIANGLE_STRIP:
3065 case GL_TRIANGLE_FAN:
3066 break;
3067 default:
3068 context->handleError(Error(GL_INVALID_ENUM));
3069 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003070 }
3071
Jamie Madill250d33f2014-06-06 17:09:03 -04003072 if (count < 0)
3073 {
Jamie Madill437fa652016-05-03 15:13:24 -04003074 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003075 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003076 }
3077
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003078 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003079
Jamie Madill250d33f2014-06-06 17:09:03 -04003080 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003081 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003082 {
Jamie Madill437fa652016-05-03 15:13:24 -04003083 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003084 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003085 }
3086
Jamie Madill51f40ec2016-06-15 14:06:00 -04003087 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04003088 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04003089 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04003090 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
He Yunchaoced53ae2016-11-29 15:00:51 +08003091 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
3092 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003093 const DepthStencilState &depthStencilState = state.getDepthStencilState();
3094 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3095 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04003096 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04003097 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3098 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04003099 {
3100 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3101 // Section 6.10 of the WebGL 1.0 spec
He Yunchaoced53ae2016-11-29 15:00:51 +08003102 ERR("This ANGLE implementation does not support separate front/back stencil "
Geoff Lang3a86ad32015-09-01 11:47:05 -04003103 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04003104 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003105 return false;
3106 }
Jamie Madillac528012014-06-20 13:21:23 -04003107 }
3108
Jamie Madill51f40ec2016-06-15 14:06:00 -04003109 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003110 {
Jamie Madill437fa652016-05-03 15:13:24 -04003111 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003112 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003113 }
3114
Geoff Lang7dd2e102014-11-10 15:19:26 -05003115 gl::Program *program = state.getProgram();
3116 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003117 {
Jamie Madill437fa652016-05-03 15:13:24 -04003118 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003119 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003120 }
3121
Geoff Lang7dd2e102014-11-10 15:19:26 -05003122 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003123 {
Jamie Madill437fa652016-05-03 15:13:24 -04003124 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003125 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003126 }
3127
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003128 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003129 for (unsigned int uniformBlockIndex = 0;
3130 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003131 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003132 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003133 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003134 const OffsetBindingPointer<Buffer> &uniformBuffer =
3135 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003136
Geoff Lang5d124a62015-09-15 13:03:27 -04003137 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003138 {
3139 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003140 context->handleError(
3141 Error(GL_INVALID_OPERATION,
3142 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003143 return false;
3144 }
3145
Geoff Lang5d124a62015-09-15 13:03:27 -04003146 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003147 if (uniformBufferSize == 0)
3148 {
3149 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003150 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003151 }
3152
Jamie Madill62d31cb2015-09-11 13:25:51 -04003153 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003154 {
3155 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003156 context->handleError(
3157 Error(GL_INVALID_OPERATION,
3158 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003159 return false;
3160 }
3161 }
3162
Jamie Madill250d33f2014-06-06 17:09:03 -04003163 // No-op if zero count
3164 return (count > 0);
3165}
3166
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003167bool ValidateDrawArrays(ValidationContext *context,
3168 GLenum mode,
3169 GLint first,
3170 GLsizei count,
3171 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003172{
Jamie Madillfd716582014-06-06 17:09:04 -04003173 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003174 {
Jamie Madill437fa652016-05-03 15:13:24 -04003175 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003176 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003177 }
3178
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003179 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003180 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003181 if (curTransformFeedback && curTransformFeedback->isActive() &&
3182 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003183 {
3184 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003185 // that does not match the current transform feedback object's draw mode (if transform
3186 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003187 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003188 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003189 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003190 }
3191
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003192 if (!ValidateDrawBase(context, mode, count, primcount))
3193 {
3194 return false;
3195 }
3196
Corentin Wallez92db6942016-12-09 13:10:36 -05003197 CheckedNumeric<GLint> maxVertex = first;
3198 maxVertex += count;
3199 maxVertex -= 1;
3200
3201 if (!maxVertex.IsValid())
3202 {
3203 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3204 return false;
3205 }
3206
3207 if (!ValidateDrawAttribs(context, primcount, maxVertex.ValueOrDie(), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003208 {
3209 return false;
3210 }
3211
3212 return true;
3213}
3214
He Yunchaoced53ae2016-11-29 15:00:51 +08003215bool ValidateDrawArraysInstanced(Context *context,
3216 GLenum mode,
3217 GLint first,
3218 GLsizei count,
3219 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003220{
3221 if (primcount < 0)
3222 {
Jamie Madill437fa652016-05-03 15:13:24 -04003223 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003224 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003225 }
3226
Jamie Madill2b976812014-08-25 15:47:49 -04003227 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003228 {
3229 return false;
3230 }
3231
3232 // No-op if zero primitive count
3233 return (primcount > 0);
3234}
3235
Geoff Lang87a93302014-09-16 13:29:43 -04003236static bool ValidateDrawInstancedANGLE(Context *context)
3237{
3238 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003239 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003240
Geoff Lang7dd2e102014-11-10 15:19:26 -05003241 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003242
3243 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003244 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003245 {
3246 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003247 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003248 {
3249 return true;
3250 }
3251 }
3252
Jamie Madill437fa652016-05-03 15:13:24 -04003253 context->handleError(Error(GL_INVALID_OPERATION,
3254 "ANGLE_instanced_arrays requires that at least one active attribute"
3255 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003256 return false;
3257}
3258
He Yunchaoced53ae2016-11-29 15:00:51 +08003259bool ValidateDrawArraysInstancedANGLE(Context *context,
3260 GLenum mode,
3261 GLint first,
3262 GLsizei count,
3263 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003264{
3265 if (!ValidateDrawInstancedANGLE(context))
3266 {
3267 return false;
3268 }
3269
3270 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3271}
3272
Jamie Madillf25855c2015-11-03 11:06:18 -05003273bool ValidateDrawElements(ValidationContext *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003274 GLenum mode,
3275 GLsizei count,
3276 GLenum type,
3277 const GLvoid *indices,
3278 GLsizei primcount,
3279 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003280{
Jamie Madill250d33f2014-06-06 17:09:03 -04003281 switch (type)
3282 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003283 case GL_UNSIGNED_BYTE:
3284 case GL_UNSIGNED_SHORT:
3285 break;
3286 case GL_UNSIGNED_INT:
3287 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3288 {
3289 context->handleError(Error(GL_INVALID_ENUM));
3290 return false;
3291 }
3292 break;
3293 default:
3294 context->handleError(Error(GL_INVALID_ENUM));
3295 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003296 }
3297
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003298 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003299
3300 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003301 if (curTransformFeedback && curTransformFeedback->isActive() &&
3302 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003303 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003304 // It is an invalid operation to call DrawElements, DrawRangeElements or
3305 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003306 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003307 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003308 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003309 }
3310
3311 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003312 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003313 {
Jamie Madill437fa652016-05-03 15:13:24 -04003314 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003315 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003316 }
3317
He Yunchaoced53ae2016-11-29 15:00:51 +08003318 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003319 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003320
Jamie Madillae3000b2014-08-25 15:47:51 -04003321 if (elementArrayBuffer)
3322 {
3323 const gl::Type &typeInfo = gl::GetTypeInfo(type);
3324
3325 GLint64 offset = reinterpret_cast<GLint64>(indices);
He Yunchaoced53ae2016-11-29 15:00:51 +08003326 GLint64 byteCount =
3327 static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count) + offset;
Jamie Madillae3000b2014-08-25 15:47:51 -04003328
3329 // check for integer overflows
3330 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
3331 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3332 {
Jamie Madill437fa652016-05-03 15:13:24 -04003333 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04003334 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003335 }
3336
3337 // Check for reading past the end of the bound buffer object
3338 if (byteCount > elementArrayBuffer->getSize())
3339 {
Jamie Madill437fa652016-05-03 15:13:24 -04003340 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003341 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003342 }
3343 }
Corentin Wallez327411e2016-12-09 11:09:17 -05003344 else if (context->getExtensions().webglCompatibility && count > 0)
3345 {
3346 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3347 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3348 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3349 context->handleError(
3350 Error(GL_INVALID_OPERATION, "There is no element array buffer bound and count > 0."));
3351 return false;
3352 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003353 else if (!indices)
3354 {
Corentin Wallez327411e2016-12-09 11:09:17 -05003355 // This is an application error that would normally result in a crash,
3356 // but we catch it and return an error
3357 context->handleError(
3358 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003359 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003360 }
3361
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003362 if (!ValidateDrawBase(context, mode, count, primcount))
3363 {
3364 return false;
3365 }
3366
Jamie Madill2b976812014-08-25 15:47:49 -04003367 // Use max index to validate if our vertex buffers are large enough for the pull.
3368 // TODO: offer fast path, with disabled index validation.
3369 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3370 if (elementArrayBuffer)
3371 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003372 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003373 Error error =
3374 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3375 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003376 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003377 {
Jamie Madill437fa652016-05-03 15:13:24 -04003378 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003379 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003380 }
3381 }
3382 else
3383 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003384 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003385 }
3386
Jamie Madille79b1e12015-11-04 16:36:37 -05003387 // If we use an index greater than our maximum supported index range, return an error.
3388 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3389 // return an error if possible here.
3390 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3391 {
Jamie Madill437fa652016-05-03 15:13:24 -04003392 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003393 return false;
3394 }
3395
Corentin Wallez92db6942016-12-09 13:10:36 -05003396 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3397 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003398 {
3399 return false;
3400 }
3401
Geoff Lang3edfe032015-09-04 16:38:24 -04003402 // No op if there are no real indices in the index data (all are primitive restart).
3403 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003404}
3405
Geoff Langb1196682014-07-23 13:47:29 -04003406bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003407 GLenum mode,
3408 GLsizei count,
3409 GLenum type,
3410 const GLvoid *indices,
3411 GLsizei primcount,
3412 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003413{
3414 if (primcount < 0)
3415 {
Jamie Madill437fa652016-05-03 15:13:24 -04003416 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003417 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003418 }
3419
Jamie Madill2b976812014-08-25 15:47:49 -04003420 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003421 {
3422 return false;
3423 }
3424
3425 // No-op zero primitive count
3426 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003427}
3428
Geoff Lang3edfe032015-09-04 16:38:24 -04003429bool ValidateDrawElementsInstancedANGLE(Context *context,
3430 GLenum mode,
3431 GLsizei count,
3432 GLenum type,
3433 const GLvoid *indices,
3434 GLsizei primcount,
3435 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003436{
3437 if (!ValidateDrawInstancedANGLE(context))
3438 {
3439 return false;
3440 }
3441
He Yunchaoced53ae2016-11-29 15:00:51 +08003442 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3443 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003444}
3445
He Yunchaoced53ae2016-11-29 15:00:51 +08003446bool ValidateFramebufferTextureBase(Context *context,
3447 GLenum target,
3448 GLenum attachment,
3449 GLuint texture,
3450 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003451{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003452 if (!ValidFramebufferTarget(target))
3453 {
Jamie Madill437fa652016-05-03 15:13:24 -04003454 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003455 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003456 }
3457
3458 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003459 {
3460 return false;
3461 }
3462
Jamie Madill55ec3b12014-07-03 10:38:57 -04003463 if (texture != 0)
3464 {
3465 gl::Texture *tex = context->getTexture(texture);
3466
3467 if (tex == NULL)
3468 {
Jamie Madill437fa652016-05-03 15:13:24 -04003469 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003470 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003471 }
3472
3473 if (level < 0)
3474 {
Jamie Madill437fa652016-05-03 15:13:24 -04003475 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003476 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003477 }
3478 }
3479
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003480 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003481 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003482
Jamie Madill84115c92015-04-23 15:00:07 -04003483 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003484 {
Jamie Madill437fa652016-05-03 15:13:24 -04003485 context->handleError(
3486 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003487 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003488 }
3489
3490 return true;
3491}
3492
He Yunchaoced53ae2016-11-29 15:00:51 +08003493bool ValidateFramebufferTexture2D(Context *context,
3494 GLenum target,
3495 GLenum attachment,
3496 GLenum textarget,
3497 GLuint texture,
3498 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003499{
He Yunchaoced53ae2016-11-29 15:00:51 +08003500 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3501 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003502 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3503 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003504 {
Jamie Madill437fa652016-05-03 15:13:24 -04003505 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003506 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003507 }
3508
3509 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003510 {
3511 return false;
3512 }
3513
Jamie Madill55ec3b12014-07-03 10:38:57 -04003514 if (texture != 0)
3515 {
3516 gl::Texture *tex = context->getTexture(texture);
3517 ASSERT(tex);
3518
Jamie Madill2a6564e2014-07-11 09:53:19 -04003519 const gl::Caps &caps = context->getCaps();
3520
Jamie Madill55ec3b12014-07-03 10:38:57 -04003521 switch (textarget)
3522 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003523 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003524 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003525 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003526 {
Jamie Madill437fa652016-05-03 15:13:24 -04003527 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003528 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003529 }
3530 if (tex->getTarget() != GL_TEXTURE_2D)
3531 {
Jamie Madill437fa652016-05-03 15:13:24 -04003532 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003533 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003534 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003535 }
3536 break;
3537
He Yunchaoced53ae2016-11-29 15:00:51 +08003538 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3539 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3540 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3541 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3542 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3543 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003544 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003545 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003546 {
Jamie Madill437fa652016-05-03 15:13:24 -04003547 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003548 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003549 }
3550 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3551 {
Jamie Madill437fa652016-05-03 15:13:24 -04003552 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003553 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003554 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003555 }
3556 break;
3557
He Yunchaoced53ae2016-11-29 15:00:51 +08003558 default:
3559 context->handleError(Error(GL_INVALID_ENUM));
3560 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003561 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003562
Jamie Madilla3944d42016-07-22 22:13:26 -04003563 const Format &format = tex->getFormat(textarget, level);
3564 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003565 {
Jamie Madill437fa652016-05-03 15:13:24 -04003566 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003567 return false;
3568 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003569 }
3570
Jamie Madill570f7c82014-07-03 10:38:54 -04003571 return true;
3572}
3573
Geoff Langb1196682014-07-23 13:47:29 -04003574bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003575{
3576 if (program == 0)
3577 {
Jamie Madill437fa652016-05-03 15:13:24 -04003578 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003579 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003580 }
3581
Dian Xiang769769a2015-09-09 15:20:08 -07003582 gl::Program *programObject = GetValidProgram(context, program);
3583 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003584 {
3585 return false;
3586 }
3587
Jamie Madill0063c512014-08-25 15:47:53 -04003588 if (!programObject || !programObject->isLinked())
3589 {
Jamie Madill437fa652016-05-03 15:13:24 -04003590 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003591 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003592 }
3593
Geoff Lang7dd2e102014-11-10 15:19:26 -05003594 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003595 {
Jamie Madill437fa652016-05-03 15:13:24 -04003596 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003597 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003598 }
3599
Jamie Madill0063c512014-08-25 15:47:53 -04003600 return true;
3601}
3602
He Yunchaoced53ae2016-11-29 15:00:51 +08003603bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003604{
3605 return ValidateGetUniformBase(context, program, location);
3606}
3607
He Yunchaoced53ae2016-11-29 15:00:51 +08003608bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003609{
Jamie Madill78f41802014-08-25 15:47:55 -04003610 return ValidateGetUniformBase(context, program, location);
3611}
3612
Geoff Langf41d0ee2016-10-07 13:04:23 -04003613static bool ValidateSizedGetUniform(Context *context,
3614 GLuint program,
3615 GLint location,
3616 GLsizei bufSize,
3617 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003618{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003619 if (length)
3620 {
3621 *length = 0;
3622 }
3623
Jamie Madill78f41802014-08-25 15:47:55 -04003624 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003625 {
Jamie Madill78f41802014-08-25 15:47:55 -04003626 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003627 }
3628
Geoff Langf41d0ee2016-10-07 13:04:23 -04003629 if (bufSize < 0)
3630 {
3631 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3632 return false;
3633 }
3634
Jamie Madilla502c742014-08-28 17:19:13 -04003635 gl::Program *programObject = context->getProgram(program);
3636 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003637
Jamie Madill78f41802014-08-25 15:47:55 -04003638 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003639 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003640 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003641 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003642 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003643 context->handleError(
3644 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003645 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003646 }
3647
Geoff Langf41d0ee2016-10-07 13:04:23 -04003648 if (length)
3649 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003650 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003651 }
3652
Jamie Madill0063c512014-08-25 15:47:53 -04003653 return true;
3654}
3655
He Yunchaoced53ae2016-11-29 15:00:51 +08003656bool ValidateGetnUniformfvEXT(Context *context,
3657 GLuint program,
3658 GLint location,
3659 GLsizei bufSize,
3660 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003661{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003662 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003663}
3664
He Yunchaoced53ae2016-11-29 15:00:51 +08003665bool ValidateGetnUniformivEXT(Context *context,
3666 GLuint program,
3667 GLint location,
3668 GLsizei bufSize,
3669 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003670{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003671 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3672}
3673
3674bool ValidateGetUniformfvRobustANGLE(Context *context,
3675 GLuint program,
3676 GLint location,
3677 GLsizei bufSize,
3678 GLsizei *length,
3679 GLfloat *params)
3680{
3681 if (!ValidateRobustEntryPoint(context, bufSize))
3682 {
3683 return false;
3684 }
3685
3686 // bufSize is validated in ValidateSizedGetUniform
3687 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3688}
3689
3690bool ValidateGetUniformivRobustANGLE(Context *context,
3691 GLuint program,
3692 GLint location,
3693 GLsizei bufSize,
3694 GLsizei *length,
3695 GLint *params)
3696{
3697 if (!ValidateRobustEntryPoint(context, bufSize))
3698 {
3699 return false;
3700 }
3701
3702 // bufSize is validated in ValidateSizedGetUniform
3703 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3704}
3705
3706bool ValidateGetUniformuivRobustANGLE(Context *context,
3707 GLuint program,
3708 GLint location,
3709 GLsizei bufSize,
3710 GLsizei *length,
3711 GLuint *params)
3712{
3713 if (!ValidateRobustEntryPoint(context, bufSize))
3714 {
3715 return false;
3716 }
3717
3718 if (context->getClientMajorVersion() < 3)
3719 {
3720 context->handleError(
3721 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3722 return false;
3723 }
3724
3725 // bufSize is validated in ValidateSizedGetUniform
3726 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003727}
3728
He Yunchaoced53ae2016-11-29 15:00:51 +08003729bool ValidateDiscardFramebufferBase(Context *context,
3730 GLenum target,
3731 GLsizei numAttachments,
3732 const GLenum *attachments,
3733 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003734{
3735 if (numAttachments < 0)
3736 {
Jamie Madill437fa652016-05-03 15:13:24 -04003737 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003738 return false;
3739 }
3740
3741 for (GLsizei i = 0; i < numAttachments; ++i)
3742 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003743 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003744 {
3745 if (defaultFramebuffer)
3746 {
Jamie Madill437fa652016-05-03 15:13:24 -04003747 context->handleError(Error(
3748 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003749 return false;
3750 }
3751
3752 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3753 {
Jamie Madill437fa652016-05-03 15:13:24 -04003754 context->handleError(Error(GL_INVALID_OPERATION,
3755 "Requested color attachment is greater than the maximum "
3756 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003757 return false;
3758 }
3759 }
3760 else
3761 {
3762 switch (attachments[i])
3763 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003764 case GL_DEPTH_ATTACHMENT:
3765 case GL_STENCIL_ATTACHMENT:
3766 case GL_DEPTH_STENCIL_ATTACHMENT:
3767 if (defaultFramebuffer)
3768 {
3769 context->handleError(
3770 Error(GL_INVALID_ENUM,
3771 "Invalid attachment when the default framebuffer is bound"));
3772 return false;
3773 }
3774 break;
3775 case GL_COLOR:
3776 case GL_DEPTH:
3777 case GL_STENCIL:
3778 if (!defaultFramebuffer)
3779 {
3780 context->handleError(
3781 Error(GL_INVALID_ENUM,
3782 "Invalid attachment when the default framebuffer is not bound"));
3783 return false;
3784 }
3785 break;
3786 default:
3787 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003788 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003789 }
3790 }
3791 }
3792
3793 return true;
3794}
3795
Austin Kinross6ee1e782015-05-29 17:05:37 -07003796bool ValidateInsertEventMarkerEXT(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 (marker == nullptr)
3806 {
3807 return false;
3808 }
3809
3810 return true;
3811}
3812
3813bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3814{
3815 // Note that debug marker calls must not set error state
3816
3817 if (length < 0)
3818 {
3819 return false;
3820 }
3821
3822 if (length > 0 && marker == nullptr)
3823 {
3824 return false;
3825 }
3826
3827 return true;
3828}
3829
Geoff Langdcab33b2015-07-21 13:03:16 -04003830bool ValidateEGLImageTargetTexture2DOES(Context *context,
3831 egl::Display *display,
3832 GLenum target,
3833 egl::Image *image)
3834{
Geoff Langa8406172015-07-21 16:53:39 -04003835 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3836 {
Jamie Madill437fa652016-05-03 15:13:24 -04003837 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003838 return false;
3839 }
3840
3841 switch (target)
3842 {
3843 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003844 if (!context->getExtensions().eglImage)
3845 {
3846 context->handleError(Error(
3847 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3848 }
3849 break;
3850
3851 case GL_TEXTURE_EXTERNAL_OES:
3852 if (!context->getExtensions().eglImageExternal)
3853 {
3854 context->handleError(Error(
3855 GL_INVALID_ENUM,
3856 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3857 }
Geoff Langa8406172015-07-21 16:53:39 -04003858 break;
3859
3860 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003861 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003862 return false;
3863 }
3864
3865 if (!display->isValidImage(image))
3866 {
Jamie Madill437fa652016-05-03 15:13:24 -04003867 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003868 return false;
3869 }
3870
3871 if (image->getSamples() > 0)
3872 {
Jamie Madill437fa652016-05-03 15:13:24 -04003873 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003874 "cannot create a 2D texture from a multisampled EGL image."));
3875 return false;
3876 }
3877
Jamie Madilla3944d42016-07-22 22:13:26 -04003878 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003879 if (!textureCaps.texturable)
3880 {
Jamie Madill437fa652016-05-03 15:13:24 -04003881 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003882 "EGL image internal format is not supported as a texture."));
3883 return false;
3884 }
3885
Geoff Langdcab33b2015-07-21 13:03:16 -04003886 return true;
3887}
3888
3889bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3890 egl::Display *display,
3891 GLenum target,
3892 egl::Image *image)
3893{
Geoff Langa8406172015-07-21 16:53:39 -04003894 if (!context->getExtensions().eglImage)
3895 {
Jamie Madill437fa652016-05-03 15:13:24 -04003896 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003897 return false;
3898 }
3899
3900 switch (target)
3901 {
3902 case GL_RENDERBUFFER:
3903 break;
3904
3905 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003906 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003907 return false;
3908 }
3909
3910 if (!display->isValidImage(image))
3911 {
Jamie Madill437fa652016-05-03 15:13:24 -04003912 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003913 return false;
3914 }
3915
Jamie Madilla3944d42016-07-22 22:13:26 -04003916 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003917 if (!textureCaps.renderable)
3918 {
Jamie Madill437fa652016-05-03 15:13:24 -04003919 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003920 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3921 return false;
3922 }
3923
Geoff Langdcab33b2015-07-21 13:03:16 -04003924 return true;
3925}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003926
3927bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3928{
Geoff Lang36167ab2015-12-07 10:27:14 -05003929 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003930 {
3931 // The default VAO should always exist
3932 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003933 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003934 return false;
3935 }
3936
3937 return true;
3938}
3939
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003940bool ValidateLinkProgram(Context *context, GLuint program)
3941{
3942 if (context->hasActiveTransformFeedback(program))
3943 {
3944 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003945 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003946 "Cannot link program while program is associated with an active "
3947 "transform feedback object."));
3948 return false;
3949 }
3950 return true;
3951}
3952
Geoff Langc5629752015-12-07 16:29:04 -05003953bool ValidateProgramBinaryBase(Context *context,
3954 GLuint program,
3955 GLenum binaryFormat,
3956 const void *binary,
3957 GLint length)
3958{
3959 Program *programObject = GetValidProgram(context, program);
3960 if (programObject == nullptr)
3961 {
3962 return false;
3963 }
3964
3965 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3966 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3967 programBinaryFormats.end())
3968 {
Jamie Madill437fa652016-05-03 15:13:24 -04003969 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05003970 return false;
3971 }
3972
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003973 if (context->hasActiveTransformFeedback(program))
3974 {
3975 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003976 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003977 "Cannot change program binary while program is associated with "
3978 "an active transform feedback object."));
3979 return false;
3980 }
3981
Geoff Langc5629752015-12-07 16:29:04 -05003982 return true;
3983}
3984
3985bool ValidateGetProgramBinaryBase(Context *context,
3986 GLuint program,
3987 GLsizei bufSize,
3988 GLsizei *length,
3989 GLenum *binaryFormat,
3990 void *binary)
3991{
3992 Program *programObject = GetValidProgram(context, program);
3993 if (programObject == nullptr)
3994 {
3995 return false;
3996 }
3997
3998 if (!programObject->isLinked())
3999 {
Jamie Madill437fa652016-05-03 15:13:24 -04004000 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004001 return false;
4002 }
4003
4004 return true;
4005}
Jamie Madillc29968b2016-01-20 11:17:23 -05004006
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004007bool ValidateUseProgram(Context *context, GLuint program)
4008{
4009 if (program != 0)
4010 {
4011 Program *programObject = context->getProgram(program);
4012 if (!programObject)
4013 {
4014 // ES 3.1.0 section 7.3 page 72
4015 if (context->getShader(program))
4016 {
Jamie Madill437fa652016-05-03 15:13:24 -04004017 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004018 Error(GL_INVALID_OPERATION,
4019 "Attempted to use a single shader instead of a shader program."));
4020 return false;
4021 }
4022 else
4023 {
Jamie Madill437fa652016-05-03 15:13:24 -04004024 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004025 return false;
4026 }
4027 }
4028 if (!programObject->isLinked())
4029 {
Jamie Madill437fa652016-05-03 15:13:24 -04004030 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004031 return false;
4032 }
4033 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004034 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004035 {
4036 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004037 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004038 Error(GL_INVALID_OPERATION,
4039 "Cannot change active program while transform feedback is unpaused."));
4040 return false;
4041 }
4042
4043 return true;
4044}
4045
Jamie Madillc29968b2016-01-20 11:17:23 -05004046bool ValidateCopyTexImage2D(ValidationContext *context,
4047 GLenum target,
4048 GLint level,
4049 GLenum internalformat,
4050 GLint x,
4051 GLint y,
4052 GLsizei width,
4053 GLsizei height,
4054 GLint border)
4055{
Martin Radev1be913c2016-07-11 17:59:16 +03004056 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004057 {
4058 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4059 0, x, y, width, height, border);
4060 }
4061
Martin Radev1be913c2016-07-11 17:59:16 +03004062 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004063 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4064 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004065}
Jamie Madillc29968b2016-01-20 11:17:23 -05004066
4067bool ValidateFramebufferRenderbuffer(Context *context,
4068 GLenum target,
4069 GLenum attachment,
4070 GLenum renderbuffertarget,
4071 GLuint renderbuffer)
4072{
4073 if (!ValidFramebufferTarget(target) ||
4074 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4075 {
Jamie Madill437fa652016-05-03 15:13:24 -04004076 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004077 return false;
4078 }
4079
4080 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4081 renderbuffertarget, renderbuffer);
4082}
4083
4084bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4085{
4086 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4087 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4088 {
Jamie Madill437fa652016-05-03 15:13:24 -04004089 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004090 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4091 return false;
4092 }
4093
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004094 ASSERT(context->getGLState().getDrawFramebuffer());
4095 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004096 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4097
4098 // This should come first before the check for the default frame buffer
4099 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4100 // rather than INVALID_OPERATION
4101 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4102 {
4103 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4104
4105 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004106 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4107 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004108 {
4109 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004110 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4111 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4112 // 3.1 is still a bit ambiguous about the error, but future specs are
4113 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004114 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004115 return false;
4116 }
4117 else if (bufs[colorAttachment] >= maxColorAttachment)
4118 {
Jamie Madill437fa652016-05-03 15:13:24 -04004119 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004120 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004121 return false;
4122 }
4123 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4124 frameBufferId != 0)
4125 {
4126 // INVALID_OPERATION-GL is bound to buffer and ith argument
4127 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004128 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004129 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4130 return false;
4131 }
4132 }
4133
4134 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4135 // and n is not 1 or bufs is bound to value other than BACK and NONE
4136 if (frameBufferId == 0)
4137 {
4138 if (n != 1)
4139 {
Jamie Madill437fa652016-05-03 15:13:24 -04004140 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004141 "n must be 1 when GL is bound to the default framebuffer"));
4142 return false;
4143 }
4144
4145 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4146 {
Jamie Madill437fa652016-05-03 15:13:24 -04004147 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004148 GL_INVALID_OPERATION,
4149 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4150 return false;
4151 }
4152 }
4153
4154 return true;
4155}
4156
4157bool ValidateCopyTexSubImage2D(Context *context,
4158 GLenum target,
4159 GLint level,
4160 GLint xoffset,
4161 GLint yoffset,
4162 GLint x,
4163 GLint y,
4164 GLsizei width,
4165 GLsizei height)
4166{
Martin Radev1be913c2016-07-11 17:59:16 +03004167 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004168 {
4169 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4170 yoffset, x, y, width, height, 0);
4171 }
4172
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004173 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4174 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004175}
4176
Geoff Lang496c02d2016-10-20 11:38:11 -07004177bool ValidateGetBufferPointervBase(Context *context,
4178 GLenum target,
4179 GLenum pname,
4180 GLsizei *length,
4181 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004182{
Geoff Lang496c02d2016-10-20 11:38:11 -07004183 if (length)
4184 {
4185 *length = 0;
4186 }
4187
4188 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4189 {
4190 context->handleError(
4191 Error(GL_INVALID_OPERATION,
4192 "Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
4193 return false;
4194 }
4195
Olli Etuaho4f667482016-03-30 15:56:35 +03004196 if (!ValidBufferTarget(context, target))
4197 {
Jamie Madill437fa652016-05-03 15:13:24 -04004198 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004199 return false;
4200 }
4201
Geoff Lang496c02d2016-10-20 11:38:11 -07004202 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004203 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004204 case GL_BUFFER_MAP_POINTER:
4205 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004206
Geoff Lang496c02d2016-10-20 11:38:11 -07004207 default:
4208 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4209 return false;
4210 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004211
4212 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4213 // target bound to zero generate an INVALID_OPERATION error."
4214 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004215 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004216 {
Jamie Madill437fa652016-05-03 15:13:24 -04004217 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004218 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4219 return false;
4220 }
4221
Geoff Lang496c02d2016-10-20 11:38:11 -07004222 if (length)
4223 {
4224 *length = 1;
4225 }
4226
Olli Etuaho4f667482016-03-30 15:56:35 +03004227 return true;
4228}
4229
4230bool ValidateUnmapBufferBase(Context *context, GLenum target)
4231{
4232 if (!ValidBufferTarget(context, target))
4233 {
Jamie Madill437fa652016-05-03 15:13:24 -04004234 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004235 return false;
4236 }
4237
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004238 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004239
4240 if (buffer == nullptr || !buffer->isMapped())
4241 {
Jamie Madill437fa652016-05-03 15:13:24 -04004242 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004243 return false;
4244 }
4245
4246 return true;
4247}
4248
4249bool ValidateMapBufferRangeBase(Context *context,
4250 GLenum target,
4251 GLintptr offset,
4252 GLsizeiptr length,
4253 GLbitfield access)
4254{
4255 if (!ValidBufferTarget(context, target))
4256 {
Jamie Madill437fa652016-05-03 15:13:24 -04004257 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004258 return false;
4259 }
4260
4261 if (offset < 0 || length < 0)
4262 {
Jamie Madill437fa652016-05-03 15:13:24 -04004263 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004264 return false;
4265 }
4266
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004267 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004268
4269 if (!buffer)
4270 {
Jamie Madill437fa652016-05-03 15:13:24 -04004271 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004272 return false;
4273 }
4274
4275 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004276 CheckedNumeric<size_t> checkedOffset(offset);
4277 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004278
Jamie Madille2e406c2016-06-02 13:04:10 -04004279 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004280 {
Jamie Madill437fa652016-05-03 15:13:24 -04004281 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004282 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4283 return false;
4284 }
4285
4286 // Check for invalid bits in the mask
4287 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4288 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4289 GL_MAP_UNSYNCHRONIZED_BIT;
4290
4291 if (access & ~(allAccessBits))
4292 {
Jamie Madill437fa652016-05-03 15:13:24 -04004293 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004294 return false;
4295 }
4296
4297 if (length == 0)
4298 {
Jamie Madill437fa652016-05-03 15:13:24 -04004299 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004300 return false;
4301 }
4302
4303 if (buffer->isMapped())
4304 {
Jamie Madill437fa652016-05-03 15:13:24 -04004305 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004306 return false;
4307 }
4308
4309 // Check for invalid bit combinations
4310 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4311 {
Jamie Madill437fa652016-05-03 15:13:24 -04004312 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004313 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4314 return false;
4315 }
4316
4317 GLbitfield writeOnlyBits =
4318 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4319
4320 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4321 {
Jamie Madill437fa652016-05-03 15:13:24 -04004322 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004323 "Invalid access bits when mapping buffer for reading: 0x%X.",
4324 access));
4325 return false;
4326 }
4327
4328 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4329 {
Jamie Madill437fa652016-05-03 15:13:24 -04004330 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004331 GL_INVALID_OPERATION,
4332 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4333 return false;
4334 }
4335 return true;
4336}
4337
4338bool ValidateFlushMappedBufferRangeBase(Context *context,
4339 GLenum target,
4340 GLintptr offset,
4341 GLsizeiptr length)
4342{
4343 if (offset < 0 || length < 0)
4344 {
Jamie Madill437fa652016-05-03 15:13:24 -04004345 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004346 return false;
4347 }
4348
4349 if (!ValidBufferTarget(context, target))
4350 {
Jamie Madill437fa652016-05-03 15:13:24 -04004351 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004352 return false;
4353 }
4354
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004355 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004356
4357 if (buffer == nullptr)
4358 {
Jamie Madill437fa652016-05-03 15:13:24 -04004359 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004360 return false;
4361 }
4362
4363 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4364 {
Jamie Madill437fa652016-05-03 15:13:24 -04004365 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004366 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4367 return false;
4368 }
4369
4370 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004371 CheckedNumeric<size_t> checkedOffset(offset);
4372 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004373
Jamie Madille2e406c2016-06-02 13:04:10 -04004374 if (!checkedSize.IsValid() ||
4375 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004376 {
Jamie Madill437fa652016-05-03 15:13:24 -04004377 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004378 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4379 return false;
4380 }
4381
4382 return true;
4383}
4384
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004385bool ValidateGenerateMipmap(Context *context, GLenum target)
4386{
4387 if (!ValidTextureTarget(context, target))
4388 {
4389 context->handleError(Error(GL_INVALID_ENUM));
4390 return false;
4391 }
4392
4393 Texture *texture = context->getTargetTexture(target);
4394
4395 if (texture == nullptr)
4396 {
4397 context->handleError(Error(GL_INVALID_OPERATION));
4398 return false;
4399 }
4400
4401 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4402
4403 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4404 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4405 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4406 {
4407 context->handleError(Error(GL_INVALID_OPERATION));
4408 return false;
4409 }
4410
Jamie Madilla3944d42016-07-22 22:13:26 -04004411 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4412 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4413 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004414
4415 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4416 // unsized formats or that are color renderable and filterable. Since we do not track if
4417 // the texture was created with sized or unsized format (only sized formats are stored),
4418 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4419 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4420 // textures since they're the only texture format that can be created with unsized formats
4421 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4422 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004423 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4424 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004425 {
4426 context->handleError(Error(GL_INVALID_OPERATION));
4427 return false;
4428 }
4429
4430 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004431 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004432 {
4433 context->handleError(Error(GL_INVALID_OPERATION));
4434 return false;
4435 }
4436
4437 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004438 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004439 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4440 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4441 {
Geoff Lang55482a12016-11-21 16:54:01 -05004442 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004443 context->handleError(Error(GL_INVALID_OPERATION));
4444 return false;
4445 }
4446
4447 // Cube completeness check
4448 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4449 {
4450 context->handleError(Error(GL_INVALID_OPERATION));
4451 return false;
4452 }
4453
4454 return true;
4455}
4456
Olli Etuaho41997e72016-03-10 13:38:39 +02004457bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4458{
4459 return ValidateGenOrDelete(context, n);
4460}
4461
4462bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4463{
4464 return ValidateGenOrDelete(context, n);
4465}
4466
4467bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4468{
4469 return ValidateGenOrDelete(context, n);
4470}
4471
4472bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4473{
4474 return ValidateGenOrDelete(context, n);
4475}
4476
4477bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4478{
4479 return ValidateGenOrDelete(context, n);
4480}
4481
4482bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4483{
4484 return ValidateGenOrDelete(context, n);
4485}
4486
4487bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4488{
4489 return ValidateGenOrDelete(context, n);
4490}
4491
4492bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4493{
4494 return ValidateGenOrDelete(context, n);
4495}
4496
4497bool ValidateGenOrDelete(Context *context, GLint n)
4498{
4499 if (n < 0)
4500 {
Jamie Madill437fa652016-05-03 15:13:24 -04004501 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004502 return false;
4503 }
4504 return true;
4505}
4506
Geoff Langf41a7152016-09-19 15:11:17 -04004507bool ValidateEnable(Context *context, GLenum cap)
4508{
4509 if (!ValidCap(context, cap, false))
4510 {
4511 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4512 return false;
4513 }
4514
4515 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4516 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4517 {
4518 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4519 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4520
4521 // We also output an error message to the debugger window if tracing is active, so that
4522 // developers can see the error message.
4523 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004524 return false;
4525 }
4526
4527 return true;
4528}
4529
4530bool ValidateDisable(Context *context, GLenum cap)
4531{
4532 if (!ValidCap(context, cap, false))
4533 {
4534 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4535 return false;
4536 }
4537
4538 return true;
4539}
4540
4541bool ValidateIsEnabled(Context *context, GLenum cap)
4542{
4543 if (!ValidCap(context, cap, true))
4544 {
4545 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4546 return false;
4547 }
4548
4549 return true;
4550}
4551
Geoff Langff5b2d52016-09-07 11:32:23 -04004552bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4553{
4554 if (!context->getExtensions().robustClientMemory)
4555 {
4556 context->handleError(
4557 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4558 return false;
4559 }
4560
4561 if (bufSize < 0)
4562 {
4563 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4564 return false;
4565 }
4566
4567 return true;
4568}
4569
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004570bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4571{
4572 if (bufSize < numParams)
4573 {
4574 context->handleError(Error(GL_INVALID_OPERATION,
4575 "%u parameters are required but %i were provided.", numParams,
4576 bufSize));
4577 return false;
4578 }
4579
4580 return true;
4581}
4582
Geoff Langff5b2d52016-09-07 11:32:23 -04004583bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4584 GLenum target,
4585 GLenum attachment,
4586 GLenum pname,
4587 GLsizei *numParams)
4588{
4589 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4590 *numParams = 1;
4591
4592 if (!ValidFramebufferTarget(target))
4593 {
4594 context->handleError(Error(GL_INVALID_ENUM));
4595 return false;
4596 }
4597
4598 int clientVersion = context->getClientMajorVersion();
4599
4600 switch (pname)
4601 {
4602 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4603 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4604 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4605 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4606 break;
4607
4608 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4609 if (clientVersion < 3 && !context->getExtensions().sRGB)
4610 {
4611 context->handleError(Error(GL_INVALID_ENUM));
4612 return false;
4613 }
4614 break;
4615
4616 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4617 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4618 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4619 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4620 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4621 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4622 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4623 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4624 if (clientVersion < 3)
4625 {
4626 context->handleError(Error(GL_INVALID_ENUM));
4627 return false;
4628 }
4629 break;
4630
4631 default:
4632 context->handleError(Error(GL_INVALID_ENUM));
4633 return false;
4634 }
4635
4636 // Determine if the attachment is a valid enum
4637 switch (attachment)
4638 {
4639 case GL_BACK:
4640 case GL_FRONT:
4641 case GL_DEPTH:
4642 case GL_STENCIL:
4643 case GL_DEPTH_STENCIL_ATTACHMENT:
4644 if (clientVersion < 3)
4645 {
4646 context->handleError(Error(GL_INVALID_ENUM));
4647 return false;
4648 }
4649 break;
4650
4651 case GL_DEPTH_ATTACHMENT:
4652 case GL_STENCIL_ATTACHMENT:
4653 break;
4654
4655 default:
4656 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4657 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4658 {
4659 context->handleError(Error(GL_INVALID_ENUM));
4660 return false;
4661 }
4662 break;
4663 }
4664
4665 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4666 ASSERT(framebuffer);
4667
4668 if (framebuffer->id() == 0)
4669 {
4670 if (clientVersion < 3)
4671 {
4672 context->handleError(Error(GL_INVALID_OPERATION));
4673 return false;
4674 }
4675
4676 switch (attachment)
4677 {
4678 case GL_BACK:
4679 case GL_DEPTH:
4680 case GL_STENCIL:
4681 break;
4682
4683 default:
4684 context->handleError(Error(GL_INVALID_OPERATION));
4685 return false;
4686 }
4687 }
4688 else
4689 {
4690 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4691 {
4692 // Valid attachment query
4693 }
4694 else
4695 {
4696 switch (attachment)
4697 {
4698 case GL_DEPTH_ATTACHMENT:
4699 case GL_STENCIL_ATTACHMENT:
4700 break;
4701
4702 case GL_DEPTH_STENCIL_ATTACHMENT:
4703 if (!framebuffer->hasValidDepthStencil())
4704 {
4705 context->handleError(Error(GL_INVALID_OPERATION));
4706 return false;
4707 }
4708 break;
4709
4710 default:
4711 context->handleError(Error(GL_INVALID_OPERATION));
4712 return false;
4713 }
4714 }
4715 }
4716
4717 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4718 if (attachmentObject)
4719 {
4720 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4721 attachmentObject->type() == GL_TEXTURE ||
4722 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4723
4724 switch (pname)
4725 {
4726 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4727 if (attachmentObject->type() != GL_RENDERBUFFER &&
4728 attachmentObject->type() != GL_TEXTURE)
4729 {
4730 context->handleError(Error(GL_INVALID_ENUM));
4731 return false;
4732 }
4733 break;
4734
4735 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4736 if (attachmentObject->type() != GL_TEXTURE)
4737 {
4738 context->handleError(Error(GL_INVALID_ENUM));
4739 return false;
4740 }
4741 break;
4742
4743 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4744 if (attachmentObject->type() != GL_TEXTURE)
4745 {
4746 context->handleError(Error(GL_INVALID_ENUM));
4747 return false;
4748 }
4749 break;
4750
4751 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4752 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4753 {
4754 context->handleError(Error(GL_INVALID_OPERATION));
4755 return false;
4756 }
4757 break;
4758
4759 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4760 if (attachmentObject->type() != GL_TEXTURE)
4761 {
4762 context->handleError(Error(GL_INVALID_ENUM));
4763 return false;
4764 }
4765 break;
4766
4767 default:
4768 break;
4769 }
4770 }
4771 else
4772 {
4773 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4774 // is NONE, then querying any other pname will generate INVALID_ENUM.
4775
4776 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4777 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4778 // INVALID_OPERATION for all other pnames
4779
4780 switch (pname)
4781 {
4782 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4783 break;
4784
4785 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4786 if (clientVersion < 3)
4787 {
4788 context->handleError(Error(GL_INVALID_ENUM));
4789 return false;
4790 }
4791 break;
4792
4793 default:
4794 if (clientVersion < 3)
4795 {
4796 context->handleError(Error(GL_INVALID_ENUM));
4797 return false;
4798 }
4799 else
4800 {
4801 context->handleError(Error(GL_INVALID_OPERATION));
4802 return false;
4803 }
4804 }
4805 }
4806
4807 return true;
4808}
4809
4810bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4811 GLenum target,
4812 GLenum attachment,
4813 GLenum pname,
4814 GLsizei bufSize,
4815 GLsizei *numParams)
4816{
4817 if (!ValidateRobustEntryPoint(context, bufSize))
4818 {
4819 return false;
4820 }
4821
4822 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4823 {
4824 return false;
4825 }
4826
4827 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4828 {
4829 return false;
4830 }
4831
4832 return true;
4833}
4834
4835bool ValidateGetBufferParameteriv(ValidationContext *context,
4836 GLenum target,
4837 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04004838 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004839{
Geoff Langebebe1c2016-10-14 12:01:31 -04004840 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04004841}
4842
4843bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4844 GLenum target,
4845 GLenum pname,
4846 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004847 GLsizei *length,
4848 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004849{
4850 if (!ValidateRobustEntryPoint(context, bufSize))
4851 {
4852 return false;
4853 }
4854
Geoff Langebebe1c2016-10-14 12:01:31 -04004855 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004856 {
4857 return false;
4858 }
4859
Geoff Langebebe1c2016-10-14 12:01:31 -04004860 if (!ValidateRobustBufferSize(context, bufSize, *length))
4861 {
4862 return false;
4863 }
4864
4865 return true;
4866}
4867
4868bool ValidateGetBufferParameteri64v(ValidationContext *context,
4869 GLenum target,
4870 GLenum pname,
4871 GLint64 *params)
4872{
4873 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4874}
4875
4876bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4877 GLenum target,
4878 GLenum pname,
4879 GLsizei bufSize,
4880 GLsizei *length,
4881 GLint64 *params)
4882{
4883 if (!ValidateRobustEntryPoint(context, bufSize))
4884 {
4885 return false;
4886 }
4887
4888 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4889 {
4890 return false;
4891 }
4892
4893 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004894 {
4895 return false;
4896 }
4897
4898 return true;
4899}
4900
4901bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4902{
4903 // Currently, all GetProgramiv queries return 1 parameter
4904 *numParams = 1;
4905
4906 Program *programObject = GetValidProgram(context, program);
4907 if (!programObject)
4908 {
4909 return false;
4910 }
4911
4912 switch (pname)
4913 {
4914 case GL_DELETE_STATUS:
4915 case GL_LINK_STATUS:
4916 case GL_VALIDATE_STATUS:
4917 case GL_INFO_LOG_LENGTH:
4918 case GL_ATTACHED_SHADERS:
4919 case GL_ACTIVE_ATTRIBUTES:
4920 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4921 case GL_ACTIVE_UNIFORMS:
4922 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4923 break;
4924
4925 case GL_PROGRAM_BINARY_LENGTH:
4926 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4927 {
4928 context->handleError(Error(GL_INVALID_ENUM,
4929 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4930 "GL_OES_get_program_binary or ES 3.0."));
4931 return false;
4932 }
4933 break;
4934
4935 case GL_ACTIVE_UNIFORM_BLOCKS:
4936 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4937 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4938 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4939 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4940 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4941 if (context->getClientMajorVersion() < 3)
4942 {
4943 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4944 return false;
4945 }
4946 break;
4947
4948 default:
4949 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4950 return false;
4951 }
4952
4953 return true;
4954}
4955
4956bool ValidateGetProgramivRobustANGLE(Context *context,
4957 GLuint program,
4958 GLenum pname,
4959 GLsizei bufSize,
4960 GLsizei *numParams)
4961{
4962 if (!ValidateRobustEntryPoint(context, bufSize))
4963 {
4964 return false;
4965 }
4966
4967 if (!ValidateGetProgramiv(context, program, pname, numParams))
4968 {
4969 return false;
4970 }
4971
4972 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4973 {
4974 return false;
4975 }
4976
4977 return true;
4978}
4979
Geoff Lang740d9022016-10-07 11:20:52 -04004980bool ValidateGetRenderbufferParameteriv(Context *context,
4981 GLenum target,
4982 GLenum pname,
4983 GLint *params)
4984{
4985 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
4986}
4987
4988bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4989 GLenum target,
4990 GLenum pname,
4991 GLsizei bufSize,
4992 GLsizei *length,
4993 GLint *params)
4994{
4995 if (!ValidateRobustEntryPoint(context, bufSize))
4996 {
4997 return false;
4998 }
4999
5000 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5001 {
5002 return false;
5003 }
5004
5005 if (!ValidateRobustBufferSize(context, bufSize, *length))
5006 {
5007 return false;
5008 }
5009
5010 return true;
5011}
5012
Geoff Langd7d0ed32016-10-07 11:33:51 -04005013bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5014{
5015 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5016}
5017
5018bool ValidateGetShaderivRobustANGLE(Context *context,
5019 GLuint shader,
5020 GLenum pname,
5021 GLsizei bufSize,
5022 GLsizei *length,
5023 GLint *params)
5024{
5025 if (!ValidateRobustEntryPoint(context, bufSize))
5026 {
5027 return false;
5028 }
5029
5030 if (!ValidateGetShaderivBase(context, shader, pname, length))
5031 {
5032 return false;
5033 }
5034
5035 if (!ValidateRobustBufferSize(context, bufSize, *length))
5036 {
5037 return false;
5038 }
5039
5040 return true;
5041}
5042
Geoff Langc1984ed2016-10-07 12:41:00 -04005043bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5044{
5045 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5046}
5047
5048bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5049 GLenum target,
5050 GLenum pname,
5051 GLsizei bufSize,
5052 GLsizei *length,
5053 GLfloat *params)
5054{
5055 if (!ValidateRobustEntryPoint(context, bufSize))
5056 {
5057 return false;
5058 }
5059
5060 if (!ValidateGetTexParameterBase(context, target, pname, length))
5061 {
5062 return false;
5063 }
5064
5065 if (!ValidateRobustBufferSize(context, bufSize, *length))
5066 {
5067 return false;
5068 }
5069
5070 return true;
5071}
5072
5073bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5074{
5075 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5076}
5077
5078bool ValidateGetTexParameterivRobustANGLE(Context *context,
5079 GLenum target,
5080 GLenum pname,
5081 GLsizei bufSize,
5082 GLsizei *length,
5083 GLint *params)
5084{
5085 if (!ValidateRobustEntryPoint(context, bufSize))
5086 {
5087 return false;
5088 }
5089
5090 if (!ValidateGetTexParameterBase(context, target, pname, length))
5091 {
5092 return false;
5093 }
5094
5095 if (!ValidateRobustBufferSize(context, bufSize, *length))
5096 {
5097 return false;
5098 }
5099
5100 return true;
5101}
5102
5103bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5104{
5105 return ValidateTexParameterBase(context, target, pname, -1, &param);
5106}
5107
5108bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5109{
5110 return ValidateTexParameterBase(context, target, pname, -1, params);
5111}
5112
5113bool ValidateTexParameterfvRobustANGLE(Context *context,
5114 GLenum target,
5115 GLenum pname,
5116 GLsizei bufSize,
5117 const GLfloat *params)
5118{
5119 if (!ValidateRobustEntryPoint(context, bufSize))
5120 {
5121 return false;
5122 }
5123
5124 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5125}
5126
5127bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5128{
5129 return ValidateTexParameterBase(context, target, pname, -1, &param);
5130}
5131
5132bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5133{
5134 return ValidateTexParameterBase(context, target, pname, -1, params);
5135}
5136
5137bool ValidateTexParameterivRobustANGLE(Context *context,
5138 GLenum target,
5139 GLenum pname,
5140 GLsizei bufSize,
5141 const GLint *params)
5142{
5143 if (!ValidateRobustEntryPoint(context, bufSize))
5144 {
5145 return false;
5146 }
5147
5148 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5149}
5150
5151bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5152{
5153 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5154}
5155
5156bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5157 GLuint sampler,
5158 GLenum pname,
5159 GLuint bufSize,
5160 GLsizei *length,
5161 GLfloat *params)
5162{
5163 if (!ValidateRobustEntryPoint(context, bufSize))
5164 {
5165 return false;
5166 }
5167
5168 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5169 {
5170 return false;
5171 }
5172
5173 if (!ValidateRobustBufferSize(context, bufSize, *length))
5174 {
5175 return false;
5176 }
5177
5178 return true;
5179}
5180
5181bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5182{
5183 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5184}
5185
5186bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5187 GLuint sampler,
5188 GLenum pname,
5189 GLuint bufSize,
5190 GLsizei *length,
5191 GLint *params)
5192{
5193 if (!ValidateRobustEntryPoint(context, bufSize))
5194 {
5195 return false;
5196 }
5197
5198 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5199 {
5200 return false;
5201 }
5202
5203 if (!ValidateRobustBufferSize(context, bufSize, *length))
5204 {
5205 return false;
5206 }
5207
5208 return true;
5209}
5210
5211bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5212{
5213 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5214}
5215
5216bool ValidateSamplerParameterfv(Context *context,
5217 GLuint sampler,
5218 GLenum pname,
5219 const GLfloat *params)
5220{
5221 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5222}
5223
5224bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5225 GLuint sampler,
5226 GLenum pname,
5227 GLsizei bufSize,
5228 const GLfloat *params)
5229{
5230 if (!ValidateRobustEntryPoint(context, bufSize))
5231 {
5232 return false;
5233 }
5234
5235 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5236}
5237
5238bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5239{
5240 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5241}
5242
5243bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5244{
5245 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5246}
5247
5248bool ValidateSamplerParameterivRobustANGLE(Context *context,
5249 GLuint sampler,
5250 GLenum pname,
5251 GLsizei bufSize,
5252 const GLint *params)
5253{
5254 if (!ValidateRobustEntryPoint(context, bufSize))
5255 {
5256 return false;
5257 }
5258
5259 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5260}
5261
Geoff Lang0b031062016-10-13 14:30:04 -04005262bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5263{
5264 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5265}
5266
5267bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5268 GLuint index,
5269 GLenum pname,
5270 GLsizei bufSize,
5271 GLsizei *length,
5272 GLfloat *params)
5273{
5274 if (!ValidateRobustEntryPoint(context, bufSize))
5275 {
5276 return false;
5277 }
5278
5279 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5280 {
5281 return false;
5282 }
5283
5284 if (!ValidateRobustBufferSize(context, bufSize, *length))
5285 {
5286 return false;
5287 }
5288
5289 return true;
5290}
5291
5292bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5293{
5294 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5295}
5296
5297bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5298 GLuint index,
5299 GLenum pname,
5300 GLsizei bufSize,
5301 GLsizei *length,
5302 GLint *params)
5303{
5304 if (!ValidateRobustEntryPoint(context, bufSize))
5305 {
5306 return false;
5307 }
5308
5309 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5310 {
5311 return false;
5312 }
5313
5314 if (!ValidateRobustBufferSize(context, bufSize, *length))
5315 {
5316 return false;
5317 }
5318
5319 return true;
5320}
5321
5322bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5323{
5324 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5325}
5326
5327bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5328 GLuint index,
5329 GLenum pname,
5330 GLsizei bufSize,
5331 GLsizei *length,
5332 void **pointer)
5333{
5334 if (!ValidateRobustEntryPoint(context, bufSize))
5335 {
5336 return false;
5337 }
5338
5339 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5340 {
5341 return false;
5342 }
5343
5344 if (!ValidateRobustBufferSize(context, bufSize, *length))
5345 {
5346 return false;
5347 }
5348
5349 return true;
5350}
5351
5352bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5353{
5354 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5355}
5356
5357bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5358 GLuint index,
5359 GLenum pname,
5360 GLsizei bufSize,
5361 GLsizei *length,
5362 GLint *params)
5363{
5364 if (!ValidateRobustEntryPoint(context, bufSize))
5365 {
5366 return false;
5367 }
5368
5369 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5370 {
5371 return false;
5372 }
5373
5374 if (!ValidateRobustBufferSize(context, bufSize, *length))
5375 {
5376 return false;
5377 }
5378
5379 return true;
5380}
5381
5382bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5383{
5384 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5385}
5386
5387bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5388 GLuint index,
5389 GLenum pname,
5390 GLsizei bufSize,
5391 GLsizei *length,
5392 GLuint *params)
5393{
5394 if (!ValidateRobustEntryPoint(context, bufSize))
5395 {
5396 return false;
5397 }
5398
5399 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5400 {
5401 return false;
5402 }
5403
5404 if (!ValidateRobustBufferSize(context, bufSize, *length))
5405 {
5406 return false;
5407 }
5408
5409 return true;
5410}
5411
Geoff Lang6899b872016-10-14 11:30:13 -04005412bool ValidateGetActiveUniformBlockiv(Context *context,
5413 GLuint program,
5414 GLuint uniformBlockIndex,
5415 GLenum pname,
5416 GLint *params)
5417{
5418 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5419}
5420
5421bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5422 GLuint program,
5423 GLuint uniformBlockIndex,
5424 GLenum pname,
5425 GLsizei bufSize,
5426 GLsizei *length,
5427 GLint *params)
5428{
5429 if (!ValidateRobustEntryPoint(context, bufSize))
5430 {
5431 return false;
5432 }
5433
5434 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5435 {
5436 return false;
5437 }
5438
5439 if (!ValidateRobustBufferSize(context, bufSize, *length))
5440 {
5441 return false;
5442 }
5443
5444 return true;
5445}
5446
Geoff Lang0a9661f2016-10-20 10:59:20 -07005447bool ValidateGetInternalFormativ(Context *context,
5448 GLenum target,
5449 GLenum internalformat,
5450 GLenum pname,
5451 GLsizei bufSize,
5452 GLint *params)
5453{
5454 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5455 nullptr);
5456}
5457
5458bool ValidateGetInternalFormativRobustANGLE(Context *context,
5459 GLenum target,
5460 GLenum internalformat,
5461 GLenum pname,
5462 GLsizei bufSize,
5463 GLsizei *length,
5464 GLint *params)
5465{
5466 if (!ValidateRobustEntryPoint(context, bufSize))
5467 {
5468 return false;
5469 }
5470
5471 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5472 {
5473 return false;
5474 }
5475
5476 if (!ValidateRobustBufferSize(context, bufSize, *length))
5477 {
5478 return false;
5479 }
5480
5481 return true;
5482}
5483
Jamie Madillc29968b2016-01-20 11:17:23 -05005484} // namespace gl