blob: 96f13c9f4d6b2d99bac961bd939793a53e17a580 [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/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040012#include "libANGLE/Display.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070013#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040016#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050017#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Query.h"
19#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/TransformFeedback.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040021#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050022#include "libANGLE/VertexArray.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040023#include "libANGLE/formatutils.h"
24#include "libANGLE/validationES2.h"
25#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040026
27#include "common/mathutil.h"
28#include "common/utilities.h"
29
Jamie Madille2e406c2016-06-02 13:04:10 -040030using namespace angle;
31
Geoff Lange8ebe7f2013-08-05 15:03:13 -040032namespace gl
33{
Jamie Madill1ca74672015-07-21 15:14:11 -040034namespace
35{
Corentin Wallez92db6942016-12-09 13:10:36 -050036bool ValidateDrawAttribs(ValidationContext *context,
37 GLint primcount,
38 GLint maxVertex,
39 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040040{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070041 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040042 const gl::Program *program = state.getProgram();
43
Corentin Wallez327411e2016-12-09 11:09:17 -050044 bool webglCompatibility = context->getExtensions().webglCompatibility;
45
Jamie Madill231c7f52017-04-26 13:45:37 -040046 const VertexArray *vao = state.getVertexArray();
47 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080048 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madill231c7f52017-04-26 13:45:37 -040049 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];
Corentin Wallez672f7f32017-06-15 17:42:17 -040053
54 // No need to range check for disabled attribs.
55 if (!attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040056 {
Corentin Wallezfd456442016-12-21 17:57:00 -050057 continue;
58 }
Jamie Madill1ca74672015-07-21 15:14:11 -040059
Jamie Madill231c7f52017-04-26 13:45:37 -040060 // If we have no buffer, then we either get an error, or there are no more checks to be
61 // done.
Corentin Wallez672f7f32017-06-15 17:42:17 -040062 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
63 gl::Buffer *buffer = binding.getBuffer().get();
Corentin Wallezfd456442016-12-21 17:57:00 -050064 if (!buffer)
65 {
Geoff Langfeb8c682017-02-13 16:07:35 -050066 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050067 {
68 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050069 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
70 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
71 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
72 // error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050073 context->handleError(InvalidOperation()
74 << "An enabled vertex array has no buffer.");
Corentin Wallezfd456442016-12-21 17:57:00 -050075 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050076 }
Corentin Wallezfd456442016-12-21 17:57:00 -050077 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040078 {
79 // This is an application error that would normally result in a crash,
80 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050081 context->handleError(InvalidOperation()
82 << "An enabled vertex array has no buffer and no pointer.");
Jamie Madill1ca74672015-07-21 15:14:11 -040083 return false;
84 }
Corentin Wallezfd456442016-12-21 17:57:00 -050085 continue;
86 }
87
Corentin Wallez672f7f32017-06-15 17:42:17 -040088 // This needs to come after the check for client arrays as even unused attributes cannot use
89 // client-side arrays
90 if (!program->isAttribLocationActive(attributeIndex))
91 {
92 continue;
93 }
94
Corentin Wallezfd456442016-12-21 17:57:00 -050095 // If we're drawing zero vertices, we have enough data.
96 if (vertexCount <= 0 || primcount <= 0)
97 {
98 continue;
99 }
100
101 GLint maxVertexElement = 0;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300102 GLuint divisor = binding.getDivisor();
103 if (divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500104 {
105 maxVertexElement = maxVertex;
106 }
107 else
108 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300109 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500110 }
111
112 // We do manual overflow checks here instead of using safe_math.h because it was
113 // a bottleneck. Thanks to some properties of GL we know inequalities that can
114 // help us make the overflow checks faster.
115
116 // The max possible attribSize is 16 for a vector of 4 32 bit values.
117 constexpr uint64_t kMaxAttribSize = 16;
118 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
119 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
120
121 // We know attribStride is given as a GLsizei which is typedefed to int.
122 // We also know an upper bound for attribSize.
123 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800124 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500125 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
126 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
127
128 // Computing the max offset using uint64_t without attrib.offset is overflow
129 // safe. Note: Last vertex element does not take the full stride!
130 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
131 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
132
133 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800134 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
135 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500136 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500137 context->handleError(InvalidOperation() << "Integer overflow.");
Corentin Wallezfd456442016-12-21 17:57:00 -0500138 return false;
139 }
140 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
141
142 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
143 // We can return INVALID_OPERATION if our vertex attribute does not have
144 // enough backing data.
145 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
146 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500147 context->handleError(InvalidOperation()
148 << "Vertex buffer is not big enough for the draw call");
Corentin Wallezfd456442016-12-21 17:57:00 -0500149 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400150 }
151 }
152
153 return true;
154}
155
Geoff Langf607c602016-09-21 11:46:48 -0400156bool ValidReadPixelsFormatType(ValidationContext *context,
157 GLenum framebufferComponentType,
158 GLenum format,
159 GLenum type)
160{
161 switch (framebufferComponentType)
162 {
163 case GL_UNSIGNED_NORMALIZED:
164 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
165 // ReadPixels with BGRA even if the extension is not present
166 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
167 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
168 type == GL_UNSIGNED_BYTE);
169
170 case GL_SIGNED_NORMALIZED:
171 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
172
173 case GL_INT:
174 return (format == GL_RGBA_INTEGER && type == GL_INT);
175
176 case GL_UNSIGNED_INT:
177 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
178
179 case GL_FLOAT:
180 return (format == GL_RGBA && type == GL_FLOAT);
181
182 default:
183 UNREACHABLE();
184 return false;
185 }
186}
187
Geoff Langc1984ed2016-10-07 12:41:00 -0400188template <typename ParamType>
189bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
190{
191 switch (ConvertToGLenum(params[0]))
192 {
193 case GL_CLAMP_TO_EDGE:
194 break;
195
196 case GL_REPEAT:
197 case GL_MIRRORED_REPEAT:
198 if (isExternalTextureTarget)
199 {
200 // OES_EGL_image_external specifies this error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500201 context->handleError(InvalidEnum()
202 << "external textures only support CLAMP_TO_EDGE wrap mode");
Geoff Langc1984ed2016-10-07 12:41:00 -0400203 return false;
204 }
205 break;
206
207 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500208 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400209 return false;
210 }
211
212 return true;
213}
214
215template <typename ParamType>
216bool ValidateTextureMinFilterValue(Context *context,
217 ParamType *params,
218 bool isExternalTextureTarget)
219{
220 switch (ConvertToGLenum(params[0]))
221 {
222 case GL_NEAREST:
223 case GL_LINEAR:
224 break;
225
226 case GL_NEAREST_MIPMAP_NEAREST:
227 case GL_LINEAR_MIPMAP_NEAREST:
228 case GL_NEAREST_MIPMAP_LINEAR:
229 case GL_LINEAR_MIPMAP_LINEAR:
230 if (isExternalTextureTarget)
231 {
232 // OES_EGL_image_external specifies this error.
233 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500234 InvalidEnum() << "external textures only support NEAREST and LINEAR filtering");
Geoff Langc1984ed2016-10-07 12:41:00 -0400235 return false;
236 }
237 break;
238
239 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700240 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400241 return false;
242 }
243
244 return true;
245}
246
247template <typename ParamType>
248bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
249{
250 switch (ConvertToGLenum(params[0]))
251 {
252 case GL_NEAREST:
253 case GL_LINEAR:
254 break;
255
256 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700257 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400258 return false;
259 }
260
261 return true;
262}
263
264template <typename ParamType>
265bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
266{
267 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
268 switch (ConvertToGLenum(params[0]))
269 {
270 case GL_NONE:
271 case GL_COMPARE_REF_TO_TEXTURE:
272 break;
273
274 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500275 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400276 return false;
277 }
278
279 return true;
280}
281
282template <typename ParamType>
283bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
284{
285 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
286 switch (ConvertToGLenum(params[0]))
287 {
288 case GL_LEQUAL:
289 case GL_GEQUAL:
290 case GL_LESS:
291 case GL_GREATER:
292 case GL_EQUAL:
293 case GL_NOTEQUAL:
294 case GL_ALWAYS:
295 case GL_NEVER:
296 break;
297
298 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500299 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400300 return false;
301 }
302
303 return true;
304}
305
306template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700307bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
308{
309 if (!context->getExtensions().textureSRGBDecode)
310 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700311 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700312 return false;
313 }
314
315 switch (ConvertToGLenum(params[0]))
316 {
317 case GL_DECODE_EXT:
318 case GL_SKIP_DECODE_EXT:
319 break;
320
321 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500322 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Lang81c6b572016-10-19 14:07:52 -0700323 return false;
324 }
325
326 return true;
327}
328
329template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400330bool ValidateSamplerParameterBase(Context *context,
331 GLuint sampler,
332 GLenum pname,
333 GLsizei bufSize,
334 ParamType *params)
335{
336 if (context->getClientMajorVersion() < 3)
337 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500338 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400339 return false;
340 }
341
342 if (!context->isSampler(sampler))
343 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500344 context->handleError(InvalidOperation() << "Sampler is not valid.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400345 return false;
346 }
347
348 const GLsizei minBufSize = 1;
349 if (bufSize >= 0 && bufSize < minBufSize)
350 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500351 context->handleError(InvalidOperation() << "bufSize must be at least " << minBufSize);
Geoff Langc1984ed2016-10-07 12:41:00 -0400352 return false;
353 }
354
355 switch (pname)
356 {
357 case GL_TEXTURE_WRAP_S:
358 case GL_TEXTURE_WRAP_T:
359 case GL_TEXTURE_WRAP_R:
360 if (!ValidateTextureWrapModeValue(context, params, false))
361 {
362 return false;
363 }
364 break;
365
366 case GL_TEXTURE_MIN_FILTER:
367 if (!ValidateTextureMinFilterValue(context, params, false))
368 {
369 return false;
370 }
371 break;
372
373 case GL_TEXTURE_MAG_FILTER:
374 if (!ValidateTextureMagFilterValue(context, params))
375 {
376 return false;
377 }
378 break;
379
380 case GL_TEXTURE_MIN_LOD:
381 case GL_TEXTURE_MAX_LOD:
382 // any value is permissible
383 break;
384
385 case GL_TEXTURE_COMPARE_MODE:
386 if (!ValidateTextureCompareModeValue(context, params))
387 {
388 return false;
389 }
390 break;
391
392 case GL_TEXTURE_COMPARE_FUNC:
393 if (!ValidateTextureCompareFuncValue(context, params))
394 {
395 return false;
396 }
397 break;
398
Geoff Lang81c6b572016-10-19 14:07:52 -0700399 case GL_TEXTURE_SRGB_DECODE_EXT:
400 if (!ValidateTextureSRGBDecodeValue(context, params))
401 {
402 return false;
403 }
404 break;
405
Geoff Langc1984ed2016-10-07 12:41:00 -0400406 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700407 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langc1984ed2016-10-07 12:41:00 -0400408 return false;
409 }
410
411 return true;
412}
413
414bool ValidateGetSamplerParameterBase(Context *context,
415 GLuint sampler,
416 GLenum pname,
417 GLsizei *length)
418{
419 if (length)
420 {
421 *length = 0;
422 }
423
424 if (context->getClientMajorVersion() < 3)
425 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500426 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400427 return false;
428 }
429
430 if (!context->isSampler(sampler))
431 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500432 context->handleError(InvalidOperation() << "Sampler is not valid.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400433 return false;
434 }
435
436 switch (pname)
437 {
438 case GL_TEXTURE_WRAP_S:
439 case GL_TEXTURE_WRAP_T:
440 case GL_TEXTURE_WRAP_R:
441 case GL_TEXTURE_MIN_FILTER:
442 case GL_TEXTURE_MAG_FILTER:
443 case GL_TEXTURE_MIN_LOD:
444 case GL_TEXTURE_MAX_LOD:
445 case GL_TEXTURE_COMPARE_MODE:
446 case GL_TEXTURE_COMPARE_FUNC:
447 break;
448
Geoff Lang81c6b572016-10-19 14:07:52 -0700449 case GL_TEXTURE_SRGB_DECODE_EXT:
450 if (!context->getExtensions().textureSRGBDecode)
451 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500452 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Geoff Lang81c6b572016-10-19 14:07:52 -0700453 return false;
454 }
455 break;
456
Geoff Langc1984ed2016-10-07 12:41:00 -0400457 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700458 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langc1984ed2016-10-07 12:41:00 -0400459 return false;
460 }
461
462 if (length)
463 {
464 *length = 1;
465 }
466 return true;
467}
468
Geoff Lang6899b872016-10-14 11:30:13 -0400469bool ValidateGetActiveUniformBlockivBase(Context *context,
470 GLuint program,
471 GLuint uniformBlockIndex,
472 GLenum pname,
473 GLsizei *length)
474{
475 if (length)
476 {
477 *length = 0;
478 }
479
480 if (context->getClientMajorVersion() < 3)
481 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500482 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Lang6899b872016-10-14 11:30:13 -0400483 return false;
484 }
485
486 Program *programObject = GetValidProgram(context, program);
487 if (!programObject)
488 {
489 return false;
490 }
491
492 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
493 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500494 context->handleError(InvalidValue()
495 << "uniformBlockIndex exceeds active uniform block count.");
Geoff Lang6899b872016-10-14 11:30:13 -0400496 return false;
497 }
498
499 switch (pname)
500 {
501 case GL_UNIFORM_BLOCK_BINDING:
502 case GL_UNIFORM_BLOCK_DATA_SIZE:
503 case GL_UNIFORM_BLOCK_NAME_LENGTH:
504 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
505 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
506 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
507 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
508 break;
509
510 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700511 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang6899b872016-10-14 11:30:13 -0400512 return false;
513 }
514
515 if (length)
516 {
517 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
518 {
519 const UniformBlock &uniformBlock =
520 programObject->getUniformBlockByIndex(uniformBlockIndex);
jchen10eaef1e52017-06-13 10:44:11 +0800521 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
Geoff Lang6899b872016-10-14 11:30:13 -0400522 }
523 else
524 {
525 *length = 1;
526 }
527 }
528
529 return true;
530}
531
Geoff Lang0a9661f2016-10-20 10:59:20 -0700532bool ValidateGetInternalFormativBase(Context *context,
533 GLenum target,
534 GLenum internalformat,
535 GLenum pname,
536 GLsizei bufSize,
537 GLsizei *numParams)
538{
539 if (numParams)
540 {
541 *numParams = 0;
542 }
543
544 if (context->getClientMajorVersion() < 3)
545 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500546 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700547 return false;
548 }
549
550 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
551 if (!formatCaps.renderable)
552 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500553 context->handleError(InvalidEnum() << "Internal format is not renderable.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700554 return false;
555 }
556
557 switch (target)
558 {
559 case GL_RENDERBUFFER:
560 break;
561
JiangYizhoubddc46b2016-12-09 09:50:51 +0800562 case GL_TEXTURE_2D_MULTISAMPLE:
563 if (context->getClientVersion() < ES_3_1)
564 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500565 context->handleError(InvalidOperation()
566 << "Texture target requires at least OpenGL ES 3.1.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800567 return false;
568 }
569 break;
570
Geoff Lang0a9661f2016-10-20 10:59:20 -0700571 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500572 context->handleError(InvalidEnum() << "Invalid target.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700573 return false;
574 }
575
576 if (bufSize < 0)
577 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700578 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
Geoff Lang0a9661f2016-10-20 10:59:20 -0700579 return false;
580 }
581
582 GLsizei maxWriteParams = 0;
583 switch (pname)
584 {
585 case GL_NUM_SAMPLE_COUNTS:
586 maxWriteParams = 1;
587 break;
588
589 case GL_SAMPLES:
590 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
591 break;
592
593 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700594 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang0a9661f2016-10-20 10:59:20 -0700595 return false;
596 }
597
598 if (numParams)
599 {
600 // glGetInternalFormativ will not overflow bufSize
601 *numParams = std::min(bufSize, maxWriteParams);
602 }
603
604 return true;
605}
606
Jamie Madillc1d770e2017-04-13 17:31:24 -0400607bool ValidateUniformCommonBase(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500608 gl::Program *program,
609 GLint location,
610 GLsizei count,
611 const LinkedUniform **uniformOut)
612{
613 // TODO(Jiajia): Add image uniform check in future.
614 if (count < 0)
615 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700616 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500617 return false;
618 }
619
Brandon Jones6cad5662017-06-14 13:25:13 -0700620 if (!program)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500621 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700622 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
623 return false;
624 }
625
626 if (!program->isLinked())
627 {
628 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500629 return false;
630 }
631
632 if (location == -1)
633 {
634 // Silently ignore the uniform command
635 return false;
636 }
637
638 const auto &uniformLocations = program->getUniformLocations();
Jamie Madillbe849e42017-05-02 15:49:00 -0400639 size_t castedLocation = static_cast<size_t>(location);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500640 if (castedLocation >= uniformLocations.size())
641 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500642 context->handleError(InvalidOperation() << "Invalid uniform location");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500643 return false;
644 }
645
646 const auto &uniformLocation = uniformLocations[castedLocation];
647 if (uniformLocation.ignored)
648 {
649 // Silently ignore the uniform command
650 return false;
651 }
652
653 if (!uniformLocation.used)
654 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500655 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500656 return false;
657 }
658
659 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
660
661 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
662 if (!uniform.isArray() && count > 1)
663 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500664 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500665 return false;
666 }
667
668 *uniformOut = &uniform;
669 return true;
670}
671
Frank Henigman999b0fd2017-02-02 21:45:55 -0500672bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -0500673 GLenum uniformType,
674 GLsizei count,
675 const GLint *value)
676{
677 // Value type is GL_INT, because we only get here from glUniform1i{v}.
678 // It is compatible with INT or BOOL.
679 // Do these cheap tests first, for a little extra speed.
680 if (GL_INT == uniformType || GL_BOOL == uniformType)
681 {
682 return true;
683 }
684
685 if (IsSamplerType(uniformType))
686 {
Frank Henigman999b0fd2017-02-02 21:45:55 -0500687 // Check that the values are in range.
688 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
689 for (GLsizei i = 0; i < count; ++i)
690 {
691 if (value[i] < 0 || value[i] >= max)
692 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500693 context->handleError(InvalidValue() << "sampler uniform value out of range");
Frank Henigman999b0fd2017-02-02 21:45:55 -0500694 return false;
695 }
696 }
Frank Henigmana98a6472017-02-02 21:38:32 -0500697 return true;
698 }
699
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500700 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmana98a6472017-02-02 21:38:32 -0500701 return false;
702}
703
Jamie Madillc1d770e2017-04-13 17:31:24 -0400704bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500705{
706 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -0500707 // Do the cheaper test first, for a little extra speed.
708 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500709 {
710 return true;
711 }
712
Brandon Jones6cad5662017-06-14 13:25:13 -0700713 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeDoesNotMatchMethod);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500714 return false;
715}
716
Jamie Madillc1d770e2017-04-13 17:31:24 -0400717bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500718{
719 // Check that the value type is compatible with uniform type.
720 if (valueType == uniformType)
721 {
722 return true;
723 }
724
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500725 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500726 return false;
727}
728
Geoff Lange0cff192017-05-30 13:04:56 -0400729bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
730{
731 const Program *program = context->getGLState().getProgram();
732 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
733
734 const auto &programOutputTypes = program->getOutputVariableTypes();
735 for (size_t drawBufferIdx = 0; drawBufferIdx < programOutputTypes.size(); drawBufferIdx++)
736 {
737 GLenum outputType = programOutputTypes[drawBufferIdx];
738 GLenum inputType = framebuffer->getDrawbufferWriteType(drawBufferIdx);
739 if (outputType != GL_NONE && inputType != GL_NONE && inputType != outputType)
740 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500741 context->handleError(InvalidOperation() << "Fragment shader output type does not "
742 "match the bound framebuffer attachment "
743 "type.");
Geoff Lange0cff192017-05-30 13:04:56 -0400744 return false;
745 }
746 }
747
748 return true;
749}
750
Geoff Lang9ab5b822017-05-30 16:19:23 -0400751bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
752{
753 const Program *program = context->getGLState().getProgram();
754 const VertexArray *vao = context->getGLState().getVertexArray();
755
756 for (const auto &shaderAttribute : program->getAttributes())
757 {
Geoff Lang69df2422017-07-05 12:42:31 -0400758 // gl_VertexID and gl_InstanceID are active attributes but don't have a bound attribute.
759 if (shaderAttribute.isBuiltIn())
760 {
761 continue;
762 }
763
Geoff Lang9ab5b822017-05-30 16:19:23 -0400764 GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
765
766 const auto &attrib = vao->getVertexAttribute(shaderAttribute.location);
767 const auto &currentValue =
768 context->getGLState().getVertexAttribCurrentValue(shaderAttribute.location);
769 GLenum vertexType = attrib.enabled ? GetVertexAttributeBaseType(attrib) : currentValue.Type;
770
771 if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
772 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500773 context->handleError(InvalidOperation() << "Vertex shader input type does not "
774 "match the type of the bound vertex "
775 "attribute.");
Geoff Lang9ab5b822017-05-30 16:19:23 -0400776 return false;
777 }
778 }
779
780 return true;
781}
782
Geoff Langf41a7152016-09-19 15:11:17 -0400783} // anonymous namespace
784
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500785bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400786{
Jamie Madilld7460c72014-01-21 16:38:14 -0500787 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400788 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800789 case GL_TEXTURE_2D:
790 case GL_TEXTURE_CUBE_MAP:
791 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400792
He Yunchaoced53ae2016-11-29 15:00:51 +0800793 case GL_TEXTURE_3D:
794 case GL_TEXTURE_2D_ARRAY:
795 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500796
He Yunchaoced53ae2016-11-29 15:00:51 +0800797 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800798 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400799
He Yunchaoced53ae2016-11-29 15:00:51 +0800800 default:
801 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500802 }
Jamie Madill35d15012013-10-07 10:46:37 -0400803}
804
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500805bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
806{
807 switch (target)
808 {
809 case GL_TEXTURE_2D:
810 case GL_TEXTURE_CUBE_MAP:
811 return true;
812
813 default:
814 return false;
815 }
816}
817
818bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
819{
820 switch (target)
821 {
822 case GL_TEXTURE_3D:
823 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300824 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500825
826 default:
827 return false;
828 }
829}
830
Ian Ewellbda75592016-04-18 17:25:54 -0400831// Most texture GL calls are not compatible with external textures, so we have a separate validation
832// function for use in the GL calls that do
833bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
834{
835 return (target == GL_TEXTURE_EXTERNAL_OES) &&
836 (context->getExtensions().eglImageExternal ||
837 context->getExtensions().eglStreamConsumerExternal);
838}
839
Shannon Woods4dfed832014-03-17 20:03:39 -0400840// This function differs from ValidTextureTarget in that the target must be
841// usable as the destination of a 2D operation-- so a cube face is valid, but
842// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400843// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500844bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400845{
846 switch (target)
847 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800848 case GL_TEXTURE_2D:
849 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
850 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
851 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
852 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
853 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
854 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
855 return true;
856 default:
857 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500858 }
859}
860
Jamie Madillbe849e42017-05-02 15:49:00 -0400861bool ValidateDrawElementsInstancedBase(ValidationContext *context,
862 GLenum mode,
863 GLsizei count,
864 GLenum type,
865 const GLvoid *indices,
866 GLsizei primcount)
867{
868 if (primcount < 0)
869 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500870 context->handleError(InvalidValue() << "primcount cannot be negative.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400871 return false;
872 }
873
874 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
875 {
876 return false;
877 }
878
879 // No-op zero primitive count
880 return (primcount > 0);
881}
882
883bool ValidateDrawArraysInstancedBase(Context *context,
884 GLenum mode,
885 GLint first,
886 GLsizei count,
887 GLsizei primcount)
888{
889 if (primcount < 0)
890 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500891 context->handleError(InvalidValue() << "primcount cannot be negative.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400892 return false;
893 }
894
895 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
896 {
897 return false;
898 }
899
900 // No-op if zero primitive count
901 return (primcount > 0);
902}
903
Corentin Wallez0dc97812017-06-22 14:38:44 -0400904bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400905{
906 // Verify there is at least one active attribute with a divisor of zero
907 const State &state = context->getGLState();
908
909 Program *program = state.getProgram();
910
911 const auto &attribs = state.getVertexArray()->getVertexAttributes();
912 const auto &bindings = state.getVertexArray()->getVertexBindings();
913 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
914 {
915 const VertexAttribute &attrib = attribs[attributeIndex];
916 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300917 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400918 {
919 return true;
920 }
921 }
922
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500923 context->handleError(InvalidOperation()
924 << "At least one attribute must have a divisor of zero.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400925 return false;
926}
927
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500928bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
929{
930 switch (target)
931 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800932 case GL_TEXTURE_3D:
933 case GL_TEXTURE_2D_ARRAY:
934 return true;
935 default:
936 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400937 }
938}
939
He Yunchao11b038b2016-11-22 21:24:04 +0800940bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
941{
942 switch (target)
943 {
944 case GL_TEXTURE_2D:
945 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
946 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
947 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
948 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
949 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
950 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
951 case GL_TEXTURE_3D:
952 case GL_TEXTURE_2D_ARRAY:
953 case GL_TEXTURE_2D_MULTISAMPLE:
954 return true;
955 default:
956 return false;
957 }
958}
959
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500960bool ValidFramebufferTarget(GLenum target)
961{
He Yunchaoced53ae2016-11-29 15:00:51 +0800962 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
963 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400964 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500965
966 switch (target)
967 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800968 case GL_FRAMEBUFFER:
969 return true;
970 case GL_READ_FRAMEBUFFER:
971 return true;
972 case GL_DRAW_FRAMEBUFFER:
973 return true;
974 default:
975 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500976 }
977}
978
Jamie Madill29639852016-09-02 15:00:09 -0400979bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -0500980{
981 switch (target)
982 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800983 case GL_ARRAY_BUFFER:
984 case GL_ELEMENT_ARRAY_BUFFER:
985 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -0500986
He Yunchaoced53ae2016-11-29 15:00:51 +0800987 case GL_PIXEL_PACK_BUFFER:
988 case GL_PIXEL_UNPACK_BUFFER:
989 return (context->getExtensions().pixelBufferObject ||
990 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -0400991
He Yunchaoced53ae2016-11-29 15:00:51 +0800992 case GL_COPY_READ_BUFFER:
993 case GL_COPY_WRITE_BUFFER:
994 case GL_TRANSFORM_FEEDBACK_BUFFER:
995 case GL_UNIFORM_BUFFER:
996 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -0500997
He Yunchaoced53ae2016-11-29 15:00:51 +0800998 case GL_ATOMIC_COUNTER_BUFFER:
999 case GL_SHADER_STORAGE_BUFFER:
1000 case GL_DRAW_INDIRECT_BUFFER:
1001 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001002 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001003
He Yunchaoced53ae2016-11-29 15:00:51 +08001004 default:
1005 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001006 }
1007}
1008
Jamie Madillc29968b2016-01-20 11:17:23 -05001009bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001010{
Jamie Madillc29968b2016-01-20 11:17:23 -05001011 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001012 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001013 switch (target)
1014 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001015 case GL_TEXTURE_2D:
1016 maxDimension = caps.max2DTextureSize;
1017 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001018 case GL_TEXTURE_CUBE_MAP:
1019 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1020 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1021 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1022 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1023 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1024 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1025 maxDimension = caps.maxCubeMapTextureSize;
1026 break;
1027 case GL_TEXTURE_3D:
1028 maxDimension = caps.max3DTextureSize;
1029 break;
1030 case GL_TEXTURE_2D_ARRAY:
1031 maxDimension = caps.max2DTextureSize;
1032 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001033 case GL_TEXTURE_2D_MULTISAMPLE:
1034 maxDimension = caps.max2DTextureSize;
1035 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001036 default:
1037 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001038 }
1039
Brandon Jones6cad5662017-06-14 13:25:13 -07001040 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -04001041}
1042
Brandon Jones6cad5662017-06-14 13:25:13 -07001043bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001044 GLenum target,
1045 GLint level,
1046 GLsizei width,
1047 GLsizei height,
1048 GLsizei depth,
1049 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001050{
Brandon Jones6cad5662017-06-14 13:25:13 -07001051 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -04001052 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001053 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -04001054 return false;
1055 }
Austin Kinross08528e12015-10-07 16:24:40 -07001056 // TexSubImage parameters can be NPOT without textureNPOT extension,
1057 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001058 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001059 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001060 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001061 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001062 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001063 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -04001064 return false;
1065 }
1066
1067 if (!ValidMipLevel(context, target, level))
1068 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001069 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -04001070 return false;
1071 }
1072
1073 return true;
1074}
1075
Geoff Lang0d8b7242015-09-09 14:56:53 -04001076bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1077{
1078 // List of compressed format that require that the texture size is smaller than or a multiple of
1079 // the compressed block size.
1080 switch (internalFormat)
1081 {
1082 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1083 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1084 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1085 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -04001086 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
1087 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
1088 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
1089 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -08001090 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001091 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1092 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1093 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1094 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1095 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
1096 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001097 return true;
1098
1099 default:
1100 return false;
1101 }
1102}
1103
Geoff Lang966c9402017-04-18 12:38:27 -04001104bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
1105{
1106 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
1107 (size % blockSize == 0);
1108}
1109
Jamie Madillc29968b2016-01-20 11:17:23 -05001110bool ValidCompressedImageSize(const ValidationContext *context,
1111 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -04001112 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -05001113 GLsizei width,
1114 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001115{
Geoff Langca271392017-04-05 12:30:00 -04001116 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -04001117 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001118 {
1119 return false;
1120 }
1121
Geoff Lang966c9402017-04-18 12:38:27 -04001122 if (width < 0 || height < 0)
1123 {
1124 return false;
1125 }
1126
1127 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1128 {
1129 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
1130 // block size for level 0 but WebGL disallows this.
1131 bool smallerThanBlockSizeAllowed =
1132 level > 0 || !context->getExtensions().webglCompatibility;
1133
1134 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
1135 smallerThanBlockSizeAllowed) ||
1136 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
1137 smallerThanBlockSizeAllowed))
1138 {
1139 return false;
1140 }
1141 }
1142
1143 return true;
1144}
1145
1146bool ValidCompressedSubImageSize(const ValidationContext *context,
1147 GLenum internalFormat,
1148 GLint xoffset,
1149 GLint yoffset,
1150 GLsizei width,
1151 GLsizei height,
1152 size_t textureWidth,
1153 size_t textureHeight)
1154{
1155 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
1156 if (!formatInfo.compressed)
1157 {
1158 return false;
1159 }
1160
Geoff Lang44ff5a72017-02-03 15:15:43 -05001161 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001162 {
1163 return false;
1164 }
1165
Geoff Lang0d8b7242015-09-09 14:56:53 -04001166 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1167 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05001168 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -04001169 yoffset % formatInfo.compressedBlockHeight != 0)
1170 {
1171 return false;
1172 }
1173
1174 // Allowed to either have data that is a multiple of block size or is smaller than the block
1175 // size but fills the entire mip
1176 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
1177 static_cast<size_t>(width) == textureWidth &&
1178 static_cast<size_t>(height) == textureHeight;
1179 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
1180 (height % formatInfo.compressedBlockHeight) == 0;
1181 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -04001182 {
1183 return false;
1184 }
1185 }
1186
Geoff Langd4f180b2013-09-24 13:57:44 -04001187 return true;
1188}
1189
Geoff Langff5b2d52016-09-07 11:32:23 -04001190bool ValidImageDataSize(ValidationContext *context,
1191 GLenum textureTarget,
1192 GLsizei width,
1193 GLsizei height,
1194 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -04001195 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -04001196 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001197 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001198 GLsizei imageSize)
1199{
1200 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1201 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1202 {
1203 // Checks are not required
1204 return true;
1205 }
1206
1207 // ...the data would be unpacked from the buffer object such that the memory reads required
1208 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -04001209 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
1210 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -04001211 const gl::Extents size(width, height, depth);
1212 const auto &unpack = context->getGLState().getUnpackState();
1213
1214 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1215 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1216 if (endByteOrErr.isError())
1217 {
1218 context->handleError(endByteOrErr.getError());
1219 return false;
1220 }
1221
1222 GLuint endByte = endByteOrErr.getResult();
1223
1224 if (pixelUnpackBuffer)
1225 {
1226 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1227 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1228 checkedEndByte += checkedOffset;
1229
1230 if (!checkedEndByte.IsValid() ||
1231 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1232 {
1233 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001234 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04001235 return false;
1236 }
1237 }
1238 else
1239 {
1240 ASSERT(imageSize >= 0);
1241 if (pixels == nullptr && imageSize != 0)
1242 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001243 context->handleError(InvalidOperation()
1244 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001245 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001246 }
1247
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001248 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001249 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001250 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001251 return false;
1252 }
1253 }
1254
1255 return true;
1256}
1257
Geoff Lang37dde692014-01-31 16:34:54 -05001258bool ValidQueryType(const Context *context, GLenum queryType)
1259{
He Yunchaoced53ae2016-11-29 15:00:51 +08001260 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1261 "GL extension enums not equal.");
1262 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1263 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001264
1265 switch (queryType)
1266 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001267 case GL_ANY_SAMPLES_PASSED:
1268 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1269 return true;
1270 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1271 return (context->getClientMajorVersion() >= 3);
1272 case GL_TIME_ELAPSED_EXT:
1273 return context->getExtensions().disjointTimerQuery;
1274 case GL_COMMANDS_COMPLETED_CHROMIUM:
1275 return context->getExtensions().syncQuery;
1276 default:
1277 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001278 }
1279}
1280
Geoff Lang2d62ab72017-03-23 16:54:40 -04001281bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
1282 GLenum type,
1283 GLboolean normalized,
1284 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001285 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001286 bool pureInteger)
1287{
1288 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001289 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1290 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1291 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1292 // parameter exceeds 255.
1293 constexpr GLsizei kMaxWebGLStride = 255;
1294 if (stride > kMaxWebGLStride)
1295 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001296 context->handleError(InvalidValue()
1297 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001298 return false;
1299 }
1300
1301 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1302 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1303 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1304 // or an INVALID_OPERATION error is generated.
1305 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1306 size_t typeSize = GetVertexFormatTypeSize(internalType);
1307
1308 ASSERT(isPow2(typeSize) && typeSize > 0);
1309 size_t sizeMask = (typeSize - 1);
1310 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1311 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001312 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001313 return false;
1314 }
1315
1316 if ((stride & sizeMask) != 0)
1317 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001318 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001319 return false;
1320 }
1321
1322 return true;
1323}
1324
Jamie Madillef300b12016-10-07 15:12:09 -04001325Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001326{
He Yunchaoced53ae2016-11-29 15:00:51 +08001327 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1328 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1329 // or program object and INVALID_OPERATION if the provided name identifies an object
1330 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001331
Dian Xiang769769a2015-09-09 15:20:08 -07001332 Program *validProgram = context->getProgram(id);
1333
1334 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001335 {
Dian Xiang769769a2015-09-09 15:20:08 -07001336 if (context->getShader(id))
1337 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001338 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001339 }
1340 else
1341 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001342 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001343 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001344 }
Dian Xiang769769a2015-09-09 15:20:08 -07001345
1346 return validProgram;
1347}
1348
Jamie Madillef300b12016-10-07 15:12:09 -04001349Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001350{
1351 // See ValidProgram for spec details.
1352
1353 Shader *validShader = context->getShader(id);
1354
1355 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001356 {
Dian Xiang769769a2015-09-09 15:20:08 -07001357 if (context->getProgram(id))
1358 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001359 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001360 }
1361 else
1362 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001363 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001364 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001365 }
Dian Xiang769769a2015-09-09 15:20:08 -07001366
1367 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001368}
1369
Geoff Langb1196682014-07-23 13:47:29 -04001370bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001371{
1372 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1373 {
1374 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1375
Geoff Langaae65a42014-05-26 12:43:44 -04001376 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001377 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001378 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001379 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001380 }
1381 }
1382 else
1383 {
1384 switch (attachment)
1385 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001386 case GL_DEPTH_ATTACHMENT:
1387 case GL_STENCIL_ATTACHMENT:
1388 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001389
He Yunchaoced53ae2016-11-29 15:00:51 +08001390 case GL_DEPTH_STENCIL_ATTACHMENT:
1391 if (!context->getExtensions().webglCompatibility &&
1392 context->getClientMajorVersion() < 3)
1393 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001394 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001395 return false;
1396 }
1397 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001398
He Yunchaoced53ae2016-11-29 15:00:51 +08001399 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001400 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001401 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001402 }
1403 }
1404
1405 return true;
1406}
1407
Jamie Madille8fb6402017-02-14 17:56:40 -05001408bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001409 GLenum target,
1410 GLsizei samples,
1411 GLenum internalformat,
1412 GLsizei width,
1413 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001414{
1415 switch (target)
1416 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001417 case GL_RENDERBUFFER:
1418 break;
1419 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001420 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001421 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001422 }
1423
1424 if (width < 0 || height < 0 || samples < 0)
1425 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001426 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001427 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001428 }
1429
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001430 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1431 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1432
1433 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001434 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001435 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001436 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001437 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001438 }
1439
1440 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1441 // 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 -08001442 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001443 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1444 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001445 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001446 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001447 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001448 }
1449
Geoff Langaae65a42014-05-26 12:43:44 -04001450 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001451 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001452 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001453 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001454 }
1455
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001456 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001457 if (handle == 0)
1458 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001459 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001460 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001461 }
1462
1463 return true;
1464}
1465
He Yunchaoced53ae2016-11-29 15:00:51 +08001466bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1467 GLenum target,
1468 GLenum attachment,
1469 GLenum renderbuffertarget,
1470 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001471{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001472 if (!ValidFramebufferTarget(target))
1473 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001474 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001475 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001476 }
1477
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001478 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001479
Jamie Madill84115c92015-04-23 15:00:07 -04001480 ASSERT(framebuffer);
1481 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001482 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001483 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001484 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001485 }
1486
Jamie Madillb4472272014-07-03 10:38:55 -04001487 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001488 {
Jamie Madillb4472272014-07-03 10:38:55 -04001489 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001490 }
1491
Jamie Madillab9d82c2014-01-21 16:38:14 -05001492 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1493 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1494 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1495 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1496 if (renderbuffer != 0)
1497 {
1498 if (!context->getRenderbuffer(renderbuffer))
1499 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001500 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001501 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001502 }
1503 }
1504
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001505 return true;
1506}
1507
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001508bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001509 GLint srcX0,
1510 GLint srcY0,
1511 GLint srcX1,
1512 GLint srcY1,
1513 GLint dstX0,
1514 GLint dstY0,
1515 GLint dstX1,
1516 GLint dstY1,
1517 GLbitfield mask,
1518 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001519{
1520 switch (filter)
1521 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001522 case GL_NEAREST:
1523 break;
1524 case GL_LINEAR:
1525 break;
1526 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001527 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001528 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001529 }
1530
1531 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1532 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001533 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001534 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001535 }
1536
1537 if (mask == 0)
1538 {
1539 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1540 // buffers are copied.
1541 return false;
1542 }
1543
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001544 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1545 // color buffer, leaving only nearest being unfiltered from above
1546 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1547 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001548 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001549 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001550 }
1551
Jamie Madill51f40ec2016-06-15 14:06:00 -04001552 const auto &glState = context->getGLState();
1553 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1554 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001555
1556 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001557 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001558 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001559 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001560 }
1561
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001562 if (readFramebuffer->id() == drawFramebuffer->id())
1563 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001564 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001565 return false;
1566 }
1567
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001568 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001569 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001570 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001571 return false;
1572 }
1573
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001574 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001575 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001576 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001577 return false;
1578 }
1579
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001580 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001581 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001582 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001583 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001584 }
1585
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001586 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1587
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001588 if (mask & GL_COLOR_BUFFER_BIT)
1589 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001590 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001591 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001592
He Yunchao66a41a22016-12-15 16:45:05 +08001593 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001594 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001595 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001596
Geoff Langa15472a2015-08-11 11:48:03 -04001597 for (size_t drawbufferIdx = 0;
1598 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001599 {
Geoff Langa15472a2015-08-11 11:48:03 -04001600 const FramebufferAttachment *attachment =
1601 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1602 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001603 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001604 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001605
Geoff Langb2f3d052013-08-13 12:49:27 -04001606 // The GL ES 3.0.2 spec (pg 193) states that:
1607 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001608 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1609 // as well
1610 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1611 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001612 // Changes with EXT_color_buffer_float:
1613 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001614 GLenum readComponentType = readFormat.info->componentType;
1615 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001616 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001617 readComponentType == GL_SIGNED_NORMALIZED);
1618 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1619 drawComponentType == GL_SIGNED_NORMALIZED);
1620
1621 if (extensions.colorBufferFloat)
1622 {
1623 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1624 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1625
1626 if (readFixedOrFloat != drawFixedOrFloat)
1627 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001628 context->handleError(InvalidOperation()
1629 << "If the read buffer contains fixed-point or "
1630 "floating-point values, the draw buffer must "
1631 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001632 return false;
1633 }
1634 }
1635 else if (readFixedPoint != drawFixedPoint)
1636 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001637 context->handleError(InvalidOperation()
1638 << "If the read buffer contains fixed-point values, "
1639 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001640 return false;
1641 }
1642
1643 if (readComponentType == GL_UNSIGNED_INT &&
1644 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001646 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001647 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001648 }
1649
Jamie Madill6163c752015-12-07 16:32:59 -05001650 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001651 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001652 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001653 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001654 }
1655
Jamie Madilla3944d42016-07-22 22:13:26 -04001656 if (readColorBuffer->getSamples() > 0 &&
1657 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001659 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001660 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001661 }
Geoff Lange4915782017-04-12 15:19:07 -04001662
1663 if (context->getExtensions().webglCompatibility &&
1664 *readColorBuffer == *attachment)
1665 {
1666 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001667 InvalidOperation()
1668 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001669 return false;
1670 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001671 }
1672 }
1673
Jamie Madilla3944d42016-07-22 22:13:26 -04001674 if ((readFormat.info->componentType == GL_INT ||
1675 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1676 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001677 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001678 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001679 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001680 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001681 }
He Yunchao66a41a22016-12-15 16:45:05 +08001682 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1683 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1684 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1685 // situation is an application error that would lead to a crash in ANGLE.
1686 else if (drawFramebuffer->hasEnabledDrawBuffer())
1687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001688 context->handleError(
1689 InvalidOperation()
1690 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001691 return false;
1692 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001693 }
1694
He Yunchaoced53ae2016-11-29 15:00:51 +08001695 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001696 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1697 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001698 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001699 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001700 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001701 const gl::FramebufferAttachment *readBuffer =
1702 readFramebuffer->getAttachment(attachments[i]);
1703 const gl::FramebufferAttachment *drawBuffer =
1704 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001705
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001706 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001707 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001708 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001709 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001710 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001711 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001712 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001713
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001714 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001715 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001716 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001717 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001718 }
Geoff Lange4915782017-04-12 15:19:07 -04001719
1720 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1721 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001722 context->handleError(
1723 InvalidOperation()
1724 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001725 return false;
1726 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001727 }
He Yunchao66a41a22016-12-15 16:45:05 +08001728 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1729 else if (drawBuffer)
1730 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001731 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1732 "depth/stencil attachment of a "
1733 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001734 return false;
1735 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001736 }
1737 }
1738
1739 return true;
1740}
1741
Jamie Madill4928b7c2017-06-20 12:57:39 -04001742bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001743 GLint x,
1744 GLint y,
1745 GLsizei width,
1746 GLsizei height,
1747 GLenum format,
1748 GLenum type,
1749 GLsizei bufSize,
1750 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001751 GLsizei *columns,
1752 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001753 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001754{
1755 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001756 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001757 return false;
1758 }
1759
Geoff Lang62fce5b2016-09-30 10:46:35 -04001760 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001761 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001762 {
Geoff Langb1196682014-07-23 13:47:29 -04001763 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001764 }
1765
Geoff Lang62fce5b2016-09-30 10:46:35 -04001766 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001767 {
Geoff Langb1196682014-07-23 13:47:29 -04001768 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001769 }
1770
Jamie Madillc29968b2016-01-20 11:17:23 -05001771 return true;
1772}
1773
1774bool ValidateReadnPixelsEXT(Context *context,
1775 GLint x,
1776 GLint y,
1777 GLsizei width,
1778 GLsizei height,
1779 GLenum format,
1780 GLenum type,
1781 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001782 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001783{
1784 if (bufSize < 0)
1785 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001786 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001787 return false;
1788 }
1789
Geoff Lang62fce5b2016-09-30 10:46:35 -04001790 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001791 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001792}
Jamie Madill26e91952014-03-05 15:01:27 -05001793
Jamie Madill4928b7c2017-06-20 12:57:39 -04001794bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001795 GLint x,
1796 GLint y,
1797 GLsizei width,
1798 GLsizei height,
1799 GLenum format,
1800 GLenum type,
1801 GLsizei bufSize,
1802 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001803 GLsizei *columns,
1804 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001805 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001806{
1807 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001808 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001809 return false;
1810 }
1811
Geoff Lange93daba2017-03-30 13:54:40 -04001812 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1813 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001814 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001815 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001816 }
1817
Geoff Lang62fce5b2016-09-30 10:46:35 -04001818 if (!ValidateRobustBufferSize(context, bufSize, *length))
1819 {
1820 return false;
1821 }
1822
1823 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001824}
1825
Olli Etuaho41997e72016-03-10 13:38:39 +02001826bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001827{
1828 if (!context->getExtensions().occlusionQueryBoolean &&
1829 !context->getExtensions().disjointTimerQuery)
1830 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001831 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001832 return false;
1833 }
1834
Olli Etuaho41997e72016-03-10 13:38:39 +02001835 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001836}
1837
Olli Etuaho41997e72016-03-10 13:38:39 +02001838bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001839{
1840 if (!context->getExtensions().occlusionQueryBoolean &&
1841 !context->getExtensions().disjointTimerQuery)
1842 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001843 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001844 return false;
1845 }
1846
Olli Etuaho41997e72016-03-10 13:38:39 +02001847 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001848}
1849
1850bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001851{
1852 if (!ValidQueryType(context, target))
1853 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001854 context->handleError(InvalidEnum() << "Invalid query target");
Geoff Langb1196682014-07-23 13:47:29 -04001855 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001856 }
1857
1858 if (id == 0)
1859 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001860 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001861 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001862 }
1863
1864 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1865 // of zero, if the active query object name for <target> is non-zero (for the
1866 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1867 // the active query for either target is non-zero), if <id> is the name of an
1868 // existing query object whose type does not match <target>, or if <id> is the
1869 // active query object name for any query type, the error INVALID_OPERATION is
1870 // generated.
1871
1872 // Ensure no other queries are active
1873 // NOTE: If other queries than occlusion are supported, we will need to check
1874 // separately that:
1875 // a) The query ID passed is not the current active query for any target/type
1876 // b) There are no active queries for the requested target (and in the case
1877 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1878 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001879
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001880 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001881 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001882 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001883 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001884 }
1885
1886 Query *queryObject = context->getQuery(id, true, target);
1887
1888 // check that name was obtained with glGenQueries
1889 if (!queryObject)
1890 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001891 context->handleError(InvalidOperation() << "Invalid query id");
Geoff Langb1196682014-07-23 13:47:29 -04001892 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001893 }
1894
1895 // check for type mismatch
1896 if (queryObject->getType() != target)
1897 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001898 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001899 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001900 }
1901
1902 return true;
1903}
1904
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001905bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1906{
1907 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001908 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001909 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001910 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001911 return false;
1912 }
1913
1914 return ValidateBeginQueryBase(context, target, id);
1915}
1916
1917bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001918{
1919 if (!ValidQueryType(context, target))
1920 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001921 context->handleError(InvalidEnum() << "Invalid query target");
Geoff Langb1196682014-07-23 13:47:29 -04001922 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001923 }
1924
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001925 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001926
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001927 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001928 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001929 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001930 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001931 }
1932
Jamie Madill45c785d2014-05-13 14:09:34 -04001933 return true;
1934}
1935
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001936bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1937{
1938 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001939 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001940 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001941 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001942 return false;
1943 }
1944
1945 return ValidateEndQueryBase(context, target);
1946}
1947
1948bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1949{
1950 if (!context->getExtensions().disjointTimerQuery)
1951 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001952 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001953 return false;
1954 }
1955
1956 if (target != GL_TIMESTAMP_EXT)
1957 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001958 context->handleError(InvalidEnum() << "Invalid query target");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001959 return false;
1960 }
1961
1962 Query *queryObject = context->getQuery(id, true, target);
1963 if (queryObject == nullptr)
1964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001965 context->handleError(InvalidOperation() << "Invalid query id");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001966 return false;
1967 }
1968
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001969 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001970 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001971 context->handleError(InvalidOperation() << "Query is active");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001972 return false;
1973 }
1974
1975 return true;
1976}
1977
Geoff Lang2186c382016-10-14 10:54:54 -04001978bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001979{
Geoff Lang2186c382016-10-14 10:54:54 -04001980 if (numParams)
1981 {
1982 *numParams = 0;
1983 }
1984
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001985 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1986 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001987 context->handleError(InvalidEnum() << "Invalid query type");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001988 return false;
1989 }
1990
1991 switch (pname)
1992 {
1993 case GL_CURRENT_QUERY_EXT:
1994 if (target == GL_TIMESTAMP_EXT)
1995 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001996 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001997 return false;
1998 }
1999 break;
2000 case GL_QUERY_COUNTER_BITS_EXT:
2001 if (!context->getExtensions().disjointTimerQuery ||
2002 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2003 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002004 context->handleError(InvalidEnum() << "Invalid pname");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002005 return false;
2006 }
2007 break;
2008 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002009 context->handleError(InvalidEnum() << "Invalid pname");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002010 return false;
2011 }
2012
Geoff Lang2186c382016-10-14 10:54:54 -04002013 if (numParams)
2014 {
2015 // All queries return only one value
2016 *numParams = 1;
2017 }
2018
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002019 return true;
2020}
2021
2022bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2023{
2024 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002025 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002026 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002027 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002028 return false;
2029 }
2030
Geoff Lang2186c382016-10-14 10:54:54 -04002031 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002032}
2033
Geoff Lang2186c382016-10-14 10:54:54 -04002034bool ValidateGetQueryivRobustANGLE(Context *context,
2035 GLenum target,
2036 GLenum pname,
2037 GLsizei bufSize,
2038 GLsizei *length,
2039 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002040{
Geoff Lang2186c382016-10-14 10:54:54 -04002041 if (!ValidateRobustEntryPoint(context, bufSize))
2042 {
2043 return false;
2044 }
2045
2046 if (!ValidateGetQueryivBase(context, target, pname, length))
2047 {
2048 return false;
2049 }
2050
2051 if (!ValidateRobustBufferSize(context, bufSize, *length))
2052 {
2053 return false;
2054 }
2055
2056 return true;
2057}
2058
2059bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2060{
2061 if (numParams)
2062 {
2063 *numParams = 0;
2064 }
2065
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002066 Query *queryObject = context->getQuery(id, false, GL_NONE);
2067
2068 if (!queryObject)
2069 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002070 context->handleError(InvalidOperation() << "Query does not exist");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002071 return false;
2072 }
2073
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002074 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002075 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002076 context->handleError(InvalidOperation() << "Query currently active");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002077 return false;
2078 }
2079
2080 switch (pname)
2081 {
2082 case GL_QUERY_RESULT_EXT:
2083 case GL_QUERY_RESULT_AVAILABLE_EXT:
2084 break;
2085
2086 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002087 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002088 return false;
2089 }
2090
Geoff Lang2186c382016-10-14 10:54:54 -04002091 if (numParams)
2092 {
2093 *numParams = 1;
2094 }
2095
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002096 return true;
2097}
2098
2099bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2100{
2101 if (!context->getExtensions().disjointTimerQuery)
2102 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002103 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002104 return false;
2105 }
Geoff Lang2186c382016-10-14 10:54:54 -04002106 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2107}
2108
2109bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2110 GLuint id,
2111 GLenum pname,
2112 GLsizei bufSize,
2113 GLsizei *length,
2114 GLint *params)
2115{
2116 if (!context->getExtensions().disjointTimerQuery)
2117 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002118 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002119 return false;
2120 }
2121
2122 if (!ValidateRobustEntryPoint(context, bufSize))
2123 {
2124 return false;
2125 }
2126
2127 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2128 {
2129 return false;
2130 }
2131
2132 if (!ValidateRobustBufferSize(context, bufSize, *length))
2133 {
2134 return false;
2135 }
2136
2137 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002138}
2139
2140bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2141{
2142 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002143 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002144 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002145 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002146 return false;
2147 }
Geoff Lang2186c382016-10-14 10:54:54 -04002148 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2149}
2150
2151bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2152 GLuint id,
2153 GLenum pname,
2154 GLsizei bufSize,
2155 GLsizei *length,
2156 GLuint *params)
2157{
2158 if (!context->getExtensions().disjointTimerQuery &&
2159 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2160 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002161 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002162 return false;
2163 }
2164
2165 if (!ValidateRobustEntryPoint(context, bufSize))
2166 {
2167 return false;
2168 }
2169
2170 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2171 {
2172 return false;
2173 }
2174
2175 if (!ValidateRobustBufferSize(context, bufSize, *length))
2176 {
2177 return false;
2178 }
2179
2180 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002181}
2182
2183bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2184{
2185 if (!context->getExtensions().disjointTimerQuery)
2186 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002187 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002188 return false;
2189 }
Geoff Lang2186c382016-10-14 10:54:54 -04002190 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2191}
2192
2193bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2194 GLuint id,
2195 GLenum pname,
2196 GLsizei bufSize,
2197 GLsizei *length,
2198 GLint64 *params)
2199{
2200 if (!context->getExtensions().disjointTimerQuery)
2201 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002202 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002203 return false;
2204 }
2205
2206 if (!ValidateRobustEntryPoint(context, bufSize))
2207 {
2208 return false;
2209 }
2210
2211 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2212 {
2213 return false;
2214 }
2215
2216 if (!ValidateRobustBufferSize(context, bufSize, *length))
2217 {
2218 return false;
2219 }
2220
2221 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002222}
2223
2224bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2225{
2226 if (!context->getExtensions().disjointTimerQuery)
2227 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002228 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002229 return false;
2230 }
Geoff Lang2186c382016-10-14 10:54:54 -04002231 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2232}
2233
2234bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2235 GLuint id,
2236 GLenum pname,
2237 GLsizei bufSize,
2238 GLsizei *length,
2239 GLuint64 *params)
2240{
2241 if (!context->getExtensions().disjointTimerQuery)
2242 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002243 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002244 return false;
2245 }
2246
2247 if (!ValidateRobustEntryPoint(context, bufSize))
2248 {
2249 return false;
2250 }
2251
2252 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2253 {
2254 return false;
2255 }
2256
2257 if (!ValidateRobustBufferSize(context, bufSize, *length))
2258 {
2259 return false;
2260 }
2261
2262 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002263}
2264
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002265bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002266 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002267 GLuint program,
2268 GLint location,
2269 GLsizei count)
2270{
2271 // Check for ES31 program uniform entry points
2272 if (context->getClientVersion() < Version(3, 1))
2273 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002274 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002275 return false;
2276 }
2277
2278 const LinkedUniform *uniform = nullptr;
2279 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002280 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2281 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002282}
2283
Frank Henigmana98a6472017-02-02 21:38:32 -05002284bool ValidateProgramUniform1iv(gl::Context *context,
2285 GLuint program,
2286 GLint location,
2287 GLsizei count,
2288 const GLint *value)
2289{
2290 // Check for ES31 program uniform entry points
2291 if (context->getClientVersion() < Version(3, 1))
2292 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002293 context->handleError(InvalidOperation());
Frank Henigmana98a6472017-02-02 21:38:32 -05002294 return false;
2295 }
2296
2297 const LinkedUniform *uniform = nullptr;
2298 gl::Program *programObject = GetValidProgram(context, program);
2299 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2300 ValidateUniform1ivValue(context, uniform->type, count, value);
2301}
2302
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002303bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002304 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002305 GLuint program,
2306 GLint location,
2307 GLsizei count,
2308 GLboolean transpose)
2309{
2310 // Check for ES31 program uniform entry points
2311 if (context->getClientVersion() < Version(3, 1))
2312 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002313 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002314 return false;
2315 }
2316
2317 const LinkedUniform *uniform = nullptr;
2318 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002319 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2320 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002321}
2322
Jamie Madillc1d770e2017-04-13 17:31:24 -04002323bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002324{
2325 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002326 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002327 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002328 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002329 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002330 }
2331
Jamie Madill62d31cb2015-09-11 13:25:51 -04002332 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002333 gl::Program *programObject = context->getGLState().getProgram();
2334 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2335 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002336}
2337
Jamie Madillbe849e42017-05-02 15:49:00 -04002338bool ValidateUniform1iv(ValidationContext *context,
2339 GLint location,
2340 GLsizei count,
2341 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002342{
2343 const LinkedUniform *uniform = nullptr;
2344 gl::Program *programObject = context->getGLState().getProgram();
2345 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2346 ValidateUniform1ivValue(context, uniform->type, count, value);
2347}
2348
Jamie Madillc1d770e2017-04-13 17:31:24 -04002349bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002350 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002351 GLint location,
2352 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002353 GLboolean transpose)
2354{
2355 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002356 int rows = VariableRowCount(valueType);
2357 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002358 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002359 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002360 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002361 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002362 }
2363
Martin Radev1be913c2016-07-11 17:59:16 +03002364 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002365 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002366 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002367 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002368 }
2369
Jamie Madill62d31cb2015-09-11 13:25:51 -04002370 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002371 gl::Program *programObject = context->getGLState().getProgram();
2372 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2373 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002374}
2375
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002376bool ValidateStateQuery(ValidationContext *context,
2377 GLenum pname,
2378 GLenum *nativeType,
2379 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002380{
2381 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2382 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002383 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002384 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002385 }
2386
Jamie Madill0af26e12015-03-05 19:54:33 -05002387 const Caps &caps = context->getCaps();
2388
Jamie Madill893ab082014-05-16 16:56:10 -04002389 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2390 {
2391 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2392
Jamie Madill0af26e12015-03-05 19:54:33 -05002393 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002394 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002395 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002396 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002397 }
2398 }
2399
2400 switch (pname)
2401 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002402 case GL_TEXTURE_BINDING_2D:
2403 case GL_TEXTURE_BINDING_CUBE_MAP:
2404 case GL_TEXTURE_BINDING_3D:
2405 case GL_TEXTURE_BINDING_2D_ARRAY:
2406 break;
2407 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2408 if (!context->getExtensions().eglStreamConsumerExternal &&
2409 !context->getExtensions().eglImageExternal)
2410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002411 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2412 "nor GL_OES_EGL_image_external "
2413 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002414 return false;
2415 }
2416 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002417
He Yunchaoced53ae2016-11-29 15:00:51 +08002418 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2419 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002420 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002421 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2422 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002423 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002424 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002425 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002426 }
2427
Jamie Madill51f40ec2016-06-15 14:06:00 -04002428 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2429 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002430
2431 if (framebuffer->getReadBufferState() == GL_NONE)
2432 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002433 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Martin Radev138064f2016-07-15 12:03:41 +03002434 return false;
2435 }
2436
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002437 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002438 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002439 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002440 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002441 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002442 }
2443 }
2444 break;
2445
He Yunchaoced53ae2016-11-29 15:00:51 +08002446 default:
2447 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002448 }
2449
2450 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002451 if (*numParams == 0)
2452 {
2453 return false;
2454 }
2455
2456 return true;
2457}
2458
2459bool ValidateRobustStateQuery(ValidationContext *context,
2460 GLenum pname,
2461 GLsizei bufSize,
2462 GLenum *nativeType,
2463 unsigned int *numParams)
2464{
2465 if (!ValidateRobustEntryPoint(context, bufSize))
2466 {
2467 return false;
2468 }
2469
2470 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2471 {
2472 return false;
2473 }
2474
2475 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002476 {
2477 return false;
2478 }
2479
2480 return true;
2481}
2482
Jamie Madillc29968b2016-01-20 11:17:23 -05002483bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2484 GLenum target,
2485 GLint level,
2486 GLenum internalformat,
2487 bool isSubImage,
2488 GLint xoffset,
2489 GLint yoffset,
2490 GLint zoffset,
2491 GLint x,
2492 GLint y,
2493 GLsizei width,
2494 GLsizei height,
2495 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002496 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002497{
Brandon Jones6cad5662017-06-14 13:25:13 -07002498 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002499 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002500 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2501 return false;
2502 }
2503
2504 if (width < 0 || height < 0)
2505 {
2506 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002507 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002508 }
2509
He Yunchaoced53ae2016-11-29 15:00:51 +08002510 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2511 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002513 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002514 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002515 }
2516
2517 if (border != 0)
2518 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002519 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002520 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002521 }
2522
2523 if (!ValidMipLevel(context, target, level))
2524 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002525 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002526 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002527 }
2528
Jamie Madill51f40ec2016-06-15 14:06:00 -04002529 const auto &state = context->getGLState();
2530 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002531 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002532 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002533 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002534 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002535 }
2536
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002537 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002538 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002539 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002540 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002541 }
2542
Martin Radev138064f2016-07-15 12:03:41 +03002543 if (readFramebuffer->getReadBufferState() == GL_NONE)
2544 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002545 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Martin Radev138064f2016-07-15 12:03:41 +03002546 return false;
2547 }
2548
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002549 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2550 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002551 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002552 // situation is an application error that would lead to a crash in ANGLE.
2553 if (readFramebuffer->getReadColorbuffer() == nullptr)
2554 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002555 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002556 return false;
2557 }
2558
Geoff Langaae65a42014-05-26 12:43:44 -04002559 const gl::Caps &caps = context->getCaps();
2560
Geoff Langaae65a42014-05-26 12:43:44 -04002561 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002562 switch (target)
2563 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002564 case GL_TEXTURE_2D:
2565 maxDimension = caps.max2DTextureSize;
2566 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002567
He Yunchaoced53ae2016-11-29 15:00:51 +08002568 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2569 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2570 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2571 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2572 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2573 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2574 maxDimension = caps.maxCubeMapTextureSize;
2575 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002576
He Yunchaoced53ae2016-11-29 15:00:51 +08002577 case GL_TEXTURE_2D_ARRAY:
2578 maxDimension = caps.max2DTextureSize;
2579 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002580
He Yunchaoced53ae2016-11-29 15:00:51 +08002581 case GL_TEXTURE_3D:
2582 maxDimension = caps.max3DTextureSize;
2583 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002584
He Yunchaoced53ae2016-11-29 15:00:51 +08002585 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002586 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002587 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002588 }
2589
Jamie Madillc29968b2016-01-20 11:17:23 -05002590 gl::Texture *texture =
2591 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002592 if (!texture)
2593 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002594 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002595 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002596 }
2597
Geoff Lang69cce582015-09-17 13:20:36 -04002598 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002599 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002600 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002601 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002602 }
2603
Geoff Langca271392017-04-05 12:30:00 -04002604 const gl::InternalFormat &formatInfo =
2605 gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002606
Geoff Lang966c9402017-04-18 12:38:27 -04002607 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002608 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002609 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002610 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002611 }
2612
2613 if (isSubImage)
2614 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002615 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2616 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2617 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002618 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002619 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002620 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002621 }
2622 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002623 else
2624 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002625 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002626 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002627 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002628 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002629 }
2630
Geoff Langeb66a6e2016-10-31 13:06:12 -04002631 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002632 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002633 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002634 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002635 }
2636
2637 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002638 if (static_cast<int>(width) > maxLevelDimension ||
2639 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002640 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002641 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002642 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002643 }
2644 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002645
Jamie Madill0c8abca2016-07-22 20:21:26 -04002646 if (textureFormatOut)
2647 {
2648 *textureFormatOut = texture->getFormat(target, level);
2649 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002650
2651 // Detect texture copying feedback loops for WebGL.
2652 if (context->getExtensions().webglCompatibility)
2653 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002654 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002655 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002656 context->handleError(InvalidOperation() << "Texture copying feedback loop formed "
2657 "between Framebuffer and specified "
2658 "Texture level.");
Jamie Madillf695a3a2017-01-11 17:36:35 -05002659 return false;
2660 }
2661 }
2662
Jamie Madill560a8d82014-05-21 13:06:20 -04002663 return true;
2664}
2665
Jiajia Qind9671222016-11-29 16:30:31 +08002666bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002667{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002668 switch (mode)
2669 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002670 case GL_POINTS:
2671 case GL_LINES:
2672 case GL_LINE_LOOP:
2673 case GL_LINE_STRIP:
2674 case GL_TRIANGLES:
2675 case GL_TRIANGLE_STRIP:
2676 case GL_TRIANGLE_FAN:
2677 break;
2678 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002679 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002680 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002681 }
2682
Jamie Madill250d33f2014-06-06 17:09:03 -04002683 if (count < 0)
2684 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002685 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002686 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002687 }
2688
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002689 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002690
Jamie Madill250d33f2014-06-06 17:09:03 -04002691 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002692 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002693 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002694 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002695 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002696 }
2697
Jamie Madillcbcde722017-01-06 14:50:00 -05002698 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2699 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002700 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002701 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
2702 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002703 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002704 const FramebufferAttachment *dsAttachment =
2705 framebuffer->getStencilOrDepthStencilAttachment();
2706 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002707 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002708 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002709
2710 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2711 bool differentWritemasks =
2712 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2713 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2714 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2715 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2716
2717 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002718 {
Jamie Madillcbcde722017-01-06 14:50:00 -05002719 if (!context->getExtensions().webglCompatibility)
2720 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002721 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2722 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002723 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002724 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002725 return false;
2726 }
Jamie Madillac528012014-06-20 13:21:23 -04002727 }
2728
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002729 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002730 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002731 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002732 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002733 }
2734
Geoff Lang7dd2e102014-11-10 15:19:26 -05002735 gl::Program *program = state.getProgram();
2736 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002737 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002738 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002739 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002740 }
2741
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002742 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002743 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002744 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002745 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002746 }
2747
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002748 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002749 for (unsigned int uniformBlockIndex = 0;
2750 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002751 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002752 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002753 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002754 const OffsetBindingPointer<Buffer> &uniformBuffer =
2755 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002756
Geoff Lang5d124a62015-09-15 13:03:27 -04002757 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002758 {
2759 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002760 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002761 InvalidOperation()
2762 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002763 return false;
2764 }
2765
Geoff Lang5d124a62015-09-15 13:03:27 -04002766 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002767 if (uniformBufferSize == 0)
2768 {
2769 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002770 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002771 }
2772
Jamie Madill62d31cb2015-09-11 13:25:51 -04002773 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002774 {
2775 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002776 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002777 InvalidOperation()
2778 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002779 return false;
2780 }
2781 }
2782
Geoff Lange0cff192017-05-30 13:04:56 -04002783 // Do some additonal WebGL-specific validation
Jamie Madilla4595b82017-01-11 17:36:34 -05002784 if (context->getExtensions().webglCompatibility)
2785 {
Geoff Lange0cff192017-05-30 13:04:56 -04002786 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002787 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2788 {
2789 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002790 InvalidOperation()
2791 << "Rendering feedback loop formed between Framebuffer and active Texture.");
Jamie Madilla4595b82017-01-11 17:36:34 -05002792 return false;
2793 }
Geoff Lange0cff192017-05-30 13:04:56 -04002794
Geoff Lang9ab5b822017-05-30 16:19:23 -04002795 // Detect that the vertex shader input types match the attribute types
2796 if (!ValidateVertexShaderAttributeTypeMatch(context))
2797 {
2798 return false;
2799 }
2800
Geoff Lange0cff192017-05-30 13:04:56 -04002801 // Detect that the color buffer types match the fragment shader output types
2802 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2803 {
2804 return false;
2805 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002806 }
2807
Jamie Madill250d33f2014-06-06 17:09:03 -04002808 // No-op if zero count
2809 return (count > 0);
2810}
2811
Jamie Madillc1d770e2017-04-13 17:31:24 -04002812bool ValidateDrawArraysCommon(ValidationContext *context,
2813 GLenum mode,
2814 GLint first,
2815 GLsizei count,
2816 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002817{
Jamie Madillfd716582014-06-06 17:09:04 -04002818 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002819 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002820 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002821 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002822 }
2823
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002824 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002825 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002826 if (curTransformFeedback && curTransformFeedback->isActive() &&
2827 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002828 {
2829 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002830 // that does not match the current transform feedback object's draw mode (if transform
2831 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002832 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002833 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002834 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002835 }
2836
Jiajia Qind9671222016-11-29 16:30:31 +08002837 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002838 {
2839 return false;
2840 }
2841
Corentin Wallez71168a02016-12-19 15:11:18 -08002842 // Check the computation of maxVertex doesn't overflow.
2843 // - first < 0 or count < 0 have been checked as an error condition
2844 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2845 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2846 ASSERT(count > 0 && first >= 0);
2847 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2848 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002849 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002850 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002851 return false;
2852 }
2853
Corentin Wallez71168a02016-12-19 15:11:18 -08002854 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002855 {
2856 return false;
2857 }
2858
2859 return true;
2860}
2861
He Yunchaoced53ae2016-11-29 15:00:51 +08002862bool ValidateDrawArraysInstanced(Context *context,
2863 GLenum mode,
2864 GLint first,
2865 GLsizei count,
2866 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002867{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002868 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
Geoff Lang87a93302014-09-16 13:29:43 -04002869}
2870
He Yunchaoced53ae2016-11-29 15:00:51 +08002871bool ValidateDrawArraysInstancedANGLE(Context *context,
2872 GLenum mode,
2873 GLint first,
2874 GLsizei count,
2875 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002876{
Corentin Wallez170efbf2017-05-02 13:45:01 -04002877 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002878 {
2879 return false;
2880 }
2881
Corentin Wallez0dc97812017-06-22 14:38:44 -04002882 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002883}
2884
Jiajia Qind9671222016-11-29 16:30:31 +08002885bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002886{
Jamie Madill250d33f2014-06-06 17:09:03 -04002887 switch (type)
2888 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002889 case GL_UNSIGNED_BYTE:
2890 case GL_UNSIGNED_SHORT:
2891 break;
2892 case GL_UNSIGNED_INT:
2893 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2894 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002895 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002896 return false;
2897 }
2898 break;
2899 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002900 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002901 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002902 }
2903
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002904 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002905
2906 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002907 if (curTransformFeedback && curTransformFeedback->isActive() &&
2908 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002909 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002910 // It is an invalid operation to call DrawElements, DrawRangeElements or
2911 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002912 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002913 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002914 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002915 }
2916
Jiajia Qind9671222016-11-29 16:30:31 +08002917 return true;
2918}
2919
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002920bool ValidateDrawElementsCommon(ValidationContext *context,
2921 GLenum mode,
2922 GLsizei count,
2923 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002924 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002925 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002926{
2927 if (!ValidateDrawElementsBase(context, type))
2928 return false;
2929
2930 const State &state = context->getGLState();
2931
Corentin Wallez170efbf2017-05-02 13:45:01 -04002932 if (!ValidateDrawBase(context, mode, count))
2933 {
2934 return false;
2935 }
2936
Jamie Madill250d33f2014-06-06 17:09:03 -04002937 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002938 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002939 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002940 context->handleError(InvalidOperation() << "Index buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -04002941 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002942 }
2943
He Yunchaoced53ae2016-11-29 15:00:51 +08002944 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002945 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002946
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002947 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2948
2949 if (context->getExtensions().webglCompatibility)
2950 {
2951 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2952 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2953 {
2954 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2955 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2956 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002957 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002958 return false;
2959 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002960
2961 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2962 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2963 // error is generated.
2964 if (reinterpret_cast<intptr_t>(indices) < 0)
2965 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002966 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002967 return false;
2968 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002969 }
2970
2971 if (context->getExtensions().webglCompatibility ||
2972 !context->getGLState().areClientArraysEnabled())
2973 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002974 if (!elementArrayBuffer && count > 0)
2975 {
2976 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2977 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2978 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002979 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002980 return false;
2981 }
2982 }
2983
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002984 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002985 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002986 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002987 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002988 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2989 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2990 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2991 constexpr uint64_t kMaxTypeSize = 8;
2992 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2993 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2994 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002995
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002996 uint64_t typeSize = typeBytes;
2997 uint64_t elementCount = static_cast<uint64_t>(count);
2998 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2999
3000 // Doing the multiplication here is overflow-safe
3001 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3002
3003 // The offset can be any value, check for overflows
3004 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3005 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003006 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003007 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003008 return false;
3009 }
3010
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003011 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3012 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003013 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003014 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003015 return false;
3016 }
3017 }
3018 else if (!indices)
3019 {
3020 // This is an application error that would normally result in a crash,
3021 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003022 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04003023 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003024 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003025 }
3026
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003027 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill2b976812014-08-25 15:47:49 -04003028 // TODO: offer fast path, with disabled index validation.
3029 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003030 const auto &params = context->getParams<HasIndexRange>();
3031 const auto &indexRangeOpt = params.getIndexRange();
3032 if (!indexRangeOpt.valid())
Jamie Madill2b976812014-08-25 15:47:49 -04003033 {
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003034 // Unexpected error.
3035 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003036 }
3037
Jamie Madille79b1e12015-11-04 16:36:37 -05003038 // If we use an index greater than our maximum supported index range, return an error.
3039 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3040 // return an error if possible here.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003041 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
Jamie Madille79b1e12015-11-04 16:36:37 -05003042 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003043 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
Jamie Madille79b1e12015-11-04 16:36:37 -05003044 return false;
3045 }
3046
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003047 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
3048 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003049 {
3050 return false;
3051 }
3052
Geoff Lang3edfe032015-09-04 16:38:24 -04003053 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003054 return (indexRangeOpt.value().vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003055}
3056
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003057bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
3058 GLenum mode,
3059 GLsizei count,
3060 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003061 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003062 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003063{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003064 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003065}
3066
Geoff Lang3edfe032015-09-04 16:38:24 -04003067bool ValidateDrawElementsInstancedANGLE(Context *context,
3068 GLenum mode,
3069 GLsizei count,
3070 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003071 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003072 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003073{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003074 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003075 {
3076 return false;
3077 }
3078
Corentin Wallez0dc97812017-06-22 14:38:44 -04003079 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003080}
3081
He Yunchaoced53ae2016-11-29 15:00:51 +08003082bool ValidateFramebufferTextureBase(Context *context,
3083 GLenum target,
3084 GLenum attachment,
3085 GLuint texture,
3086 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003087{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003088 if (!ValidFramebufferTarget(target))
3089 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003090 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003091 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003092 }
3093
3094 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003095 {
3096 return false;
3097 }
3098
Jamie Madill55ec3b12014-07-03 10:38:57 -04003099 if (texture != 0)
3100 {
3101 gl::Texture *tex = context->getTexture(texture);
3102
Jamie Madillbe849e42017-05-02 15:49:00 -04003103 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003104 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003105 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003106 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003107 }
3108
3109 if (level < 0)
3110 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003111 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003112 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003113 }
3114 }
3115
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003116 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003117 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003118
Jamie Madill84115c92015-04-23 15:00:07 -04003119 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003120 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003121 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003122 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003123 }
3124
3125 return true;
3126}
3127
Geoff Langb1196682014-07-23 13:47:29 -04003128bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003129{
3130 if (program == 0)
3131 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003132 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003133 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003134 }
3135
Dian Xiang769769a2015-09-09 15:20:08 -07003136 gl::Program *programObject = GetValidProgram(context, program);
3137 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003138 {
3139 return false;
3140 }
3141
Jamie Madill0063c512014-08-25 15:47:53 -04003142 if (!programObject || !programObject->isLinked())
3143 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003144 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003145 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003146 }
3147
Geoff Lang7dd2e102014-11-10 15:19:26 -05003148 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003149 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003150 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003151 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003152 }
3153
Jamie Madill0063c512014-08-25 15:47:53 -04003154 return true;
3155}
3156
Geoff Langf41d0ee2016-10-07 13:04:23 -04003157static bool ValidateSizedGetUniform(Context *context,
3158 GLuint program,
3159 GLint location,
3160 GLsizei bufSize,
3161 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003162{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003163 if (length)
3164 {
3165 *length = 0;
3166 }
3167
Jamie Madill78f41802014-08-25 15:47:55 -04003168 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003169 {
Jamie Madill78f41802014-08-25 15:47:55 -04003170 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003171 }
3172
Geoff Langf41d0ee2016-10-07 13:04:23 -04003173 if (bufSize < 0)
3174 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003175 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003176 return false;
3177 }
3178
Jamie Madilla502c742014-08-28 17:19:13 -04003179 gl::Program *programObject = context->getProgram(program);
3180 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003181
Jamie Madill78f41802014-08-25 15:47:55 -04003182 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003183 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003184 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003185 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003186 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003187 context->handleError(InvalidOperation()
3188 << "bufSize of at least " << requiredBytes << " is required.");
Geoff Langb1196682014-07-23 13:47:29 -04003189 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003190 }
3191
Geoff Langf41d0ee2016-10-07 13:04:23 -04003192 if (length)
3193 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003194 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003195 }
3196
Jamie Madill0063c512014-08-25 15:47:53 -04003197 return true;
3198}
3199
He Yunchaoced53ae2016-11-29 15:00:51 +08003200bool ValidateGetnUniformfvEXT(Context *context,
3201 GLuint program,
3202 GLint location,
3203 GLsizei bufSize,
3204 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003205{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003206 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003207}
3208
He Yunchaoced53ae2016-11-29 15:00:51 +08003209bool ValidateGetnUniformivEXT(Context *context,
3210 GLuint program,
3211 GLint location,
3212 GLsizei bufSize,
3213 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003214{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003215 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3216}
3217
3218bool ValidateGetUniformfvRobustANGLE(Context *context,
3219 GLuint program,
3220 GLint location,
3221 GLsizei bufSize,
3222 GLsizei *length,
3223 GLfloat *params)
3224{
3225 if (!ValidateRobustEntryPoint(context, bufSize))
3226 {
3227 return false;
3228 }
3229
3230 // bufSize is validated in ValidateSizedGetUniform
3231 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3232}
3233
3234bool ValidateGetUniformivRobustANGLE(Context *context,
3235 GLuint program,
3236 GLint location,
3237 GLsizei bufSize,
3238 GLsizei *length,
3239 GLint *params)
3240{
3241 if (!ValidateRobustEntryPoint(context, bufSize))
3242 {
3243 return false;
3244 }
3245
3246 // bufSize is validated in ValidateSizedGetUniform
3247 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3248}
3249
3250bool ValidateGetUniformuivRobustANGLE(Context *context,
3251 GLuint program,
3252 GLint location,
3253 GLsizei bufSize,
3254 GLsizei *length,
3255 GLuint *params)
3256{
3257 if (!ValidateRobustEntryPoint(context, bufSize))
3258 {
3259 return false;
3260 }
3261
3262 if (context->getClientMajorVersion() < 3)
3263 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003264 context->handleError(InvalidOperation() << "Entry point requires at least OpenGL ES 3.0.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003265 return false;
3266 }
3267
3268 // bufSize is validated in ValidateSizedGetUniform
3269 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003270}
3271
He Yunchaoced53ae2016-11-29 15:00:51 +08003272bool ValidateDiscardFramebufferBase(Context *context,
3273 GLenum target,
3274 GLsizei numAttachments,
3275 const GLenum *attachments,
3276 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003277{
3278 if (numAttachments < 0)
3279 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003280 context->handleError(InvalidValue() << "numAttachments must not be less than zero");
Austin Kinross08332632015-05-05 13:35:47 -07003281 return false;
3282 }
3283
3284 for (GLsizei i = 0; i < numAttachments; ++i)
3285 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003286 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003287 {
3288 if (defaultFramebuffer)
3289 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003290 context->handleError(InvalidEnum()
3291 << "Invalid attachment when the default framebuffer is bound");
Austin Kinross08332632015-05-05 13:35:47 -07003292 return false;
3293 }
3294
3295 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3296 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003297 context->handleError(InvalidOperation() << "Requested color attachment is "
3298 "greater than the maximum supported "
3299 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003300 return false;
3301 }
3302 }
3303 else
3304 {
3305 switch (attachments[i])
3306 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003307 case GL_DEPTH_ATTACHMENT:
3308 case GL_STENCIL_ATTACHMENT:
3309 case GL_DEPTH_STENCIL_ATTACHMENT:
3310 if (defaultFramebuffer)
3311 {
3312 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003313 InvalidEnum()
3314 << "Invalid attachment when the default framebuffer is bound");
He Yunchaoced53ae2016-11-29 15:00:51 +08003315 return false;
3316 }
3317 break;
3318 case GL_COLOR:
3319 case GL_DEPTH:
3320 case GL_STENCIL:
3321 if (!defaultFramebuffer)
3322 {
3323 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003324 InvalidEnum()
3325 << "Invalid attachment when the default framebuffer is not bound");
He Yunchaoced53ae2016-11-29 15:00:51 +08003326 return false;
3327 }
3328 break;
3329 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003330 context->handleError(InvalidEnum() << "Invalid attachment");
Austin Kinross08332632015-05-05 13:35:47 -07003331 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003332 }
3333 }
3334 }
3335
3336 return true;
3337}
3338
Austin Kinross6ee1e782015-05-29 17:05:37 -07003339bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3340{
3341 // Note that debug marker calls must not set error state
3342
3343 if (length < 0)
3344 {
3345 return false;
3346 }
3347
3348 if (marker == nullptr)
3349 {
3350 return false;
3351 }
3352
3353 return true;
3354}
3355
3356bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3357{
3358 // Note that debug marker calls must not set error state
3359
3360 if (length < 0)
3361 {
3362 return false;
3363 }
3364
3365 if (length > 0 && marker == nullptr)
3366 {
3367 return false;
3368 }
3369
3370 return true;
3371}
3372
Geoff Langdcab33b2015-07-21 13:03:16 -04003373bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003374 GLenum target,
3375 egl::Image *image)
3376{
Geoff Langa8406172015-07-21 16:53:39 -04003377 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3378 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003379 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003380 return false;
3381 }
3382
3383 switch (target)
3384 {
3385 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003386 if (!context->getExtensions().eglImage)
3387 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003388 context->handleError(InvalidEnum()
3389 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003390 }
3391 break;
3392
3393 case GL_TEXTURE_EXTERNAL_OES:
3394 if (!context->getExtensions().eglImageExternal)
3395 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003396 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3397 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003398 }
Geoff Langa8406172015-07-21 16:53:39 -04003399 break;
3400
3401 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003402 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003403 return false;
3404 }
3405
Jamie Madill61e16b42017-06-19 11:13:23 -04003406 ASSERT(context->getCurrentDisplay());
3407 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003408 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003409 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003410 return false;
3411 }
3412
3413 if (image->getSamples() > 0)
3414 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003415 context->handleError(InvalidOperation()
3416 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003417 return false;
3418 }
3419
Geoff Langca271392017-04-05 12:30:00 -04003420 const TextureCaps &textureCaps =
3421 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003422 if (!textureCaps.texturable)
3423 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003424 context->handleError(InvalidOperation()
3425 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003426 return false;
3427 }
3428
Geoff Langdcab33b2015-07-21 13:03:16 -04003429 return true;
3430}
3431
3432bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003433 GLenum target,
3434 egl::Image *image)
3435{
Geoff Langa8406172015-07-21 16:53:39 -04003436 if (!context->getExtensions().eglImage)
3437 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003438 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003439 return false;
3440 }
3441
3442 switch (target)
3443 {
3444 case GL_RENDERBUFFER:
3445 break;
3446
3447 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003448 context->handleError(InvalidEnum() << "invalid renderbuffer target.");
Geoff Langa8406172015-07-21 16:53:39 -04003449 return false;
3450 }
3451
Jamie Madill61e16b42017-06-19 11:13:23 -04003452 ASSERT(context->getCurrentDisplay());
3453 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003454 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003455 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003456 return false;
3457 }
3458
Geoff Langca271392017-04-05 12:30:00 -04003459 const TextureCaps &textureCaps =
3460 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003461 if (!textureCaps.renderable)
3462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003463 context->handleError(InvalidOperation()
3464 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003465 return false;
3466 }
3467
Geoff Langdcab33b2015-07-21 13:03:16 -04003468 return true;
3469}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003470
3471bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3472{
Geoff Lang36167ab2015-12-07 10:27:14 -05003473 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003474 {
3475 // The default VAO should always exist
3476 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003477 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003478 return false;
3479 }
3480
3481 return true;
3482}
3483
Geoff Langc5629752015-12-07 16:29:04 -05003484bool ValidateProgramBinaryBase(Context *context,
3485 GLuint program,
3486 GLenum binaryFormat,
3487 const void *binary,
3488 GLint length)
3489{
3490 Program *programObject = GetValidProgram(context, program);
3491 if (programObject == nullptr)
3492 {
3493 return false;
3494 }
3495
3496 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3497 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3498 programBinaryFormats.end())
3499 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003500 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003501 return false;
3502 }
3503
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003504 if (context->hasActiveTransformFeedback(program))
3505 {
3506 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003507 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3508 "is associated with an active transform "
3509 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003510 return false;
3511 }
3512
Geoff Langc5629752015-12-07 16:29:04 -05003513 return true;
3514}
3515
3516bool ValidateGetProgramBinaryBase(Context *context,
3517 GLuint program,
3518 GLsizei bufSize,
3519 GLsizei *length,
3520 GLenum *binaryFormat,
3521 void *binary)
3522{
3523 Program *programObject = GetValidProgram(context, program);
3524 if (programObject == nullptr)
3525 {
3526 return false;
3527 }
3528
3529 if (!programObject->isLinked())
3530 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003531 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003532 return false;
3533 }
3534
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003535 if (context->getCaps().programBinaryFormats.empty())
3536 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003537 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003538 return false;
3539 }
3540
Geoff Langc5629752015-12-07 16:29:04 -05003541 return true;
3542}
Jamie Madillc29968b2016-01-20 11:17:23 -05003543
Jamie Madillc29968b2016-01-20 11:17:23 -05003544bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3545{
3546 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3547 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3548 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003549 context->handleError(InvalidValue()
3550 << "n must be non-negative and no greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003551 return false;
3552 }
3553
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003554 ASSERT(context->getGLState().getDrawFramebuffer());
3555 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003556 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3557
3558 // This should come first before the check for the default frame buffer
3559 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3560 // rather than INVALID_OPERATION
3561 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3562 {
3563 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3564
3565 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003566 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3567 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003568 {
3569 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003570 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3571 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3572 // 3.1 is still a bit ambiguous about the error, but future specs are
3573 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003574 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003575 return false;
3576 }
3577 else if (bufs[colorAttachment] >= maxColorAttachment)
3578 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003579 context->handleError(InvalidOperation()
3580 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003581 return false;
3582 }
3583 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3584 frameBufferId != 0)
3585 {
3586 // INVALID_OPERATION-GL is bound to buffer and ith argument
3587 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003588 context->handleError(InvalidOperation()
3589 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003590 return false;
3591 }
3592 }
3593
3594 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3595 // and n is not 1 or bufs is bound to value other than BACK and NONE
3596 if (frameBufferId == 0)
3597 {
3598 if (n != 1)
3599 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003600 context->handleError(InvalidOperation()
3601 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003602 return false;
3603 }
3604
3605 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3606 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003607 context->handleError(
3608 InvalidOperation()
3609 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003610 return false;
3611 }
3612 }
3613
3614 return true;
3615}
3616
Geoff Lang496c02d2016-10-20 11:38:11 -07003617bool ValidateGetBufferPointervBase(Context *context,
3618 GLenum target,
3619 GLenum pname,
3620 GLsizei *length,
3621 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003622{
Geoff Lang496c02d2016-10-20 11:38:11 -07003623 if (length)
3624 {
3625 *length = 0;
3626 }
3627
3628 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3629 {
3630 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003631 InvalidOperation()
3632 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003633 return false;
3634 }
3635
Olli Etuaho4f667482016-03-30 15:56:35 +03003636 if (!ValidBufferTarget(context, target))
3637 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003638 context->handleError(InvalidEnum() << "Buffer target not valid: 0x" << std::hex
3639 << std::uppercase << target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003640 return false;
3641 }
3642
Geoff Lang496c02d2016-10-20 11:38:11 -07003643 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003644 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003645 case GL_BUFFER_MAP_POINTER:
3646 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003647
Geoff Lang496c02d2016-10-20 11:38:11 -07003648 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003649 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003650 return false;
3651 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003652
3653 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3654 // target bound to zero generate an INVALID_OPERATION error."
3655 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003656 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003657 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003658 context->handleError(InvalidOperation()
3659 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003660 return false;
3661 }
3662
Geoff Lang496c02d2016-10-20 11:38:11 -07003663 if (length)
3664 {
3665 *length = 1;
3666 }
3667
Olli Etuaho4f667482016-03-30 15:56:35 +03003668 return true;
3669}
3670
3671bool ValidateUnmapBufferBase(Context *context, GLenum target)
3672{
3673 if (!ValidBufferTarget(context, target))
3674 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003675 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003676 return false;
3677 }
3678
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003679 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003680
3681 if (buffer == nullptr || !buffer->isMapped())
3682 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003683 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003684 return false;
3685 }
3686
3687 return true;
3688}
3689
3690bool ValidateMapBufferRangeBase(Context *context,
3691 GLenum target,
3692 GLintptr offset,
3693 GLsizeiptr length,
3694 GLbitfield access)
3695{
3696 if (!ValidBufferTarget(context, target))
3697 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003698 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003699 return false;
3700 }
3701
Brandon Jones6cad5662017-06-14 13:25:13 -07003702 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003703 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003704 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3705 return false;
3706 }
3707
3708 if (length < 0)
3709 {
3710 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003711 return false;
3712 }
3713
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003714 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003715
3716 if (!buffer)
3717 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003718 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003719 return false;
3720 }
3721
3722 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003723 CheckedNumeric<size_t> checkedOffset(offset);
3724 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003725
Jamie Madille2e406c2016-06-02 13:04:10 -04003726 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003727 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003728 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003729 return false;
3730 }
3731
3732 // Check for invalid bits in the mask
3733 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3734 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3735 GL_MAP_UNSYNCHRONIZED_BIT;
3736
3737 if (access & ~(allAccessBits))
3738 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003739 context->handleError(InvalidValue()
3740 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003741 return false;
3742 }
3743
3744 if (length == 0)
3745 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003746 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003747 return false;
3748 }
3749
3750 if (buffer->isMapped())
3751 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003752 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003753 return false;
3754 }
3755
3756 // Check for invalid bit combinations
3757 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3758 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003759 context->handleError(InvalidOperation()
3760 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003761 return false;
3762 }
3763
3764 GLbitfield writeOnlyBits =
3765 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3766
3767 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3768 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003769 context->handleError(InvalidOperation()
3770 << "Invalid access bits when mapping buffer for reading: 0x"
3771 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003772 return false;
3773 }
3774
3775 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3776 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003777 context->handleError(
3778 InvalidOperation()
3779 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003780 return false;
3781 }
3782 return true;
3783}
3784
3785bool ValidateFlushMappedBufferRangeBase(Context *context,
3786 GLenum target,
3787 GLintptr offset,
3788 GLsizeiptr length)
3789{
Brandon Jones6cad5662017-06-14 13:25:13 -07003790 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003791 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003792 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3793 return false;
3794 }
3795
3796 if (length < 0)
3797 {
3798 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003799 return false;
3800 }
3801
3802 if (!ValidBufferTarget(context, target))
3803 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003804 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003805 return false;
3806 }
3807
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003808 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003809
3810 if (buffer == nullptr)
3811 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003812 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003813 return false;
3814 }
3815
3816 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3817 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003818 context->handleError(InvalidOperation()
3819 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003820 return false;
3821 }
3822
3823 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003824 CheckedNumeric<size_t> checkedOffset(offset);
3825 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003826
Jamie Madille2e406c2016-06-02 13:04:10 -04003827 if (!checkedSize.IsValid() ||
3828 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003829 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003830 context->handleError(InvalidValue()
3831 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003832 return false;
3833 }
3834
3835 return true;
3836}
3837
Olli Etuaho41997e72016-03-10 13:38:39 +02003838bool ValidateGenOrDelete(Context *context, GLint n)
3839{
3840 if (n < 0)
3841 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003842 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003843 return false;
3844 }
3845 return true;
3846}
3847
Geoff Langff5b2d52016-09-07 11:32:23 -04003848bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3849{
3850 if (!context->getExtensions().robustClientMemory)
3851 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003852 context->handleError(InvalidOperation()
3853 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003854 return false;
3855 }
3856
3857 if (bufSize < 0)
3858 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003859 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003860 return false;
3861 }
3862
3863 return true;
3864}
3865
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003866bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3867{
3868 if (bufSize < numParams)
3869 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003870 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3871 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003872 return false;
3873 }
3874
3875 return true;
3876}
3877
Jamie Madillbe849e42017-05-02 15:49:00 -04003878bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3879 GLenum target,
3880 GLenum attachment,
3881 GLenum pname,
3882 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003883{
3884 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
Yunchao He33151a52017-04-13 09:58:17 +08003885 if (numParams)
3886 {
3887 *numParams = 1;
3888 }
Geoff Langff5b2d52016-09-07 11:32:23 -04003889
3890 if (!ValidFramebufferTarget(target))
3891 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003892 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003893 return false;
3894 }
3895
3896 int clientVersion = context->getClientMajorVersion();
3897
3898 switch (pname)
3899 {
3900 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3901 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3902 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3903 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3904 break;
3905
3906 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3907 if (clientVersion < 3 && !context->getExtensions().sRGB)
3908 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003909 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003910 return false;
3911 }
3912 break;
3913
3914 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3915 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3916 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3917 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3918 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3919 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3920 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3921 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3922 if (clientVersion < 3)
3923 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003924 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003925 return false;
3926 }
3927 break;
3928
3929 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003930 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003931 return false;
3932 }
3933
3934 // Determine if the attachment is a valid enum
3935 switch (attachment)
3936 {
3937 case GL_BACK:
3938 case GL_FRONT:
3939 case GL_DEPTH:
3940 case GL_STENCIL:
3941 case GL_DEPTH_STENCIL_ATTACHMENT:
3942 if (clientVersion < 3)
3943 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003944 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003945 return false;
3946 }
3947 break;
3948
3949 case GL_DEPTH_ATTACHMENT:
3950 case GL_STENCIL_ATTACHMENT:
3951 break;
3952
3953 default:
3954 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
3955 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3956 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003957 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003958 return false;
3959 }
3960 break;
3961 }
3962
3963 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3964 ASSERT(framebuffer);
3965
3966 if (framebuffer->id() == 0)
3967 {
3968 if (clientVersion < 3)
3969 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003970 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003971 return false;
3972 }
3973
3974 switch (attachment)
3975 {
3976 case GL_BACK:
3977 case GL_DEPTH:
3978 case GL_STENCIL:
3979 break;
3980
3981 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003982 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FramebufferInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003983 return false;
3984 }
3985 }
3986 else
3987 {
3988 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3989 {
3990 // Valid attachment query
3991 }
3992 else
3993 {
3994 switch (attachment)
3995 {
3996 case GL_DEPTH_ATTACHMENT:
3997 case GL_STENCIL_ATTACHMENT:
3998 break;
3999
4000 case GL_DEPTH_STENCIL_ATTACHMENT:
4001 if (!framebuffer->hasValidDepthStencil())
4002 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004003 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004004 return false;
4005 }
4006 break;
4007
4008 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004009 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FramebufferInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004010 return false;
4011 }
4012 }
4013 }
4014
4015 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4016 if (attachmentObject)
4017 {
4018 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4019 attachmentObject->type() == GL_TEXTURE ||
4020 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4021
4022 switch (pname)
4023 {
4024 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4025 if (attachmentObject->type() != GL_RENDERBUFFER &&
4026 attachmentObject->type() != GL_TEXTURE)
4027 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004028 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004029 return false;
4030 }
4031 break;
4032
4033 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4034 if (attachmentObject->type() != GL_TEXTURE)
4035 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004036 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004037 return false;
4038 }
4039 break;
4040
4041 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4042 if (attachmentObject->type() != GL_TEXTURE)
4043 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004044 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004045 return false;
4046 }
4047 break;
4048
4049 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4050 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4051 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004052 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FramebufferInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004053 return false;
4054 }
4055 break;
4056
4057 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4058 if (attachmentObject->type() != GL_TEXTURE)
4059 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004060 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004061 return false;
4062 }
4063 break;
4064
4065 default:
4066 break;
4067 }
4068 }
4069 else
4070 {
4071 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4072 // is NONE, then querying any other pname will generate INVALID_ENUM.
4073
4074 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4075 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4076 // INVALID_OPERATION for all other pnames
4077
4078 switch (pname)
4079 {
4080 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4081 break;
4082
4083 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4084 if (clientVersion < 3)
4085 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004086 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
4087 InvalidRenderbufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004088 return false;
4089 }
4090 break;
4091
4092 default:
4093 if (clientVersion < 3)
4094 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004095 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
4096 InvalidRenderbufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004097 return false;
4098 }
4099 else
4100 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004101 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
4102 InvalidRenderbufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004103 return false;
4104 }
4105 }
4106 }
4107
4108 return true;
4109}
4110
4111bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4112 GLenum target,
4113 GLenum attachment,
4114 GLenum pname,
4115 GLsizei bufSize,
4116 GLsizei *numParams)
4117{
4118 if (!ValidateRobustEntryPoint(context, bufSize))
4119 {
4120 return false;
4121 }
4122
Jamie Madillbe849e42017-05-02 15:49:00 -04004123 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4124 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004125 {
4126 return false;
4127 }
4128
4129 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4130 {
4131 return false;
4132 }
4133
4134 return true;
4135}
4136
Geoff Langff5b2d52016-09-07 11:32:23 -04004137bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4138 GLenum target,
4139 GLenum pname,
4140 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004141 GLsizei *length,
4142 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004143{
4144 if (!ValidateRobustEntryPoint(context, bufSize))
4145 {
4146 return false;
4147 }
4148
Geoff Langebebe1c2016-10-14 12:01:31 -04004149 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004150 {
4151 return false;
4152 }
4153
Geoff Langebebe1c2016-10-14 12:01:31 -04004154 if (!ValidateRobustBufferSize(context, bufSize, *length))
4155 {
4156 return false;
4157 }
4158
4159 return true;
4160}
4161
4162bool ValidateGetBufferParameteri64v(ValidationContext *context,
4163 GLenum target,
4164 GLenum pname,
4165 GLint64 *params)
4166{
4167 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4168}
4169
4170bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4171 GLenum target,
4172 GLenum pname,
4173 GLsizei bufSize,
4174 GLsizei *length,
4175 GLint64 *params)
4176{
4177 if (!ValidateRobustEntryPoint(context, bufSize))
4178 {
4179 return false;
4180 }
4181
4182 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4183 {
4184 return false;
4185 }
4186
4187 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004188 {
4189 return false;
4190 }
4191
4192 return true;
4193}
4194
Jamie Madillbe849e42017-05-02 15:49:00 -04004195bool ValidateGetProgramivBase(ValidationContext *context,
4196 GLuint program,
4197 GLenum pname,
4198 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004199{
4200 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004201 if (numParams)
4202 {
4203 *numParams = 1;
4204 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004205
4206 Program *programObject = GetValidProgram(context, program);
4207 if (!programObject)
4208 {
4209 return false;
4210 }
4211
4212 switch (pname)
4213 {
4214 case GL_DELETE_STATUS:
4215 case GL_LINK_STATUS:
4216 case GL_VALIDATE_STATUS:
4217 case GL_INFO_LOG_LENGTH:
4218 case GL_ATTACHED_SHADERS:
4219 case GL_ACTIVE_ATTRIBUTES:
4220 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4221 case GL_ACTIVE_UNIFORMS:
4222 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4223 break;
4224
4225 case GL_PROGRAM_BINARY_LENGTH:
4226 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4227 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004228 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4229 "requires GL_OES_get_program_binary or "
4230 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004231 return false;
4232 }
4233 break;
4234
4235 case GL_ACTIVE_UNIFORM_BLOCKS:
4236 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4237 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4238 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4239 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4240 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4241 if (context->getClientMajorVersion() < 3)
4242 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004243 context->handleError(InvalidEnum() << "Querying requires at least ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004244 return false;
4245 }
4246 break;
4247
Yunchao He61afff12017-03-14 15:34:03 +08004248 case GL_PROGRAM_SEPARABLE:
4249 if (context->getClientVersion() < Version(3, 1))
4250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004251 context->handleError(InvalidEnum() << "Querying requires at least ES 3.1.");
Yunchao He61afff12017-03-14 15:34:03 +08004252 return false;
4253 }
4254 break;
4255
Geoff Langff5b2d52016-09-07 11:32:23 -04004256 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004257 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004258 return false;
4259 }
4260
4261 return true;
4262}
4263
4264bool ValidateGetProgramivRobustANGLE(Context *context,
4265 GLuint program,
4266 GLenum pname,
4267 GLsizei bufSize,
4268 GLsizei *numParams)
4269{
4270 if (!ValidateRobustEntryPoint(context, bufSize))
4271 {
4272 return false;
4273 }
4274
Jamie Madillbe849e42017-05-02 15:49:00 -04004275 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004276 {
4277 return false;
4278 }
4279
4280 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4281 {
4282 return false;
4283 }
4284
4285 return true;
4286}
4287
Geoff Lang740d9022016-10-07 11:20:52 -04004288bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4289 GLenum target,
4290 GLenum pname,
4291 GLsizei bufSize,
4292 GLsizei *length,
4293 GLint *params)
4294{
4295 if (!ValidateRobustEntryPoint(context, bufSize))
4296 {
4297 return false;
4298 }
4299
4300 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4301 {
4302 return false;
4303 }
4304
4305 if (!ValidateRobustBufferSize(context, bufSize, *length))
4306 {
4307 return false;
4308 }
4309
4310 return true;
4311}
4312
Geoff Langd7d0ed32016-10-07 11:33:51 -04004313bool ValidateGetShaderivRobustANGLE(Context *context,
4314 GLuint shader,
4315 GLenum pname,
4316 GLsizei bufSize,
4317 GLsizei *length,
4318 GLint *params)
4319{
4320 if (!ValidateRobustEntryPoint(context, bufSize))
4321 {
4322 return false;
4323 }
4324
4325 if (!ValidateGetShaderivBase(context, shader, pname, length))
4326 {
4327 return false;
4328 }
4329
4330 if (!ValidateRobustBufferSize(context, bufSize, *length))
4331 {
4332 return false;
4333 }
4334
4335 return true;
4336}
4337
Geoff Langc1984ed2016-10-07 12:41:00 -04004338bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4339 GLenum target,
4340 GLenum pname,
4341 GLsizei bufSize,
4342 GLsizei *length,
4343 GLfloat *params)
4344{
4345 if (!ValidateRobustEntryPoint(context, bufSize))
4346 {
4347 return false;
4348 }
4349
4350 if (!ValidateGetTexParameterBase(context, target, pname, length))
4351 {
4352 return false;
4353 }
4354
4355 if (!ValidateRobustBufferSize(context, bufSize, *length))
4356 {
4357 return false;
4358 }
4359
4360 return true;
4361}
4362
Geoff Langc1984ed2016-10-07 12:41:00 -04004363bool ValidateGetTexParameterivRobustANGLE(Context *context,
4364 GLenum target,
4365 GLenum pname,
4366 GLsizei bufSize,
4367 GLsizei *length,
4368 GLint *params)
4369{
4370 if (!ValidateRobustEntryPoint(context, bufSize))
4371 {
4372 return false;
4373 }
4374
4375 if (!ValidateGetTexParameterBase(context, target, pname, length))
4376 {
4377 return false;
4378 }
4379
4380 if (!ValidateRobustBufferSize(context, bufSize, *length))
4381 {
4382 return false;
4383 }
4384
4385 return true;
4386}
4387
Geoff Langc1984ed2016-10-07 12:41:00 -04004388bool ValidateTexParameterfvRobustANGLE(Context *context,
4389 GLenum target,
4390 GLenum pname,
4391 GLsizei bufSize,
4392 const GLfloat *params)
4393{
4394 if (!ValidateRobustEntryPoint(context, bufSize))
4395 {
4396 return false;
4397 }
4398
4399 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4400}
4401
Geoff Langc1984ed2016-10-07 12:41:00 -04004402bool ValidateTexParameterivRobustANGLE(Context *context,
4403 GLenum target,
4404 GLenum pname,
4405 GLsizei bufSize,
4406 const GLint *params)
4407{
4408 if (!ValidateRobustEntryPoint(context, bufSize))
4409 {
4410 return false;
4411 }
4412
4413 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4414}
4415
4416bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4417{
4418 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4419}
4420
4421bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4422 GLuint sampler,
4423 GLenum pname,
4424 GLuint bufSize,
4425 GLsizei *length,
4426 GLfloat *params)
4427{
4428 if (!ValidateRobustEntryPoint(context, bufSize))
4429 {
4430 return false;
4431 }
4432
4433 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4434 {
4435 return false;
4436 }
4437
4438 if (!ValidateRobustBufferSize(context, bufSize, *length))
4439 {
4440 return false;
4441 }
4442
4443 return true;
4444}
4445
4446bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4447{
4448 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4449}
4450
4451bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4452 GLuint sampler,
4453 GLenum pname,
4454 GLuint bufSize,
4455 GLsizei *length,
4456 GLint *params)
4457{
4458 if (!ValidateRobustEntryPoint(context, bufSize))
4459 {
4460 return false;
4461 }
4462
4463 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4464 {
4465 return false;
4466 }
4467
4468 if (!ValidateRobustBufferSize(context, bufSize, *length))
4469 {
4470 return false;
4471 }
4472
4473 return true;
4474}
4475
4476bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4477{
4478 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4479}
4480
4481bool ValidateSamplerParameterfv(Context *context,
4482 GLuint sampler,
4483 GLenum pname,
4484 const GLfloat *params)
4485{
4486 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4487}
4488
4489bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4490 GLuint sampler,
4491 GLenum pname,
4492 GLsizei bufSize,
4493 const GLfloat *params)
4494{
4495 if (!ValidateRobustEntryPoint(context, bufSize))
4496 {
4497 return false;
4498 }
4499
4500 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4501}
4502
4503bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4504{
4505 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4506}
4507
4508bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4509{
4510 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4511}
4512
4513bool ValidateSamplerParameterivRobustANGLE(Context *context,
4514 GLuint sampler,
4515 GLenum pname,
4516 GLsizei bufSize,
4517 const GLint *params)
4518{
4519 if (!ValidateRobustEntryPoint(context, bufSize))
4520 {
4521 return false;
4522 }
4523
4524 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4525}
4526
Geoff Lang0b031062016-10-13 14:30:04 -04004527bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4528 GLuint index,
4529 GLenum pname,
4530 GLsizei bufSize,
4531 GLsizei *length,
4532 GLfloat *params)
4533{
4534 if (!ValidateRobustEntryPoint(context, bufSize))
4535 {
4536 return false;
4537 }
4538
4539 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4540 {
4541 return false;
4542 }
4543
4544 if (!ValidateRobustBufferSize(context, bufSize, *length))
4545 {
4546 return false;
4547 }
4548
4549 return true;
4550}
4551
Geoff Lang0b031062016-10-13 14:30:04 -04004552bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4553 GLuint index,
4554 GLenum pname,
4555 GLsizei bufSize,
4556 GLsizei *length,
4557 GLint *params)
4558{
4559 if (!ValidateRobustEntryPoint(context, bufSize))
4560 {
4561 return false;
4562 }
4563
4564 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4565 {
4566 return false;
4567 }
4568
4569 if (!ValidateRobustBufferSize(context, bufSize, *length))
4570 {
4571 return false;
4572 }
4573
4574 return true;
4575}
4576
Geoff Lang0b031062016-10-13 14:30:04 -04004577bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4578 GLuint index,
4579 GLenum pname,
4580 GLsizei bufSize,
4581 GLsizei *length,
4582 void **pointer)
4583{
4584 if (!ValidateRobustEntryPoint(context, bufSize))
4585 {
4586 return false;
4587 }
4588
4589 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4590 {
4591 return false;
4592 }
4593
4594 if (!ValidateRobustBufferSize(context, bufSize, *length))
4595 {
4596 return false;
4597 }
4598
4599 return true;
4600}
4601
4602bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4603{
4604 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4605}
4606
4607bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4608 GLuint index,
4609 GLenum pname,
4610 GLsizei bufSize,
4611 GLsizei *length,
4612 GLint *params)
4613{
4614 if (!ValidateRobustEntryPoint(context, bufSize))
4615 {
4616 return false;
4617 }
4618
4619 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4620 {
4621 return false;
4622 }
4623
4624 if (!ValidateRobustBufferSize(context, bufSize, *length))
4625 {
4626 return false;
4627 }
4628
4629 return true;
4630}
4631
4632bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4633{
4634 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4635}
4636
4637bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4638 GLuint index,
4639 GLenum pname,
4640 GLsizei bufSize,
4641 GLsizei *length,
4642 GLuint *params)
4643{
4644 if (!ValidateRobustEntryPoint(context, bufSize))
4645 {
4646 return false;
4647 }
4648
4649 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4650 {
4651 return false;
4652 }
4653
4654 if (!ValidateRobustBufferSize(context, bufSize, *length))
4655 {
4656 return false;
4657 }
4658
4659 return true;
4660}
4661
Geoff Lang6899b872016-10-14 11:30:13 -04004662bool ValidateGetActiveUniformBlockiv(Context *context,
4663 GLuint program,
4664 GLuint uniformBlockIndex,
4665 GLenum pname,
4666 GLint *params)
4667{
4668 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
4669}
4670
4671bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4672 GLuint program,
4673 GLuint uniformBlockIndex,
4674 GLenum pname,
4675 GLsizei bufSize,
4676 GLsizei *length,
4677 GLint *params)
4678{
4679 if (!ValidateRobustEntryPoint(context, bufSize))
4680 {
4681 return false;
4682 }
4683
4684 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4685 {
4686 return false;
4687 }
4688
4689 if (!ValidateRobustBufferSize(context, bufSize, *length))
4690 {
4691 return false;
4692 }
4693
4694 return true;
4695}
4696
Geoff Lang0a9661f2016-10-20 10:59:20 -07004697bool ValidateGetInternalFormativ(Context *context,
4698 GLenum target,
4699 GLenum internalformat,
4700 GLenum pname,
4701 GLsizei bufSize,
4702 GLint *params)
4703{
4704 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4705 nullptr);
4706}
4707
4708bool ValidateGetInternalFormativRobustANGLE(Context *context,
4709 GLenum target,
4710 GLenum internalformat,
4711 GLenum pname,
4712 GLsizei bufSize,
4713 GLsizei *length,
4714 GLint *params)
4715{
4716 if (!ValidateRobustEntryPoint(context, bufSize))
4717 {
4718 return false;
4719 }
4720
4721 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4722 {
4723 return false;
4724 }
4725
4726 if (!ValidateRobustBufferSize(context, bufSize, *length))
4727 {
4728 return false;
4729 }
4730
4731 return true;
4732}
4733
Shao80957d92017-02-20 21:25:59 +08004734bool ValidateVertexFormatBase(ValidationContext *context,
4735 GLuint attribIndex,
4736 GLint size,
4737 GLenum type,
4738 GLboolean pureInteger)
4739{
4740 const Caps &caps = context->getCaps();
4741 if (attribIndex >= caps.maxVertexAttributes)
4742 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004743 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Shao80957d92017-02-20 21:25:59 +08004744 return false;
4745 }
4746
4747 if (size < 1 || size > 4)
4748 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004749 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004750 return false;
Shao80957d92017-02-20 21:25:59 +08004751 }
4752
4753 switch (type)
4754 {
4755 case GL_BYTE:
4756 case GL_UNSIGNED_BYTE:
4757 case GL_SHORT:
4758 case GL_UNSIGNED_SHORT:
4759 break;
4760
4761 case GL_INT:
4762 case GL_UNSIGNED_INT:
4763 if (context->getClientMajorVersion() < 3)
4764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004765 context->handleError(InvalidEnum()
4766 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004767 return false;
4768 }
4769 break;
4770
4771 case GL_FIXED:
4772 case GL_FLOAT:
4773 if (pureInteger)
4774 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004775 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004776 return false;
4777 }
4778 break;
4779
4780 case GL_HALF_FLOAT:
4781 if (context->getClientMajorVersion() < 3)
4782 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004783 context->handleError(InvalidEnum()
4784 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004785 return false;
4786 }
4787 if (pureInteger)
4788 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004789 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004790 return false;
4791 }
4792 break;
4793
4794 case GL_INT_2_10_10_10_REV:
4795 case GL_UNSIGNED_INT_2_10_10_10_REV:
4796 if (context->getClientMajorVersion() < 3)
4797 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004798 context->handleError(InvalidEnum()
4799 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004800 return false;
4801 }
4802 if (pureInteger)
4803 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004804 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004805 return false;
4806 }
4807 if (size != 4)
4808 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004809 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4810 "UNSIGNED_INT_2_10_10_10_REV and "
4811 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004812 return false;
4813 }
4814 break;
4815
4816 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004817 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004818 return false;
4819 }
4820
4821 return true;
4822}
4823
Geoff Lang76e65652017-03-27 14:58:02 -04004824// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4825// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4826// specified clear value and the type of a buffer that is being cleared generates an
4827// INVALID_OPERATION error instead of producing undefined results
4828bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4829 GLint drawbuffer,
4830 const GLenum *validComponentTypes,
4831 size_t validComponentTypeCount)
4832{
4833 const FramebufferAttachment *attachment =
4834 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4835 if (attachment)
4836 {
4837 GLenum componentType = attachment->getFormat().info->componentType;
4838 const GLenum *end = validComponentTypes + validComponentTypeCount;
4839 if (std::find(validComponentTypes, end, componentType) == end)
4840 {
4841 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004842 InvalidOperation()
4843 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004844 return false;
4845 }
4846 }
4847
4848 return true;
4849}
4850
Corentin Wallezb2931602017-04-11 15:58:57 -04004851bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4852 GLsizei imageSize,
4853 GLsizei dataSize)
4854{
4855 if (!ValidateRobustEntryPoint(context, dataSize))
4856 {
4857 return false;
4858 }
4859
4860 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
4861 if (pixelUnpackBuffer == nullptr)
4862 {
4863 if (dataSize < imageSize)
4864 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004865 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004866 }
4867 }
4868 return true;
4869}
4870
Jamie Madillbe849e42017-05-02 15:49:00 -04004871bool ValidateGetBufferParameterBase(ValidationContext *context,
4872 GLenum target,
4873 GLenum pname,
4874 bool pointerVersion,
4875 GLsizei *numParams)
4876{
4877 if (numParams)
4878 {
4879 *numParams = 0;
4880 }
4881
4882 if (!ValidBufferTarget(context, target))
4883 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004884 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004885 return false;
4886 }
4887
4888 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4889 if (!buffer)
4890 {
4891 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004892 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004893 return false;
4894 }
4895
4896 const Extensions &extensions = context->getExtensions();
4897
4898 switch (pname)
4899 {
4900 case GL_BUFFER_USAGE:
4901 case GL_BUFFER_SIZE:
4902 break;
4903
4904 case GL_BUFFER_ACCESS_OES:
4905 if (!extensions.mapBuffer)
4906 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004907 context->handleError(InvalidEnum()
4908 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004909 return false;
4910 }
4911 break;
4912
4913 case GL_BUFFER_MAPPED:
4914 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4915 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4916 !extensions.mapBufferRange)
4917 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004918 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4919 "GL_OES_mapbuffer or "
4920 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004921 return false;
4922 }
4923 break;
4924
4925 case GL_BUFFER_MAP_POINTER:
4926 if (!pointerVersion)
4927 {
4928 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004929 InvalidEnum()
4930 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004931 return false;
4932 }
4933 break;
4934
4935 case GL_BUFFER_ACCESS_FLAGS:
4936 case GL_BUFFER_MAP_OFFSET:
4937 case GL_BUFFER_MAP_LENGTH:
4938 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4939 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004940 context->handleError(InvalidEnum()
4941 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004942 return false;
4943 }
4944 break;
4945
4946 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004947 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004948 return false;
4949 }
4950
4951 // All buffer parameter queries return one value.
4952 if (numParams)
4953 {
4954 *numParams = 1;
4955 }
4956
4957 return true;
4958}
4959
4960bool ValidateGetRenderbufferParameterivBase(Context *context,
4961 GLenum target,
4962 GLenum pname,
4963 GLsizei *length)
4964{
4965 if (length)
4966 {
4967 *length = 0;
4968 }
4969
4970 if (target != GL_RENDERBUFFER)
4971 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004972 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004973 return false;
4974 }
4975
4976 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4977 if (renderbuffer == nullptr)
4978 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004979 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004980 return false;
4981 }
4982
4983 switch (pname)
4984 {
4985 case GL_RENDERBUFFER_WIDTH:
4986 case GL_RENDERBUFFER_HEIGHT:
4987 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4988 case GL_RENDERBUFFER_RED_SIZE:
4989 case GL_RENDERBUFFER_GREEN_SIZE:
4990 case GL_RENDERBUFFER_BLUE_SIZE:
4991 case GL_RENDERBUFFER_ALPHA_SIZE:
4992 case GL_RENDERBUFFER_DEPTH_SIZE:
4993 case GL_RENDERBUFFER_STENCIL_SIZE:
4994 break;
4995
4996 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4997 if (!context->getExtensions().framebufferMultisample)
4998 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004999 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005000 return false;
5001 }
5002 break;
5003
5004 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005005 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005006 return false;
5007 }
5008
5009 if (length)
5010 {
5011 *length = 1;
5012 }
5013 return true;
5014}
5015
5016bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5017{
5018 if (length)
5019 {
5020 *length = 0;
5021 }
5022
5023 if (GetValidShader(context, shader) == nullptr)
5024 {
5025 return false;
5026 }
5027
5028 switch (pname)
5029 {
5030 case GL_SHADER_TYPE:
5031 case GL_DELETE_STATUS:
5032 case GL_COMPILE_STATUS:
5033 case GL_INFO_LOG_LENGTH:
5034 case GL_SHADER_SOURCE_LENGTH:
5035 break;
5036
5037 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5038 if (!context->getExtensions().translatedShaderSource)
5039 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005040 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005041 return false;
5042 }
5043 break;
5044
5045 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005046 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005047 return false;
5048 }
5049
5050 if (length)
5051 {
5052 *length = 1;
5053 }
5054 return true;
5055}
5056
5057bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
5058{
5059 if (length)
5060 {
5061 *length = 0;
5062 }
5063
5064 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5065 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005066 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005067 return false;
5068 }
5069
5070 if (context->getTargetTexture(target) == nullptr)
5071 {
5072 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005073 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005074 return false;
5075 }
5076
5077 switch (pname)
5078 {
5079 case GL_TEXTURE_MAG_FILTER:
5080 case GL_TEXTURE_MIN_FILTER:
5081 case GL_TEXTURE_WRAP_S:
5082 case GL_TEXTURE_WRAP_T:
5083 break;
5084
5085 case GL_TEXTURE_USAGE_ANGLE:
5086 if (!context->getExtensions().textureUsage)
5087 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005088 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005089 return false;
5090 }
5091 break;
5092
5093 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5094 if (!context->getExtensions().textureFilterAnisotropic)
5095 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005096 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005097 return false;
5098 }
5099 break;
5100
5101 case GL_TEXTURE_IMMUTABLE_FORMAT:
5102 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5103 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005104 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005105 return false;
5106 }
5107 break;
5108
5109 case GL_TEXTURE_WRAP_R:
5110 case GL_TEXTURE_IMMUTABLE_LEVELS:
5111 case GL_TEXTURE_SWIZZLE_R:
5112 case GL_TEXTURE_SWIZZLE_G:
5113 case GL_TEXTURE_SWIZZLE_B:
5114 case GL_TEXTURE_SWIZZLE_A:
5115 case GL_TEXTURE_BASE_LEVEL:
5116 case GL_TEXTURE_MAX_LEVEL:
5117 case GL_TEXTURE_MIN_LOD:
5118 case GL_TEXTURE_MAX_LOD:
5119 case GL_TEXTURE_COMPARE_MODE:
5120 case GL_TEXTURE_COMPARE_FUNC:
5121 if (context->getClientMajorVersion() < 3)
5122 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005123 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005124 return false;
5125 }
5126 break;
5127
5128 case GL_TEXTURE_SRGB_DECODE_EXT:
5129 if (!context->getExtensions().textureSRGBDecode)
5130 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005131 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005132 return false;
5133 }
5134 break;
5135
5136 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005137 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005138 return false;
5139 }
5140
5141 if (length)
5142 {
5143 *length = 1;
5144 }
5145 return true;
5146}
5147
5148bool ValidateGetVertexAttribBase(Context *context,
5149 GLuint index,
5150 GLenum pname,
5151 GLsizei *length,
5152 bool pointer,
5153 bool pureIntegerEntryPoint)
5154{
5155 if (length)
5156 {
5157 *length = 0;
5158 }
5159
5160 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5161 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005162 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005163 return false;
5164 }
5165
5166 if (index >= context->getCaps().maxVertexAttributes)
5167 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005168 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madillbe849e42017-05-02 15:49:00 -04005169 return false;
5170 }
5171
5172 if (pointer)
5173 {
5174 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5175 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005176 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005177 return false;
5178 }
5179 }
5180 else
5181 {
5182 switch (pname)
5183 {
5184 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5185 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5186 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5187 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5188 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5189 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5190 case GL_CURRENT_VERTEX_ATTRIB:
5191 break;
5192
5193 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5194 static_assert(
5195 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5196 "ANGLE extension enums not equal to GL enums.");
5197 if (context->getClientMajorVersion() < 3 &&
5198 !context->getExtensions().instancedArrays)
5199 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005200 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5201 "requires OpenGL ES 3.0 or "
5202 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005203 return false;
5204 }
5205 break;
5206
5207 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5208 if (context->getClientMajorVersion() < 3)
5209 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005210 context->handleError(
5211 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005212 return false;
5213 }
5214 break;
5215
5216 case GL_VERTEX_ATTRIB_BINDING:
5217 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5218 if (context->getClientVersion() < ES_3_1)
5219 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005220 context->handleError(InvalidEnum()
5221 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005222 return false;
5223 }
5224 break;
5225
5226 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005227 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005228 return false;
5229 }
5230 }
5231
5232 if (length)
5233 {
5234 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5235 {
5236 *length = 4;
5237 }
5238 else
5239 {
5240 *length = 1;
5241 }
5242 }
5243
5244 return true;
5245}
5246
Jamie Madill4928b7c2017-06-20 12:57:39 -04005247bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005248 GLint x,
5249 GLint y,
5250 GLsizei width,
5251 GLsizei height,
5252 GLenum format,
5253 GLenum type,
5254 GLsizei bufSize,
5255 GLsizei *length,
5256 GLsizei *columns,
5257 GLsizei *rows,
5258 void *pixels)
5259{
5260 if (length != nullptr)
5261 {
5262 *length = 0;
5263 }
5264 if (rows != nullptr)
5265 {
5266 *rows = 0;
5267 }
5268 if (columns != nullptr)
5269 {
5270 *columns = 0;
5271 }
5272
5273 if (width < 0 || height < 0)
5274 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005275 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005276 return false;
5277 }
5278
5279 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5280
5281 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5282 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005283 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005284 return false;
5285 }
5286
5287 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5288 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005289 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005290 return false;
5291 }
5292
5293 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5294 ASSERT(framebuffer);
5295
5296 if (framebuffer->getReadBufferState() == GL_NONE)
5297 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005298 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Jamie Madillbe849e42017-05-02 15:49:00 -04005299 return false;
5300 }
5301
5302 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5303 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5304 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5305 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5306 // situation is an application error that would lead to a crash in ANGLE.
5307 if (readBuffer == nullptr)
5308 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005309 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005310 return false;
5311 }
5312
Jamie Madill4928b7c2017-06-20 12:57:39 -04005313 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5314 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005315 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5316
5317 bool validFormatTypeCombination =
5318 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5319
5320 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5321 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005322 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005323 return false;
5324 }
5325
5326 // Check for pixel pack buffer related API errors
5327 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5328 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5329 {
5330 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005331 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005332 return false;
5333 }
5334
5335 // .. the data would be packed to the buffer object such that the memory writes required
5336 // would exceed the data store size.
5337 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5338 const gl::Extents size(width, height, 1);
5339 const auto &pack = context->getGLState().getPackState();
5340
5341 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5342 if (endByteOrErr.isError())
5343 {
5344 context->handleError(endByteOrErr.getError());
5345 return false;
5346 }
5347
5348 size_t endByte = endByteOrErr.getResult();
5349 if (bufSize >= 0)
5350 {
5351 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5352 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005353 context->handleError(InvalidOperation()
5354 << "bufSize must be at least " << endByte << " bytes.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005355 return false;
5356 }
5357 }
5358
5359 if (pixelPackBuffer != nullptr)
5360 {
5361 CheckedNumeric<size_t> checkedEndByte(endByte);
5362 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5363 checkedEndByte += checkedOffset;
5364
5365 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5366 {
5367 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005368 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005369 return false;
5370 }
5371 }
5372
5373 if (pixelPackBuffer == nullptr && length != nullptr)
5374 {
5375 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5376 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005377 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005378 return false;
5379 }
5380
5381 *length = static_cast<GLsizei>(endByte);
5382 }
5383
5384 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5385 angle::CheckedNumeric<int> clippedExtent(length);
5386 if (start < 0)
5387 {
5388 // "subtract" the area that is less than 0
5389 clippedExtent += start;
5390 }
5391
5392 const int readExtent = start + length;
5393 if (readExtent > bufferSize)
5394 {
5395 // Subtract the region to the right of the read buffer
5396 clippedExtent -= (readExtent - bufferSize);
5397 }
5398
5399 if (!clippedExtent.IsValid())
5400 {
5401 return 0;
5402 }
5403
5404 return std::max(clippedExtent.ValueOrDie(), 0);
5405 };
5406
5407 if (columns != nullptr)
5408 {
5409 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5410 }
5411
5412 if (rows != nullptr)
5413 {
5414 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5415 }
5416
5417 return true;
5418}
5419
5420template <typename ParamType>
5421bool ValidateTexParameterBase(Context *context,
5422 GLenum target,
5423 GLenum pname,
5424 GLsizei bufSize,
5425 const ParamType *params)
5426{
5427 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5428 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005429 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005430 return false;
5431 }
5432
5433 if (context->getTargetTexture(target) == nullptr)
5434 {
5435 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005436 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005437 return false;
5438 }
5439
5440 const GLsizei minBufSize = 1;
5441 if (bufSize >= 0 && bufSize < minBufSize)
5442 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005443 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005444 return false;
5445 }
5446
5447 switch (pname)
5448 {
5449 case GL_TEXTURE_WRAP_R:
5450 case GL_TEXTURE_SWIZZLE_R:
5451 case GL_TEXTURE_SWIZZLE_G:
5452 case GL_TEXTURE_SWIZZLE_B:
5453 case GL_TEXTURE_SWIZZLE_A:
5454 case GL_TEXTURE_BASE_LEVEL:
5455 case GL_TEXTURE_MAX_LEVEL:
5456 case GL_TEXTURE_COMPARE_MODE:
5457 case GL_TEXTURE_COMPARE_FUNC:
5458 case GL_TEXTURE_MIN_LOD:
5459 case GL_TEXTURE_MAX_LOD:
5460 if (context->getClientMajorVersion() < 3)
5461 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005462 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005463 return false;
5464 }
5465 if (target == GL_TEXTURE_EXTERNAL_OES &&
5466 !context->getExtensions().eglImageExternalEssl3)
5467 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005468 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5469 "available without "
5470 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005471 return false;
5472 }
5473 break;
5474
5475 default:
5476 break;
5477 }
5478
5479 switch (pname)
5480 {
5481 case GL_TEXTURE_WRAP_S:
5482 case GL_TEXTURE_WRAP_T:
5483 case GL_TEXTURE_WRAP_R:
5484 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
5485 {
5486 return false;
5487 }
5488 break;
5489
5490 case GL_TEXTURE_MIN_FILTER:
5491 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
5492 {
5493 return false;
5494 }
5495 break;
5496
5497 case GL_TEXTURE_MAG_FILTER:
5498 if (!ValidateTextureMagFilterValue(context, params))
5499 {
5500 return false;
5501 }
5502 break;
5503
5504 case GL_TEXTURE_USAGE_ANGLE:
5505 switch (ConvertToGLenum(params[0]))
5506 {
5507 case GL_NONE:
5508 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5509 break;
5510
5511 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005512 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005513 return false;
5514 }
5515 break;
5516
5517 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5518 if (!context->getExtensions().textureFilterAnisotropic)
5519 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005520 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005521 return false;
5522 }
5523
5524 // we assume the parameter passed to this validation method is truncated, not rounded
5525 if (params[0] < 1)
5526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005527 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005528 return false;
5529 }
5530 break;
5531
5532 case GL_TEXTURE_MIN_LOD:
5533 case GL_TEXTURE_MAX_LOD:
5534 // any value is permissible
5535 break;
5536
5537 case GL_TEXTURE_COMPARE_MODE:
5538 if (!ValidateTextureCompareModeValue(context, params))
5539 {
5540 return false;
5541 }
5542 break;
5543
5544 case GL_TEXTURE_COMPARE_FUNC:
5545 if (!ValidateTextureCompareFuncValue(context, params))
5546 {
5547 return false;
5548 }
5549 break;
5550
5551 case GL_TEXTURE_SWIZZLE_R:
5552 case GL_TEXTURE_SWIZZLE_G:
5553 case GL_TEXTURE_SWIZZLE_B:
5554 case GL_TEXTURE_SWIZZLE_A:
5555 switch (ConvertToGLenum(params[0]))
5556 {
5557 case GL_RED:
5558 case GL_GREEN:
5559 case GL_BLUE:
5560 case GL_ALPHA:
5561 case GL_ZERO:
5562 case GL_ONE:
5563 break;
5564
5565 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005566 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005567 return false;
5568 }
5569 break;
5570
5571 case GL_TEXTURE_BASE_LEVEL:
5572 if (params[0] < 0)
5573 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005574 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005575 return false;
5576 }
5577 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5578 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005579 context->handleError(InvalidOperation()
5580 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005581 return false;
5582 }
5583 break;
5584
5585 case GL_TEXTURE_MAX_LEVEL:
5586 if (params[0] < 0)
5587 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005588 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005589 return false;
5590 }
5591 break;
5592
5593 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5594 if (context->getClientVersion() < Version(3, 1))
5595 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005596 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005597 return false;
5598 }
5599 switch (ConvertToGLenum(params[0]))
5600 {
5601 case GL_DEPTH_COMPONENT:
5602 case GL_STENCIL_INDEX:
5603 break;
5604
5605 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005606 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005607 return false;
5608 }
5609 break;
5610
5611 case GL_TEXTURE_SRGB_DECODE_EXT:
5612 if (!ValidateTextureSRGBDecodeValue(context, params))
5613 {
5614 return false;
5615 }
5616 break;
5617
5618 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005619 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005620 return false;
5621 }
5622
5623 return true;
5624}
5625
5626template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5627template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5628
Jamie Madillc29968b2016-01-20 11:17:23 -05005629} // namespace gl