blob: 5a4b2569f6aafceaaa2f6dc85f4cf88e3adf2afa [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/validationES2.h"
12#include "libANGLE/validationES3.h"
13#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040014#include "libANGLE/Display.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Texture.h"
16#include "libANGLE/Framebuffer.h"
17#include "libANGLE/FramebufferAttachment.h"
18#include "libANGLE/formatutils.h"
Geoff Langa8406172015-07-21 16:53:39 -040019#include "libANGLE/Image.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/Query.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050021#include "libANGLE/Program.h"
22#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050023#include "libANGLE/TransformFeedback.h"
24#include "libANGLE/VertexArray.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025
26#include "common/mathutil.h"
27#include "common/utilities.h"
28
Jamie Madille2e406c2016-06-02 13:04:10 -040029using namespace angle;
30
Geoff Lange8ebe7f2013-08-05 15:03:13 -040031namespace gl
32{
Jamie Madille79b1e12015-11-04 16:36:37 -050033const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum element index.";
34
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
Corentin Wallez92db6942016-12-09 13:10:36 -050037bool ValidateDrawAttribs(ValidationContext *context,
38 GLint primcount,
39 GLint maxVertex,
40 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040041{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070042 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040043 const gl::Program *program = state.getProgram();
44
Corentin Wallez327411e2016-12-09 11:09:17 -050045 bool webglCompatibility = context->getExtensions().webglCompatibility;
46
He Yunchaoced53ae2016-11-29 15:00:51 +080047 const VertexArray *vao = state.getVertexArray();
48 const auto &vertexAttribs = vao->getVertexAttributes();
49 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040050 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
51 {
52 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Jamie Madill63805b42015-08-25 13:17:39 -040053 if (program->isAttribLocationActive(attributeIndex) && attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040054 {
55 gl::Buffer *buffer = attrib.buffer.get();
56
57 if (buffer)
58 {
Corentin Wallez92db6942016-12-09 13:10:36 -050059 CheckedNumeric<GLint64> maxVertexElement = 0;
60 bool readsData = false;
61 if (attrib.divisor == 0)
Jamie Madill1ca74672015-07-21 15:14:11 -040062 {
Corentin Wallez92db6942016-12-09 13:10:36 -050063 readsData = vertexCount > 0;
Jamie Madill1ca74672015-07-21 15:14:11 -040064 maxVertexElement = static_cast<GLint64>(maxVertex);
65 }
Corentin Wallez92db6942016-12-09 13:10:36 -050066 else if (primcount > 0)
67 {
68 readsData = true;
69 maxVertexElement =
70 static_cast<GLint64>(primcount - 1) / static_cast<GLint64>(attrib.divisor);
71 }
Jamie Madill1ca74672015-07-21 15:14:11 -040072
73 // If we're drawing zero vertices, we have enough data.
Corentin Wallez92db6942016-12-09 13:10:36 -050074 if (readsData)
Jamie Madill1ca74672015-07-21 15:14:11 -040075 {
76 // Note: Last vertex element does not take the full stride!
Corentin Wallez92db6942016-12-09 13:10:36 -050077 CheckedNumeric<GLint64> attribStride = ComputeVertexAttributeStride(attrib);
78 CheckedNumeric<GLint64> attribSize = ComputeVertexAttributeTypeSize(attrib);
79 CheckedNumeric<GLint64> attribDataSize =
80 maxVertexElement * attribStride + attribSize;
81 CheckedNumeric<GLint64> maxOffset = attribDataSize + attrib.offset;
82
83 if (!maxOffset.IsValid())
84 {
85 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
86 return false;
87 }
Jamie Madill1ca74672015-07-21 15:14:11 -040088
89 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
90 // We can return INVALID_OPERATION if our vertex attribute does not have
91 // enough backing data.
Corentin Wallez92db6942016-12-09 13:10:36 -050092 if (maxOffset.ValueOrDie() > buffer->getSize())
Jamie Madill1ca74672015-07-21 15:14:11 -040093 {
Jamie Madill437fa652016-05-03 15:13:24 -040094 context->handleError(
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040095 Error(GL_INVALID_OPERATION,
96 "Vertex buffer is not big enough for the draw call"));
Jamie Madill1ca74672015-07-21 15:14:11 -040097 return false;
98 }
99 }
100 }
Corentin Wallez327411e2016-12-09 11:09:17 -0500101 else if (webglCompatibility)
102 {
103 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
104 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
105 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then
106 // calls to drawArrays or drawElements will generate an INVALID_OPERATION error.
107 context->handleError(
108 Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer."));
109 }
Jamie Madill1ca74672015-07-21 15:14:11 -0400110 else if (attrib.pointer == NULL)
111 {
112 // This is an application error that would normally result in a crash,
113 // but we catch it and return an error
Jamie Madill437fa652016-05-03 15:13:24 -0400114 context->handleError(Error(
Jamie Madill1ca74672015-07-21 15:14:11 -0400115 GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer."));
116 return false;
117 }
118 }
119 }
120
121 return true;
122}
123
Geoff Langf607c602016-09-21 11:46:48 -0400124bool ValidReadPixelsFormatType(ValidationContext *context,
125 GLenum framebufferComponentType,
126 GLenum format,
127 GLenum type)
128{
129 switch (framebufferComponentType)
130 {
131 case GL_UNSIGNED_NORMALIZED:
132 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
133 // ReadPixels with BGRA even if the extension is not present
134 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
135 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
136 type == GL_UNSIGNED_BYTE);
137
138 case GL_SIGNED_NORMALIZED:
139 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
140
141 case GL_INT:
142 return (format == GL_RGBA_INTEGER && type == GL_INT);
143
144 case GL_UNSIGNED_INT:
145 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
146
147 case GL_FLOAT:
148 return (format == GL_RGBA && type == GL_FLOAT);
149
150 default:
151 UNREACHABLE();
152 return false;
153 }
154}
155
Geoff Langf41a7152016-09-19 15:11:17 -0400156bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
Geoff Lang0550d032014-01-30 11:29:07 -0500157{
158 switch (cap)
159 {
Geoff Langf41a7152016-09-19 15:11:17 -0400160 // EXT_multisample_compatibility
161 case GL_MULTISAMPLE_EXT:
162 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
163 return context->getExtensions().multisampleCompatibility;
Sami Väisänen74c23472016-05-09 17:30:30 +0300164
Geoff Langf41a7152016-09-19 15:11:17 -0400165 case GL_CULL_FACE:
166 case GL_POLYGON_OFFSET_FILL:
167 case GL_SAMPLE_ALPHA_TO_COVERAGE:
168 case GL_SAMPLE_COVERAGE:
169 case GL_SCISSOR_TEST:
170 case GL_STENCIL_TEST:
171 case GL_DEPTH_TEST:
172 case GL_BLEND:
173 case GL_DITHER:
174 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -0500175
Geoff Langf41a7152016-09-19 15:11:17 -0400176 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
177 case GL_RASTERIZER_DISCARD:
178 return (context->getClientMajorVersion() >= 3);
Geoff Lang70d0f492015-12-10 17:45:46 -0500179
Geoff Langf41a7152016-09-19 15:11:17 -0400180 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
181 case GL_DEBUG_OUTPUT:
182 return context->getExtensions().debug;
Geoff Lang70d0f492015-12-10 17:45:46 -0500183
Geoff Langf41a7152016-09-19 15:11:17 -0400184 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
185 return queryOnly && context->getExtensions().bindGeneratesResource;
186
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700187 case GL_FRAMEBUFFER_SRGB_EXT:
188 return context->getExtensions().sRGBWriteControl;
189
Geoff Lang3b573612016-10-31 14:08:10 -0400190 case GL_SAMPLE_MASK:
Geoff Lang3b573612016-10-31 14:08:10 -0400191 return context->getClientVersion() >= Version(3, 1);
192
Geoff Langf41a7152016-09-19 15:11:17 -0400193 default:
194 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500195 }
196}
197
Geoff Lang62fce5b2016-09-30 10:46:35 -0400198bool ValidateReadPixelsBase(ValidationContext *context,
199 GLint x,
200 GLint y,
201 GLsizei width,
202 GLsizei height,
203 GLenum format,
204 GLenum type,
205 GLsizei bufSize,
206 GLsizei *length,
207 GLvoid *pixels)
208{
209 if (length != nullptr)
210 {
211 *length = 0;
212 }
213
214 if (width < 0 || height < 0)
215 {
216 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
217 return false;
218 }
219
220 auto readFramebuffer = context->getGLState().getReadFramebuffer();
221
222 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
223 {
224 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
225 return false;
226 }
227
228 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
229 {
230 context->handleError(Error(GL_INVALID_OPERATION));
231 return false;
232 }
233
234 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
235 ASSERT(framebuffer);
236
237 if (framebuffer->getReadBufferState() == GL_NONE)
238 {
239 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
240 return false;
241 }
242
243 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
244 if (!readBuffer)
245 {
246 context->handleError(Error(GL_INVALID_OPERATION));
247 return false;
248 }
249
250 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
251 GLenum currentType = framebuffer->getImplementationColorReadType();
252 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
253
254 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
255 bool validFormatTypeCombination =
256 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
257
258 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
259 {
260 context->handleError(Error(GL_INVALID_OPERATION));
261 return false;
262 }
263
264 // Check for pixel pack buffer related API errors
265 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
266 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
267 {
268 // ...the buffer object's data store is currently mapped.
269 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
270 return false;
271 }
272
273 // .. the data would be packed to the buffer object such that the memory writes required
274 // would exceed the data store size.
275 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
276 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
277 const gl::Extents size(width, height, 1);
278 const auto &pack = context->getGLState().getPackState();
279
280 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
281 if (endByteOrErr.isError())
282 {
283 context->handleError(endByteOrErr.getError());
284 return false;
285 }
286
287 size_t endByte = endByteOrErr.getResult();
288 if (bufSize >= 0)
289 {
290
291 if (static_cast<size_t>(bufSize) < endByte)
292 {
293 context->handleError(
294 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
295 return false;
296 }
297 }
298
299 if (pixelPackBuffer != nullptr)
300 {
301 CheckedNumeric<size_t> checkedEndByte(endByte);
302 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
303 checkedEndByte += checkedOffset;
304
305 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
306 {
307 // Overflow past the end of the buffer
308 context->handleError(
309 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
310 return false;
311 }
312 }
313
314 if (length != nullptr)
315 {
316 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
317 {
318 context->handleError(
319 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
320 return false;
321 }
322
323 *length = static_cast<GLsizei>(endByte);
324 }
325
326 return true;
327}
328
Geoff Lang740d9022016-10-07 11:20:52 -0400329bool ValidateGetRenderbufferParameterivBase(Context *context,
330 GLenum target,
331 GLenum pname,
332 GLsizei *length)
333{
334 if (length)
335 {
336 *length = 0;
337 }
338
339 if (target != GL_RENDERBUFFER)
340 {
341 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
342 return false;
343 }
344
345 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
346 if (renderbuffer == nullptr)
347 {
348 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
349 return false;
350 }
351
352 switch (pname)
353 {
354 case GL_RENDERBUFFER_WIDTH:
355 case GL_RENDERBUFFER_HEIGHT:
356 case GL_RENDERBUFFER_INTERNAL_FORMAT:
357 case GL_RENDERBUFFER_RED_SIZE:
358 case GL_RENDERBUFFER_GREEN_SIZE:
359 case GL_RENDERBUFFER_BLUE_SIZE:
360 case GL_RENDERBUFFER_ALPHA_SIZE:
361 case GL_RENDERBUFFER_DEPTH_SIZE:
362 case GL_RENDERBUFFER_STENCIL_SIZE:
363 break;
364
365 case GL_RENDERBUFFER_SAMPLES_ANGLE:
366 if (!context->getExtensions().framebufferMultisample)
367 {
368 context->handleError(
369 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
370 return false;
371 }
372 break;
373
374 default:
375 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
376 return false;
377 }
378
379 if (length)
380 {
381 *length = 1;
382 }
383 return true;
384}
385
Geoff Langd7d0ed32016-10-07 11:33:51 -0400386bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
387{
388 if (length)
389 {
390 *length = 0;
391 }
392
393 if (GetValidShader(context, shader) == nullptr)
394 {
395 return false;
396 }
397
398 switch (pname)
399 {
400 case GL_SHADER_TYPE:
401 case GL_DELETE_STATUS:
402 case GL_COMPILE_STATUS:
403 case GL_INFO_LOG_LENGTH:
404 case GL_SHADER_SOURCE_LENGTH:
405 break;
406
407 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
408 if (!context->getExtensions().translatedShaderSource)
409 {
410 context->handleError(
411 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
412 return false;
413 }
414 break;
415
416 default:
417 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
418 return false;
419 }
420
421 if (length)
422 {
423 *length = 1;
424 }
425 return true;
426}
427
Geoff Langc1984ed2016-10-07 12:41:00 -0400428bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
429{
430 if (length)
431 {
432 *length = 0;
433 }
434
435 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
436 {
437 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
438 return false;
439 }
440
441 if (context->getTargetTexture(target) == nullptr)
442 {
443 // Should only be possible for external textures
444 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
445 return false;
446 }
447
448 switch (pname)
449 {
450 case GL_TEXTURE_MAG_FILTER:
451 case GL_TEXTURE_MIN_FILTER:
452 case GL_TEXTURE_WRAP_S:
453 case GL_TEXTURE_WRAP_T:
454 break;
455
456 case GL_TEXTURE_USAGE_ANGLE:
457 if (!context->getExtensions().textureUsage)
458 {
459 context->handleError(
460 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
461 return false;
462 }
463 break;
464
465 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
466 if (!context->getExtensions().textureFilterAnisotropic)
467 {
468 context->handleError(
469 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
470 return false;
471 }
472 break;
473
474 case GL_TEXTURE_IMMUTABLE_FORMAT:
475 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
476 {
477 context->handleError(
478 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
479 return false;
480 }
481 break;
482
483 case GL_TEXTURE_WRAP_R:
484 case GL_TEXTURE_IMMUTABLE_LEVELS:
485 case GL_TEXTURE_SWIZZLE_R:
486 case GL_TEXTURE_SWIZZLE_G:
487 case GL_TEXTURE_SWIZZLE_B:
488 case GL_TEXTURE_SWIZZLE_A:
489 case GL_TEXTURE_BASE_LEVEL:
490 case GL_TEXTURE_MAX_LEVEL:
491 case GL_TEXTURE_MIN_LOD:
492 case GL_TEXTURE_MAX_LOD:
493 case GL_TEXTURE_COMPARE_MODE:
494 case GL_TEXTURE_COMPARE_FUNC:
495 if (context->getClientMajorVersion() < 3)
496 {
497 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
498 return false;
499 }
500 break;
501
Geoff Lang81c6b572016-10-19 14:07:52 -0700502 case GL_TEXTURE_SRGB_DECODE_EXT:
503 if (!context->getExtensions().textureSRGBDecode)
504 {
505 context->handleError(
506 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
507 return false;
508 }
509 break;
510
Geoff Langc1984ed2016-10-07 12:41:00 -0400511 default:
512 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
513 return false;
514 }
515
516 if (length)
517 {
518 *length = 1;
519 }
520 return true;
521}
522
523template <typename ParamType>
524bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
525{
526 switch (ConvertToGLenum(params[0]))
527 {
528 case GL_CLAMP_TO_EDGE:
529 break;
530
531 case GL_REPEAT:
532 case GL_MIRRORED_REPEAT:
533 if (isExternalTextureTarget)
534 {
535 // OES_EGL_image_external specifies this error.
536 context->handleError(Error(
537 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
538 return false;
539 }
540 break;
541
542 default:
543 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
544 return false;
545 }
546
547 return true;
548}
549
550template <typename ParamType>
551bool ValidateTextureMinFilterValue(Context *context,
552 ParamType *params,
553 bool isExternalTextureTarget)
554{
555 switch (ConvertToGLenum(params[0]))
556 {
557 case GL_NEAREST:
558 case GL_LINEAR:
559 break;
560
561 case GL_NEAREST_MIPMAP_NEAREST:
562 case GL_LINEAR_MIPMAP_NEAREST:
563 case GL_NEAREST_MIPMAP_LINEAR:
564 case GL_LINEAR_MIPMAP_LINEAR:
565 if (isExternalTextureTarget)
566 {
567 // OES_EGL_image_external specifies this error.
568 context->handleError(
569 Error(GL_INVALID_ENUM,
570 "external textures only support NEAREST and LINEAR filtering"));
571 return false;
572 }
573 break;
574
575 default:
576 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
577 return false;
578 }
579
580 return true;
581}
582
583template <typename ParamType>
584bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
585{
586 switch (ConvertToGLenum(params[0]))
587 {
588 case GL_NEAREST:
589 case GL_LINEAR:
590 break;
591
592 default:
593 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
594 return false;
595 }
596
597 return true;
598}
599
600template <typename ParamType>
601bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
602{
603 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
604 switch (ConvertToGLenum(params[0]))
605 {
606 case GL_NONE:
607 case GL_COMPARE_REF_TO_TEXTURE:
608 break;
609
610 default:
611 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
612 return false;
613 }
614
615 return true;
616}
617
618template <typename ParamType>
619bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
620{
621 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
622 switch (ConvertToGLenum(params[0]))
623 {
624 case GL_LEQUAL:
625 case GL_GEQUAL:
626 case GL_LESS:
627 case GL_GREATER:
628 case GL_EQUAL:
629 case GL_NOTEQUAL:
630 case GL_ALWAYS:
631 case GL_NEVER:
632 break;
633
634 default:
635 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
636 return false;
637 }
638
639 return true;
640}
641
642template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700643bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
644{
645 if (!context->getExtensions().textureSRGBDecode)
646 {
647 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
648 return false;
649 }
650
651 switch (ConvertToGLenum(params[0]))
652 {
653 case GL_DECODE_EXT:
654 case GL_SKIP_DECODE_EXT:
655 break;
656
657 default:
658 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
659 return false;
660 }
661
662 return true;
663}
664
665template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400666bool ValidateTexParameterBase(Context *context,
667 GLenum target,
668 GLenum pname,
669 GLsizei bufSize,
670 ParamType *params)
671{
672 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
673 {
674 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
675 return false;
676 }
677
678 if (context->getTargetTexture(target) == nullptr)
679 {
680 // Should only be possible for external textures
681 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
682 return false;
683 }
684
685 const GLsizei minBufSize = 1;
686 if (bufSize >= 0 && bufSize < minBufSize)
687 {
688 context->handleError(
689 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
690 return false;
691 }
692
693 switch (pname)
694 {
695 case GL_TEXTURE_WRAP_R:
696 case GL_TEXTURE_SWIZZLE_R:
697 case GL_TEXTURE_SWIZZLE_G:
698 case GL_TEXTURE_SWIZZLE_B:
699 case GL_TEXTURE_SWIZZLE_A:
700 case GL_TEXTURE_BASE_LEVEL:
701 case GL_TEXTURE_MAX_LEVEL:
702 case GL_TEXTURE_COMPARE_MODE:
703 case GL_TEXTURE_COMPARE_FUNC:
704 case GL_TEXTURE_MIN_LOD:
705 case GL_TEXTURE_MAX_LOD:
706 if (context->getClientMajorVersion() < 3)
707 {
708 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
709 return false;
710 }
711 if (target == GL_TEXTURE_EXTERNAL_OES &&
712 !context->getExtensions().eglImageExternalEssl3)
713 {
714 context->handleError(Error(GL_INVALID_ENUM,
715 "ES3 texture parameters are not available without "
716 "GL_OES_EGL_image_external_essl3."));
717 return false;
718 }
719 break;
720
721 default:
722 break;
723 }
724
725 switch (pname)
726 {
727 case GL_TEXTURE_WRAP_S:
728 case GL_TEXTURE_WRAP_T:
729 case GL_TEXTURE_WRAP_R:
730 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
731 {
732 return false;
733 }
734 break;
735
736 case GL_TEXTURE_MIN_FILTER:
737 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
738 {
739 return false;
740 }
741 break;
742
743 case GL_TEXTURE_MAG_FILTER:
744 if (!ValidateTextureMagFilterValue(context, params))
745 {
746 return false;
747 }
748 break;
749
750 case GL_TEXTURE_USAGE_ANGLE:
751 switch (ConvertToGLenum(params[0]))
752 {
753 case GL_NONE:
754 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
755 break;
756
757 default:
758 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
759 return false;
760 }
761 break;
762
763 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
764 if (!context->getExtensions().textureFilterAnisotropic)
765 {
766 context->handleError(
767 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
768 return false;
769 }
770
771 // we assume the parameter passed to this validation method is truncated, not rounded
772 if (params[0] < 1)
773 {
774 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
775 return false;
776 }
777 break;
778
779 case GL_TEXTURE_MIN_LOD:
780 case GL_TEXTURE_MAX_LOD:
781 // any value is permissible
782 break;
783
784 case GL_TEXTURE_COMPARE_MODE:
785 if (!ValidateTextureCompareModeValue(context, params))
786 {
787 return false;
788 }
789 break;
790
791 case GL_TEXTURE_COMPARE_FUNC:
792 if (!ValidateTextureCompareFuncValue(context, params))
793 {
794 return false;
795 }
796 break;
797
798 case GL_TEXTURE_SWIZZLE_R:
799 case GL_TEXTURE_SWIZZLE_G:
800 case GL_TEXTURE_SWIZZLE_B:
801 case GL_TEXTURE_SWIZZLE_A:
802 switch (ConvertToGLenum(params[0]))
803 {
804 case GL_RED:
805 case GL_GREEN:
806 case GL_BLUE:
807 case GL_ALPHA:
808 case GL_ZERO:
809 case GL_ONE:
810 break;
811
812 default:
813 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
814 return false;
815 }
816 break;
817
818 case GL_TEXTURE_BASE_LEVEL:
819 if (params[0] < 0)
820 {
821 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
822 return false;
823 }
824 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
825 {
826 context->handleError(
827 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
828 return false;
829 }
830 break;
831
832 case GL_TEXTURE_MAX_LEVEL:
833 if (params[0] < 0)
834 {
835 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
836 return false;
837 }
838 break;
839
Geoff Lang3b573612016-10-31 14:08:10 -0400840 case GL_DEPTH_STENCIL_TEXTURE_MODE:
841 if (context->getClientVersion() < Version(3, 1))
842 {
843 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
844 return false;
845 }
Geoff Lang9f090372016-12-02 10:20:43 -0500846 switch (ConvertToGLenum(params[0]))
847 {
848 case GL_DEPTH_COMPONENT:
849 case GL_STENCIL_INDEX:
850 break;
851
852 default:
853 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
854 return false;
855 }
Geoff Lang3b573612016-10-31 14:08:10 -0400856 break;
857
Geoff Lang81c6b572016-10-19 14:07:52 -0700858 case GL_TEXTURE_SRGB_DECODE_EXT:
859 if (!ValidateTextureSRGBDecodeValue(context, params))
860 {
861 return false;
862 }
863 break;
864
Geoff Langc1984ed2016-10-07 12:41:00 -0400865 default:
866 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
867 return false;
868 }
869
870 return true;
871}
872
873template <typename ParamType>
874bool ValidateSamplerParameterBase(Context *context,
875 GLuint sampler,
876 GLenum pname,
877 GLsizei bufSize,
878 ParamType *params)
879{
880 if (context->getClientMajorVersion() < 3)
881 {
882 context->handleError(
883 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
884 return false;
885 }
886
887 if (!context->isSampler(sampler))
888 {
889 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
890 return false;
891 }
892
893 const GLsizei minBufSize = 1;
894 if (bufSize >= 0 && bufSize < minBufSize)
895 {
896 context->handleError(
897 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
898 return false;
899 }
900
901 switch (pname)
902 {
903 case GL_TEXTURE_WRAP_S:
904 case GL_TEXTURE_WRAP_T:
905 case GL_TEXTURE_WRAP_R:
906 if (!ValidateTextureWrapModeValue(context, params, false))
907 {
908 return false;
909 }
910 break;
911
912 case GL_TEXTURE_MIN_FILTER:
913 if (!ValidateTextureMinFilterValue(context, params, false))
914 {
915 return false;
916 }
917 break;
918
919 case GL_TEXTURE_MAG_FILTER:
920 if (!ValidateTextureMagFilterValue(context, params))
921 {
922 return false;
923 }
924 break;
925
926 case GL_TEXTURE_MIN_LOD:
927 case GL_TEXTURE_MAX_LOD:
928 // any value is permissible
929 break;
930
931 case GL_TEXTURE_COMPARE_MODE:
932 if (!ValidateTextureCompareModeValue(context, params))
933 {
934 return false;
935 }
936 break;
937
938 case GL_TEXTURE_COMPARE_FUNC:
939 if (!ValidateTextureCompareFuncValue(context, params))
940 {
941 return false;
942 }
943 break;
944
Geoff Lang81c6b572016-10-19 14:07:52 -0700945 case GL_TEXTURE_SRGB_DECODE_EXT:
946 if (!ValidateTextureSRGBDecodeValue(context, params))
947 {
948 return false;
949 }
950 break;
951
Geoff Langc1984ed2016-10-07 12:41:00 -0400952 default:
953 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
954 return false;
955 }
956
957 return true;
958}
959
960bool ValidateGetSamplerParameterBase(Context *context,
961 GLuint sampler,
962 GLenum pname,
963 GLsizei *length)
964{
965 if (length)
966 {
967 *length = 0;
968 }
969
970 if (context->getClientMajorVersion() < 3)
971 {
972 context->handleError(
973 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
974 return false;
975 }
976
977 if (!context->isSampler(sampler))
978 {
979 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
980 return false;
981 }
982
983 switch (pname)
984 {
985 case GL_TEXTURE_WRAP_S:
986 case GL_TEXTURE_WRAP_T:
987 case GL_TEXTURE_WRAP_R:
988 case GL_TEXTURE_MIN_FILTER:
989 case GL_TEXTURE_MAG_FILTER:
990 case GL_TEXTURE_MIN_LOD:
991 case GL_TEXTURE_MAX_LOD:
992 case GL_TEXTURE_COMPARE_MODE:
993 case GL_TEXTURE_COMPARE_FUNC:
994 break;
995
Geoff Lang81c6b572016-10-19 14:07:52 -0700996 case GL_TEXTURE_SRGB_DECODE_EXT:
997 if (!context->getExtensions().textureSRGBDecode)
998 {
999 context->handleError(
1000 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
1001 return false;
1002 }
1003 break;
1004
Geoff Langc1984ed2016-10-07 12:41:00 -04001005 default:
1006 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1007 return false;
1008 }
1009
1010 if (length)
1011 {
1012 *length = 1;
1013 }
1014 return true;
1015}
1016
Geoff Lang0b031062016-10-13 14:30:04 -04001017bool ValidateGetVertexAttribBase(Context *context,
1018 GLuint index,
1019 GLenum pname,
1020 GLsizei *length,
1021 bool pointer,
1022 bool pureIntegerEntryPoint)
1023{
1024 if (length)
1025 {
1026 *length = 0;
1027 }
1028
1029 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
1030 {
1031 context->handleError(
1032 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1033 return false;
1034 }
1035
1036 if (index >= context->getCaps().maxVertexAttributes)
1037 {
1038 context->handleError(Error(
1039 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
1040 return false;
1041 }
1042
1043 if (pointer)
1044 {
1045 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1046 {
1047 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1048 return false;
1049 }
1050 }
1051 else
1052 {
1053 switch (pname)
1054 {
1055 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1056 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1057 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1058 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1059 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1060 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1061 case GL_CURRENT_VERTEX_ATTRIB:
1062 break;
1063
1064 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1065 static_assert(
1066 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1067 "ANGLE extension enums not equal to GL enums.");
1068 if (context->getClientMajorVersion() < 3 &&
1069 !context->getExtensions().instancedArrays)
1070 {
1071 context->handleError(Error(GL_INVALID_ENUM,
1072 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1073 "3.0 or GL_ANGLE_instanced_arrays."));
1074 return false;
1075 }
1076 break;
1077
1078 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1079 if (context->getClientMajorVersion() < 3)
1080 {
1081 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
1082 return false;
1083 }
1084 break;
1085
1086 default:
1087 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1088 return false;
1089 }
1090 }
1091
1092 if (length)
1093 {
1094 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1095 {
1096 *length = 4;
1097 }
1098 else
1099 {
1100 *length = 1;
1101 }
1102 }
1103
1104 return true;
1105}
1106
Geoff Lang6899b872016-10-14 11:30:13 -04001107bool ValidateGetActiveUniformBlockivBase(Context *context,
1108 GLuint program,
1109 GLuint uniformBlockIndex,
1110 GLenum pname,
1111 GLsizei *length)
1112{
1113 if (length)
1114 {
1115 *length = 0;
1116 }
1117
1118 if (context->getClientMajorVersion() < 3)
1119 {
1120 context->handleError(
1121 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1122 return false;
1123 }
1124
1125 Program *programObject = GetValidProgram(context, program);
1126 if (!programObject)
1127 {
1128 return false;
1129 }
1130
1131 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1132 {
1133 context->handleError(
1134 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1135 return false;
1136 }
1137
1138 switch (pname)
1139 {
1140 case GL_UNIFORM_BLOCK_BINDING:
1141 case GL_UNIFORM_BLOCK_DATA_SIZE:
1142 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1143 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1144 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1145 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1146 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1147 break;
1148
1149 default:
1150 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1151 return false;
1152 }
1153
1154 if (length)
1155 {
1156 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1157 {
1158 const UniformBlock &uniformBlock =
1159 programObject->getUniformBlockByIndex(uniformBlockIndex);
1160 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1161 }
1162 else
1163 {
1164 *length = 1;
1165 }
1166 }
1167
1168 return true;
1169}
1170
Geoff Langebebe1c2016-10-14 12:01:31 -04001171bool ValidateGetBufferParameterBase(ValidationContext *context,
1172 GLenum target,
1173 GLenum pname,
1174 bool pointerVersion,
1175 GLsizei *numParams)
1176{
1177 if (numParams)
1178 {
1179 *numParams = 0;
1180 }
1181
1182 if (!ValidBufferTarget(context, target))
1183 {
1184 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1185 return false;
1186 }
1187
1188 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1189 if (!buffer)
1190 {
1191 // A null buffer means that "0" is bound to the requested buffer target
1192 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1193 return false;
1194 }
1195
1196 const Extensions &extensions = context->getExtensions();
1197
1198 switch (pname)
1199 {
1200 case GL_BUFFER_USAGE:
1201 case GL_BUFFER_SIZE:
1202 break;
1203
1204 case GL_BUFFER_ACCESS_OES:
1205 if (!extensions.mapBuffer)
1206 {
1207 context->handleError(
1208 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_map_buffer."));
1209 return false;
1210 }
1211 break;
1212
1213 case GL_BUFFER_MAPPED:
1214 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1215 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1216 !extensions.mapBufferRange)
1217 {
1218 context->handleError(Error(
1219 GL_INVALID_ENUM,
1220 "pname requires OpenGL ES 3.0, GL_OES_map_buffer or GL_EXT_map_buffer_range."));
1221 return false;
1222 }
1223 break;
1224
1225 case GL_BUFFER_MAP_POINTER:
1226 if (!pointerVersion)
1227 {
1228 context->handleError(
1229 Error(GL_INVALID_ENUM,
1230 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1231 return false;
1232 }
1233 break;
1234
1235 case GL_BUFFER_ACCESS_FLAGS:
1236 case GL_BUFFER_MAP_OFFSET:
1237 case GL_BUFFER_MAP_LENGTH:
1238 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1239 {
1240 context->handleError(Error(
1241 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1242 return false;
1243 }
1244 break;
1245
1246 default:
1247 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1248 return false;
1249 }
1250
1251 // All buffer parameter queries return one value.
1252 if (numParams)
1253 {
1254 *numParams = 1;
1255 }
1256
1257 return true;
1258}
1259
Geoff Lang0a9661f2016-10-20 10:59:20 -07001260bool ValidateGetInternalFormativBase(Context *context,
1261 GLenum target,
1262 GLenum internalformat,
1263 GLenum pname,
1264 GLsizei bufSize,
1265 GLsizei *numParams)
1266{
1267 if (numParams)
1268 {
1269 *numParams = 0;
1270 }
1271
1272 if (context->getClientMajorVersion() < 3)
1273 {
1274 context->handleError(
1275 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1276 return false;
1277 }
1278
1279 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1280 if (!formatCaps.renderable)
1281 {
1282 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1283 return false;
1284 }
1285
1286 switch (target)
1287 {
1288 case GL_RENDERBUFFER:
1289 break;
1290
1291 default:
1292 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1293 return false;
1294 }
1295
1296 if (bufSize < 0)
1297 {
1298 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1299 return false;
1300 }
1301
1302 GLsizei maxWriteParams = 0;
1303 switch (pname)
1304 {
1305 case GL_NUM_SAMPLE_COUNTS:
1306 maxWriteParams = 1;
1307 break;
1308
1309 case GL_SAMPLES:
1310 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1311 break;
1312
1313 default:
1314 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1315 return false;
1316 }
1317
1318 if (numParams)
1319 {
1320 // glGetInternalFormativ will not overflow bufSize
1321 *numParams = std::min(bufSize, maxWriteParams);
1322 }
1323
1324 return true;
1325}
1326
Geoff Langf41a7152016-09-19 15:11:17 -04001327} // anonymous namespace
1328
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001329bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001330{
Jamie Madilld7460c72014-01-21 16:38:14 -05001331 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001332 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001333 case GL_TEXTURE_2D:
1334 case GL_TEXTURE_CUBE_MAP:
1335 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001336
He Yunchaoced53ae2016-11-29 15:00:51 +08001337 case GL_TEXTURE_3D:
1338 case GL_TEXTURE_2D_ARRAY:
1339 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001340
He Yunchaoced53ae2016-11-29 15:00:51 +08001341 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001342 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001343
He Yunchaoced53ae2016-11-29 15:00:51 +08001344 default:
1345 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001346 }
Jamie Madill35d15012013-10-07 10:46:37 -04001347}
1348
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001349bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1350{
1351 switch (target)
1352 {
1353 case GL_TEXTURE_2D:
1354 case GL_TEXTURE_CUBE_MAP:
1355 return true;
1356
1357 default:
1358 return false;
1359 }
1360}
1361
1362bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1363{
1364 switch (target)
1365 {
1366 case GL_TEXTURE_3D:
1367 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001368 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001369
1370 default:
1371 return false;
1372 }
1373}
1374
Ian Ewellbda75592016-04-18 17:25:54 -04001375// Most texture GL calls are not compatible with external textures, so we have a separate validation
1376// function for use in the GL calls that do
1377bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1378{
1379 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1380 (context->getExtensions().eglImageExternal ||
1381 context->getExtensions().eglStreamConsumerExternal);
1382}
1383
Shannon Woods4dfed832014-03-17 20:03:39 -04001384// This function differs from ValidTextureTarget in that the target must be
1385// usable as the destination of a 2D operation-- so a cube face is valid, but
1386// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001387// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001388bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001389{
1390 switch (target)
1391 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001392 case GL_TEXTURE_2D:
1393 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1394 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1395 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1396 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1397 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1398 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1399 return true;
1400 default:
1401 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001402 }
1403}
1404
1405bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1406{
1407 switch (target)
1408 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001409 case GL_TEXTURE_3D:
1410 case GL_TEXTURE_2D_ARRAY:
1411 return true;
1412 default:
1413 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001414 }
1415}
1416
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001417bool ValidFramebufferTarget(GLenum target)
1418{
He Yunchaoced53ae2016-11-29 15:00:51 +08001419 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1420 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001421 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001422
1423 switch (target)
1424 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001425 case GL_FRAMEBUFFER:
1426 return true;
1427 case GL_READ_FRAMEBUFFER:
1428 return true;
1429 case GL_DRAW_FRAMEBUFFER:
1430 return true;
1431 default:
1432 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001433 }
1434}
1435
Jamie Madill29639852016-09-02 15:00:09 -04001436bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001437{
1438 switch (target)
1439 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001440 case GL_ARRAY_BUFFER:
1441 case GL_ELEMENT_ARRAY_BUFFER:
1442 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001443
He Yunchaoced53ae2016-11-29 15:00:51 +08001444 case GL_PIXEL_PACK_BUFFER:
1445 case GL_PIXEL_UNPACK_BUFFER:
1446 return (context->getExtensions().pixelBufferObject ||
1447 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001448
He Yunchaoced53ae2016-11-29 15:00:51 +08001449 case GL_COPY_READ_BUFFER:
1450 case GL_COPY_WRITE_BUFFER:
1451 case GL_TRANSFORM_FEEDBACK_BUFFER:
1452 case GL_UNIFORM_BUFFER:
1453 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001454
He Yunchaoced53ae2016-11-29 15:00:51 +08001455 case GL_ATOMIC_COUNTER_BUFFER:
1456 case GL_SHADER_STORAGE_BUFFER:
1457 case GL_DRAW_INDIRECT_BUFFER:
1458 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001459 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001460
He Yunchaoced53ae2016-11-29 15:00:51 +08001461 default:
1462 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001463 }
1464}
1465
Jamie Madillc29968b2016-01-20 11:17:23 -05001466bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001467{
Jamie Madillc29968b2016-01-20 11:17:23 -05001468 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001469 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001470 switch (target)
1471 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001472 case GL_TEXTURE_2D:
1473 maxDimension = caps.max2DTextureSize;
1474 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001475 case GL_TEXTURE_CUBE_MAP:
1476 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1477 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1478 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1479 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1480 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1481 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1482 maxDimension = caps.maxCubeMapTextureSize;
1483 break;
1484 case GL_TEXTURE_3D:
1485 maxDimension = caps.max3DTextureSize;
1486 break;
1487 case GL_TEXTURE_2D_ARRAY:
1488 maxDimension = caps.max2DTextureSize;
1489 break;
1490 default:
1491 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001492 }
1493
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001494 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001495}
1496
Geoff Langcc507aa2016-12-12 10:09:52 -05001497bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001498 GLenum target,
1499 GLint level,
1500 GLsizei width,
1501 GLsizei height,
1502 GLsizei depth,
1503 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001504{
1505 if (level < 0 || width < 0 || height < 0 || depth < 0)
1506 {
1507 return false;
1508 }
1509
Austin Kinross08528e12015-10-07 16:24:40 -07001510 // TexSubImage parameters can be NPOT without textureNPOT extension,
1511 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001512 bool hasNPOTSupport =
1513 context->getExtensions().textureNPOT && context->getClientVersion() >= Version(3, 0);
1514 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001515 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001516 {
1517 return false;
1518 }
1519
1520 if (!ValidMipLevel(context, target, level))
1521 {
1522 return false;
1523 }
1524
1525 return true;
1526}
1527
Geoff Lang0d8b7242015-09-09 14:56:53 -04001528bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1529{
1530 // List of compressed format that require that the texture size is smaller than or a multiple of
1531 // the compressed block size.
1532 switch (internalFormat)
1533 {
1534 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1535 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1536 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1537 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001538 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001539 return true;
1540
1541 default:
1542 return false;
1543 }
1544}
1545
Jamie Madillc29968b2016-01-20 11:17:23 -05001546bool ValidCompressedImageSize(const ValidationContext *context,
1547 GLenum internalFormat,
1548 GLsizei width,
1549 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001550{
Geoff Lang5d601382014-07-22 15:14:06 -04001551 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1552 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001553 {
1554 return false;
1555 }
1556
Geoff Lang0d8b7242015-09-09 14:56:53 -04001557 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001558 {
1559 return false;
1560 }
1561
Geoff Lang0d8b7242015-09-09 14:56:53 -04001562 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1563 {
1564 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1565 width % formatInfo.compressedBlockWidth != 0) ||
1566 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1567 height % formatInfo.compressedBlockHeight != 0))
1568 {
1569 return false;
1570 }
1571 }
1572
Geoff Langd4f180b2013-09-24 13:57:44 -04001573 return true;
1574}
1575
Geoff Langff5b2d52016-09-07 11:32:23 -04001576bool ValidImageDataSize(ValidationContext *context,
1577 GLenum textureTarget,
1578 GLsizei width,
1579 GLsizei height,
1580 GLsizei depth,
1581 GLenum internalFormat,
1582 GLenum type,
1583 const GLvoid *pixels,
1584 GLsizei imageSize)
1585{
1586 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1587 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1588 {
1589 // Checks are not required
1590 return true;
1591 }
1592
1593 // ...the data would be unpacked from the buffer object such that the memory reads required
1594 // would exceed the data store size.
1595 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1596 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1597 const gl::Extents size(width, height, depth);
1598 const auto &unpack = context->getGLState().getUnpackState();
1599
1600 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1601 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1602 if (endByteOrErr.isError())
1603 {
1604 context->handleError(endByteOrErr.getError());
1605 return false;
1606 }
1607
1608 GLuint endByte = endByteOrErr.getResult();
1609
1610 if (pixelUnpackBuffer)
1611 {
1612 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1613 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1614 checkedEndByte += checkedOffset;
1615
1616 if (!checkedEndByte.IsValid() ||
1617 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1618 {
1619 // Overflow past the end of the buffer
1620 context->handleError(Error(GL_INVALID_OPERATION));
1621 return false;
1622 }
1623 }
1624 else
1625 {
1626 ASSERT(imageSize >= 0);
1627 if (pixels == nullptr && imageSize != 0)
1628 {
1629 context->handleError(
1630 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001631 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001632 }
1633
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001634 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001635 {
1636 context->handleError(
1637 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1638 return false;
1639 }
1640 }
1641
1642 return true;
1643}
1644
Geoff Lang37dde692014-01-31 16:34:54 -05001645bool ValidQueryType(const Context *context, GLenum queryType)
1646{
He Yunchaoced53ae2016-11-29 15:00:51 +08001647 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1648 "GL extension enums not equal.");
1649 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1650 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001651
1652 switch (queryType)
1653 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001654 case GL_ANY_SAMPLES_PASSED:
1655 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1656 return true;
1657 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1658 return (context->getClientMajorVersion() >= 3);
1659 case GL_TIME_ELAPSED_EXT:
1660 return context->getExtensions().disjointTimerQuery;
1661 case GL_COMMANDS_COMPLETED_CHROMIUM:
1662 return context->getExtensions().syncQuery;
1663 default:
1664 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001665 }
1666}
1667
Jamie Madillef300b12016-10-07 15:12:09 -04001668Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001669{
He Yunchaoced53ae2016-11-29 15:00:51 +08001670 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1671 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1672 // or program object and INVALID_OPERATION if the provided name identifies an object
1673 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001674
Dian Xiang769769a2015-09-09 15:20:08 -07001675 Program *validProgram = context->getProgram(id);
1676
1677 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001678 {
Dian Xiang769769a2015-09-09 15:20:08 -07001679 if (context->getShader(id))
1680 {
Jamie Madill437fa652016-05-03 15:13:24 -04001681 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001682 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1683 }
1684 else
1685 {
Jamie Madill437fa652016-05-03 15:13:24 -04001686 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001687 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001688 }
Dian Xiang769769a2015-09-09 15:20:08 -07001689
1690 return validProgram;
1691}
1692
Jamie Madillef300b12016-10-07 15:12:09 -04001693Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001694{
1695 // See ValidProgram for spec details.
1696
1697 Shader *validShader = context->getShader(id);
1698
1699 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001700 {
Dian Xiang769769a2015-09-09 15:20:08 -07001701 if (context->getProgram(id))
1702 {
Jamie Madill437fa652016-05-03 15:13:24 -04001703 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001704 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1705 }
1706 else
1707 {
Jamie Madill437fa652016-05-03 15:13:24 -04001708 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001709 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001710 }
Dian Xiang769769a2015-09-09 15:20:08 -07001711
1712 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001713}
1714
Geoff Langb1196682014-07-23 13:47:29 -04001715bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001716{
1717 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1718 {
1719 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1720
Geoff Langaae65a42014-05-26 12:43:44 -04001721 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001722 {
Jamie Madill437fa652016-05-03 15:13:24 -04001723 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001724 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001725 }
1726 }
1727 else
1728 {
1729 switch (attachment)
1730 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001731 case GL_DEPTH_ATTACHMENT:
1732 case GL_STENCIL_ATTACHMENT:
1733 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001734
He Yunchaoced53ae2016-11-29 15:00:51 +08001735 case GL_DEPTH_STENCIL_ATTACHMENT:
1736 if (!context->getExtensions().webglCompatibility &&
1737 context->getClientMajorVersion() < 3)
1738 {
1739 context->handleError(Error(GL_INVALID_ENUM));
1740 return false;
1741 }
1742 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001743
He Yunchaoced53ae2016-11-29 15:00:51 +08001744 default:
1745 context->handleError(Error(GL_INVALID_ENUM));
1746 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001747 }
1748 }
1749
1750 return true;
1751}
1752
He Yunchaoced53ae2016-11-29 15:00:51 +08001753bool ValidateRenderbufferStorageParametersBase(gl::Context *context,
1754 GLenum target,
1755 GLsizei samples,
1756 GLenum internalformat,
1757 GLsizei width,
1758 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001759{
1760 switch (target)
1761 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001762 case GL_RENDERBUFFER:
1763 break;
1764 default:
1765 context->handleError(Error(GL_INVALID_ENUM));
1766 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001767 }
1768
1769 if (width < 0 || height < 0 || samples < 0)
1770 {
Jamie Madill437fa652016-05-03 15:13:24 -04001771 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001772 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001773 }
1774
Geoff Langd87878e2014-09-19 15:42:59 -04001775 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1776 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001777 {
Jamie Madill437fa652016-05-03 15:13:24 -04001778 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001779 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001780 }
1781
1782 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1783 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
Corentin Walleze0902642014-11-04 12:32:15 -08001784 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001785 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001786 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001787 {
Jamie Madill437fa652016-05-03 15:13:24 -04001788 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001789 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001790 }
1791
Geoff Langaae65a42014-05-26 12:43:44 -04001792 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001793 {
Jamie Madill437fa652016-05-03 15:13:24 -04001794 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001795 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001796 }
1797
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001798 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001799 if (handle == 0)
1800 {
Jamie Madill437fa652016-05-03 15:13:24 -04001801 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001802 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001803 }
1804
1805 return true;
1806}
1807
He Yunchaoced53ae2016-11-29 15:00:51 +08001808bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context,
1809 GLenum target,
1810 GLsizei samples,
1811 GLenum internalformat,
1812 GLsizei width,
1813 GLsizei height)
Corentin Walleze0902642014-11-04 12:32:15 -08001814{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001815 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001816
1817 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001818 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001819 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001820 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001821 {
Jamie Madill437fa652016-05-03 15:13:24 -04001822 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001823 return false;
1824 }
1825
1826 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1827 // the specified storage. This is different than ES 3.0 in which a sample number higher
1828 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001829 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001830 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001831 {
Geoff Langa4903b72015-03-02 16:02:48 -08001832 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1833 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1834 {
Jamie Madill437fa652016-05-03 15:13:24 -04001835 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001836 return false;
1837 }
Corentin Walleze0902642014-11-04 12:32:15 -08001838 }
1839
He Yunchaoced53ae2016-11-29 15:00:51 +08001840 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
1841 width, height);
Corentin Walleze0902642014-11-04 12:32:15 -08001842}
1843
He Yunchaoced53ae2016-11-29 15:00:51 +08001844bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1845 GLenum target,
1846 GLenum attachment,
1847 GLenum renderbuffertarget,
1848 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001849{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001850 if (!ValidFramebufferTarget(target))
1851 {
Jamie Madill437fa652016-05-03 15:13:24 -04001852 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001853 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001854 }
1855
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001856 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001857
Jamie Madill84115c92015-04-23 15:00:07 -04001858 ASSERT(framebuffer);
1859 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001860 {
Jamie Madill437fa652016-05-03 15:13:24 -04001861 context->handleError(
1862 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001863 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001864 }
1865
Jamie Madillb4472272014-07-03 10:38:55 -04001866 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001867 {
Jamie Madillb4472272014-07-03 10:38:55 -04001868 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001869 }
1870
Jamie Madillab9d82c2014-01-21 16:38:14 -05001871 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1872 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1873 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1874 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1875 if (renderbuffer != 0)
1876 {
1877 if (!context->getRenderbuffer(renderbuffer))
1878 {
Jamie Madill437fa652016-05-03 15:13:24 -04001879 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001880 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001881 }
1882 }
1883
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001884 return true;
1885}
1886
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001887bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001888 GLint srcX0,
1889 GLint srcY0,
1890 GLint srcX1,
1891 GLint srcY1,
1892 GLint dstX0,
1893 GLint dstY0,
1894 GLint dstX1,
1895 GLint dstY1,
1896 GLbitfield mask,
1897 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001898{
1899 switch (filter)
1900 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001901 case GL_NEAREST:
1902 break;
1903 case GL_LINEAR:
1904 break;
1905 default:
1906 context->handleError(Error(GL_INVALID_ENUM));
1907 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001908 }
1909
1910 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1911 {
Jamie Madill437fa652016-05-03 15:13:24 -04001912 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001913 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001914 }
1915
1916 if (mask == 0)
1917 {
1918 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1919 // buffers are copied.
1920 return false;
1921 }
1922
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001923 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1924 // color buffer, leaving only nearest being unfiltered from above
1925 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1926 {
Jamie Madill437fa652016-05-03 15:13:24 -04001927 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001928 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001929 }
1930
Jamie Madill51f40ec2016-06-15 14:06:00 -04001931 const auto &glState = context->getGLState();
1932 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1933 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001934
1935 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001936 {
Jamie Madill437fa652016-05-03 15:13:24 -04001937 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001938 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001939 }
1940
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001941 if (readFramebuffer->id() == drawFramebuffer->id())
1942 {
1943 context->handleError(Error(GL_INVALID_OPERATION));
1944 return false;
1945 }
1946
Jamie Madill51f40ec2016-06-15 14:06:00 -04001947 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001948 {
Jamie Madill437fa652016-05-03 15:13:24 -04001949 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001950 return false;
1951 }
1952
Jamie Madill51f40ec2016-06-15 14:06:00 -04001953 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001954 {
Jamie Madill437fa652016-05-03 15:13:24 -04001955 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001956 return false;
1957 }
1958
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001959 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001960 {
Jamie Madill437fa652016-05-03 15:13:24 -04001961 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001962 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001963 }
1964
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001965 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1966
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001967 if (mask & GL_COLOR_BUFFER_BIT)
1968 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001969 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1970 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001971 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001972
1973 if (readColorBuffer && drawColorBuffer)
1974 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001975 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001976
Geoff Langa15472a2015-08-11 11:48:03 -04001977 for (size_t drawbufferIdx = 0;
1978 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001979 {
Geoff Langa15472a2015-08-11 11:48:03 -04001980 const FramebufferAttachment *attachment =
1981 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1982 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001983 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001984 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001985
Geoff Langb2f3d052013-08-13 12:49:27 -04001986 // The GL ES 3.0.2 spec (pg 193) states that:
1987 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001988 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1989 // as well
1990 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1991 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001992 // Changes with EXT_color_buffer_float:
1993 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001994 GLenum readComponentType = readFormat.info->componentType;
1995 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001996 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001997 readComponentType == GL_SIGNED_NORMALIZED);
1998 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1999 drawComponentType == GL_SIGNED_NORMALIZED);
2000
2001 if (extensions.colorBufferFloat)
2002 {
2003 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2004 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2005
2006 if (readFixedOrFloat != drawFixedOrFloat)
2007 {
Jamie Madill437fa652016-05-03 15:13:24 -04002008 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002009 "If the read buffer contains fixed-point or "
2010 "floating-point values, the draw buffer "
2011 "must as well."));
2012 return false;
2013 }
2014 }
2015 else if (readFixedPoint != drawFixedPoint)
2016 {
Jamie Madill437fa652016-05-03 15:13:24 -04002017 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002018 "If the read buffer contains fixed-point "
2019 "values, the draw buffer must as well."));
2020 return false;
2021 }
2022
2023 if (readComponentType == GL_UNSIGNED_INT &&
2024 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002025 {
Jamie Madill437fa652016-05-03 15:13:24 -04002026 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002027 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002028 }
2029
Jamie Madill6163c752015-12-07 16:32:59 -05002030 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002031 {
Jamie Madill437fa652016-05-03 15:13:24 -04002032 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002033 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002034 }
2035
Jamie Madilla3944d42016-07-22 22:13:26 -04002036 if (readColorBuffer->getSamples() > 0 &&
2037 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002038 {
Jamie Madill437fa652016-05-03 15:13:24 -04002039 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002040 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002041 }
2042 }
2043 }
2044
Jamie Madilla3944d42016-07-22 22:13:26 -04002045 if ((readFormat.info->componentType == GL_INT ||
2046 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2047 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002048 {
Jamie Madill437fa652016-05-03 15:13:24 -04002049 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002050 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002051 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002052 }
2053 }
2054
He Yunchaoced53ae2016-11-29 15:00:51 +08002055 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002056 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2057 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002058 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002059 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002060 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002061 const gl::FramebufferAttachment *readBuffer =
2062 readFramebuffer->getAttachment(attachments[i]);
2063 const gl::FramebufferAttachment *drawBuffer =
2064 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002065
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002066 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002067 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002068 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002069 {
Jamie Madill437fa652016-05-03 15:13:24 -04002070 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002071 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002072 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002073
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002074 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002075 {
Jamie Madill437fa652016-05-03 15:13:24 -04002076 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002077 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002078 }
2079 }
2080 }
2081 }
2082
2083 return true;
2084}
2085
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002086bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002087 GLint x,
2088 GLint y,
2089 GLsizei width,
2090 GLsizei height,
2091 GLenum format,
2092 GLenum type,
2093 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002094{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002095 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2096}
2097
2098bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2099 GLint x,
2100 GLint y,
2101 GLsizei width,
2102 GLsizei height,
2103 GLenum format,
2104 GLenum type,
2105 GLsizei bufSize,
2106 GLsizei *length,
2107 GLvoid *pixels)
2108{
2109 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002110 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002111 return false;
2112 }
2113
Geoff Lang62fce5b2016-09-30 10:46:35 -04002114 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2115 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002116 {
Geoff Langb1196682014-07-23 13:47:29 -04002117 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002118 }
2119
Geoff Lang62fce5b2016-09-30 10:46:35 -04002120 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002121 {
Geoff Langb1196682014-07-23 13:47:29 -04002122 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002123 }
2124
Jamie Madillc29968b2016-01-20 11:17:23 -05002125 return true;
2126}
2127
2128bool ValidateReadnPixelsEXT(Context *context,
2129 GLint x,
2130 GLint y,
2131 GLsizei width,
2132 GLsizei height,
2133 GLenum format,
2134 GLenum type,
2135 GLsizei bufSize,
2136 GLvoid *pixels)
2137{
2138 if (bufSize < 0)
2139 {
Jamie Madill437fa652016-05-03 15:13:24 -04002140 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002141 return false;
2142 }
2143
Geoff Lang62fce5b2016-09-30 10:46:35 -04002144 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2145 pixels);
2146}
Jamie Madill26e91952014-03-05 15:01:27 -05002147
Geoff Lang62fce5b2016-09-30 10:46:35 -04002148bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2149 GLint x,
2150 GLint y,
2151 GLsizei width,
2152 GLsizei height,
2153 GLenum format,
2154 GLenum type,
2155 GLsizei bufSize,
2156 GLsizei *length,
2157 GLvoid *data)
2158{
2159 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002160 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002161 return false;
2162 }
2163
Geoff Lang62fce5b2016-09-30 10:46:35 -04002164 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002165 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002166 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002167 }
2168
Geoff Lang62fce5b2016-09-30 10:46:35 -04002169 if (!ValidateRobustBufferSize(context, bufSize, *length))
2170 {
2171 return false;
2172 }
2173
2174 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002175}
2176
Olli Etuaho41997e72016-03-10 13:38:39 +02002177bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002178{
2179 if (!context->getExtensions().occlusionQueryBoolean &&
2180 !context->getExtensions().disjointTimerQuery)
2181 {
Jamie Madill437fa652016-05-03 15:13:24 -04002182 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002183 return false;
2184 }
2185
Olli Etuaho41997e72016-03-10 13:38:39 +02002186 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002187}
2188
Olli Etuaho41997e72016-03-10 13:38:39 +02002189bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002190{
2191 if (!context->getExtensions().occlusionQueryBoolean &&
2192 !context->getExtensions().disjointTimerQuery)
2193 {
Jamie Madill437fa652016-05-03 15:13:24 -04002194 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002195 return false;
2196 }
2197
Olli Etuaho41997e72016-03-10 13:38:39 +02002198 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002199}
2200
2201bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002202{
2203 if (!ValidQueryType(context, target))
2204 {
Jamie Madill437fa652016-05-03 15:13:24 -04002205 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002206 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002207 }
2208
2209 if (id == 0)
2210 {
Jamie Madill437fa652016-05-03 15:13:24 -04002211 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002212 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002213 }
2214
2215 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2216 // of zero, if the active query object name for <target> is non-zero (for the
2217 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2218 // the active query for either target is non-zero), if <id> is the name of an
2219 // existing query object whose type does not match <target>, or if <id> is the
2220 // active query object name for any query type, the error INVALID_OPERATION is
2221 // generated.
2222
2223 // Ensure no other queries are active
2224 // NOTE: If other queries than occlusion are supported, we will need to check
2225 // separately that:
2226 // a) The query ID passed is not the current active query for any target/type
2227 // b) There are no active queries for the requested target (and in the case
2228 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2229 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002230
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002231 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002232 {
Jamie Madill437fa652016-05-03 15:13:24 -04002233 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002234 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002235 }
2236
2237 Query *queryObject = context->getQuery(id, true, target);
2238
2239 // check that name was obtained with glGenQueries
2240 if (!queryObject)
2241 {
Jamie Madill437fa652016-05-03 15:13:24 -04002242 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002243 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002244 }
2245
2246 // check for type mismatch
2247 if (queryObject->getType() != target)
2248 {
Jamie Madill437fa652016-05-03 15:13:24 -04002249 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002250 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002251 }
2252
2253 return true;
2254}
2255
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002256bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2257{
2258 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002259 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002260 {
Jamie Madill437fa652016-05-03 15:13:24 -04002261 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002262 return false;
2263 }
2264
2265 return ValidateBeginQueryBase(context, target, id);
2266}
2267
2268bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002269{
2270 if (!ValidQueryType(context, target))
2271 {
Jamie Madill437fa652016-05-03 15:13:24 -04002272 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002273 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002274 }
2275
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002276 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002277
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002278 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002279 {
Jamie Madill437fa652016-05-03 15:13:24 -04002280 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002281 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002282 }
2283
Jamie Madill45c785d2014-05-13 14:09:34 -04002284 return true;
2285}
2286
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002287bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2288{
2289 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002290 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002291 {
Jamie Madill437fa652016-05-03 15:13:24 -04002292 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002293 return false;
2294 }
2295
2296 return ValidateEndQueryBase(context, target);
2297}
2298
2299bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2300{
2301 if (!context->getExtensions().disjointTimerQuery)
2302 {
Jamie Madill437fa652016-05-03 15:13:24 -04002303 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002304 return false;
2305 }
2306
2307 if (target != GL_TIMESTAMP_EXT)
2308 {
Jamie Madill437fa652016-05-03 15:13:24 -04002309 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002310 return false;
2311 }
2312
2313 Query *queryObject = context->getQuery(id, true, target);
2314 if (queryObject == nullptr)
2315 {
Jamie Madill437fa652016-05-03 15:13:24 -04002316 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002317 return false;
2318 }
2319
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002320 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002321 {
Jamie Madill437fa652016-05-03 15:13:24 -04002322 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002323 return false;
2324 }
2325
2326 return true;
2327}
2328
Geoff Lang2186c382016-10-14 10:54:54 -04002329bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002330{
Geoff Lang2186c382016-10-14 10:54:54 -04002331 if (numParams)
2332 {
2333 *numParams = 0;
2334 }
2335
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002336 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2337 {
Jamie Madill437fa652016-05-03 15:13:24 -04002338 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002339 return false;
2340 }
2341
2342 switch (pname)
2343 {
2344 case GL_CURRENT_QUERY_EXT:
2345 if (target == GL_TIMESTAMP_EXT)
2346 {
Jamie Madill437fa652016-05-03 15:13:24 -04002347 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002348 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2349 return false;
2350 }
2351 break;
2352 case GL_QUERY_COUNTER_BITS_EXT:
2353 if (!context->getExtensions().disjointTimerQuery ||
2354 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2355 {
Jamie Madill437fa652016-05-03 15:13:24 -04002356 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002357 return false;
2358 }
2359 break;
2360 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002361 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002362 return false;
2363 }
2364
Geoff Lang2186c382016-10-14 10:54:54 -04002365 if (numParams)
2366 {
2367 // All queries return only one value
2368 *numParams = 1;
2369 }
2370
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002371 return true;
2372}
2373
2374bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2375{
2376 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002377 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002378 {
Jamie Madill437fa652016-05-03 15:13:24 -04002379 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002380 return false;
2381 }
2382
Geoff Lang2186c382016-10-14 10:54:54 -04002383 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002384}
2385
Geoff Lang2186c382016-10-14 10:54:54 -04002386bool ValidateGetQueryivRobustANGLE(Context *context,
2387 GLenum target,
2388 GLenum pname,
2389 GLsizei bufSize,
2390 GLsizei *length,
2391 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002392{
Geoff Lang2186c382016-10-14 10:54:54 -04002393 if (!ValidateRobustEntryPoint(context, bufSize))
2394 {
2395 return false;
2396 }
2397
2398 if (!ValidateGetQueryivBase(context, target, pname, length))
2399 {
2400 return false;
2401 }
2402
2403 if (!ValidateRobustBufferSize(context, bufSize, *length))
2404 {
2405 return false;
2406 }
2407
2408 return true;
2409}
2410
2411bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2412{
2413 if (numParams)
2414 {
2415 *numParams = 0;
2416 }
2417
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002418 Query *queryObject = context->getQuery(id, false, GL_NONE);
2419
2420 if (!queryObject)
2421 {
Jamie Madill437fa652016-05-03 15:13:24 -04002422 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002423 return false;
2424 }
2425
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002426 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002427 {
Jamie Madill437fa652016-05-03 15:13:24 -04002428 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002429 return false;
2430 }
2431
2432 switch (pname)
2433 {
2434 case GL_QUERY_RESULT_EXT:
2435 case GL_QUERY_RESULT_AVAILABLE_EXT:
2436 break;
2437
2438 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002439 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002440 return false;
2441 }
2442
Geoff Lang2186c382016-10-14 10:54:54 -04002443 if (numParams)
2444 {
2445 *numParams = 1;
2446 }
2447
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002448 return true;
2449}
2450
2451bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2452{
2453 if (!context->getExtensions().disjointTimerQuery)
2454 {
Jamie Madill437fa652016-05-03 15:13:24 -04002455 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002456 return false;
2457 }
Geoff Lang2186c382016-10-14 10:54:54 -04002458 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2459}
2460
2461bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2462 GLuint id,
2463 GLenum pname,
2464 GLsizei bufSize,
2465 GLsizei *length,
2466 GLint *params)
2467{
2468 if (!context->getExtensions().disjointTimerQuery)
2469 {
2470 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2471 return false;
2472 }
2473
2474 if (!ValidateRobustEntryPoint(context, bufSize))
2475 {
2476 return false;
2477 }
2478
2479 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2480 {
2481 return false;
2482 }
2483
2484 if (!ValidateRobustBufferSize(context, bufSize, *length))
2485 {
2486 return false;
2487 }
2488
2489 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002490}
2491
2492bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2493{
2494 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002495 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002496 {
Jamie Madill437fa652016-05-03 15:13:24 -04002497 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002498 return false;
2499 }
Geoff Lang2186c382016-10-14 10:54:54 -04002500 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2501}
2502
2503bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2504 GLuint id,
2505 GLenum pname,
2506 GLsizei bufSize,
2507 GLsizei *length,
2508 GLuint *params)
2509{
2510 if (!context->getExtensions().disjointTimerQuery &&
2511 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2512 {
2513 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2514 return false;
2515 }
2516
2517 if (!ValidateRobustEntryPoint(context, bufSize))
2518 {
2519 return false;
2520 }
2521
2522 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2523 {
2524 return false;
2525 }
2526
2527 if (!ValidateRobustBufferSize(context, bufSize, *length))
2528 {
2529 return false;
2530 }
2531
2532 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002533}
2534
2535bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2536{
2537 if (!context->getExtensions().disjointTimerQuery)
2538 {
Jamie Madill437fa652016-05-03 15:13:24 -04002539 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002540 return false;
2541 }
Geoff Lang2186c382016-10-14 10:54:54 -04002542 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2543}
2544
2545bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2546 GLuint id,
2547 GLenum pname,
2548 GLsizei bufSize,
2549 GLsizei *length,
2550 GLint64 *params)
2551{
2552 if (!context->getExtensions().disjointTimerQuery)
2553 {
2554 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2555 return false;
2556 }
2557
2558 if (!ValidateRobustEntryPoint(context, bufSize))
2559 {
2560 return false;
2561 }
2562
2563 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2564 {
2565 return false;
2566 }
2567
2568 if (!ValidateRobustBufferSize(context, bufSize, *length))
2569 {
2570 return false;
2571 }
2572
2573 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002574}
2575
2576bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2577{
2578 if (!context->getExtensions().disjointTimerQuery)
2579 {
Jamie Madill437fa652016-05-03 15:13:24 -04002580 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002581 return false;
2582 }
Geoff Lang2186c382016-10-14 10:54:54 -04002583 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2584}
2585
2586bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2587 GLuint id,
2588 GLenum pname,
2589 GLsizei bufSize,
2590 GLsizei *length,
2591 GLuint64 *params)
2592{
2593 if (!context->getExtensions().disjointTimerQuery)
2594 {
2595 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2596 return false;
2597 }
2598
2599 if (!ValidateRobustEntryPoint(context, bufSize))
2600 {
2601 return false;
2602 }
2603
2604 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2605 {
2606 return false;
2607 }
2608
2609 if (!ValidateRobustBufferSize(context, bufSize, *length))
2610 {
2611 return false;
2612 }
2613
2614 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002615}
2616
Jamie Madill62d31cb2015-09-11 13:25:51 -04002617static bool ValidateUniformCommonBase(gl::Context *context,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002618 gl::Program *program,
Jamie Madill62d31cb2015-09-11 13:25:51 -04002619 GLenum targetUniformType,
2620 GLint location,
2621 GLsizei count,
2622 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002623{
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002624 // TODO(Jiajia): Add image uniform check in future.
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002625 if (count < 0)
2626 {
Jamie Madill437fa652016-05-03 15:13:24 -04002627 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002628 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002629 }
2630
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002631 if (!program || !program->isLinked())
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002632 {
Jamie Madill437fa652016-05-03 15:13:24 -04002633 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002634 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002635 }
2636
Geoff Langd8605522016-04-13 10:19:12 -04002637 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002638 {
2639 // Silently ignore the uniform command
2640 return false;
2641 }
2642
Geoff Lang7dd2e102014-11-10 15:19:26 -05002643 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04002644 {
Jamie Madill437fa652016-05-03 15:13:24 -04002645 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002646 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002647 }
2648
Jamie Madill62d31cb2015-09-11 13:25:51 -04002649 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04002650
2651 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002652 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002653 {
Jamie Madill437fa652016-05-03 15:13:24 -04002654 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002655 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002656 }
2657
Jamie Madill62d31cb2015-09-11 13:25:51 -04002658 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002659 return true;
2660}
2661
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002662bool ValidateProgramUniform(gl::Context *context,
2663 GLenum uniformType,
2664 GLuint program,
2665 GLint location,
2666 GLsizei count)
2667{
2668 // Check for ES31 program uniform entry points
2669 if (context->getClientVersion() < Version(3, 1))
2670 {
2671 context->handleError(Error(GL_INVALID_OPERATION));
2672 return false;
2673 }
2674
2675 const LinkedUniform *uniform = nullptr;
2676 gl::Program *programObject = GetValidProgram(context, program);
2677 if (!ValidateUniformCommonBase(context, programObject, uniformType, location, count, &uniform))
2678 {
2679 return false;
2680 }
2681
2682 GLenum targetBoolType = VariableBoolVectorType(uniformType);
2683 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
2684 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2685 {
2686 context->handleError(Error(GL_INVALID_OPERATION));
2687 return false;
2688 }
2689
2690 return true;
2691}
2692
2693bool ValidateProgramUniformMatrix(gl::Context *context,
2694 GLenum matrixType,
2695 GLuint program,
2696 GLint location,
2697 GLsizei count,
2698 GLboolean transpose)
2699{
2700 // Check for ES31 program uniform entry points
2701 if (context->getClientVersion() < Version(3, 1))
2702 {
2703 context->handleError(Error(GL_INVALID_OPERATION));
2704 return false;
2705 }
2706
2707 const LinkedUniform *uniform = nullptr;
2708 gl::Program *programObject = GetValidProgram(context, program);
2709 if (!ValidateUniformCommonBase(context, programObject, matrixType, location, count, &uniform))
2710 {
2711 return false;
2712 }
2713
2714 if (uniform->type != matrixType)
2715 {
2716 context->handleError(Error(GL_INVALID_OPERATION));
2717 return false;
2718 }
2719
2720 return true;
2721}
2722
Jamie Madillaa981bd2014-05-20 10:55:55 -04002723bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2724{
2725 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002726 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2727 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002728 {
Jamie Madill437fa652016-05-03 15:13:24 -04002729 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002730 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002731 }
2732
Jamie Madill62d31cb2015-09-11 13:25:51 -04002733 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002734 gl::Program *program = context->getGLState().getProgram();
2735 if (!ValidateUniformCommonBase(context, program, uniformType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002736 {
2737 return false;
2738 }
2739
He Yunchaoced53ae2016-11-29 15:00:51 +08002740 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002741 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002742 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2743 {
Jamie Madill437fa652016-05-03 15:13:24 -04002744 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002745 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002746 }
2747
2748 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002749}
2750
He Yunchaoced53ae2016-11-29 15:00:51 +08002751bool ValidateUniformMatrix(gl::Context *context,
2752 GLenum matrixType,
2753 GLint location,
2754 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002755 GLboolean transpose)
2756{
2757 // Check for ES3 uniform entry points
2758 int rows = VariableRowCount(matrixType);
2759 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002760 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002761 {
Jamie Madill437fa652016-05-03 15:13:24 -04002762 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002763 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002764 }
2765
Martin Radev1be913c2016-07-11 17:59:16 +03002766 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002767 {
Jamie Madill437fa652016-05-03 15:13:24 -04002768 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002769 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002770 }
2771
Jamie Madill62d31cb2015-09-11 13:25:51 -04002772 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002773 gl::Program *program = context->getGLState().getProgram();
2774 if (!ValidateUniformCommonBase(context, program, matrixType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002775 {
2776 return false;
2777 }
2778
2779 if (uniform->type != matrixType)
2780 {
Jamie Madill437fa652016-05-03 15:13:24 -04002781 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002782 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002783 }
2784
2785 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002786}
2787
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002788bool ValidateStateQuery(ValidationContext *context,
2789 GLenum pname,
2790 GLenum *nativeType,
2791 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002792{
2793 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2794 {
Jamie Madill437fa652016-05-03 15:13:24 -04002795 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002796 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002797 }
2798
Jamie Madill0af26e12015-03-05 19:54:33 -05002799 const Caps &caps = context->getCaps();
2800
Jamie Madill893ab082014-05-16 16:56:10 -04002801 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2802 {
2803 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2804
Jamie Madill0af26e12015-03-05 19:54:33 -05002805 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002806 {
Jamie Madill437fa652016-05-03 15:13:24 -04002807 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002808 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002809 }
2810 }
2811
2812 switch (pname)
2813 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002814 case GL_TEXTURE_BINDING_2D:
2815 case GL_TEXTURE_BINDING_CUBE_MAP:
2816 case GL_TEXTURE_BINDING_3D:
2817 case GL_TEXTURE_BINDING_2D_ARRAY:
2818 break;
2819 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2820 if (!context->getExtensions().eglStreamConsumerExternal &&
2821 !context->getExtensions().eglImageExternal)
2822 {
2823 context->handleError(Error(GL_INVALID_ENUM,
2824 "Neither NV_EGL_stream_consumer_external nor "
2825 "GL_OES_EGL_image_external extensions enabled"));
2826 return false;
2827 }
2828 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002829
He Yunchaoced53ae2016-11-29 15:00:51 +08002830 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2831 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002832 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002833 if (context->getGLState().getReadFramebuffer()->checkStatus(
2834 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002835 {
Jamie Madill437fa652016-05-03 15:13:24 -04002836 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002837 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002838 }
2839
Jamie Madill51f40ec2016-06-15 14:06:00 -04002840 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2841 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002842
2843 if (framebuffer->getReadBufferState() == GL_NONE)
2844 {
2845 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2846 return false;
2847 }
2848
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002849 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002850 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002851 {
Jamie Madill437fa652016-05-03 15:13:24 -04002852 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002853 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002854 }
2855 }
2856 break;
2857
He Yunchaoced53ae2016-11-29 15:00:51 +08002858 default:
2859 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002860 }
2861
2862 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002863 if (*numParams == 0)
2864 {
2865 return false;
2866 }
2867
2868 return true;
2869}
2870
2871bool ValidateRobustStateQuery(ValidationContext *context,
2872 GLenum pname,
2873 GLsizei bufSize,
2874 GLenum *nativeType,
2875 unsigned int *numParams)
2876{
2877 if (!ValidateRobustEntryPoint(context, bufSize))
2878 {
2879 return false;
2880 }
2881
2882 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2883 {
2884 return false;
2885 }
2886
2887 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002888 {
2889 return false;
2890 }
2891
2892 return true;
2893}
2894
Jamie Madillc29968b2016-01-20 11:17:23 -05002895bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2896 GLenum target,
2897 GLint level,
2898 GLenum internalformat,
2899 bool isSubImage,
2900 GLint xoffset,
2901 GLint yoffset,
2902 GLint zoffset,
2903 GLint x,
2904 GLint y,
2905 GLsizei width,
2906 GLsizei height,
2907 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002908 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002909{
Jamie Madill560a8d82014-05-21 13:06:20 -04002910 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2911 {
Jamie Madill437fa652016-05-03 15:13:24 -04002912 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002913 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002914 }
2915
He Yunchaoced53ae2016-11-29 15:00:51 +08002916 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2917 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002918 {
Jamie Madill437fa652016-05-03 15:13:24 -04002919 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002920 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002921 }
2922
2923 if (border != 0)
2924 {
Jamie Madill437fa652016-05-03 15:13:24 -04002925 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002926 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002927 }
2928
2929 if (!ValidMipLevel(context, target, level))
2930 {
Jamie Madill437fa652016-05-03 15:13:24 -04002931 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002932 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002933 }
2934
Jamie Madill51f40ec2016-06-15 14:06:00 -04002935 const auto &state = context->getGLState();
2936 auto readFramebuffer = state.getReadFramebuffer();
2937 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002938 {
Jamie Madill437fa652016-05-03 15:13:24 -04002939 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002940 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002941 }
2942
Jamie Madill51f40ec2016-06-15 14:06:00 -04002943 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002944 {
Jamie Madill437fa652016-05-03 15:13:24 -04002945 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002946 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002947 }
2948
Martin Radev138064f2016-07-15 12:03:41 +03002949 if (readFramebuffer->getReadBufferState() == GL_NONE)
2950 {
2951 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2952 return false;
2953 }
2954
Geoff Langaae65a42014-05-26 12:43:44 -04002955 const gl::Caps &caps = context->getCaps();
2956
Geoff Langaae65a42014-05-26 12:43:44 -04002957 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002958 switch (target)
2959 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002960 case GL_TEXTURE_2D:
2961 maxDimension = caps.max2DTextureSize;
2962 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002963
He Yunchaoced53ae2016-11-29 15:00:51 +08002964 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2965 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2966 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2967 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2968 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2969 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2970 maxDimension = caps.maxCubeMapTextureSize;
2971 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002972
He Yunchaoced53ae2016-11-29 15:00:51 +08002973 case GL_TEXTURE_2D_ARRAY:
2974 maxDimension = caps.max2DTextureSize;
2975 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002976
He Yunchaoced53ae2016-11-29 15:00:51 +08002977 case GL_TEXTURE_3D:
2978 maxDimension = caps.max3DTextureSize;
2979 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002980
He Yunchaoced53ae2016-11-29 15:00:51 +08002981 default:
2982 context->handleError(Error(GL_INVALID_ENUM));
2983 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002984 }
2985
Jamie Madillc29968b2016-01-20 11:17:23 -05002986 gl::Texture *texture =
2987 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002988 if (!texture)
2989 {
Jamie Madill437fa652016-05-03 15:13:24 -04002990 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002991 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002992 }
2993
Geoff Lang69cce582015-09-17 13:20:36 -04002994 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002995 {
Jamie Madill437fa652016-05-03 15:13:24 -04002996 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002997 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002998 }
2999
Geoff Lang5d601382014-07-22 15:14:06 -04003000 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
3001
3002 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003003 {
Jamie Madill437fa652016-05-03 15:13:24 -04003004 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003005 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003006 }
3007
Geoff Langa9be0dc2014-12-17 12:34:40 -05003008 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003009 {
Jamie Madill437fa652016-05-03 15:13:24 -04003010 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003011 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003012 }
3013
3014 if (isSubImage)
3015 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003016 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3017 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3018 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003019 {
Jamie Madill437fa652016-05-03 15:13:24 -04003020 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003021 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003022 }
3023 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003024 else
3025 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003026 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003027 {
Jamie Madill437fa652016-05-03 15:13:24 -04003028 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003029 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003030 }
3031
Geoff Langeb66a6e2016-10-31 13:06:12 -04003032 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003033 {
Jamie Madill437fa652016-05-03 15:13:24 -04003034 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003035 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003036 }
3037
3038 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003039 if (static_cast<int>(width) > maxLevelDimension ||
3040 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003041 {
Jamie Madill437fa652016-05-03 15:13:24 -04003042 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003043 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003044 }
3045 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003046
Jamie Madill0c8abca2016-07-22 20:21:26 -04003047 if (textureFormatOut)
3048 {
3049 *textureFormatOut = texture->getFormat(target, level);
3050 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003051 return true;
3052}
3053
Jiajia Qind9671222016-11-29 16:30:31 +08003054bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003055{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003056 switch (mode)
3057 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003058 case GL_POINTS:
3059 case GL_LINES:
3060 case GL_LINE_LOOP:
3061 case GL_LINE_STRIP:
3062 case GL_TRIANGLES:
3063 case GL_TRIANGLE_STRIP:
3064 case GL_TRIANGLE_FAN:
3065 break;
3066 default:
3067 context->handleError(Error(GL_INVALID_ENUM));
3068 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003069 }
3070
Jamie Madill250d33f2014-06-06 17:09:03 -04003071 if (count < 0)
3072 {
Jamie Madill437fa652016-05-03 15:13:24 -04003073 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003074 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003075 }
3076
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003077 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003078
Jamie Madill250d33f2014-06-06 17:09:03 -04003079 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003080 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003081 {
Jamie Madill437fa652016-05-03 15:13:24 -04003082 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003083 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003084 }
3085
Jamie Madill51f40ec2016-06-15 14:06:00 -04003086 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04003087 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04003088 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04003089 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
He Yunchaoced53ae2016-11-29 15:00:51 +08003090 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
3091 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003092 const DepthStencilState &depthStencilState = state.getDepthStencilState();
3093 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3094 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04003095 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04003096 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3097 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04003098 {
3099 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3100 // Section 6.10 of the WebGL 1.0 spec
He Yunchaoced53ae2016-11-29 15:00:51 +08003101 ERR("This ANGLE implementation does not support separate front/back stencil "
Geoff Lang3a86ad32015-09-01 11:47:05 -04003102 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04003103 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003104 return false;
3105 }
Jamie Madillac528012014-06-20 13:21:23 -04003106 }
3107
Jamie Madill51f40ec2016-06-15 14:06:00 -04003108 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003109 {
Jamie Madill437fa652016-05-03 15:13:24 -04003110 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003111 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003112 }
3113
Geoff Lang7dd2e102014-11-10 15:19:26 -05003114 gl::Program *program = state.getProgram();
3115 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003116 {
Jamie Madill437fa652016-05-03 15:13:24 -04003117 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003118 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003119 }
3120
Geoff Lang7dd2e102014-11-10 15:19:26 -05003121 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003122 {
Jamie Madill437fa652016-05-03 15:13:24 -04003123 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003124 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003125 }
3126
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003127 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003128 for (unsigned int uniformBlockIndex = 0;
3129 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003130 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003131 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003132 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003133 const OffsetBindingPointer<Buffer> &uniformBuffer =
3134 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003135
Geoff Lang5d124a62015-09-15 13:03:27 -04003136 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003137 {
3138 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003139 context->handleError(
3140 Error(GL_INVALID_OPERATION,
3141 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003142 return false;
3143 }
3144
Geoff Lang5d124a62015-09-15 13:03:27 -04003145 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003146 if (uniformBufferSize == 0)
3147 {
3148 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003149 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003150 }
3151
Jamie Madill62d31cb2015-09-11 13:25:51 -04003152 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003153 {
3154 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003155 context->handleError(
3156 Error(GL_INVALID_OPERATION,
3157 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003158 return false;
3159 }
3160 }
3161
Jamie Madill250d33f2014-06-06 17:09:03 -04003162 // No-op if zero count
3163 return (count > 0);
3164}
3165
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003166bool ValidateDrawArrays(ValidationContext *context,
3167 GLenum mode,
3168 GLint first,
3169 GLsizei count,
3170 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003171{
Jamie Madillfd716582014-06-06 17:09:04 -04003172 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003173 {
Jamie Madill437fa652016-05-03 15:13:24 -04003174 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003175 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003176 }
3177
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003178 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003179 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003180 if (curTransformFeedback && curTransformFeedback->isActive() &&
3181 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003182 {
3183 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003184 // that does not match the current transform feedback object's draw mode (if transform
3185 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003186 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003187 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003188 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003189 }
3190
Jiajia Qind9671222016-11-29 16:30:31 +08003191 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003192 {
3193 return false;
3194 }
3195
Corentin Wallez92db6942016-12-09 13:10:36 -05003196 CheckedNumeric<GLint> maxVertex = first;
3197 maxVertex += count;
3198 maxVertex -= 1;
3199
3200 if (!maxVertex.IsValid())
3201 {
3202 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3203 return false;
3204 }
3205
3206 if (!ValidateDrawAttribs(context, primcount, maxVertex.ValueOrDie(), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003207 {
3208 return false;
3209 }
3210
3211 return true;
3212}
3213
He Yunchaoced53ae2016-11-29 15:00:51 +08003214bool ValidateDrawArraysInstanced(Context *context,
3215 GLenum mode,
3216 GLint first,
3217 GLsizei count,
3218 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003219{
3220 if (primcount < 0)
3221 {
Jamie Madill437fa652016-05-03 15:13:24 -04003222 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003223 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003224 }
3225
Jamie Madill2b976812014-08-25 15:47:49 -04003226 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003227 {
3228 return false;
3229 }
3230
3231 // No-op if zero primitive count
3232 return (primcount > 0);
3233}
3234
Geoff Lang87a93302014-09-16 13:29:43 -04003235static bool ValidateDrawInstancedANGLE(Context *context)
3236{
3237 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003238 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003239
Geoff Lang7dd2e102014-11-10 15:19:26 -05003240 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003241
3242 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003243 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003244 {
3245 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003246 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003247 {
3248 return true;
3249 }
3250 }
3251
Jamie Madill437fa652016-05-03 15:13:24 -04003252 context->handleError(Error(GL_INVALID_OPERATION,
3253 "ANGLE_instanced_arrays requires that at least one active attribute"
3254 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003255 return false;
3256}
3257
He Yunchaoced53ae2016-11-29 15:00:51 +08003258bool ValidateDrawArraysInstancedANGLE(Context *context,
3259 GLenum mode,
3260 GLint first,
3261 GLsizei count,
3262 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003263{
3264 if (!ValidateDrawInstancedANGLE(context))
3265 {
3266 return false;
3267 }
3268
3269 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3270}
3271
Jiajia Qind9671222016-11-29 16:30:31 +08003272bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003273{
Jamie Madill250d33f2014-06-06 17:09:03 -04003274 switch (type)
3275 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003276 case GL_UNSIGNED_BYTE:
3277 case GL_UNSIGNED_SHORT:
3278 break;
3279 case GL_UNSIGNED_INT:
3280 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3281 {
3282 context->handleError(Error(GL_INVALID_ENUM));
3283 return false;
3284 }
3285 break;
3286 default:
3287 context->handleError(Error(GL_INVALID_ENUM));
3288 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003289 }
3290
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003291 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003292
3293 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003294 if (curTransformFeedback && curTransformFeedback->isActive() &&
3295 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003296 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003297 // It is an invalid operation to call DrawElements, DrawRangeElements or
3298 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003299 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003300 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003301 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003302 }
3303
Jiajia Qind9671222016-11-29 16:30:31 +08003304 return true;
3305}
3306
3307bool ValidateDrawElements(ValidationContext *context,
3308 GLenum mode,
3309 GLsizei count,
3310 GLenum type,
3311 const GLvoid *indices,
3312 GLsizei primcount,
3313 IndexRange *indexRangeOut)
3314{
3315 if (!ValidateDrawElementsBase(context, type))
3316 return false;
3317
3318 const State &state = context->getGLState();
3319
Jamie Madill250d33f2014-06-06 17:09:03 -04003320 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003321 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003322 {
Jamie Madill437fa652016-05-03 15:13:24 -04003323 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003324 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003325 }
3326
He Yunchaoced53ae2016-11-29 15:00:51 +08003327 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003328 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003329
Jamie Madillae3000b2014-08-25 15:47:51 -04003330 if (elementArrayBuffer)
3331 {
3332 const gl::Type &typeInfo = gl::GetTypeInfo(type);
3333
3334 GLint64 offset = reinterpret_cast<GLint64>(indices);
He Yunchaoced53ae2016-11-29 15:00:51 +08003335 GLint64 byteCount =
3336 static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count) + offset;
Jamie Madillae3000b2014-08-25 15:47:51 -04003337
3338 // check for integer overflows
3339 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
3340 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3341 {
Jamie Madill437fa652016-05-03 15:13:24 -04003342 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04003343 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003344 }
3345
3346 // Check for reading past the end of the bound buffer object
3347 if (byteCount > elementArrayBuffer->getSize())
3348 {
Jamie Madill437fa652016-05-03 15:13:24 -04003349 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003350 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003351 }
3352 }
Corentin Wallez327411e2016-12-09 11:09:17 -05003353 else if (context->getExtensions().webglCompatibility && count > 0)
3354 {
3355 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3356 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3357 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3358 context->handleError(
3359 Error(GL_INVALID_OPERATION, "There is no element array buffer bound and count > 0."));
3360 return false;
3361 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003362 else if (!indices)
3363 {
Corentin Wallez327411e2016-12-09 11:09:17 -05003364 // This is an application error that would normally result in a crash,
3365 // but we catch it and return an error
3366 context->handleError(
3367 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003368 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003369 }
3370
Jiajia Qind9671222016-11-29 16:30:31 +08003371 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003372 {
3373 return false;
3374 }
3375
Jamie Madill2b976812014-08-25 15:47:49 -04003376 // Use max index to validate if our vertex buffers are large enough for the pull.
3377 // TODO: offer fast path, with disabled index validation.
3378 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3379 if (elementArrayBuffer)
3380 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003381 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003382 Error error =
3383 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3384 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003385 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003386 {
Jamie Madill437fa652016-05-03 15:13:24 -04003387 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003388 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003389 }
3390 }
3391 else
3392 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003393 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003394 }
3395
Jamie Madille79b1e12015-11-04 16:36:37 -05003396 // If we use an index greater than our maximum supported index range, return an error.
3397 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3398 // return an error if possible here.
3399 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3400 {
Jamie Madill437fa652016-05-03 15:13:24 -04003401 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003402 return false;
3403 }
3404
Corentin Wallez92db6942016-12-09 13:10:36 -05003405 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3406 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003407 {
3408 return false;
3409 }
3410
Geoff Lang3edfe032015-09-04 16:38:24 -04003411 // No op if there are no real indices in the index data (all are primitive restart).
3412 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003413}
3414
Geoff Langb1196682014-07-23 13:47:29 -04003415bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003416 GLenum mode,
3417 GLsizei count,
3418 GLenum type,
3419 const GLvoid *indices,
3420 GLsizei primcount,
3421 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003422{
3423 if (primcount < 0)
3424 {
Jamie Madill437fa652016-05-03 15:13:24 -04003425 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003426 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003427 }
3428
Jamie Madill2b976812014-08-25 15:47:49 -04003429 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003430 {
3431 return false;
3432 }
3433
3434 // No-op zero primitive count
3435 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003436}
3437
Geoff Lang3edfe032015-09-04 16:38:24 -04003438bool ValidateDrawElementsInstancedANGLE(Context *context,
3439 GLenum mode,
3440 GLsizei count,
3441 GLenum type,
3442 const GLvoid *indices,
3443 GLsizei primcount,
3444 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003445{
3446 if (!ValidateDrawInstancedANGLE(context))
3447 {
3448 return false;
3449 }
3450
He Yunchaoced53ae2016-11-29 15:00:51 +08003451 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3452 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003453}
3454
He Yunchaoced53ae2016-11-29 15:00:51 +08003455bool ValidateFramebufferTextureBase(Context *context,
3456 GLenum target,
3457 GLenum attachment,
3458 GLuint texture,
3459 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003460{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003461 if (!ValidFramebufferTarget(target))
3462 {
Jamie Madill437fa652016-05-03 15:13:24 -04003463 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003464 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003465 }
3466
3467 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003468 {
3469 return false;
3470 }
3471
Jamie Madill55ec3b12014-07-03 10:38:57 -04003472 if (texture != 0)
3473 {
3474 gl::Texture *tex = context->getTexture(texture);
3475
3476 if (tex == NULL)
3477 {
Jamie Madill437fa652016-05-03 15:13:24 -04003478 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003479 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003480 }
3481
3482 if (level < 0)
3483 {
Jamie Madill437fa652016-05-03 15:13:24 -04003484 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003485 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003486 }
3487 }
3488
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003489 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003490 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003491
Jamie Madill84115c92015-04-23 15:00:07 -04003492 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003493 {
Jamie Madill437fa652016-05-03 15:13:24 -04003494 context->handleError(
3495 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003496 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003497 }
3498
3499 return true;
3500}
3501
He Yunchaoced53ae2016-11-29 15:00:51 +08003502bool ValidateFramebufferTexture2D(Context *context,
3503 GLenum target,
3504 GLenum attachment,
3505 GLenum textarget,
3506 GLuint texture,
3507 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003508{
He Yunchaoced53ae2016-11-29 15:00:51 +08003509 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3510 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003511 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3512 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003513 {
Jamie Madill437fa652016-05-03 15:13:24 -04003514 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003515 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003516 }
3517
3518 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003519 {
3520 return false;
3521 }
3522
Jamie Madill55ec3b12014-07-03 10:38:57 -04003523 if (texture != 0)
3524 {
3525 gl::Texture *tex = context->getTexture(texture);
3526 ASSERT(tex);
3527
Jamie Madill2a6564e2014-07-11 09:53:19 -04003528 const gl::Caps &caps = context->getCaps();
3529
Jamie Madill55ec3b12014-07-03 10:38:57 -04003530 switch (textarget)
3531 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003532 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003533 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003534 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003535 {
Jamie Madill437fa652016-05-03 15:13:24 -04003536 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003537 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003538 }
3539 if (tex->getTarget() != GL_TEXTURE_2D)
3540 {
Jamie Madill437fa652016-05-03 15:13:24 -04003541 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003542 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003543 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003544 }
3545 break;
3546
He Yunchaoced53ae2016-11-29 15:00:51 +08003547 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3548 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3549 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3550 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3551 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3552 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003553 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003554 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003555 {
Jamie Madill437fa652016-05-03 15:13:24 -04003556 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003557 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003558 }
3559 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3560 {
Jamie Madill437fa652016-05-03 15:13:24 -04003561 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003562 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003563 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003564 }
3565 break;
3566
He Yunchaoced53ae2016-11-29 15:00:51 +08003567 default:
3568 context->handleError(Error(GL_INVALID_ENUM));
3569 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003570 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003571
Jamie Madilla3944d42016-07-22 22:13:26 -04003572 const Format &format = tex->getFormat(textarget, level);
3573 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003574 {
Jamie Madill437fa652016-05-03 15:13:24 -04003575 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003576 return false;
3577 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003578 }
3579
Jamie Madill570f7c82014-07-03 10:38:54 -04003580 return true;
3581}
3582
Geoff Langb1196682014-07-23 13:47:29 -04003583bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003584{
3585 if (program == 0)
3586 {
Jamie Madill437fa652016-05-03 15:13:24 -04003587 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003588 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003589 }
3590
Dian Xiang769769a2015-09-09 15:20:08 -07003591 gl::Program *programObject = GetValidProgram(context, program);
3592 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003593 {
3594 return false;
3595 }
3596
Jamie Madill0063c512014-08-25 15:47:53 -04003597 if (!programObject || !programObject->isLinked())
3598 {
Jamie Madill437fa652016-05-03 15:13:24 -04003599 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003600 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003601 }
3602
Geoff Lang7dd2e102014-11-10 15:19:26 -05003603 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003604 {
Jamie Madill437fa652016-05-03 15:13:24 -04003605 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003606 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003607 }
3608
Jamie Madill0063c512014-08-25 15:47:53 -04003609 return true;
3610}
3611
He Yunchaoced53ae2016-11-29 15:00:51 +08003612bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003613{
3614 return ValidateGetUniformBase(context, program, location);
3615}
3616
He Yunchaoced53ae2016-11-29 15:00:51 +08003617bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003618{
Jamie Madill78f41802014-08-25 15:47:55 -04003619 return ValidateGetUniformBase(context, program, location);
3620}
3621
Geoff Langf41d0ee2016-10-07 13:04:23 -04003622static bool ValidateSizedGetUniform(Context *context,
3623 GLuint program,
3624 GLint location,
3625 GLsizei bufSize,
3626 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003627{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003628 if (length)
3629 {
3630 *length = 0;
3631 }
3632
Jamie Madill78f41802014-08-25 15:47:55 -04003633 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003634 {
Jamie Madill78f41802014-08-25 15:47:55 -04003635 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003636 }
3637
Geoff Langf41d0ee2016-10-07 13:04:23 -04003638 if (bufSize < 0)
3639 {
3640 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3641 return false;
3642 }
3643
Jamie Madilla502c742014-08-28 17:19:13 -04003644 gl::Program *programObject = context->getProgram(program);
3645 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003646
Jamie Madill78f41802014-08-25 15:47:55 -04003647 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003648 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003649 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003650 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003651 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003652 context->handleError(
3653 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003654 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003655 }
3656
Geoff Langf41d0ee2016-10-07 13:04:23 -04003657 if (length)
3658 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003659 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003660 }
3661
Jamie Madill0063c512014-08-25 15:47:53 -04003662 return true;
3663}
3664
He Yunchaoced53ae2016-11-29 15:00:51 +08003665bool ValidateGetnUniformfvEXT(Context *context,
3666 GLuint program,
3667 GLint location,
3668 GLsizei bufSize,
3669 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003670{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003671 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003672}
3673
He Yunchaoced53ae2016-11-29 15:00:51 +08003674bool ValidateGetnUniformivEXT(Context *context,
3675 GLuint program,
3676 GLint location,
3677 GLsizei bufSize,
3678 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003679{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003680 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3681}
3682
3683bool ValidateGetUniformfvRobustANGLE(Context *context,
3684 GLuint program,
3685 GLint location,
3686 GLsizei bufSize,
3687 GLsizei *length,
3688 GLfloat *params)
3689{
3690 if (!ValidateRobustEntryPoint(context, bufSize))
3691 {
3692 return false;
3693 }
3694
3695 // bufSize is validated in ValidateSizedGetUniform
3696 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3697}
3698
3699bool ValidateGetUniformivRobustANGLE(Context *context,
3700 GLuint program,
3701 GLint location,
3702 GLsizei bufSize,
3703 GLsizei *length,
3704 GLint *params)
3705{
3706 if (!ValidateRobustEntryPoint(context, bufSize))
3707 {
3708 return false;
3709 }
3710
3711 // bufSize is validated in ValidateSizedGetUniform
3712 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3713}
3714
3715bool ValidateGetUniformuivRobustANGLE(Context *context,
3716 GLuint program,
3717 GLint location,
3718 GLsizei bufSize,
3719 GLsizei *length,
3720 GLuint *params)
3721{
3722 if (!ValidateRobustEntryPoint(context, bufSize))
3723 {
3724 return false;
3725 }
3726
3727 if (context->getClientMajorVersion() < 3)
3728 {
3729 context->handleError(
3730 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3731 return false;
3732 }
3733
3734 // bufSize is validated in ValidateSizedGetUniform
3735 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003736}
3737
He Yunchaoced53ae2016-11-29 15:00:51 +08003738bool ValidateDiscardFramebufferBase(Context *context,
3739 GLenum target,
3740 GLsizei numAttachments,
3741 const GLenum *attachments,
3742 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003743{
3744 if (numAttachments < 0)
3745 {
Jamie Madill437fa652016-05-03 15:13:24 -04003746 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003747 return false;
3748 }
3749
3750 for (GLsizei i = 0; i < numAttachments; ++i)
3751 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003752 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003753 {
3754 if (defaultFramebuffer)
3755 {
Jamie Madill437fa652016-05-03 15:13:24 -04003756 context->handleError(Error(
3757 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003758 return false;
3759 }
3760
3761 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3762 {
Jamie Madill437fa652016-05-03 15:13:24 -04003763 context->handleError(Error(GL_INVALID_OPERATION,
3764 "Requested color attachment is greater than the maximum "
3765 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003766 return false;
3767 }
3768 }
3769 else
3770 {
3771 switch (attachments[i])
3772 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003773 case GL_DEPTH_ATTACHMENT:
3774 case GL_STENCIL_ATTACHMENT:
3775 case GL_DEPTH_STENCIL_ATTACHMENT:
3776 if (defaultFramebuffer)
3777 {
3778 context->handleError(
3779 Error(GL_INVALID_ENUM,
3780 "Invalid attachment when the default framebuffer is bound"));
3781 return false;
3782 }
3783 break;
3784 case GL_COLOR:
3785 case GL_DEPTH:
3786 case GL_STENCIL:
3787 if (!defaultFramebuffer)
3788 {
3789 context->handleError(
3790 Error(GL_INVALID_ENUM,
3791 "Invalid attachment when the default framebuffer is not bound"));
3792 return false;
3793 }
3794 break;
3795 default:
3796 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003797 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003798 }
3799 }
3800 }
3801
3802 return true;
3803}
3804
Austin Kinross6ee1e782015-05-29 17:05:37 -07003805bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3806{
3807 // Note that debug marker calls must not set error state
3808
3809 if (length < 0)
3810 {
3811 return false;
3812 }
3813
3814 if (marker == nullptr)
3815 {
3816 return false;
3817 }
3818
3819 return true;
3820}
3821
3822bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3823{
3824 // Note that debug marker calls must not set error state
3825
3826 if (length < 0)
3827 {
3828 return false;
3829 }
3830
3831 if (length > 0 && marker == nullptr)
3832 {
3833 return false;
3834 }
3835
3836 return true;
3837}
3838
Geoff Langdcab33b2015-07-21 13:03:16 -04003839bool ValidateEGLImageTargetTexture2DOES(Context *context,
3840 egl::Display *display,
3841 GLenum target,
3842 egl::Image *image)
3843{
Geoff Langa8406172015-07-21 16:53:39 -04003844 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3845 {
Jamie Madill437fa652016-05-03 15:13:24 -04003846 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003847 return false;
3848 }
3849
3850 switch (target)
3851 {
3852 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003853 if (!context->getExtensions().eglImage)
3854 {
3855 context->handleError(Error(
3856 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3857 }
3858 break;
3859
3860 case GL_TEXTURE_EXTERNAL_OES:
3861 if (!context->getExtensions().eglImageExternal)
3862 {
3863 context->handleError(Error(
3864 GL_INVALID_ENUM,
3865 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3866 }
Geoff Langa8406172015-07-21 16:53:39 -04003867 break;
3868
3869 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003870 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003871 return false;
3872 }
3873
3874 if (!display->isValidImage(image))
3875 {
Jamie Madill437fa652016-05-03 15:13:24 -04003876 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003877 return false;
3878 }
3879
3880 if (image->getSamples() > 0)
3881 {
Jamie Madill437fa652016-05-03 15:13:24 -04003882 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003883 "cannot create a 2D texture from a multisampled EGL image."));
3884 return false;
3885 }
3886
Jamie Madilla3944d42016-07-22 22:13:26 -04003887 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003888 if (!textureCaps.texturable)
3889 {
Jamie Madill437fa652016-05-03 15:13:24 -04003890 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003891 "EGL image internal format is not supported as a texture."));
3892 return false;
3893 }
3894
Geoff Langdcab33b2015-07-21 13:03:16 -04003895 return true;
3896}
3897
3898bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3899 egl::Display *display,
3900 GLenum target,
3901 egl::Image *image)
3902{
Geoff Langa8406172015-07-21 16:53:39 -04003903 if (!context->getExtensions().eglImage)
3904 {
Jamie Madill437fa652016-05-03 15:13:24 -04003905 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003906 return false;
3907 }
3908
3909 switch (target)
3910 {
3911 case GL_RENDERBUFFER:
3912 break;
3913
3914 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003915 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003916 return false;
3917 }
3918
3919 if (!display->isValidImage(image))
3920 {
Jamie Madill437fa652016-05-03 15:13:24 -04003921 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003922 return false;
3923 }
3924
Jamie Madilla3944d42016-07-22 22:13:26 -04003925 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003926 if (!textureCaps.renderable)
3927 {
Jamie Madill437fa652016-05-03 15:13:24 -04003928 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003929 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3930 return false;
3931 }
3932
Geoff Langdcab33b2015-07-21 13:03:16 -04003933 return true;
3934}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003935
3936bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3937{
Geoff Lang36167ab2015-12-07 10:27:14 -05003938 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003939 {
3940 // The default VAO should always exist
3941 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003942 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003943 return false;
3944 }
3945
3946 return true;
3947}
3948
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003949bool ValidateLinkProgram(Context *context, GLuint program)
3950{
3951 if (context->hasActiveTransformFeedback(program))
3952 {
3953 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003954 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003955 "Cannot link program while program is associated with an active "
3956 "transform feedback object."));
3957 return false;
3958 }
3959 return true;
3960}
3961
Geoff Langc5629752015-12-07 16:29:04 -05003962bool ValidateProgramBinaryBase(Context *context,
3963 GLuint program,
3964 GLenum binaryFormat,
3965 const void *binary,
3966 GLint length)
3967{
3968 Program *programObject = GetValidProgram(context, program);
3969 if (programObject == nullptr)
3970 {
3971 return false;
3972 }
3973
3974 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3975 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3976 programBinaryFormats.end())
3977 {
Jamie Madill437fa652016-05-03 15:13:24 -04003978 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05003979 return false;
3980 }
3981
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003982 if (context->hasActiveTransformFeedback(program))
3983 {
3984 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003985 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003986 "Cannot change program binary while program is associated with "
3987 "an active transform feedback object."));
3988 return false;
3989 }
3990
Geoff Langc5629752015-12-07 16:29:04 -05003991 return true;
3992}
3993
3994bool ValidateGetProgramBinaryBase(Context *context,
3995 GLuint program,
3996 GLsizei bufSize,
3997 GLsizei *length,
3998 GLenum *binaryFormat,
3999 void *binary)
4000{
4001 Program *programObject = GetValidProgram(context, program);
4002 if (programObject == nullptr)
4003 {
4004 return false;
4005 }
4006
4007 if (!programObject->isLinked())
4008 {
Jamie Madill437fa652016-05-03 15:13:24 -04004009 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004010 return false;
4011 }
4012
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004013 if (context->getCaps().programBinaryFormats.empty())
4014 {
4015 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4016 return false;
4017 }
4018
Geoff Langc5629752015-12-07 16:29:04 -05004019 return true;
4020}
Jamie Madillc29968b2016-01-20 11:17:23 -05004021
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004022bool ValidateUseProgram(Context *context, GLuint program)
4023{
4024 if (program != 0)
4025 {
4026 Program *programObject = context->getProgram(program);
4027 if (!programObject)
4028 {
4029 // ES 3.1.0 section 7.3 page 72
4030 if (context->getShader(program))
4031 {
Jamie Madill437fa652016-05-03 15:13:24 -04004032 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004033 Error(GL_INVALID_OPERATION,
4034 "Attempted to use a single shader instead of a shader program."));
4035 return false;
4036 }
4037 else
4038 {
Jamie Madill437fa652016-05-03 15:13:24 -04004039 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004040 return false;
4041 }
4042 }
4043 if (!programObject->isLinked())
4044 {
Jamie Madill437fa652016-05-03 15:13:24 -04004045 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004046 return false;
4047 }
4048 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004049 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004050 {
4051 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004052 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004053 Error(GL_INVALID_OPERATION,
4054 "Cannot change active program while transform feedback is unpaused."));
4055 return false;
4056 }
4057
4058 return true;
4059}
4060
Jamie Madillc29968b2016-01-20 11:17:23 -05004061bool ValidateCopyTexImage2D(ValidationContext *context,
4062 GLenum target,
4063 GLint level,
4064 GLenum internalformat,
4065 GLint x,
4066 GLint y,
4067 GLsizei width,
4068 GLsizei height,
4069 GLint border)
4070{
Martin Radev1be913c2016-07-11 17:59:16 +03004071 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004072 {
4073 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4074 0, x, y, width, height, border);
4075 }
4076
Martin Radev1be913c2016-07-11 17:59:16 +03004077 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004078 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4079 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004080}
Jamie Madillc29968b2016-01-20 11:17:23 -05004081
4082bool ValidateFramebufferRenderbuffer(Context *context,
4083 GLenum target,
4084 GLenum attachment,
4085 GLenum renderbuffertarget,
4086 GLuint renderbuffer)
4087{
4088 if (!ValidFramebufferTarget(target) ||
4089 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4090 {
Jamie Madill437fa652016-05-03 15:13:24 -04004091 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004092 return false;
4093 }
4094
4095 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4096 renderbuffertarget, renderbuffer);
4097}
4098
4099bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4100{
4101 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4102 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4103 {
Jamie Madill437fa652016-05-03 15:13:24 -04004104 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004105 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4106 return false;
4107 }
4108
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004109 ASSERT(context->getGLState().getDrawFramebuffer());
4110 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004111 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4112
4113 // This should come first before the check for the default frame buffer
4114 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4115 // rather than INVALID_OPERATION
4116 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4117 {
4118 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4119
4120 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004121 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4122 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004123 {
4124 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004125 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4126 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4127 // 3.1 is still a bit ambiguous about the error, but future specs are
4128 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004129 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004130 return false;
4131 }
4132 else if (bufs[colorAttachment] >= maxColorAttachment)
4133 {
Jamie Madill437fa652016-05-03 15:13:24 -04004134 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004135 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004136 return false;
4137 }
4138 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4139 frameBufferId != 0)
4140 {
4141 // INVALID_OPERATION-GL is bound to buffer and ith argument
4142 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004143 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004144 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4145 return false;
4146 }
4147 }
4148
4149 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4150 // and n is not 1 or bufs is bound to value other than BACK and NONE
4151 if (frameBufferId == 0)
4152 {
4153 if (n != 1)
4154 {
Jamie Madill437fa652016-05-03 15:13:24 -04004155 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004156 "n must be 1 when GL is bound to the default framebuffer"));
4157 return false;
4158 }
4159
4160 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4161 {
Jamie Madill437fa652016-05-03 15:13:24 -04004162 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004163 GL_INVALID_OPERATION,
4164 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4165 return false;
4166 }
4167 }
4168
4169 return true;
4170}
4171
4172bool ValidateCopyTexSubImage2D(Context *context,
4173 GLenum target,
4174 GLint level,
4175 GLint xoffset,
4176 GLint yoffset,
4177 GLint x,
4178 GLint y,
4179 GLsizei width,
4180 GLsizei height)
4181{
Martin Radev1be913c2016-07-11 17:59:16 +03004182 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004183 {
4184 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4185 yoffset, x, y, width, height, 0);
4186 }
4187
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004188 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4189 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004190}
4191
Geoff Lang496c02d2016-10-20 11:38:11 -07004192bool ValidateGetBufferPointervBase(Context *context,
4193 GLenum target,
4194 GLenum pname,
4195 GLsizei *length,
4196 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004197{
Geoff Lang496c02d2016-10-20 11:38:11 -07004198 if (length)
4199 {
4200 *length = 0;
4201 }
4202
4203 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4204 {
4205 context->handleError(
4206 Error(GL_INVALID_OPERATION,
4207 "Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
4208 return false;
4209 }
4210
Olli Etuaho4f667482016-03-30 15:56:35 +03004211 if (!ValidBufferTarget(context, target))
4212 {
Jamie Madill437fa652016-05-03 15:13:24 -04004213 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004214 return false;
4215 }
4216
Geoff Lang496c02d2016-10-20 11:38:11 -07004217 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004218 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004219 case GL_BUFFER_MAP_POINTER:
4220 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004221
Geoff Lang496c02d2016-10-20 11:38:11 -07004222 default:
4223 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4224 return false;
4225 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004226
4227 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4228 // target bound to zero generate an INVALID_OPERATION error."
4229 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004230 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004231 {
Jamie Madill437fa652016-05-03 15:13:24 -04004232 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004233 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4234 return false;
4235 }
4236
Geoff Lang496c02d2016-10-20 11:38:11 -07004237 if (length)
4238 {
4239 *length = 1;
4240 }
4241
Olli Etuaho4f667482016-03-30 15:56:35 +03004242 return true;
4243}
4244
4245bool ValidateUnmapBufferBase(Context *context, GLenum target)
4246{
4247 if (!ValidBufferTarget(context, target))
4248 {
Jamie Madill437fa652016-05-03 15:13:24 -04004249 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004250 return false;
4251 }
4252
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004253 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004254
4255 if (buffer == nullptr || !buffer->isMapped())
4256 {
Jamie Madill437fa652016-05-03 15:13:24 -04004257 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004258 return false;
4259 }
4260
4261 return true;
4262}
4263
4264bool ValidateMapBufferRangeBase(Context *context,
4265 GLenum target,
4266 GLintptr offset,
4267 GLsizeiptr length,
4268 GLbitfield access)
4269{
4270 if (!ValidBufferTarget(context, target))
4271 {
Jamie Madill437fa652016-05-03 15:13:24 -04004272 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004273 return false;
4274 }
4275
4276 if (offset < 0 || length < 0)
4277 {
Jamie Madill437fa652016-05-03 15:13:24 -04004278 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004279 return false;
4280 }
4281
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004282 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004283
4284 if (!buffer)
4285 {
Jamie Madill437fa652016-05-03 15:13:24 -04004286 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004287 return false;
4288 }
4289
4290 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004291 CheckedNumeric<size_t> checkedOffset(offset);
4292 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004293
Jamie Madille2e406c2016-06-02 13:04:10 -04004294 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004295 {
Jamie Madill437fa652016-05-03 15:13:24 -04004296 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004297 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4298 return false;
4299 }
4300
4301 // Check for invalid bits in the mask
4302 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4303 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4304 GL_MAP_UNSYNCHRONIZED_BIT;
4305
4306 if (access & ~(allAccessBits))
4307 {
Jamie Madill437fa652016-05-03 15:13:24 -04004308 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004309 return false;
4310 }
4311
4312 if (length == 0)
4313 {
Jamie Madill437fa652016-05-03 15:13:24 -04004314 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004315 return false;
4316 }
4317
4318 if (buffer->isMapped())
4319 {
Jamie Madill437fa652016-05-03 15:13:24 -04004320 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004321 return false;
4322 }
4323
4324 // Check for invalid bit combinations
4325 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4326 {
Jamie Madill437fa652016-05-03 15:13:24 -04004327 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004328 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4329 return false;
4330 }
4331
4332 GLbitfield writeOnlyBits =
4333 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4334
4335 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4336 {
Jamie Madill437fa652016-05-03 15:13:24 -04004337 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004338 "Invalid access bits when mapping buffer for reading: 0x%X.",
4339 access));
4340 return false;
4341 }
4342
4343 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4344 {
Jamie Madill437fa652016-05-03 15:13:24 -04004345 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004346 GL_INVALID_OPERATION,
4347 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4348 return false;
4349 }
4350 return true;
4351}
4352
4353bool ValidateFlushMappedBufferRangeBase(Context *context,
4354 GLenum target,
4355 GLintptr offset,
4356 GLsizeiptr length)
4357{
4358 if (offset < 0 || length < 0)
4359 {
Jamie Madill437fa652016-05-03 15:13:24 -04004360 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004361 return false;
4362 }
4363
4364 if (!ValidBufferTarget(context, target))
4365 {
Jamie Madill437fa652016-05-03 15:13:24 -04004366 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004367 return false;
4368 }
4369
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004370 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004371
4372 if (buffer == nullptr)
4373 {
Jamie Madill437fa652016-05-03 15:13:24 -04004374 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004375 return false;
4376 }
4377
4378 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4379 {
Jamie Madill437fa652016-05-03 15:13:24 -04004380 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004381 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4382 return false;
4383 }
4384
4385 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004386 CheckedNumeric<size_t> checkedOffset(offset);
4387 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004388
Jamie Madille2e406c2016-06-02 13:04:10 -04004389 if (!checkedSize.IsValid() ||
4390 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004391 {
Jamie Madill437fa652016-05-03 15:13:24 -04004392 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004393 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4394 return false;
4395 }
4396
4397 return true;
4398}
4399
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004400bool ValidateGenerateMipmap(Context *context, GLenum target)
4401{
4402 if (!ValidTextureTarget(context, target))
4403 {
4404 context->handleError(Error(GL_INVALID_ENUM));
4405 return false;
4406 }
4407
4408 Texture *texture = context->getTargetTexture(target);
4409
4410 if (texture == nullptr)
4411 {
4412 context->handleError(Error(GL_INVALID_OPERATION));
4413 return false;
4414 }
4415
4416 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4417
4418 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4419 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4420 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4421 {
4422 context->handleError(Error(GL_INVALID_OPERATION));
4423 return false;
4424 }
4425
Jamie Madilla3944d42016-07-22 22:13:26 -04004426 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4427 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4428 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004429
4430 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4431 // unsized formats or that are color renderable and filterable. Since we do not track if
4432 // the texture was created with sized or unsized format (only sized formats are stored),
4433 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4434 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4435 // textures since they're the only texture format that can be created with unsized formats
4436 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4437 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004438 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4439 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004440 {
4441 context->handleError(Error(GL_INVALID_OPERATION));
4442 return false;
4443 }
4444
4445 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004446 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004447 {
4448 context->handleError(Error(GL_INVALID_OPERATION));
4449 return false;
4450 }
4451
4452 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004453 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004454 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4455 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4456 {
Geoff Lang55482a12016-11-21 16:54:01 -05004457 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004458 context->handleError(Error(GL_INVALID_OPERATION));
4459 return false;
4460 }
4461
4462 // Cube completeness check
4463 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4464 {
4465 context->handleError(Error(GL_INVALID_OPERATION));
4466 return false;
4467 }
4468
4469 return true;
4470}
4471
Olli Etuaho41997e72016-03-10 13:38:39 +02004472bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4473{
4474 return ValidateGenOrDelete(context, n);
4475}
4476
4477bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4478{
4479 return ValidateGenOrDelete(context, n);
4480}
4481
4482bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4483{
4484 return ValidateGenOrDelete(context, n);
4485}
4486
4487bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4488{
4489 return ValidateGenOrDelete(context, n);
4490}
4491
4492bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4493{
4494 return ValidateGenOrDelete(context, n);
4495}
4496
4497bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4498{
4499 return ValidateGenOrDelete(context, n);
4500}
4501
4502bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4503{
4504 return ValidateGenOrDelete(context, n);
4505}
4506
4507bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4508{
4509 return ValidateGenOrDelete(context, n);
4510}
4511
4512bool ValidateGenOrDelete(Context *context, GLint n)
4513{
4514 if (n < 0)
4515 {
Jamie Madill437fa652016-05-03 15:13:24 -04004516 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004517 return false;
4518 }
4519 return true;
4520}
4521
Geoff Langf41a7152016-09-19 15:11:17 -04004522bool ValidateEnable(Context *context, GLenum cap)
4523{
4524 if (!ValidCap(context, cap, false))
4525 {
4526 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4527 return false;
4528 }
4529
4530 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4531 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4532 {
4533 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4534 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4535
4536 // We also output an error message to the debugger window if tracing is active, so that
4537 // developers can see the error message.
4538 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004539 return false;
4540 }
4541
4542 return true;
4543}
4544
4545bool ValidateDisable(Context *context, GLenum cap)
4546{
4547 if (!ValidCap(context, cap, false))
4548 {
4549 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4550 return false;
4551 }
4552
4553 return true;
4554}
4555
4556bool ValidateIsEnabled(Context *context, GLenum cap)
4557{
4558 if (!ValidCap(context, cap, true))
4559 {
4560 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4561 return false;
4562 }
4563
4564 return true;
4565}
4566
Geoff Langff5b2d52016-09-07 11:32:23 -04004567bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4568{
4569 if (!context->getExtensions().robustClientMemory)
4570 {
4571 context->handleError(
4572 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4573 return false;
4574 }
4575
4576 if (bufSize < 0)
4577 {
4578 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4579 return false;
4580 }
4581
4582 return true;
4583}
4584
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004585bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4586{
4587 if (bufSize < numParams)
4588 {
4589 context->handleError(Error(GL_INVALID_OPERATION,
4590 "%u parameters are required but %i were provided.", numParams,
4591 bufSize));
4592 return false;
4593 }
4594
4595 return true;
4596}
4597
Geoff Langff5b2d52016-09-07 11:32:23 -04004598bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4599 GLenum target,
4600 GLenum attachment,
4601 GLenum pname,
4602 GLsizei *numParams)
4603{
4604 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4605 *numParams = 1;
4606
4607 if (!ValidFramebufferTarget(target))
4608 {
4609 context->handleError(Error(GL_INVALID_ENUM));
4610 return false;
4611 }
4612
4613 int clientVersion = context->getClientMajorVersion();
4614
4615 switch (pname)
4616 {
4617 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4618 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4619 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4620 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4621 break;
4622
4623 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4624 if (clientVersion < 3 && !context->getExtensions().sRGB)
4625 {
4626 context->handleError(Error(GL_INVALID_ENUM));
4627 return false;
4628 }
4629 break;
4630
4631 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4632 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4633 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4634 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4635 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4636 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4637 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4638 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4639 if (clientVersion < 3)
4640 {
4641 context->handleError(Error(GL_INVALID_ENUM));
4642 return false;
4643 }
4644 break;
4645
4646 default:
4647 context->handleError(Error(GL_INVALID_ENUM));
4648 return false;
4649 }
4650
4651 // Determine if the attachment is a valid enum
4652 switch (attachment)
4653 {
4654 case GL_BACK:
4655 case GL_FRONT:
4656 case GL_DEPTH:
4657 case GL_STENCIL:
4658 case GL_DEPTH_STENCIL_ATTACHMENT:
4659 if (clientVersion < 3)
4660 {
4661 context->handleError(Error(GL_INVALID_ENUM));
4662 return false;
4663 }
4664 break;
4665
4666 case GL_DEPTH_ATTACHMENT:
4667 case GL_STENCIL_ATTACHMENT:
4668 break;
4669
4670 default:
4671 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4672 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4673 {
4674 context->handleError(Error(GL_INVALID_ENUM));
4675 return false;
4676 }
4677 break;
4678 }
4679
4680 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4681 ASSERT(framebuffer);
4682
4683 if (framebuffer->id() == 0)
4684 {
4685 if (clientVersion < 3)
4686 {
4687 context->handleError(Error(GL_INVALID_OPERATION));
4688 return false;
4689 }
4690
4691 switch (attachment)
4692 {
4693 case GL_BACK:
4694 case GL_DEPTH:
4695 case GL_STENCIL:
4696 break;
4697
4698 default:
4699 context->handleError(Error(GL_INVALID_OPERATION));
4700 return false;
4701 }
4702 }
4703 else
4704 {
4705 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4706 {
4707 // Valid attachment query
4708 }
4709 else
4710 {
4711 switch (attachment)
4712 {
4713 case GL_DEPTH_ATTACHMENT:
4714 case GL_STENCIL_ATTACHMENT:
4715 break;
4716
4717 case GL_DEPTH_STENCIL_ATTACHMENT:
4718 if (!framebuffer->hasValidDepthStencil())
4719 {
4720 context->handleError(Error(GL_INVALID_OPERATION));
4721 return false;
4722 }
4723 break;
4724
4725 default:
4726 context->handleError(Error(GL_INVALID_OPERATION));
4727 return false;
4728 }
4729 }
4730 }
4731
4732 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4733 if (attachmentObject)
4734 {
4735 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4736 attachmentObject->type() == GL_TEXTURE ||
4737 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4738
4739 switch (pname)
4740 {
4741 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4742 if (attachmentObject->type() != GL_RENDERBUFFER &&
4743 attachmentObject->type() != GL_TEXTURE)
4744 {
4745 context->handleError(Error(GL_INVALID_ENUM));
4746 return false;
4747 }
4748 break;
4749
4750 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4751 if (attachmentObject->type() != GL_TEXTURE)
4752 {
4753 context->handleError(Error(GL_INVALID_ENUM));
4754 return false;
4755 }
4756 break;
4757
4758 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4759 if (attachmentObject->type() != GL_TEXTURE)
4760 {
4761 context->handleError(Error(GL_INVALID_ENUM));
4762 return false;
4763 }
4764 break;
4765
4766 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4767 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4768 {
4769 context->handleError(Error(GL_INVALID_OPERATION));
4770 return false;
4771 }
4772 break;
4773
4774 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4775 if (attachmentObject->type() != GL_TEXTURE)
4776 {
4777 context->handleError(Error(GL_INVALID_ENUM));
4778 return false;
4779 }
4780 break;
4781
4782 default:
4783 break;
4784 }
4785 }
4786 else
4787 {
4788 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4789 // is NONE, then querying any other pname will generate INVALID_ENUM.
4790
4791 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4792 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4793 // INVALID_OPERATION for all other pnames
4794
4795 switch (pname)
4796 {
4797 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4798 break;
4799
4800 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4801 if (clientVersion < 3)
4802 {
4803 context->handleError(Error(GL_INVALID_ENUM));
4804 return false;
4805 }
4806 break;
4807
4808 default:
4809 if (clientVersion < 3)
4810 {
4811 context->handleError(Error(GL_INVALID_ENUM));
4812 return false;
4813 }
4814 else
4815 {
4816 context->handleError(Error(GL_INVALID_OPERATION));
4817 return false;
4818 }
4819 }
4820 }
4821
4822 return true;
4823}
4824
4825bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4826 GLenum target,
4827 GLenum attachment,
4828 GLenum pname,
4829 GLsizei bufSize,
4830 GLsizei *numParams)
4831{
4832 if (!ValidateRobustEntryPoint(context, bufSize))
4833 {
4834 return false;
4835 }
4836
4837 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4838 {
4839 return false;
4840 }
4841
4842 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4843 {
4844 return false;
4845 }
4846
4847 return true;
4848}
4849
4850bool ValidateGetBufferParameteriv(ValidationContext *context,
4851 GLenum target,
4852 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04004853 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004854{
Geoff Langebebe1c2016-10-14 12:01:31 -04004855 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04004856}
4857
4858bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4859 GLenum target,
4860 GLenum pname,
4861 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004862 GLsizei *length,
4863 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004864{
4865 if (!ValidateRobustEntryPoint(context, bufSize))
4866 {
4867 return false;
4868 }
4869
Geoff Langebebe1c2016-10-14 12:01:31 -04004870 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004871 {
4872 return false;
4873 }
4874
Geoff Langebebe1c2016-10-14 12:01:31 -04004875 if (!ValidateRobustBufferSize(context, bufSize, *length))
4876 {
4877 return false;
4878 }
4879
4880 return true;
4881}
4882
4883bool ValidateGetBufferParameteri64v(ValidationContext *context,
4884 GLenum target,
4885 GLenum pname,
4886 GLint64 *params)
4887{
4888 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4889}
4890
4891bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4892 GLenum target,
4893 GLenum pname,
4894 GLsizei bufSize,
4895 GLsizei *length,
4896 GLint64 *params)
4897{
4898 if (!ValidateRobustEntryPoint(context, bufSize))
4899 {
4900 return false;
4901 }
4902
4903 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4904 {
4905 return false;
4906 }
4907
4908 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004909 {
4910 return false;
4911 }
4912
4913 return true;
4914}
4915
4916bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4917{
4918 // Currently, all GetProgramiv queries return 1 parameter
4919 *numParams = 1;
4920
4921 Program *programObject = GetValidProgram(context, program);
4922 if (!programObject)
4923 {
4924 return false;
4925 }
4926
4927 switch (pname)
4928 {
4929 case GL_DELETE_STATUS:
4930 case GL_LINK_STATUS:
4931 case GL_VALIDATE_STATUS:
4932 case GL_INFO_LOG_LENGTH:
4933 case GL_ATTACHED_SHADERS:
4934 case GL_ACTIVE_ATTRIBUTES:
4935 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4936 case GL_ACTIVE_UNIFORMS:
4937 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4938 break;
4939
4940 case GL_PROGRAM_BINARY_LENGTH:
4941 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4942 {
4943 context->handleError(Error(GL_INVALID_ENUM,
4944 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4945 "GL_OES_get_program_binary or ES 3.0."));
4946 return false;
4947 }
4948 break;
4949
4950 case GL_ACTIVE_UNIFORM_BLOCKS:
4951 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4952 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4953 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4954 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4955 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4956 if (context->getClientMajorVersion() < 3)
4957 {
4958 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4959 return false;
4960 }
4961 break;
4962
4963 default:
4964 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4965 return false;
4966 }
4967
4968 return true;
4969}
4970
4971bool ValidateGetProgramivRobustANGLE(Context *context,
4972 GLuint program,
4973 GLenum pname,
4974 GLsizei bufSize,
4975 GLsizei *numParams)
4976{
4977 if (!ValidateRobustEntryPoint(context, bufSize))
4978 {
4979 return false;
4980 }
4981
4982 if (!ValidateGetProgramiv(context, program, pname, numParams))
4983 {
4984 return false;
4985 }
4986
4987 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4988 {
4989 return false;
4990 }
4991
4992 return true;
4993}
4994
Geoff Lang740d9022016-10-07 11:20:52 -04004995bool ValidateGetRenderbufferParameteriv(Context *context,
4996 GLenum target,
4997 GLenum pname,
4998 GLint *params)
4999{
5000 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5001}
5002
5003bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5004 GLenum target,
5005 GLenum pname,
5006 GLsizei bufSize,
5007 GLsizei *length,
5008 GLint *params)
5009{
5010 if (!ValidateRobustEntryPoint(context, bufSize))
5011 {
5012 return false;
5013 }
5014
5015 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5016 {
5017 return false;
5018 }
5019
5020 if (!ValidateRobustBufferSize(context, bufSize, *length))
5021 {
5022 return false;
5023 }
5024
5025 return true;
5026}
5027
Geoff Langd7d0ed32016-10-07 11:33:51 -04005028bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5029{
5030 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5031}
5032
5033bool ValidateGetShaderivRobustANGLE(Context *context,
5034 GLuint shader,
5035 GLenum pname,
5036 GLsizei bufSize,
5037 GLsizei *length,
5038 GLint *params)
5039{
5040 if (!ValidateRobustEntryPoint(context, bufSize))
5041 {
5042 return false;
5043 }
5044
5045 if (!ValidateGetShaderivBase(context, shader, pname, length))
5046 {
5047 return false;
5048 }
5049
5050 if (!ValidateRobustBufferSize(context, bufSize, *length))
5051 {
5052 return false;
5053 }
5054
5055 return true;
5056}
5057
Geoff Langc1984ed2016-10-07 12:41:00 -04005058bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5059{
5060 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5061}
5062
5063bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5064 GLenum target,
5065 GLenum pname,
5066 GLsizei bufSize,
5067 GLsizei *length,
5068 GLfloat *params)
5069{
5070 if (!ValidateRobustEntryPoint(context, bufSize))
5071 {
5072 return false;
5073 }
5074
5075 if (!ValidateGetTexParameterBase(context, target, pname, length))
5076 {
5077 return false;
5078 }
5079
5080 if (!ValidateRobustBufferSize(context, bufSize, *length))
5081 {
5082 return false;
5083 }
5084
5085 return true;
5086}
5087
5088bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5089{
5090 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5091}
5092
5093bool ValidateGetTexParameterivRobustANGLE(Context *context,
5094 GLenum target,
5095 GLenum pname,
5096 GLsizei bufSize,
5097 GLsizei *length,
5098 GLint *params)
5099{
5100 if (!ValidateRobustEntryPoint(context, bufSize))
5101 {
5102 return false;
5103 }
5104
5105 if (!ValidateGetTexParameterBase(context, target, pname, length))
5106 {
5107 return false;
5108 }
5109
5110 if (!ValidateRobustBufferSize(context, bufSize, *length))
5111 {
5112 return false;
5113 }
5114
5115 return true;
5116}
5117
5118bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5119{
5120 return ValidateTexParameterBase(context, target, pname, -1, &param);
5121}
5122
5123bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5124{
5125 return ValidateTexParameterBase(context, target, pname, -1, params);
5126}
5127
5128bool ValidateTexParameterfvRobustANGLE(Context *context,
5129 GLenum target,
5130 GLenum pname,
5131 GLsizei bufSize,
5132 const GLfloat *params)
5133{
5134 if (!ValidateRobustEntryPoint(context, bufSize))
5135 {
5136 return false;
5137 }
5138
5139 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5140}
5141
5142bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5143{
5144 return ValidateTexParameterBase(context, target, pname, -1, &param);
5145}
5146
5147bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5148{
5149 return ValidateTexParameterBase(context, target, pname, -1, params);
5150}
5151
5152bool ValidateTexParameterivRobustANGLE(Context *context,
5153 GLenum target,
5154 GLenum pname,
5155 GLsizei bufSize,
5156 const GLint *params)
5157{
5158 if (!ValidateRobustEntryPoint(context, bufSize))
5159 {
5160 return false;
5161 }
5162
5163 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5164}
5165
5166bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5167{
5168 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5169}
5170
5171bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5172 GLuint sampler,
5173 GLenum pname,
5174 GLuint bufSize,
5175 GLsizei *length,
5176 GLfloat *params)
5177{
5178 if (!ValidateRobustEntryPoint(context, bufSize))
5179 {
5180 return false;
5181 }
5182
5183 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5184 {
5185 return false;
5186 }
5187
5188 if (!ValidateRobustBufferSize(context, bufSize, *length))
5189 {
5190 return false;
5191 }
5192
5193 return true;
5194}
5195
5196bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5197{
5198 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5199}
5200
5201bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5202 GLuint sampler,
5203 GLenum pname,
5204 GLuint bufSize,
5205 GLsizei *length,
5206 GLint *params)
5207{
5208 if (!ValidateRobustEntryPoint(context, bufSize))
5209 {
5210 return false;
5211 }
5212
5213 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5214 {
5215 return false;
5216 }
5217
5218 if (!ValidateRobustBufferSize(context, bufSize, *length))
5219 {
5220 return false;
5221 }
5222
5223 return true;
5224}
5225
5226bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5227{
5228 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5229}
5230
5231bool ValidateSamplerParameterfv(Context *context,
5232 GLuint sampler,
5233 GLenum pname,
5234 const GLfloat *params)
5235{
5236 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5237}
5238
5239bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5240 GLuint sampler,
5241 GLenum pname,
5242 GLsizei bufSize,
5243 const GLfloat *params)
5244{
5245 if (!ValidateRobustEntryPoint(context, bufSize))
5246 {
5247 return false;
5248 }
5249
5250 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5251}
5252
5253bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5254{
5255 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5256}
5257
5258bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5259{
5260 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5261}
5262
5263bool ValidateSamplerParameterivRobustANGLE(Context *context,
5264 GLuint sampler,
5265 GLenum pname,
5266 GLsizei bufSize,
5267 const GLint *params)
5268{
5269 if (!ValidateRobustEntryPoint(context, bufSize))
5270 {
5271 return false;
5272 }
5273
5274 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5275}
5276
Geoff Lang0b031062016-10-13 14:30:04 -04005277bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5278{
5279 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5280}
5281
5282bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5283 GLuint index,
5284 GLenum pname,
5285 GLsizei bufSize,
5286 GLsizei *length,
5287 GLfloat *params)
5288{
5289 if (!ValidateRobustEntryPoint(context, bufSize))
5290 {
5291 return false;
5292 }
5293
5294 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5295 {
5296 return false;
5297 }
5298
5299 if (!ValidateRobustBufferSize(context, bufSize, *length))
5300 {
5301 return false;
5302 }
5303
5304 return true;
5305}
5306
5307bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5308{
5309 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5310}
5311
5312bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5313 GLuint index,
5314 GLenum pname,
5315 GLsizei bufSize,
5316 GLsizei *length,
5317 GLint *params)
5318{
5319 if (!ValidateRobustEntryPoint(context, bufSize))
5320 {
5321 return false;
5322 }
5323
5324 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5325 {
5326 return false;
5327 }
5328
5329 if (!ValidateRobustBufferSize(context, bufSize, *length))
5330 {
5331 return false;
5332 }
5333
5334 return true;
5335}
5336
5337bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5338{
5339 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5340}
5341
5342bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5343 GLuint index,
5344 GLenum pname,
5345 GLsizei bufSize,
5346 GLsizei *length,
5347 void **pointer)
5348{
5349 if (!ValidateRobustEntryPoint(context, bufSize))
5350 {
5351 return false;
5352 }
5353
5354 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5355 {
5356 return false;
5357 }
5358
5359 if (!ValidateRobustBufferSize(context, bufSize, *length))
5360 {
5361 return false;
5362 }
5363
5364 return true;
5365}
5366
5367bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5368{
5369 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5370}
5371
5372bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5373 GLuint index,
5374 GLenum pname,
5375 GLsizei bufSize,
5376 GLsizei *length,
5377 GLint *params)
5378{
5379 if (!ValidateRobustEntryPoint(context, bufSize))
5380 {
5381 return false;
5382 }
5383
5384 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5385 {
5386 return false;
5387 }
5388
5389 if (!ValidateRobustBufferSize(context, bufSize, *length))
5390 {
5391 return false;
5392 }
5393
5394 return true;
5395}
5396
5397bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5398{
5399 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5400}
5401
5402bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5403 GLuint index,
5404 GLenum pname,
5405 GLsizei bufSize,
5406 GLsizei *length,
5407 GLuint *params)
5408{
5409 if (!ValidateRobustEntryPoint(context, bufSize))
5410 {
5411 return false;
5412 }
5413
5414 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5415 {
5416 return false;
5417 }
5418
5419 if (!ValidateRobustBufferSize(context, bufSize, *length))
5420 {
5421 return false;
5422 }
5423
5424 return true;
5425}
5426
Geoff Lang6899b872016-10-14 11:30:13 -04005427bool ValidateGetActiveUniformBlockiv(Context *context,
5428 GLuint program,
5429 GLuint uniformBlockIndex,
5430 GLenum pname,
5431 GLint *params)
5432{
5433 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5434}
5435
5436bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5437 GLuint program,
5438 GLuint uniformBlockIndex,
5439 GLenum pname,
5440 GLsizei bufSize,
5441 GLsizei *length,
5442 GLint *params)
5443{
5444 if (!ValidateRobustEntryPoint(context, bufSize))
5445 {
5446 return false;
5447 }
5448
5449 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5450 {
5451 return false;
5452 }
5453
5454 if (!ValidateRobustBufferSize(context, bufSize, *length))
5455 {
5456 return false;
5457 }
5458
5459 return true;
5460}
5461
Geoff Lang0a9661f2016-10-20 10:59:20 -07005462bool ValidateGetInternalFormativ(Context *context,
5463 GLenum target,
5464 GLenum internalformat,
5465 GLenum pname,
5466 GLsizei bufSize,
5467 GLint *params)
5468{
5469 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5470 nullptr);
5471}
5472
5473bool ValidateGetInternalFormativRobustANGLE(Context *context,
5474 GLenum target,
5475 GLenum internalformat,
5476 GLenum pname,
5477 GLsizei bufSize,
5478 GLsizei *length,
5479 GLint *params)
5480{
5481 if (!ValidateRobustEntryPoint(context, bufSize))
5482 {
5483 return false;
5484 }
5485
5486 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5487 {
5488 return false;
5489 }
5490
5491 if (!ValidateRobustBufferSize(context, bufSize, *length))
5492 {
5493 return false;
5494 }
5495
5496 return true;
5497}
5498
Jamie Madillc29968b2016-01-20 11:17:23 -05005499} // namespace gl