blob: 8c95b216eec4ac38fd8f4ceb271ab43262c1136a [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);
521 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
522 }
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 {
758 GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
759
760 const auto &attrib = vao->getVertexAttribute(shaderAttribute.location);
761 const auto &currentValue =
762 context->getGLState().getVertexAttribCurrentValue(shaderAttribute.location);
763 GLenum vertexType = attrib.enabled ? GetVertexAttributeBaseType(attrib) : currentValue.Type;
764
765 if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
766 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500767 context->handleError(InvalidOperation() << "Vertex shader input type does not "
768 "match the type of the bound vertex "
769 "attribute.");
Geoff Lang9ab5b822017-05-30 16:19:23 -0400770 return false;
771 }
772 }
773
774 return true;
775}
776
Geoff Langf41a7152016-09-19 15:11:17 -0400777} // anonymous namespace
778
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500779bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400780{
Jamie Madilld7460c72014-01-21 16:38:14 -0500781 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400782 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800783 case GL_TEXTURE_2D:
784 case GL_TEXTURE_CUBE_MAP:
785 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400786
He Yunchaoced53ae2016-11-29 15:00:51 +0800787 case GL_TEXTURE_3D:
788 case GL_TEXTURE_2D_ARRAY:
789 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500790
He Yunchaoced53ae2016-11-29 15:00:51 +0800791 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800792 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400793
He Yunchaoced53ae2016-11-29 15:00:51 +0800794 default:
795 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500796 }
Jamie Madill35d15012013-10-07 10:46:37 -0400797}
798
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500799bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
800{
801 switch (target)
802 {
803 case GL_TEXTURE_2D:
804 case GL_TEXTURE_CUBE_MAP:
805 return true;
806
807 default:
808 return false;
809 }
810}
811
812bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
813{
814 switch (target)
815 {
816 case GL_TEXTURE_3D:
817 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300818 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500819
820 default:
821 return false;
822 }
823}
824
Ian Ewellbda75592016-04-18 17:25:54 -0400825// Most texture GL calls are not compatible with external textures, so we have a separate validation
826// function for use in the GL calls that do
827bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
828{
829 return (target == GL_TEXTURE_EXTERNAL_OES) &&
830 (context->getExtensions().eglImageExternal ||
831 context->getExtensions().eglStreamConsumerExternal);
832}
833
Shannon Woods4dfed832014-03-17 20:03:39 -0400834// This function differs from ValidTextureTarget in that the target must be
835// usable as the destination of a 2D operation-- so a cube face is valid, but
836// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400837// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500838bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400839{
840 switch (target)
841 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800842 case GL_TEXTURE_2D:
843 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
844 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
845 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
846 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
847 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
848 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
849 return true;
850 default:
851 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500852 }
853}
854
Jamie Madillbe849e42017-05-02 15:49:00 -0400855bool ValidateDrawElementsInstancedBase(ValidationContext *context,
856 GLenum mode,
857 GLsizei count,
858 GLenum type,
859 const GLvoid *indices,
860 GLsizei primcount)
861{
862 if (primcount < 0)
863 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500864 context->handleError(InvalidValue() << "primcount cannot be negative.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400865 return false;
866 }
867
868 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
869 {
870 return false;
871 }
872
873 // No-op zero primitive count
874 return (primcount > 0);
875}
876
877bool ValidateDrawArraysInstancedBase(Context *context,
878 GLenum mode,
879 GLint first,
880 GLsizei count,
881 GLsizei primcount)
882{
883 if (primcount < 0)
884 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500885 context->handleError(InvalidValue() << "primcount cannot be negative.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400886 return false;
887 }
888
889 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
890 {
891 return false;
892 }
893
894 // No-op if zero primitive count
895 return (primcount > 0);
896}
897
Corentin Wallez0dc97812017-06-22 14:38:44 -0400898bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400899{
900 // Verify there is at least one active attribute with a divisor of zero
901 const State &state = context->getGLState();
902
903 Program *program = state.getProgram();
904
905 const auto &attribs = state.getVertexArray()->getVertexAttributes();
906 const auto &bindings = state.getVertexArray()->getVertexBindings();
907 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
908 {
909 const VertexAttribute &attrib = attribs[attributeIndex];
910 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300911 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400912 {
913 return true;
914 }
915 }
916
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500917 context->handleError(InvalidOperation()
918 << "At least one attribute must have a divisor of zero.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400919 return false;
920}
921
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500922bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
923{
924 switch (target)
925 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800926 case GL_TEXTURE_3D:
927 case GL_TEXTURE_2D_ARRAY:
928 return true;
929 default:
930 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400931 }
932}
933
He Yunchao11b038b2016-11-22 21:24:04 +0800934bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
935{
936 switch (target)
937 {
938 case GL_TEXTURE_2D:
939 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
940 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
941 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
942 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
943 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
944 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
945 case GL_TEXTURE_3D:
946 case GL_TEXTURE_2D_ARRAY:
947 case GL_TEXTURE_2D_MULTISAMPLE:
948 return true;
949 default:
950 return false;
951 }
952}
953
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500954bool ValidFramebufferTarget(GLenum target)
955{
He Yunchaoced53ae2016-11-29 15:00:51 +0800956 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
957 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400958 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500959
960 switch (target)
961 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800962 case GL_FRAMEBUFFER:
963 return true;
964 case GL_READ_FRAMEBUFFER:
965 return true;
966 case GL_DRAW_FRAMEBUFFER:
967 return true;
968 default:
969 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500970 }
971}
972
Jamie Madill29639852016-09-02 15:00:09 -0400973bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -0500974{
975 switch (target)
976 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800977 case GL_ARRAY_BUFFER:
978 case GL_ELEMENT_ARRAY_BUFFER:
979 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -0500980
He Yunchaoced53ae2016-11-29 15:00:51 +0800981 case GL_PIXEL_PACK_BUFFER:
982 case GL_PIXEL_UNPACK_BUFFER:
983 return (context->getExtensions().pixelBufferObject ||
984 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -0400985
He Yunchaoced53ae2016-11-29 15:00:51 +0800986 case GL_COPY_READ_BUFFER:
987 case GL_COPY_WRITE_BUFFER:
988 case GL_TRANSFORM_FEEDBACK_BUFFER:
989 case GL_UNIFORM_BUFFER:
990 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -0500991
He Yunchaoced53ae2016-11-29 15:00:51 +0800992 case GL_ATOMIC_COUNTER_BUFFER:
993 case GL_SHADER_STORAGE_BUFFER:
994 case GL_DRAW_INDIRECT_BUFFER:
995 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800996 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -0400997
He Yunchaoced53ae2016-11-29 15:00:51 +0800998 default:
999 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001000 }
1001}
1002
Jamie Madillc29968b2016-01-20 11:17:23 -05001003bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001004{
Jamie Madillc29968b2016-01-20 11:17:23 -05001005 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001006 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001007 switch (target)
1008 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001009 case GL_TEXTURE_2D:
1010 maxDimension = caps.max2DTextureSize;
1011 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001012 case GL_TEXTURE_CUBE_MAP:
1013 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1014 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1015 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1016 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1017 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1018 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1019 maxDimension = caps.maxCubeMapTextureSize;
1020 break;
1021 case GL_TEXTURE_3D:
1022 maxDimension = caps.max3DTextureSize;
1023 break;
1024 case GL_TEXTURE_2D_ARRAY:
1025 maxDimension = caps.max2DTextureSize;
1026 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001027 case GL_TEXTURE_2D_MULTISAMPLE:
1028 maxDimension = caps.max2DTextureSize;
1029 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001030 default:
1031 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001032 }
1033
Brandon Jones6cad5662017-06-14 13:25:13 -07001034 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -04001035}
1036
Brandon Jones6cad5662017-06-14 13:25:13 -07001037bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001038 GLenum target,
1039 GLint level,
1040 GLsizei width,
1041 GLsizei height,
1042 GLsizei depth,
1043 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001044{
Brandon Jones6cad5662017-06-14 13:25:13 -07001045 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -04001046 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001047 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -04001048 return false;
1049 }
Austin Kinross08528e12015-10-07 16:24:40 -07001050 // TexSubImage parameters can be NPOT without textureNPOT extension,
1051 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001052 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001053 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001054 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001055 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001056 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001057 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -04001058 return false;
1059 }
1060
1061 if (!ValidMipLevel(context, target, level))
1062 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001063 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -04001064 return false;
1065 }
1066
1067 return true;
1068}
1069
Geoff Lang0d8b7242015-09-09 14:56:53 -04001070bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1071{
1072 // List of compressed format that require that the texture size is smaller than or a multiple of
1073 // the compressed block size.
1074 switch (internalFormat)
1075 {
1076 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1077 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1078 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1079 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -04001080 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
1081 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
1082 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
1083 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -08001084 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001085 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1086 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1087 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1088 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1089 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
1090 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001091 return true;
1092
1093 default:
1094 return false;
1095 }
1096}
1097
Geoff Lang966c9402017-04-18 12:38:27 -04001098bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
1099{
1100 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
1101 (size % blockSize == 0);
1102}
1103
Jamie Madillc29968b2016-01-20 11:17:23 -05001104bool ValidCompressedImageSize(const ValidationContext *context,
1105 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -04001106 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -05001107 GLsizei width,
1108 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001109{
Geoff Langca271392017-04-05 12:30:00 -04001110 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -04001111 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001112 {
1113 return false;
1114 }
1115
Geoff Lang966c9402017-04-18 12:38:27 -04001116 if (width < 0 || height < 0)
1117 {
1118 return false;
1119 }
1120
1121 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1122 {
1123 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
1124 // block size for level 0 but WebGL disallows this.
1125 bool smallerThanBlockSizeAllowed =
1126 level > 0 || !context->getExtensions().webglCompatibility;
1127
1128 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
1129 smallerThanBlockSizeAllowed) ||
1130 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
1131 smallerThanBlockSizeAllowed))
1132 {
1133 return false;
1134 }
1135 }
1136
1137 return true;
1138}
1139
1140bool ValidCompressedSubImageSize(const ValidationContext *context,
1141 GLenum internalFormat,
1142 GLint xoffset,
1143 GLint yoffset,
1144 GLsizei width,
1145 GLsizei height,
1146 size_t textureWidth,
1147 size_t textureHeight)
1148{
1149 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
1150 if (!formatInfo.compressed)
1151 {
1152 return false;
1153 }
1154
Geoff Lang44ff5a72017-02-03 15:15:43 -05001155 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001156 {
1157 return false;
1158 }
1159
Geoff Lang0d8b7242015-09-09 14:56:53 -04001160 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1161 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05001162 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -04001163 yoffset % formatInfo.compressedBlockHeight != 0)
1164 {
1165 return false;
1166 }
1167
1168 // Allowed to either have data that is a multiple of block size or is smaller than the block
1169 // size but fills the entire mip
1170 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
1171 static_cast<size_t>(width) == textureWidth &&
1172 static_cast<size_t>(height) == textureHeight;
1173 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
1174 (height % formatInfo.compressedBlockHeight) == 0;
1175 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -04001176 {
1177 return false;
1178 }
1179 }
1180
Geoff Langd4f180b2013-09-24 13:57:44 -04001181 return true;
1182}
1183
Geoff Langff5b2d52016-09-07 11:32:23 -04001184bool ValidImageDataSize(ValidationContext *context,
1185 GLenum textureTarget,
1186 GLsizei width,
1187 GLsizei height,
1188 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -04001189 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -04001190 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001191 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001192 GLsizei imageSize)
1193{
1194 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1195 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1196 {
1197 // Checks are not required
1198 return true;
1199 }
1200
1201 // ...the data would be unpacked from the buffer object such that the memory reads required
1202 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -04001203 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
1204 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -04001205 const gl::Extents size(width, height, depth);
1206 const auto &unpack = context->getGLState().getUnpackState();
1207
1208 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1209 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1210 if (endByteOrErr.isError())
1211 {
1212 context->handleError(endByteOrErr.getError());
1213 return false;
1214 }
1215
1216 GLuint endByte = endByteOrErr.getResult();
1217
1218 if (pixelUnpackBuffer)
1219 {
1220 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1221 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1222 checkedEndByte += checkedOffset;
1223
1224 if (!checkedEndByte.IsValid() ||
1225 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1226 {
1227 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001228 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04001229 return false;
1230 }
1231 }
1232 else
1233 {
1234 ASSERT(imageSize >= 0);
1235 if (pixels == nullptr && imageSize != 0)
1236 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001237 context->handleError(InvalidOperation()
1238 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001239 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001240 }
1241
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001242 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001243 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001244 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001245 return false;
1246 }
1247 }
1248
1249 return true;
1250}
1251
Geoff Lang37dde692014-01-31 16:34:54 -05001252bool ValidQueryType(const Context *context, GLenum queryType)
1253{
He Yunchaoced53ae2016-11-29 15:00:51 +08001254 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1255 "GL extension enums not equal.");
1256 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1257 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001258
1259 switch (queryType)
1260 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001261 case GL_ANY_SAMPLES_PASSED:
1262 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1263 return true;
1264 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1265 return (context->getClientMajorVersion() >= 3);
1266 case GL_TIME_ELAPSED_EXT:
1267 return context->getExtensions().disjointTimerQuery;
1268 case GL_COMMANDS_COMPLETED_CHROMIUM:
1269 return context->getExtensions().syncQuery;
1270 default:
1271 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001272 }
1273}
1274
Geoff Lang2d62ab72017-03-23 16:54:40 -04001275bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
1276 GLenum type,
1277 GLboolean normalized,
1278 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001279 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001280 bool pureInteger)
1281{
1282 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001283 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1284 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1285 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1286 // parameter exceeds 255.
1287 constexpr GLsizei kMaxWebGLStride = 255;
1288 if (stride > kMaxWebGLStride)
1289 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001290 context->handleError(InvalidValue()
1291 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001292 return false;
1293 }
1294
1295 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1296 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1297 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1298 // or an INVALID_OPERATION error is generated.
1299 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1300 size_t typeSize = GetVertexFormatTypeSize(internalType);
1301
1302 ASSERT(isPow2(typeSize) && typeSize > 0);
1303 size_t sizeMask = (typeSize - 1);
1304 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1305 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001306 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001307 return false;
1308 }
1309
1310 if ((stride & sizeMask) != 0)
1311 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001312 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001313 return false;
1314 }
1315
1316 return true;
1317}
1318
Jamie Madillef300b12016-10-07 15:12:09 -04001319Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001320{
He Yunchaoced53ae2016-11-29 15:00:51 +08001321 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1322 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1323 // or program object and INVALID_OPERATION if the provided name identifies an object
1324 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001325
Dian Xiang769769a2015-09-09 15:20:08 -07001326 Program *validProgram = context->getProgram(id);
1327
1328 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001329 {
Dian Xiang769769a2015-09-09 15:20:08 -07001330 if (context->getShader(id))
1331 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001332 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001333 }
1334 else
1335 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001336 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001337 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001338 }
Dian Xiang769769a2015-09-09 15:20:08 -07001339
1340 return validProgram;
1341}
1342
Jamie Madillef300b12016-10-07 15:12:09 -04001343Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001344{
1345 // See ValidProgram for spec details.
1346
1347 Shader *validShader = context->getShader(id);
1348
1349 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001350 {
Dian Xiang769769a2015-09-09 15:20:08 -07001351 if (context->getProgram(id))
1352 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001353 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001354 }
1355 else
1356 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001357 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001358 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001359 }
Dian Xiang769769a2015-09-09 15:20:08 -07001360
1361 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001362}
1363
Geoff Langb1196682014-07-23 13:47:29 -04001364bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001365{
1366 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1367 {
1368 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1369
Geoff Langaae65a42014-05-26 12:43:44 -04001370 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001371 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001372 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001373 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001374 }
1375 }
1376 else
1377 {
1378 switch (attachment)
1379 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001380 case GL_DEPTH_ATTACHMENT:
1381 case GL_STENCIL_ATTACHMENT:
1382 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001383
He Yunchaoced53ae2016-11-29 15:00:51 +08001384 case GL_DEPTH_STENCIL_ATTACHMENT:
1385 if (!context->getExtensions().webglCompatibility &&
1386 context->getClientMajorVersion() < 3)
1387 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001388 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001389 return false;
1390 }
1391 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001392
He Yunchaoced53ae2016-11-29 15:00:51 +08001393 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001394 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001395 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001396 }
1397 }
1398
1399 return true;
1400}
1401
Jamie Madille8fb6402017-02-14 17:56:40 -05001402bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001403 GLenum target,
1404 GLsizei samples,
1405 GLenum internalformat,
1406 GLsizei width,
1407 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001408{
1409 switch (target)
1410 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001411 case GL_RENDERBUFFER:
1412 break;
1413 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001414 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001415 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001416 }
1417
1418 if (width < 0 || height < 0 || samples < 0)
1419 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001420 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001421 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001422 }
1423
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001424 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1425 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1426
1427 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001428 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001429 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001430 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001431 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001432 }
1433
1434 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1435 // 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 -08001436 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001437 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1438 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001439 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001440 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001441 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001442 }
1443
Geoff Langaae65a42014-05-26 12:43:44 -04001444 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001445 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001446 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001447 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001448 }
1449
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001450 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001451 if (handle == 0)
1452 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001453 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001454 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001455 }
1456
1457 return true;
1458}
1459
He Yunchaoced53ae2016-11-29 15:00:51 +08001460bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1461 GLenum target,
1462 GLenum attachment,
1463 GLenum renderbuffertarget,
1464 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001465{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001466 if (!ValidFramebufferTarget(target))
1467 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001468 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001469 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001470 }
1471
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001472 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001473
Jamie Madill84115c92015-04-23 15:00:07 -04001474 ASSERT(framebuffer);
1475 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001476 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001477 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001478 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001479 }
1480
Jamie Madillb4472272014-07-03 10:38:55 -04001481 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001482 {
Jamie Madillb4472272014-07-03 10:38:55 -04001483 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001484 }
1485
Jamie Madillab9d82c2014-01-21 16:38:14 -05001486 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1487 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1488 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1489 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1490 if (renderbuffer != 0)
1491 {
1492 if (!context->getRenderbuffer(renderbuffer))
1493 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001494 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001495 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001496 }
1497 }
1498
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001499 return true;
1500}
1501
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001502bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001503 GLint srcX0,
1504 GLint srcY0,
1505 GLint srcX1,
1506 GLint srcY1,
1507 GLint dstX0,
1508 GLint dstY0,
1509 GLint dstX1,
1510 GLint dstY1,
1511 GLbitfield mask,
1512 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001513{
1514 switch (filter)
1515 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001516 case GL_NEAREST:
1517 break;
1518 case GL_LINEAR:
1519 break;
1520 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001521 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001522 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001523 }
1524
1525 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001527 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001528 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001529 }
1530
1531 if (mask == 0)
1532 {
1533 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1534 // buffers are copied.
1535 return false;
1536 }
1537
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001538 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1539 // color buffer, leaving only nearest being unfiltered from above
1540 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1541 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001542 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001543 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001544 }
1545
Jamie Madill51f40ec2016-06-15 14:06:00 -04001546 const auto &glState = context->getGLState();
1547 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1548 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001549
1550 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001551 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001552 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001553 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001554 }
1555
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001556 if (readFramebuffer->id() == drawFramebuffer->id())
1557 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001558 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001559 return false;
1560 }
1561
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001562 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001563 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001564 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001565 return false;
1566 }
1567
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001568 if (drawFramebuffer->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->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001575 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001576 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001577 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001578 }
1579
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001580 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1581
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001582 if (mask & GL_COLOR_BUFFER_BIT)
1583 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001584 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001585 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001586
He Yunchao66a41a22016-12-15 16:45:05 +08001587 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001588 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001589 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001590
Geoff Langa15472a2015-08-11 11:48:03 -04001591 for (size_t drawbufferIdx = 0;
1592 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001593 {
Geoff Langa15472a2015-08-11 11:48:03 -04001594 const FramebufferAttachment *attachment =
1595 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1596 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001597 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001598 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001599
Geoff Langb2f3d052013-08-13 12:49:27 -04001600 // The GL ES 3.0.2 spec (pg 193) states that:
1601 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001602 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1603 // as well
1604 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1605 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001606 // Changes with EXT_color_buffer_float:
1607 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001608 GLenum readComponentType = readFormat.info->componentType;
1609 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001610 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001611 readComponentType == GL_SIGNED_NORMALIZED);
1612 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1613 drawComponentType == GL_SIGNED_NORMALIZED);
1614
1615 if (extensions.colorBufferFloat)
1616 {
1617 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1618 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1619
1620 if (readFixedOrFloat != drawFixedOrFloat)
1621 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001622 context->handleError(InvalidOperation()
1623 << "If the read buffer contains fixed-point or "
1624 "floating-point values, the draw buffer must "
1625 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001626 return false;
1627 }
1628 }
1629 else if (readFixedPoint != drawFixedPoint)
1630 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001631 context->handleError(InvalidOperation()
1632 << "If the read buffer contains fixed-point values, "
1633 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001634 return false;
1635 }
1636
1637 if (readComponentType == GL_UNSIGNED_INT &&
1638 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001639 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001640 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001641 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001642 }
1643
Jamie Madill6163c752015-12-07 16:32:59 -05001644 if (readComponentType == GL_INT && drawComponentType != GL_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 Madilla3944d42016-07-22 22:13:26 -04001650 if (readColorBuffer->getSamples() > 0 &&
1651 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001652 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001653 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001654 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001655 }
Geoff Lange4915782017-04-12 15:19:07 -04001656
1657 if (context->getExtensions().webglCompatibility &&
1658 *readColorBuffer == *attachment)
1659 {
1660 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001661 InvalidOperation()
1662 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001663 return false;
1664 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001665 }
1666 }
1667
Jamie Madilla3944d42016-07-22 22:13:26 -04001668 if ((readFormat.info->componentType == GL_INT ||
1669 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1670 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001671 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001672 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001673 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001674 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001675 }
He Yunchao66a41a22016-12-15 16:45:05 +08001676 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1677 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1678 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1679 // situation is an application error that would lead to a crash in ANGLE.
1680 else if (drawFramebuffer->hasEnabledDrawBuffer())
1681 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001682 context->handleError(
1683 InvalidOperation()
1684 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001685 return false;
1686 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001687 }
1688
He Yunchaoced53ae2016-11-29 15:00:51 +08001689 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001690 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1691 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001692 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001693 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001694 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001695 const gl::FramebufferAttachment *readBuffer =
1696 readFramebuffer->getAttachment(attachments[i]);
1697 const gl::FramebufferAttachment *drawBuffer =
1698 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001699
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001700 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001701 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001702 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001703 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001704 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001705 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001706 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001707
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001708 if (readBuffer->getSamples() > 0 && !sameBounds)
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 Lange4915782017-04-12 15:19:07 -04001713
1714 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1715 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001716 context->handleError(
1717 InvalidOperation()
1718 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001719 return false;
1720 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001721 }
He Yunchao66a41a22016-12-15 16:45:05 +08001722 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1723 else if (drawBuffer)
1724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001725 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1726 "depth/stencil attachment of a "
1727 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001728 return false;
1729 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001730 }
1731 }
1732
1733 return true;
1734}
1735
Jamie Madill4928b7c2017-06-20 12:57:39 -04001736bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001737 GLint x,
1738 GLint y,
1739 GLsizei width,
1740 GLsizei height,
1741 GLenum format,
1742 GLenum type,
1743 GLsizei bufSize,
1744 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001745 GLsizei *columns,
1746 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001747 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001748{
1749 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001750 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001751 return false;
1752 }
1753
Geoff Lang62fce5b2016-09-30 10:46:35 -04001754 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001755 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001756 {
Geoff Langb1196682014-07-23 13:47:29 -04001757 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001758 }
1759
Geoff Lang62fce5b2016-09-30 10:46:35 -04001760 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001761 {
Geoff Langb1196682014-07-23 13:47:29 -04001762 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001763 }
1764
Jamie Madillc29968b2016-01-20 11:17:23 -05001765 return true;
1766}
1767
1768bool ValidateReadnPixelsEXT(Context *context,
1769 GLint x,
1770 GLint y,
1771 GLsizei width,
1772 GLsizei height,
1773 GLenum format,
1774 GLenum type,
1775 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001776 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001777{
1778 if (bufSize < 0)
1779 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001780 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001781 return false;
1782 }
1783
Geoff Lang62fce5b2016-09-30 10:46:35 -04001784 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001785 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001786}
Jamie Madill26e91952014-03-05 15:01:27 -05001787
Jamie Madill4928b7c2017-06-20 12:57:39 -04001788bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001789 GLint x,
1790 GLint y,
1791 GLsizei width,
1792 GLsizei height,
1793 GLenum format,
1794 GLenum type,
1795 GLsizei bufSize,
1796 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001797 GLsizei *columns,
1798 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001799 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001800{
1801 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001802 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001803 return false;
1804 }
1805
Geoff Lange93daba2017-03-30 13:54:40 -04001806 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1807 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001808 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001809 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001810 }
1811
Geoff Lang62fce5b2016-09-30 10:46:35 -04001812 if (!ValidateRobustBufferSize(context, bufSize, *length))
1813 {
1814 return false;
1815 }
1816
1817 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001818}
1819
Olli Etuaho41997e72016-03-10 13:38:39 +02001820bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001821{
1822 if (!context->getExtensions().occlusionQueryBoolean &&
1823 !context->getExtensions().disjointTimerQuery)
1824 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001825 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001826 return false;
1827 }
1828
Olli Etuaho41997e72016-03-10 13:38:39 +02001829 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001830}
1831
Olli Etuaho41997e72016-03-10 13:38:39 +02001832bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001833{
1834 if (!context->getExtensions().occlusionQueryBoolean &&
1835 !context->getExtensions().disjointTimerQuery)
1836 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001837 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001838 return false;
1839 }
1840
Olli Etuaho41997e72016-03-10 13:38:39 +02001841 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001842}
1843
1844bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001845{
1846 if (!ValidQueryType(context, target))
1847 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001848 context->handleError(InvalidEnum() << "Invalid query target");
Geoff Langb1196682014-07-23 13:47:29 -04001849 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001850 }
1851
1852 if (id == 0)
1853 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001854 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001855 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001856 }
1857
1858 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1859 // of zero, if the active query object name for <target> is non-zero (for the
1860 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1861 // the active query for either target is non-zero), if <id> is the name of an
1862 // existing query object whose type does not match <target>, or if <id> is the
1863 // active query object name for any query type, the error INVALID_OPERATION is
1864 // generated.
1865
1866 // Ensure no other queries are active
1867 // NOTE: If other queries than occlusion are supported, we will need to check
1868 // separately that:
1869 // a) The query ID passed is not the current active query for any target/type
1870 // b) There are no active queries for the requested target (and in the case
1871 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1872 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001873
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001874 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001875 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001876 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001877 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001878 }
1879
1880 Query *queryObject = context->getQuery(id, true, target);
1881
1882 // check that name was obtained with glGenQueries
1883 if (!queryObject)
1884 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001885 context->handleError(InvalidOperation() << "Invalid query id");
Geoff Langb1196682014-07-23 13:47:29 -04001886 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001887 }
1888
1889 // check for type mismatch
1890 if (queryObject->getType() != target)
1891 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001892 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001893 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001894 }
1895
1896 return true;
1897}
1898
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001899bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1900{
1901 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001902 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001903 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001904 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001905 return false;
1906 }
1907
1908 return ValidateBeginQueryBase(context, target, id);
1909}
1910
1911bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001912{
1913 if (!ValidQueryType(context, target))
1914 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001915 context->handleError(InvalidEnum() << "Invalid query target");
Geoff Langb1196682014-07-23 13:47:29 -04001916 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001917 }
1918
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001919 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001920
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001921 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001922 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001923 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001924 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001925 }
1926
Jamie Madill45c785d2014-05-13 14:09:34 -04001927 return true;
1928}
1929
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001930bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1931{
1932 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001933 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001934 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001935 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001936 return false;
1937 }
1938
1939 return ValidateEndQueryBase(context, target);
1940}
1941
1942bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1943{
1944 if (!context->getExtensions().disjointTimerQuery)
1945 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001946 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001947 return false;
1948 }
1949
1950 if (target != GL_TIMESTAMP_EXT)
1951 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001952 context->handleError(InvalidEnum() << "Invalid query target");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001953 return false;
1954 }
1955
1956 Query *queryObject = context->getQuery(id, true, target);
1957 if (queryObject == nullptr)
1958 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001959 context->handleError(InvalidOperation() << "Invalid query id");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001960 return false;
1961 }
1962
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001963 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001965 context->handleError(InvalidOperation() << "Query is active");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001966 return false;
1967 }
1968
1969 return true;
1970}
1971
Geoff Lang2186c382016-10-14 10:54:54 -04001972bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001973{
Geoff Lang2186c382016-10-14 10:54:54 -04001974 if (numParams)
1975 {
1976 *numParams = 0;
1977 }
1978
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001979 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1980 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001981 context->handleError(InvalidEnum() << "Invalid query type");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001982 return false;
1983 }
1984
1985 switch (pname)
1986 {
1987 case GL_CURRENT_QUERY_EXT:
1988 if (target == GL_TIMESTAMP_EXT)
1989 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001990 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001991 return false;
1992 }
1993 break;
1994 case GL_QUERY_COUNTER_BITS_EXT:
1995 if (!context->getExtensions().disjointTimerQuery ||
1996 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1997 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001998 context->handleError(InvalidEnum() << "Invalid pname");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001999 return false;
2000 }
2001 break;
2002 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002003 context->handleError(InvalidEnum() << "Invalid pname");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002004 return false;
2005 }
2006
Geoff Lang2186c382016-10-14 10:54:54 -04002007 if (numParams)
2008 {
2009 // All queries return only one value
2010 *numParams = 1;
2011 }
2012
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002013 return true;
2014}
2015
2016bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2017{
2018 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002019 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002020 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002021 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002022 return false;
2023 }
2024
Geoff Lang2186c382016-10-14 10:54:54 -04002025 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002026}
2027
Geoff Lang2186c382016-10-14 10:54:54 -04002028bool ValidateGetQueryivRobustANGLE(Context *context,
2029 GLenum target,
2030 GLenum pname,
2031 GLsizei bufSize,
2032 GLsizei *length,
2033 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002034{
Geoff Lang2186c382016-10-14 10:54:54 -04002035 if (!ValidateRobustEntryPoint(context, bufSize))
2036 {
2037 return false;
2038 }
2039
2040 if (!ValidateGetQueryivBase(context, target, pname, length))
2041 {
2042 return false;
2043 }
2044
2045 if (!ValidateRobustBufferSize(context, bufSize, *length))
2046 {
2047 return false;
2048 }
2049
2050 return true;
2051}
2052
2053bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2054{
2055 if (numParams)
2056 {
2057 *numParams = 0;
2058 }
2059
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002060 Query *queryObject = context->getQuery(id, false, GL_NONE);
2061
2062 if (!queryObject)
2063 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002064 context->handleError(InvalidOperation() << "Query does not exist");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002065 return false;
2066 }
2067
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002068 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002069 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002070 context->handleError(InvalidOperation() << "Query currently active");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002071 return false;
2072 }
2073
2074 switch (pname)
2075 {
2076 case GL_QUERY_RESULT_EXT:
2077 case GL_QUERY_RESULT_AVAILABLE_EXT:
2078 break;
2079
2080 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002081 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002082 return false;
2083 }
2084
Geoff Lang2186c382016-10-14 10:54:54 -04002085 if (numParams)
2086 {
2087 *numParams = 1;
2088 }
2089
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002090 return true;
2091}
2092
2093bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2094{
2095 if (!context->getExtensions().disjointTimerQuery)
2096 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002097 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002098 return false;
2099 }
Geoff Lang2186c382016-10-14 10:54:54 -04002100 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2101}
2102
2103bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2104 GLuint id,
2105 GLenum pname,
2106 GLsizei bufSize,
2107 GLsizei *length,
2108 GLint *params)
2109{
2110 if (!context->getExtensions().disjointTimerQuery)
2111 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002112 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002113 return false;
2114 }
2115
2116 if (!ValidateRobustEntryPoint(context, bufSize))
2117 {
2118 return false;
2119 }
2120
2121 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2122 {
2123 return false;
2124 }
2125
2126 if (!ValidateRobustBufferSize(context, bufSize, *length))
2127 {
2128 return false;
2129 }
2130
2131 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002132}
2133
2134bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2135{
2136 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002137 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002138 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002139 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002140 return false;
2141 }
Geoff Lang2186c382016-10-14 10:54:54 -04002142 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2143}
2144
2145bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2146 GLuint id,
2147 GLenum pname,
2148 GLsizei bufSize,
2149 GLsizei *length,
2150 GLuint *params)
2151{
2152 if (!context->getExtensions().disjointTimerQuery &&
2153 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2154 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002155 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002156 return false;
2157 }
2158
2159 if (!ValidateRobustEntryPoint(context, bufSize))
2160 {
2161 return false;
2162 }
2163
2164 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2165 {
2166 return false;
2167 }
2168
2169 if (!ValidateRobustBufferSize(context, bufSize, *length))
2170 {
2171 return false;
2172 }
2173
2174 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002175}
2176
2177bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2178{
2179 if (!context->getExtensions().disjointTimerQuery)
2180 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002181 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002182 return false;
2183 }
Geoff Lang2186c382016-10-14 10:54:54 -04002184 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2185}
2186
2187bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2188 GLuint id,
2189 GLenum pname,
2190 GLsizei bufSize,
2191 GLsizei *length,
2192 GLint64 *params)
2193{
2194 if (!context->getExtensions().disjointTimerQuery)
2195 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002196 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002197 return false;
2198 }
2199
2200 if (!ValidateRobustEntryPoint(context, bufSize))
2201 {
2202 return false;
2203 }
2204
2205 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2206 {
2207 return false;
2208 }
2209
2210 if (!ValidateRobustBufferSize(context, bufSize, *length))
2211 {
2212 return false;
2213 }
2214
2215 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002216}
2217
2218bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2219{
2220 if (!context->getExtensions().disjointTimerQuery)
2221 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002222 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002223 return false;
2224 }
Geoff Lang2186c382016-10-14 10:54:54 -04002225 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2226}
2227
2228bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2229 GLuint id,
2230 GLenum pname,
2231 GLsizei bufSize,
2232 GLsizei *length,
2233 GLuint64 *params)
2234{
2235 if (!context->getExtensions().disjointTimerQuery)
2236 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002237 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002238 return false;
2239 }
2240
2241 if (!ValidateRobustEntryPoint(context, bufSize))
2242 {
2243 return false;
2244 }
2245
2246 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2247 {
2248 return false;
2249 }
2250
2251 if (!ValidateRobustBufferSize(context, bufSize, *length))
2252 {
2253 return false;
2254 }
2255
2256 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002257}
2258
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002259bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002260 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002261 GLuint program,
2262 GLint location,
2263 GLsizei count)
2264{
2265 // Check for ES31 program uniform entry points
2266 if (context->getClientVersion() < Version(3, 1))
2267 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002268 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002269 return false;
2270 }
2271
2272 const LinkedUniform *uniform = nullptr;
2273 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002274 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2275 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002276}
2277
Frank Henigmana98a6472017-02-02 21:38:32 -05002278bool ValidateProgramUniform1iv(gl::Context *context,
2279 GLuint program,
2280 GLint location,
2281 GLsizei count,
2282 const GLint *value)
2283{
2284 // Check for ES31 program uniform entry points
2285 if (context->getClientVersion() < Version(3, 1))
2286 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002287 context->handleError(InvalidOperation());
Frank Henigmana98a6472017-02-02 21:38:32 -05002288 return false;
2289 }
2290
2291 const LinkedUniform *uniform = nullptr;
2292 gl::Program *programObject = GetValidProgram(context, program);
2293 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2294 ValidateUniform1ivValue(context, uniform->type, count, value);
2295}
2296
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002297bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002298 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002299 GLuint program,
2300 GLint location,
2301 GLsizei count,
2302 GLboolean transpose)
2303{
2304 // Check for ES31 program uniform entry points
2305 if (context->getClientVersion() < Version(3, 1))
2306 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002307 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002308 return false;
2309 }
2310
2311 const LinkedUniform *uniform = nullptr;
2312 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002313 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2314 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002315}
2316
Jamie Madillc1d770e2017-04-13 17:31:24 -04002317bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002318{
2319 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002320 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002321 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002322 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002323 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002324 }
2325
Jamie Madill62d31cb2015-09-11 13:25:51 -04002326 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002327 gl::Program *programObject = context->getGLState().getProgram();
2328 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2329 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002330}
2331
Jamie Madillbe849e42017-05-02 15:49:00 -04002332bool ValidateUniform1iv(ValidationContext *context,
2333 GLint location,
2334 GLsizei count,
2335 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002336{
2337 const LinkedUniform *uniform = nullptr;
2338 gl::Program *programObject = context->getGLState().getProgram();
2339 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2340 ValidateUniform1ivValue(context, uniform->type, count, value);
2341}
2342
Jamie Madillc1d770e2017-04-13 17:31:24 -04002343bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002344 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002345 GLint location,
2346 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002347 GLboolean transpose)
2348{
2349 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002350 int rows = VariableRowCount(valueType);
2351 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002352 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002353 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002354 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002355 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002356 }
2357
Martin Radev1be913c2016-07-11 17:59:16 +03002358 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002359 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002360 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002361 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002362 }
2363
Jamie Madill62d31cb2015-09-11 13:25:51 -04002364 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002365 gl::Program *programObject = context->getGLState().getProgram();
2366 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2367 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002368}
2369
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002370bool ValidateStateQuery(ValidationContext *context,
2371 GLenum pname,
2372 GLenum *nativeType,
2373 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002374{
2375 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2376 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002377 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002378 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002379 }
2380
Jamie Madill0af26e12015-03-05 19:54:33 -05002381 const Caps &caps = context->getCaps();
2382
Jamie Madill893ab082014-05-16 16:56:10 -04002383 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2384 {
2385 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2386
Jamie Madill0af26e12015-03-05 19:54:33 -05002387 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002388 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002389 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002390 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002391 }
2392 }
2393
2394 switch (pname)
2395 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002396 case GL_TEXTURE_BINDING_2D:
2397 case GL_TEXTURE_BINDING_CUBE_MAP:
2398 case GL_TEXTURE_BINDING_3D:
2399 case GL_TEXTURE_BINDING_2D_ARRAY:
2400 break;
2401 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2402 if (!context->getExtensions().eglStreamConsumerExternal &&
2403 !context->getExtensions().eglImageExternal)
2404 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002405 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2406 "nor GL_OES_EGL_image_external "
2407 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002408 return false;
2409 }
2410 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002411
He Yunchaoced53ae2016-11-29 15:00:51 +08002412 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2413 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002414 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002415 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2416 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002417 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002418 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002419 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002420 }
2421
Jamie Madill51f40ec2016-06-15 14:06:00 -04002422 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2423 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002424
2425 if (framebuffer->getReadBufferState() == GL_NONE)
2426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002427 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Martin Radev138064f2016-07-15 12:03:41 +03002428 return false;
2429 }
2430
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002431 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002432 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002433 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002434 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002435 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002436 }
2437 }
2438 break;
2439
He Yunchaoced53ae2016-11-29 15:00:51 +08002440 default:
2441 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002442 }
2443
2444 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002445 if (*numParams == 0)
2446 {
2447 return false;
2448 }
2449
2450 return true;
2451}
2452
2453bool ValidateRobustStateQuery(ValidationContext *context,
2454 GLenum pname,
2455 GLsizei bufSize,
2456 GLenum *nativeType,
2457 unsigned int *numParams)
2458{
2459 if (!ValidateRobustEntryPoint(context, bufSize))
2460 {
2461 return false;
2462 }
2463
2464 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2465 {
2466 return false;
2467 }
2468
2469 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002470 {
2471 return false;
2472 }
2473
2474 return true;
2475}
2476
Jamie Madillc29968b2016-01-20 11:17:23 -05002477bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2478 GLenum target,
2479 GLint level,
2480 GLenum internalformat,
2481 bool isSubImage,
2482 GLint xoffset,
2483 GLint yoffset,
2484 GLint zoffset,
2485 GLint x,
2486 GLint y,
2487 GLsizei width,
2488 GLsizei height,
2489 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002490 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002491{
Brandon Jones6cad5662017-06-14 13:25:13 -07002492 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002493 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002494 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2495 return false;
2496 }
2497
2498 if (width < 0 || height < 0)
2499 {
2500 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002501 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002502 }
2503
He Yunchaoced53ae2016-11-29 15:00:51 +08002504 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2505 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002506 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002507 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002508 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002509 }
2510
2511 if (border != 0)
2512 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002513 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002514 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002515 }
2516
2517 if (!ValidMipLevel(context, target, level))
2518 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002519 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002520 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002521 }
2522
Jamie Madill51f40ec2016-06-15 14:06:00 -04002523 const auto &state = context->getGLState();
2524 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002525 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002527 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002528 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002529 }
2530
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002531 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002532 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002533 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002534 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002535 }
2536
Martin Radev138064f2016-07-15 12:03:41 +03002537 if (readFramebuffer->getReadBufferState() == GL_NONE)
2538 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002539 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Martin Radev138064f2016-07-15 12:03:41 +03002540 return false;
2541 }
2542
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002543 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2544 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002545 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002546 // situation is an application error that would lead to a crash in ANGLE.
2547 if (readFramebuffer->getReadColorbuffer() == nullptr)
2548 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002549 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002550 return false;
2551 }
2552
Geoff Langaae65a42014-05-26 12:43:44 -04002553 const gl::Caps &caps = context->getCaps();
2554
Geoff Langaae65a42014-05-26 12:43:44 -04002555 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002556 switch (target)
2557 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002558 case GL_TEXTURE_2D:
2559 maxDimension = caps.max2DTextureSize;
2560 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002561
He Yunchaoced53ae2016-11-29 15:00:51 +08002562 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2563 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2564 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2565 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2566 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2567 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2568 maxDimension = caps.maxCubeMapTextureSize;
2569 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002570
He Yunchaoced53ae2016-11-29 15:00:51 +08002571 case GL_TEXTURE_2D_ARRAY:
2572 maxDimension = caps.max2DTextureSize;
2573 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002574
He Yunchaoced53ae2016-11-29 15:00:51 +08002575 case GL_TEXTURE_3D:
2576 maxDimension = caps.max3DTextureSize;
2577 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002578
He Yunchaoced53ae2016-11-29 15:00:51 +08002579 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002580 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002581 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002582 }
2583
Jamie Madillc29968b2016-01-20 11:17:23 -05002584 gl::Texture *texture =
2585 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002586 if (!texture)
2587 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002588 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002589 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002590 }
2591
Geoff Lang69cce582015-09-17 13:20:36 -04002592 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002593 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002594 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002595 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002596 }
2597
Geoff Langca271392017-04-05 12:30:00 -04002598 const gl::InternalFormat &formatInfo =
2599 gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002600
Geoff Lang966c9402017-04-18 12:38:27 -04002601 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002602 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002603 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002604 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002605 }
2606
2607 if (isSubImage)
2608 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002609 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2610 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2611 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002612 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002613 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002614 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002615 }
2616 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002617 else
2618 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002619 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002620 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002621 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002622 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002623 }
2624
Geoff Langeb66a6e2016-10-31 13:06:12 -04002625 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002626 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002627 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002628 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002629 }
2630
2631 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002632 if (static_cast<int>(width) > maxLevelDimension ||
2633 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002634 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002635 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002636 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002637 }
2638 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002639
Jamie Madill0c8abca2016-07-22 20:21:26 -04002640 if (textureFormatOut)
2641 {
2642 *textureFormatOut = texture->getFormat(target, level);
2643 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002644
2645 // Detect texture copying feedback loops for WebGL.
2646 if (context->getExtensions().webglCompatibility)
2647 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002648 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002649 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002650 context->handleError(InvalidOperation() << "Texture copying feedback loop formed "
2651 "between Framebuffer and specified "
2652 "Texture level.");
Jamie Madillf695a3a2017-01-11 17:36:35 -05002653 return false;
2654 }
2655 }
2656
Jamie Madill560a8d82014-05-21 13:06:20 -04002657 return true;
2658}
2659
Jiajia Qind9671222016-11-29 16:30:31 +08002660bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002661{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002662 switch (mode)
2663 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002664 case GL_POINTS:
2665 case GL_LINES:
2666 case GL_LINE_LOOP:
2667 case GL_LINE_STRIP:
2668 case GL_TRIANGLES:
2669 case GL_TRIANGLE_STRIP:
2670 case GL_TRIANGLE_FAN:
2671 break;
2672 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002673 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002674 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002675 }
2676
Jamie Madill250d33f2014-06-06 17:09:03 -04002677 if (count < 0)
2678 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002679 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002680 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002681 }
2682
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002683 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002684
Jamie Madill250d33f2014-06-06 17:09:03 -04002685 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002686 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002688 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002689 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002690 }
2691
Jamie Madillcbcde722017-01-06 14:50:00 -05002692 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2693 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002694 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002695 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
2696 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002697 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002698 const FramebufferAttachment *dsAttachment =
2699 framebuffer->getStencilOrDepthStencilAttachment();
2700 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002701 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002702 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002703
2704 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2705 bool differentWritemasks =
2706 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2707 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2708 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2709 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2710
2711 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002712 {
Jamie Madillcbcde722017-01-06 14:50:00 -05002713 if (!context->getExtensions().webglCompatibility)
2714 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002715 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2716 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002717 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002718 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002719 return false;
2720 }
Jamie Madillac528012014-06-20 13:21:23 -04002721 }
2722
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002723 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002725 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002726 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002727 }
2728
Geoff Lang7dd2e102014-11-10 15:19:26 -05002729 gl::Program *program = state.getProgram();
2730 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002731 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002732 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002733 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002734 }
2735
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002736 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002737 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002738 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002739 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002740 }
2741
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002742 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002743 for (unsigned int uniformBlockIndex = 0;
2744 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002745 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002746 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002747 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002748 const OffsetBindingPointer<Buffer> &uniformBuffer =
2749 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002750
Geoff Lang5d124a62015-09-15 13:03:27 -04002751 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002752 {
2753 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002754 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002755 InvalidOperation()
2756 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002757 return false;
2758 }
2759
Geoff Lang5d124a62015-09-15 13:03:27 -04002760 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002761 if (uniformBufferSize == 0)
2762 {
2763 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002764 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002765 }
2766
Jamie Madill62d31cb2015-09-11 13:25:51 -04002767 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002768 {
2769 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002770 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002771 InvalidOperation()
2772 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002773 return false;
2774 }
2775 }
2776
Geoff Lange0cff192017-05-30 13:04:56 -04002777 // Do some additonal WebGL-specific validation
Jamie Madilla4595b82017-01-11 17:36:34 -05002778 if (context->getExtensions().webglCompatibility)
2779 {
Geoff Lange0cff192017-05-30 13:04:56 -04002780 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002781 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2782 {
2783 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002784 InvalidOperation()
2785 << "Rendering feedback loop formed between Framebuffer and active Texture.");
Jamie Madilla4595b82017-01-11 17:36:34 -05002786 return false;
2787 }
Geoff Lange0cff192017-05-30 13:04:56 -04002788
Geoff Lang9ab5b822017-05-30 16:19:23 -04002789 // Detect that the vertex shader input types match the attribute types
2790 if (!ValidateVertexShaderAttributeTypeMatch(context))
2791 {
2792 return false;
2793 }
2794
Geoff Lange0cff192017-05-30 13:04:56 -04002795 // Detect that the color buffer types match the fragment shader output types
2796 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2797 {
2798 return false;
2799 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002800 }
2801
Jamie Madill250d33f2014-06-06 17:09:03 -04002802 // No-op if zero count
2803 return (count > 0);
2804}
2805
Jamie Madillc1d770e2017-04-13 17:31:24 -04002806bool ValidateDrawArraysCommon(ValidationContext *context,
2807 GLenum mode,
2808 GLint first,
2809 GLsizei count,
2810 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002811{
Jamie Madillfd716582014-06-06 17:09:04 -04002812 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002813 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002814 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002815 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002816 }
2817
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002818 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002819 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002820 if (curTransformFeedback && curTransformFeedback->isActive() &&
2821 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002822 {
2823 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002824 // that does not match the current transform feedback object's draw mode (if transform
2825 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002826 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002827 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002828 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002829 }
2830
Jiajia Qind9671222016-11-29 16:30:31 +08002831 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002832 {
2833 return false;
2834 }
2835
Corentin Wallez71168a02016-12-19 15:11:18 -08002836 // Check the computation of maxVertex doesn't overflow.
2837 // - first < 0 or count < 0 have been checked as an error condition
2838 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2839 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2840 ASSERT(count > 0 && first >= 0);
2841 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2842 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002843 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002844 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002845 return false;
2846 }
2847
Corentin Wallez71168a02016-12-19 15:11:18 -08002848 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002849 {
2850 return false;
2851 }
2852
2853 return true;
2854}
2855
He Yunchaoced53ae2016-11-29 15:00:51 +08002856bool ValidateDrawArraysInstanced(Context *context,
2857 GLenum mode,
2858 GLint first,
2859 GLsizei count,
2860 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002861{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002862 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
Geoff Lang87a93302014-09-16 13:29:43 -04002863}
2864
He Yunchaoced53ae2016-11-29 15:00:51 +08002865bool ValidateDrawArraysInstancedANGLE(Context *context,
2866 GLenum mode,
2867 GLint first,
2868 GLsizei count,
2869 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002870{
Corentin Wallez170efbf2017-05-02 13:45:01 -04002871 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002872 {
2873 return false;
2874 }
2875
Corentin Wallez0dc97812017-06-22 14:38:44 -04002876 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002877}
2878
Jiajia Qind9671222016-11-29 16:30:31 +08002879bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002880{
Jamie Madill250d33f2014-06-06 17:09:03 -04002881 switch (type)
2882 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002883 case GL_UNSIGNED_BYTE:
2884 case GL_UNSIGNED_SHORT:
2885 break;
2886 case GL_UNSIGNED_INT:
2887 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2888 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002889 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002890 return false;
2891 }
2892 break;
2893 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002894 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002895 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002896 }
2897
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002898 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002899
2900 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002901 if (curTransformFeedback && curTransformFeedback->isActive() &&
2902 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002903 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002904 // It is an invalid operation to call DrawElements, DrawRangeElements or
2905 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002906 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002907 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002908 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002909 }
2910
Jiajia Qind9671222016-11-29 16:30:31 +08002911 return true;
2912}
2913
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002914bool ValidateDrawElementsCommon(ValidationContext *context,
2915 GLenum mode,
2916 GLsizei count,
2917 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002918 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002919 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002920{
2921 if (!ValidateDrawElementsBase(context, type))
2922 return false;
2923
2924 const State &state = context->getGLState();
2925
Corentin Wallez170efbf2017-05-02 13:45:01 -04002926 if (!ValidateDrawBase(context, mode, count))
2927 {
2928 return false;
2929 }
2930
Jamie Madill250d33f2014-06-06 17:09:03 -04002931 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002932 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002933 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002934 context->handleError(InvalidOperation() << "Index buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -04002935 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002936 }
2937
He Yunchaoced53ae2016-11-29 15:00:51 +08002938 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002939 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002940
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002941 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2942
2943 if (context->getExtensions().webglCompatibility)
2944 {
2945 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2946 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2947 {
2948 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2949 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2950 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002951 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002952 return false;
2953 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002954
2955 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2956 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2957 // error is generated.
2958 if (reinterpret_cast<intptr_t>(indices) < 0)
2959 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002960 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002961 return false;
2962 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002963 }
2964
2965 if (context->getExtensions().webglCompatibility ||
2966 !context->getGLState().areClientArraysEnabled())
2967 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002968 if (!elementArrayBuffer && count > 0)
2969 {
2970 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2971 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2972 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002973 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002974 return false;
2975 }
2976 }
2977
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002978 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002979 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002980 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002981 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002982 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2983 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2984 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2985 constexpr uint64_t kMaxTypeSize = 8;
2986 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2987 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2988 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002989
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002990 uint64_t typeSize = typeBytes;
2991 uint64_t elementCount = static_cast<uint64_t>(count);
2992 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2993
2994 // Doing the multiplication here is overflow-safe
2995 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2996
2997 // The offset can be any value, check for overflows
2998 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2999 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003000 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003001 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003002 return false;
3003 }
3004
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003005 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3006 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003007 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003008 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003009 return false;
3010 }
3011 }
3012 else if (!indices)
3013 {
3014 // This is an application error that would normally result in a crash,
3015 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003016 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04003017 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003018 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003019 }
3020
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003021 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill2b976812014-08-25 15:47:49 -04003022 // TODO: offer fast path, with disabled index validation.
3023 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003024 const auto &params = context->getParams<HasIndexRange>();
3025 const auto &indexRangeOpt = params.getIndexRange();
3026 if (!indexRangeOpt.valid())
Jamie Madill2b976812014-08-25 15:47:49 -04003027 {
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003028 // Unexpected error.
3029 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003030 }
3031
Jamie Madille79b1e12015-11-04 16:36:37 -05003032 // If we use an index greater than our maximum supported index range, return an error.
3033 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3034 // return an error if possible here.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003035 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
Jamie Madille79b1e12015-11-04 16:36:37 -05003036 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003037 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
Jamie Madille79b1e12015-11-04 16:36:37 -05003038 return false;
3039 }
3040
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003041 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
3042 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003043 {
3044 return false;
3045 }
3046
Geoff Lang3edfe032015-09-04 16:38:24 -04003047 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003048 return (indexRangeOpt.value().vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003049}
3050
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003051bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
3052 GLenum mode,
3053 GLsizei count,
3054 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003055 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003056 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003057{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003058 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003059}
3060
Geoff Lang3edfe032015-09-04 16:38:24 -04003061bool ValidateDrawElementsInstancedANGLE(Context *context,
3062 GLenum mode,
3063 GLsizei count,
3064 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003065 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003066 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003067{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003068 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003069 {
3070 return false;
3071 }
3072
Corentin Wallez0dc97812017-06-22 14:38:44 -04003073 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003074}
3075
He Yunchaoced53ae2016-11-29 15:00:51 +08003076bool ValidateFramebufferTextureBase(Context *context,
3077 GLenum target,
3078 GLenum attachment,
3079 GLuint texture,
3080 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003081{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003082 if (!ValidFramebufferTarget(target))
3083 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003084 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003085 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003086 }
3087
3088 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003089 {
3090 return false;
3091 }
3092
Jamie Madill55ec3b12014-07-03 10:38:57 -04003093 if (texture != 0)
3094 {
3095 gl::Texture *tex = context->getTexture(texture);
3096
Jamie Madillbe849e42017-05-02 15:49:00 -04003097 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003098 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003099 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003100 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003101 }
3102
3103 if (level < 0)
3104 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003105 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003106 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003107 }
3108 }
3109
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003110 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003111 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003112
Jamie Madill84115c92015-04-23 15:00:07 -04003113 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003114 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003115 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003116 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003117 }
3118
3119 return true;
3120}
3121
Geoff Langb1196682014-07-23 13:47:29 -04003122bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003123{
3124 if (program == 0)
3125 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003126 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003127 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003128 }
3129
Dian Xiang769769a2015-09-09 15:20:08 -07003130 gl::Program *programObject = GetValidProgram(context, program);
3131 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003132 {
3133 return false;
3134 }
3135
Jamie Madill0063c512014-08-25 15:47:53 -04003136 if (!programObject || !programObject->isLinked())
3137 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003138 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003139 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003140 }
3141
Geoff Lang7dd2e102014-11-10 15:19:26 -05003142 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003143 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003144 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003145 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003146 }
3147
Jamie Madill0063c512014-08-25 15:47:53 -04003148 return true;
3149}
3150
Geoff Langf41d0ee2016-10-07 13:04:23 -04003151static bool ValidateSizedGetUniform(Context *context,
3152 GLuint program,
3153 GLint location,
3154 GLsizei bufSize,
3155 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003156{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003157 if (length)
3158 {
3159 *length = 0;
3160 }
3161
Jamie Madill78f41802014-08-25 15:47:55 -04003162 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003163 {
Jamie Madill78f41802014-08-25 15:47:55 -04003164 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003165 }
3166
Geoff Langf41d0ee2016-10-07 13:04:23 -04003167 if (bufSize < 0)
3168 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003169 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003170 return false;
3171 }
3172
Jamie Madilla502c742014-08-28 17:19:13 -04003173 gl::Program *programObject = context->getProgram(program);
3174 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003175
Jamie Madill78f41802014-08-25 15:47:55 -04003176 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003177 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003178 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003179 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003180 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003181 context->handleError(InvalidOperation()
3182 << "bufSize of at least " << requiredBytes << " is required.");
Geoff Langb1196682014-07-23 13:47:29 -04003183 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003184 }
3185
Geoff Langf41d0ee2016-10-07 13:04:23 -04003186 if (length)
3187 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003188 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003189 }
3190
Jamie Madill0063c512014-08-25 15:47:53 -04003191 return true;
3192}
3193
He Yunchaoced53ae2016-11-29 15:00:51 +08003194bool ValidateGetnUniformfvEXT(Context *context,
3195 GLuint program,
3196 GLint location,
3197 GLsizei bufSize,
3198 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003199{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003200 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003201}
3202
He Yunchaoced53ae2016-11-29 15:00:51 +08003203bool ValidateGetnUniformivEXT(Context *context,
3204 GLuint program,
3205 GLint location,
3206 GLsizei bufSize,
3207 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003208{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003209 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3210}
3211
3212bool ValidateGetUniformfvRobustANGLE(Context *context,
3213 GLuint program,
3214 GLint location,
3215 GLsizei bufSize,
3216 GLsizei *length,
3217 GLfloat *params)
3218{
3219 if (!ValidateRobustEntryPoint(context, bufSize))
3220 {
3221 return false;
3222 }
3223
3224 // bufSize is validated in ValidateSizedGetUniform
3225 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3226}
3227
3228bool ValidateGetUniformivRobustANGLE(Context *context,
3229 GLuint program,
3230 GLint location,
3231 GLsizei bufSize,
3232 GLsizei *length,
3233 GLint *params)
3234{
3235 if (!ValidateRobustEntryPoint(context, bufSize))
3236 {
3237 return false;
3238 }
3239
3240 // bufSize is validated in ValidateSizedGetUniform
3241 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3242}
3243
3244bool ValidateGetUniformuivRobustANGLE(Context *context,
3245 GLuint program,
3246 GLint location,
3247 GLsizei bufSize,
3248 GLsizei *length,
3249 GLuint *params)
3250{
3251 if (!ValidateRobustEntryPoint(context, bufSize))
3252 {
3253 return false;
3254 }
3255
3256 if (context->getClientMajorVersion() < 3)
3257 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003258 context->handleError(InvalidOperation() << "Entry point requires at least OpenGL ES 3.0.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003259 return false;
3260 }
3261
3262 // bufSize is validated in ValidateSizedGetUniform
3263 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003264}
3265
He Yunchaoced53ae2016-11-29 15:00:51 +08003266bool ValidateDiscardFramebufferBase(Context *context,
3267 GLenum target,
3268 GLsizei numAttachments,
3269 const GLenum *attachments,
3270 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003271{
3272 if (numAttachments < 0)
3273 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003274 context->handleError(InvalidValue() << "numAttachments must not be less than zero");
Austin Kinross08332632015-05-05 13:35:47 -07003275 return false;
3276 }
3277
3278 for (GLsizei i = 0; i < numAttachments; ++i)
3279 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003280 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003281 {
3282 if (defaultFramebuffer)
3283 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003284 context->handleError(InvalidEnum()
3285 << "Invalid attachment when the default framebuffer is bound");
Austin Kinross08332632015-05-05 13:35:47 -07003286 return false;
3287 }
3288
3289 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3290 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003291 context->handleError(InvalidOperation() << "Requested color attachment is "
3292 "greater than the maximum supported "
3293 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003294 return false;
3295 }
3296 }
3297 else
3298 {
3299 switch (attachments[i])
3300 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003301 case GL_DEPTH_ATTACHMENT:
3302 case GL_STENCIL_ATTACHMENT:
3303 case GL_DEPTH_STENCIL_ATTACHMENT:
3304 if (defaultFramebuffer)
3305 {
3306 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003307 InvalidEnum()
3308 << "Invalid attachment when the default framebuffer is bound");
He Yunchaoced53ae2016-11-29 15:00:51 +08003309 return false;
3310 }
3311 break;
3312 case GL_COLOR:
3313 case GL_DEPTH:
3314 case GL_STENCIL:
3315 if (!defaultFramebuffer)
3316 {
3317 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003318 InvalidEnum()
3319 << "Invalid attachment when the default framebuffer is not bound");
He Yunchaoced53ae2016-11-29 15:00:51 +08003320 return false;
3321 }
3322 break;
3323 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003324 context->handleError(InvalidEnum() << "Invalid attachment");
Austin Kinross08332632015-05-05 13:35:47 -07003325 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003326 }
3327 }
3328 }
3329
3330 return true;
3331}
3332
Austin Kinross6ee1e782015-05-29 17:05:37 -07003333bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3334{
3335 // Note that debug marker calls must not set error state
3336
3337 if (length < 0)
3338 {
3339 return false;
3340 }
3341
3342 if (marker == nullptr)
3343 {
3344 return false;
3345 }
3346
3347 return true;
3348}
3349
3350bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3351{
3352 // Note that debug marker calls must not set error state
3353
3354 if (length < 0)
3355 {
3356 return false;
3357 }
3358
3359 if (length > 0 && marker == nullptr)
3360 {
3361 return false;
3362 }
3363
3364 return true;
3365}
3366
Geoff Langdcab33b2015-07-21 13:03:16 -04003367bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003368 GLenum target,
3369 egl::Image *image)
3370{
Geoff Langa8406172015-07-21 16:53:39 -04003371 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3372 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003373 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003374 return false;
3375 }
3376
3377 switch (target)
3378 {
3379 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003380 if (!context->getExtensions().eglImage)
3381 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003382 context->handleError(InvalidEnum()
3383 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003384 }
3385 break;
3386
3387 case GL_TEXTURE_EXTERNAL_OES:
3388 if (!context->getExtensions().eglImageExternal)
3389 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003390 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3391 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003392 }
Geoff Langa8406172015-07-21 16:53:39 -04003393 break;
3394
3395 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003396 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003397 return false;
3398 }
3399
Jamie Madill61e16b42017-06-19 11:13:23 -04003400 ASSERT(context->getCurrentDisplay());
3401 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003403 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003404 return false;
3405 }
3406
3407 if (image->getSamples() > 0)
3408 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003409 context->handleError(InvalidOperation()
3410 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003411 return false;
3412 }
3413
Geoff Langca271392017-04-05 12:30:00 -04003414 const TextureCaps &textureCaps =
3415 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003416 if (!textureCaps.texturable)
3417 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003418 context->handleError(InvalidOperation()
3419 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003420 return false;
3421 }
3422
Geoff Langdcab33b2015-07-21 13:03:16 -04003423 return true;
3424}
3425
3426bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003427 GLenum target,
3428 egl::Image *image)
3429{
Geoff Langa8406172015-07-21 16:53:39 -04003430 if (!context->getExtensions().eglImage)
3431 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003432 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003433 return false;
3434 }
3435
3436 switch (target)
3437 {
3438 case GL_RENDERBUFFER:
3439 break;
3440
3441 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003442 context->handleError(InvalidEnum() << "invalid renderbuffer target.");
Geoff Langa8406172015-07-21 16:53:39 -04003443 return false;
3444 }
3445
Jamie Madill61e16b42017-06-19 11:13:23 -04003446 ASSERT(context->getCurrentDisplay());
3447 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003448 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003449 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003450 return false;
3451 }
3452
Geoff Langca271392017-04-05 12:30:00 -04003453 const TextureCaps &textureCaps =
3454 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003455 if (!textureCaps.renderable)
3456 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003457 context->handleError(InvalidOperation()
3458 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003459 return false;
3460 }
3461
Geoff Langdcab33b2015-07-21 13:03:16 -04003462 return true;
3463}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003464
3465bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3466{
Geoff Lang36167ab2015-12-07 10:27:14 -05003467 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003468 {
3469 // The default VAO should always exist
3470 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003471 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003472 return false;
3473 }
3474
3475 return true;
3476}
3477
Geoff Langc5629752015-12-07 16:29:04 -05003478bool ValidateProgramBinaryBase(Context *context,
3479 GLuint program,
3480 GLenum binaryFormat,
3481 const void *binary,
3482 GLint length)
3483{
3484 Program *programObject = GetValidProgram(context, program);
3485 if (programObject == nullptr)
3486 {
3487 return false;
3488 }
3489
3490 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3491 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3492 programBinaryFormats.end())
3493 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003494 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003495 return false;
3496 }
3497
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003498 if (context->hasActiveTransformFeedback(program))
3499 {
3500 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003501 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3502 "is associated with an active transform "
3503 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003504 return false;
3505 }
3506
Geoff Langc5629752015-12-07 16:29:04 -05003507 return true;
3508}
3509
3510bool ValidateGetProgramBinaryBase(Context *context,
3511 GLuint program,
3512 GLsizei bufSize,
3513 GLsizei *length,
3514 GLenum *binaryFormat,
3515 void *binary)
3516{
3517 Program *programObject = GetValidProgram(context, program);
3518 if (programObject == nullptr)
3519 {
3520 return false;
3521 }
3522
3523 if (!programObject->isLinked())
3524 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003525 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003526 return false;
3527 }
3528
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003529 if (context->getCaps().programBinaryFormats.empty())
3530 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003531 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003532 return false;
3533 }
3534
Geoff Langc5629752015-12-07 16:29:04 -05003535 return true;
3536}
Jamie Madillc29968b2016-01-20 11:17:23 -05003537
Jamie Madillc29968b2016-01-20 11:17:23 -05003538bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3539{
3540 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3541 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3542 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003543 context->handleError(InvalidValue()
3544 << "n must be non-negative and no greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003545 return false;
3546 }
3547
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003548 ASSERT(context->getGLState().getDrawFramebuffer());
3549 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003550 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3551
3552 // This should come first before the check for the default frame buffer
3553 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3554 // rather than INVALID_OPERATION
3555 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3556 {
3557 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3558
3559 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003560 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3561 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003562 {
3563 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003564 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3565 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3566 // 3.1 is still a bit ambiguous about the error, but future specs are
3567 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003568 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003569 return false;
3570 }
3571 else if (bufs[colorAttachment] >= maxColorAttachment)
3572 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003573 context->handleError(InvalidOperation()
3574 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003575 return false;
3576 }
3577 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3578 frameBufferId != 0)
3579 {
3580 // INVALID_OPERATION-GL is bound to buffer and ith argument
3581 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003582 context->handleError(InvalidOperation()
3583 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003584 return false;
3585 }
3586 }
3587
3588 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3589 // and n is not 1 or bufs is bound to value other than BACK and NONE
3590 if (frameBufferId == 0)
3591 {
3592 if (n != 1)
3593 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003594 context->handleError(InvalidOperation()
3595 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003596 return false;
3597 }
3598
3599 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3600 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003601 context->handleError(
3602 InvalidOperation()
3603 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003604 return false;
3605 }
3606 }
3607
3608 return true;
3609}
3610
Geoff Lang496c02d2016-10-20 11:38:11 -07003611bool ValidateGetBufferPointervBase(Context *context,
3612 GLenum target,
3613 GLenum pname,
3614 GLsizei *length,
3615 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003616{
Geoff Lang496c02d2016-10-20 11:38:11 -07003617 if (length)
3618 {
3619 *length = 0;
3620 }
3621
3622 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3623 {
3624 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003625 InvalidOperation()
3626 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003627 return false;
3628 }
3629
Olli Etuaho4f667482016-03-30 15:56:35 +03003630 if (!ValidBufferTarget(context, target))
3631 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003632 context->handleError(InvalidEnum() << "Buffer target not valid: 0x" << std::hex
3633 << std::uppercase << target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003634 return false;
3635 }
3636
Geoff Lang496c02d2016-10-20 11:38:11 -07003637 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003638 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003639 case GL_BUFFER_MAP_POINTER:
3640 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003641
Geoff Lang496c02d2016-10-20 11:38:11 -07003642 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003643 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003644 return false;
3645 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003646
3647 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3648 // target bound to zero generate an INVALID_OPERATION error."
3649 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003650 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003651 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003652 context->handleError(InvalidOperation()
3653 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003654 return false;
3655 }
3656
Geoff Lang496c02d2016-10-20 11:38:11 -07003657 if (length)
3658 {
3659 *length = 1;
3660 }
3661
Olli Etuaho4f667482016-03-30 15:56:35 +03003662 return true;
3663}
3664
3665bool ValidateUnmapBufferBase(Context *context, GLenum target)
3666{
3667 if (!ValidBufferTarget(context, target))
3668 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003669 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003670 return false;
3671 }
3672
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003673 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003674
3675 if (buffer == nullptr || !buffer->isMapped())
3676 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003677 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003678 return false;
3679 }
3680
3681 return true;
3682}
3683
3684bool ValidateMapBufferRangeBase(Context *context,
3685 GLenum target,
3686 GLintptr offset,
3687 GLsizeiptr length,
3688 GLbitfield access)
3689{
3690 if (!ValidBufferTarget(context, target))
3691 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003692 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003693 return false;
3694 }
3695
Brandon Jones6cad5662017-06-14 13:25:13 -07003696 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003697 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003698 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3699 return false;
3700 }
3701
3702 if (length < 0)
3703 {
3704 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003705 return false;
3706 }
3707
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003708 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003709
3710 if (!buffer)
3711 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003712 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003713 return false;
3714 }
3715
3716 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003717 CheckedNumeric<size_t> checkedOffset(offset);
3718 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003719
Jamie Madille2e406c2016-06-02 13:04:10 -04003720 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003721 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003722 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003723 return false;
3724 }
3725
3726 // Check for invalid bits in the mask
3727 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3728 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3729 GL_MAP_UNSYNCHRONIZED_BIT;
3730
3731 if (access & ~(allAccessBits))
3732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003733 context->handleError(InvalidValue()
3734 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003735 return false;
3736 }
3737
3738 if (length == 0)
3739 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003740 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003741 return false;
3742 }
3743
3744 if (buffer->isMapped())
3745 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003746 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003747 return false;
3748 }
3749
3750 // Check for invalid bit combinations
3751 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3752 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003753 context->handleError(InvalidOperation()
3754 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003755 return false;
3756 }
3757
3758 GLbitfield writeOnlyBits =
3759 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3760
3761 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3762 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003763 context->handleError(InvalidOperation()
3764 << "Invalid access bits when mapping buffer for reading: 0x"
3765 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003766 return false;
3767 }
3768
3769 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3770 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003771 context->handleError(
3772 InvalidOperation()
3773 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003774 return false;
3775 }
3776 return true;
3777}
3778
3779bool ValidateFlushMappedBufferRangeBase(Context *context,
3780 GLenum target,
3781 GLintptr offset,
3782 GLsizeiptr length)
3783{
Brandon Jones6cad5662017-06-14 13:25:13 -07003784 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003785 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003786 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3787 return false;
3788 }
3789
3790 if (length < 0)
3791 {
3792 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003793 return false;
3794 }
3795
3796 if (!ValidBufferTarget(context, target))
3797 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003798 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003799 return false;
3800 }
3801
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003802 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003803
3804 if (buffer == nullptr)
3805 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003806 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003807 return false;
3808 }
3809
3810 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3811 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003812 context->handleError(InvalidOperation()
3813 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003814 return false;
3815 }
3816
3817 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003818 CheckedNumeric<size_t> checkedOffset(offset);
3819 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003820
Jamie Madille2e406c2016-06-02 13:04:10 -04003821 if (!checkedSize.IsValid() ||
3822 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003823 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003824 context->handleError(InvalidValue()
3825 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003826 return false;
3827 }
3828
3829 return true;
3830}
3831
Olli Etuaho41997e72016-03-10 13:38:39 +02003832bool ValidateGenOrDelete(Context *context, GLint n)
3833{
3834 if (n < 0)
3835 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003836 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003837 return false;
3838 }
3839 return true;
3840}
3841
Geoff Langff5b2d52016-09-07 11:32:23 -04003842bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3843{
3844 if (!context->getExtensions().robustClientMemory)
3845 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003846 context->handleError(InvalidOperation()
3847 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003848 return false;
3849 }
3850
3851 if (bufSize < 0)
3852 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003853 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003854 return false;
3855 }
3856
3857 return true;
3858}
3859
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003860bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3861{
3862 if (bufSize < numParams)
3863 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003864 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3865 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003866 return false;
3867 }
3868
3869 return true;
3870}
3871
Jamie Madillbe849e42017-05-02 15:49:00 -04003872bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3873 GLenum target,
3874 GLenum attachment,
3875 GLenum pname,
3876 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003877{
3878 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
Yunchao He33151a52017-04-13 09:58:17 +08003879 if (numParams)
3880 {
3881 *numParams = 1;
3882 }
Geoff Langff5b2d52016-09-07 11:32:23 -04003883
3884 if (!ValidFramebufferTarget(target))
3885 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003886 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003887 return false;
3888 }
3889
3890 int clientVersion = context->getClientMajorVersion();
3891
3892 switch (pname)
3893 {
3894 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3895 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3896 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3897 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3898 break;
3899
3900 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3901 if (clientVersion < 3 && !context->getExtensions().sRGB)
3902 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003903 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003904 return false;
3905 }
3906 break;
3907
3908 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3909 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3910 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3911 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3912 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3913 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3914 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3915 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3916 if (clientVersion < 3)
3917 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003918 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003919 return false;
3920 }
3921 break;
3922
3923 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003924 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003925 return false;
3926 }
3927
3928 // Determine if the attachment is a valid enum
3929 switch (attachment)
3930 {
3931 case GL_BACK:
3932 case GL_FRONT:
3933 case GL_DEPTH:
3934 case GL_STENCIL:
3935 case GL_DEPTH_STENCIL_ATTACHMENT:
3936 if (clientVersion < 3)
3937 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003938 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003939 return false;
3940 }
3941 break;
3942
3943 case GL_DEPTH_ATTACHMENT:
3944 case GL_STENCIL_ATTACHMENT:
3945 break;
3946
3947 default:
3948 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
3949 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3950 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003951 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003952 return false;
3953 }
3954 break;
3955 }
3956
3957 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3958 ASSERT(framebuffer);
3959
3960 if (framebuffer->id() == 0)
3961 {
3962 if (clientVersion < 3)
3963 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003964 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003965 return false;
3966 }
3967
3968 switch (attachment)
3969 {
3970 case GL_BACK:
3971 case GL_DEPTH:
3972 case GL_STENCIL:
3973 break;
3974
3975 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003976 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FramebufferInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003977 return false;
3978 }
3979 }
3980 else
3981 {
3982 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3983 {
3984 // Valid attachment query
3985 }
3986 else
3987 {
3988 switch (attachment)
3989 {
3990 case GL_DEPTH_ATTACHMENT:
3991 case GL_STENCIL_ATTACHMENT:
3992 break;
3993
3994 case GL_DEPTH_STENCIL_ATTACHMENT:
3995 if (!framebuffer->hasValidDepthStencil())
3996 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003997 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003998 return false;
3999 }
4000 break;
4001
4002 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004003 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FramebufferInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004004 return false;
4005 }
4006 }
4007 }
4008
4009 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4010 if (attachmentObject)
4011 {
4012 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4013 attachmentObject->type() == GL_TEXTURE ||
4014 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4015
4016 switch (pname)
4017 {
4018 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4019 if (attachmentObject->type() != GL_RENDERBUFFER &&
4020 attachmentObject->type() != GL_TEXTURE)
4021 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004022 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004023 return false;
4024 }
4025 break;
4026
4027 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4028 if (attachmentObject->type() != GL_TEXTURE)
4029 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004030 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004031 return false;
4032 }
4033 break;
4034
4035 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4036 if (attachmentObject->type() != GL_TEXTURE)
4037 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004038 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004039 return false;
4040 }
4041 break;
4042
4043 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4044 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4045 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004046 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FramebufferInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004047 return false;
4048 }
4049 break;
4050
4051 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4052 if (attachmentObject->type() != GL_TEXTURE)
4053 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004054 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004055 return false;
4056 }
4057 break;
4058
4059 default:
4060 break;
4061 }
4062 }
4063 else
4064 {
4065 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4066 // is NONE, then querying any other pname will generate INVALID_ENUM.
4067
4068 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4069 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4070 // INVALID_OPERATION for all other pnames
4071
4072 switch (pname)
4073 {
4074 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4075 break;
4076
4077 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4078 if (clientVersion < 3)
4079 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004080 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
4081 InvalidRenderbufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004082 return false;
4083 }
4084 break;
4085
4086 default:
4087 if (clientVersion < 3)
4088 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004089 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
4090 InvalidRenderbufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004091 return false;
4092 }
4093 else
4094 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004095 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
4096 InvalidRenderbufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004097 return false;
4098 }
4099 }
4100 }
4101
4102 return true;
4103}
4104
4105bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4106 GLenum target,
4107 GLenum attachment,
4108 GLenum pname,
4109 GLsizei bufSize,
4110 GLsizei *numParams)
4111{
4112 if (!ValidateRobustEntryPoint(context, bufSize))
4113 {
4114 return false;
4115 }
4116
Jamie Madillbe849e42017-05-02 15:49:00 -04004117 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4118 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004119 {
4120 return false;
4121 }
4122
4123 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4124 {
4125 return false;
4126 }
4127
4128 return true;
4129}
4130
Geoff Langff5b2d52016-09-07 11:32:23 -04004131bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4132 GLenum target,
4133 GLenum pname,
4134 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004135 GLsizei *length,
4136 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004137{
4138 if (!ValidateRobustEntryPoint(context, bufSize))
4139 {
4140 return false;
4141 }
4142
Geoff Langebebe1c2016-10-14 12:01:31 -04004143 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004144 {
4145 return false;
4146 }
4147
Geoff Langebebe1c2016-10-14 12:01:31 -04004148 if (!ValidateRobustBufferSize(context, bufSize, *length))
4149 {
4150 return false;
4151 }
4152
4153 return true;
4154}
4155
4156bool ValidateGetBufferParameteri64v(ValidationContext *context,
4157 GLenum target,
4158 GLenum pname,
4159 GLint64 *params)
4160{
4161 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4162}
4163
4164bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4165 GLenum target,
4166 GLenum pname,
4167 GLsizei bufSize,
4168 GLsizei *length,
4169 GLint64 *params)
4170{
4171 if (!ValidateRobustEntryPoint(context, bufSize))
4172 {
4173 return false;
4174 }
4175
4176 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4177 {
4178 return false;
4179 }
4180
4181 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004182 {
4183 return false;
4184 }
4185
4186 return true;
4187}
4188
Jamie Madillbe849e42017-05-02 15:49:00 -04004189bool ValidateGetProgramivBase(ValidationContext *context,
4190 GLuint program,
4191 GLenum pname,
4192 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004193{
4194 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004195 if (numParams)
4196 {
4197 *numParams = 1;
4198 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004199
4200 Program *programObject = GetValidProgram(context, program);
4201 if (!programObject)
4202 {
4203 return false;
4204 }
4205
4206 switch (pname)
4207 {
4208 case GL_DELETE_STATUS:
4209 case GL_LINK_STATUS:
4210 case GL_VALIDATE_STATUS:
4211 case GL_INFO_LOG_LENGTH:
4212 case GL_ATTACHED_SHADERS:
4213 case GL_ACTIVE_ATTRIBUTES:
4214 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4215 case GL_ACTIVE_UNIFORMS:
4216 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4217 break;
4218
4219 case GL_PROGRAM_BINARY_LENGTH:
4220 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4221 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004222 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4223 "requires GL_OES_get_program_binary or "
4224 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004225 return false;
4226 }
4227 break;
4228
4229 case GL_ACTIVE_UNIFORM_BLOCKS:
4230 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4231 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4232 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4233 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4234 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4235 if (context->getClientMajorVersion() < 3)
4236 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004237 context->handleError(InvalidEnum() << "Querying requires at least ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004238 return false;
4239 }
4240 break;
4241
Yunchao He61afff12017-03-14 15:34:03 +08004242 case GL_PROGRAM_SEPARABLE:
4243 if (context->getClientVersion() < Version(3, 1))
4244 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004245 context->handleError(InvalidEnum() << "Querying requires at least ES 3.1.");
Yunchao He61afff12017-03-14 15:34:03 +08004246 return false;
4247 }
4248 break;
4249
Geoff Langff5b2d52016-09-07 11:32:23 -04004250 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004251 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004252 return false;
4253 }
4254
4255 return true;
4256}
4257
4258bool ValidateGetProgramivRobustANGLE(Context *context,
4259 GLuint program,
4260 GLenum pname,
4261 GLsizei bufSize,
4262 GLsizei *numParams)
4263{
4264 if (!ValidateRobustEntryPoint(context, bufSize))
4265 {
4266 return false;
4267 }
4268
Jamie Madillbe849e42017-05-02 15:49:00 -04004269 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004270 {
4271 return false;
4272 }
4273
4274 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4275 {
4276 return false;
4277 }
4278
4279 return true;
4280}
4281
Geoff Lang740d9022016-10-07 11:20:52 -04004282bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4283 GLenum target,
4284 GLenum pname,
4285 GLsizei bufSize,
4286 GLsizei *length,
4287 GLint *params)
4288{
4289 if (!ValidateRobustEntryPoint(context, bufSize))
4290 {
4291 return false;
4292 }
4293
4294 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4295 {
4296 return false;
4297 }
4298
4299 if (!ValidateRobustBufferSize(context, bufSize, *length))
4300 {
4301 return false;
4302 }
4303
4304 return true;
4305}
4306
Geoff Langd7d0ed32016-10-07 11:33:51 -04004307bool ValidateGetShaderivRobustANGLE(Context *context,
4308 GLuint shader,
4309 GLenum pname,
4310 GLsizei bufSize,
4311 GLsizei *length,
4312 GLint *params)
4313{
4314 if (!ValidateRobustEntryPoint(context, bufSize))
4315 {
4316 return false;
4317 }
4318
4319 if (!ValidateGetShaderivBase(context, shader, pname, length))
4320 {
4321 return false;
4322 }
4323
4324 if (!ValidateRobustBufferSize(context, bufSize, *length))
4325 {
4326 return false;
4327 }
4328
4329 return true;
4330}
4331
Geoff Langc1984ed2016-10-07 12:41:00 -04004332bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4333 GLenum target,
4334 GLenum pname,
4335 GLsizei bufSize,
4336 GLsizei *length,
4337 GLfloat *params)
4338{
4339 if (!ValidateRobustEntryPoint(context, bufSize))
4340 {
4341 return false;
4342 }
4343
4344 if (!ValidateGetTexParameterBase(context, target, pname, length))
4345 {
4346 return false;
4347 }
4348
4349 if (!ValidateRobustBufferSize(context, bufSize, *length))
4350 {
4351 return false;
4352 }
4353
4354 return true;
4355}
4356
Geoff Langc1984ed2016-10-07 12:41:00 -04004357bool ValidateGetTexParameterivRobustANGLE(Context *context,
4358 GLenum target,
4359 GLenum pname,
4360 GLsizei bufSize,
4361 GLsizei *length,
4362 GLint *params)
4363{
4364 if (!ValidateRobustEntryPoint(context, bufSize))
4365 {
4366 return false;
4367 }
4368
4369 if (!ValidateGetTexParameterBase(context, target, pname, length))
4370 {
4371 return false;
4372 }
4373
4374 if (!ValidateRobustBufferSize(context, bufSize, *length))
4375 {
4376 return false;
4377 }
4378
4379 return true;
4380}
4381
Geoff Langc1984ed2016-10-07 12:41:00 -04004382bool ValidateTexParameterfvRobustANGLE(Context *context,
4383 GLenum target,
4384 GLenum pname,
4385 GLsizei bufSize,
4386 const GLfloat *params)
4387{
4388 if (!ValidateRobustEntryPoint(context, bufSize))
4389 {
4390 return false;
4391 }
4392
4393 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4394}
4395
Geoff Langc1984ed2016-10-07 12:41:00 -04004396bool ValidateTexParameterivRobustANGLE(Context *context,
4397 GLenum target,
4398 GLenum pname,
4399 GLsizei bufSize,
4400 const GLint *params)
4401{
4402 if (!ValidateRobustEntryPoint(context, bufSize))
4403 {
4404 return false;
4405 }
4406
4407 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4408}
4409
4410bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4411{
4412 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4413}
4414
4415bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4416 GLuint sampler,
4417 GLenum pname,
4418 GLuint bufSize,
4419 GLsizei *length,
4420 GLfloat *params)
4421{
4422 if (!ValidateRobustEntryPoint(context, bufSize))
4423 {
4424 return false;
4425 }
4426
4427 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4428 {
4429 return false;
4430 }
4431
4432 if (!ValidateRobustBufferSize(context, bufSize, *length))
4433 {
4434 return false;
4435 }
4436
4437 return true;
4438}
4439
4440bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4441{
4442 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4443}
4444
4445bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4446 GLuint sampler,
4447 GLenum pname,
4448 GLuint bufSize,
4449 GLsizei *length,
4450 GLint *params)
4451{
4452 if (!ValidateRobustEntryPoint(context, bufSize))
4453 {
4454 return false;
4455 }
4456
4457 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4458 {
4459 return false;
4460 }
4461
4462 if (!ValidateRobustBufferSize(context, bufSize, *length))
4463 {
4464 return false;
4465 }
4466
4467 return true;
4468}
4469
4470bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4471{
4472 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4473}
4474
4475bool ValidateSamplerParameterfv(Context *context,
4476 GLuint sampler,
4477 GLenum pname,
4478 const GLfloat *params)
4479{
4480 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4481}
4482
4483bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4484 GLuint sampler,
4485 GLenum pname,
4486 GLsizei bufSize,
4487 const GLfloat *params)
4488{
4489 if (!ValidateRobustEntryPoint(context, bufSize))
4490 {
4491 return false;
4492 }
4493
4494 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4495}
4496
4497bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4498{
4499 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4500}
4501
4502bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4503{
4504 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4505}
4506
4507bool ValidateSamplerParameterivRobustANGLE(Context *context,
4508 GLuint sampler,
4509 GLenum pname,
4510 GLsizei bufSize,
4511 const GLint *params)
4512{
4513 if (!ValidateRobustEntryPoint(context, bufSize))
4514 {
4515 return false;
4516 }
4517
4518 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4519}
4520
Geoff Lang0b031062016-10-13 14:30:04 -04004521bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4522 GLuint index,
4523 GLenum pname,
4524 GLsizei bufSize,
4525 GLsizei *length,
4526 GLfloat *params)
4527{
4528 if (!ValidateRobustEntryPoint(context, bufSize))
4529 {
4530 return false;
4531 }
4532
4533 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4534 {
4535 return false;
4536 }
4537
4538 if (!ValidateRobustBufferSize(context, bufSize, *length))
4539 {
4540 return false;
4541 }
4542
4543 return true;
4544}
4545
Geoff Lang0b031062016-10-13 14:30:04 -04004546bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4547 GLuint index,
4548 GLenum pname,
4549 GLsizei bufSize,
4550 GLsizei *length,
4551 GLint *params)
4552{
4553 if (!ValidateRobustEntryPoint(context, bufSize))
4554 {
4555 return false;
4556 }
4557
4558 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4559 {
4560 return false;
4561 }
4562
4563 if (!ValidateRobustBufferSize(context, bufSize, *length))
4564 {
4565 return false;
4566 }
4567
4568 return true;
4569}
4570
Geoff Lang0b031062016-10-13 14:30:04 -04004571bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4572 GLuint index,
4573 GLenum pname,
4574 GLsizei bufSize,
4575 GLsizei *length,
4576 void **pointer)
4577{
4578 if (!ValidateRobustEntryPoint(context, bufSize))
4579 {
4580 return false;
4581 }
4582
4583 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4584 {
4585 return false;
4586 }
4587
4588 if (!ValidateRobustBufferSize(context, bufSize, *length))
4589 {
4590 return false;
4591 }
4592
4593 return true;
4594}
4595
4596bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4597{
4598 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4599}
4600
4601bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4602 GLuint index,
4603 GLenum pname,
4604 GLsizei bufSize,
4605 GLsizei *length,
4606 GLint *params)
4607{
4608 if (!ValidateRobustEntryPoint(context, bufSize))
4609 {
4610 return false;
4611 }
4612
4613 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4614 {
4615 return false;
4616 }
4617
4618 if (!ValidateRobustBufferSize(context, bufSize, *length))
4619 {
4620 return false;
4621 }
4622
4623 return true;
4624}
4625
4626bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4627{
4628 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4629}
4630
4631bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4632 GLuint index,
4633 GLenum pname,
4634 GLsizei bufSize,
4635 GLsizei *length,
4636 GLuint *params)
4637{
4638 if (!ValidateRobustEntryPoint(context, bufSize))
4639 {
4640 return false;
4641 }
4642
4643 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4644 {
4645 return false;
4646 }
4647
4648 if (!ValidateRobustBufferSize(context, bufSize, *length))
4649 {
4650 return false;
4651 }
4652
4653 return true;
4654}
4655
Geoff Lang6899b872016-10-14 11:30:13 -04004656bool ValidateGetActiveUniformBlockiv(Context *context,
4657 GLuint program,
4658 GLuint uniformBlockIndex,
4659 GLenum pname,
4660 GLint *params)
4661{
4662 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
4663}
4664
4665bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4666 GLuint program,
4667 GLuint uniformBlockIndex,
4668 GLenum pname,
4669 GLsizei bufSize,
4670 GLsizei *length,
4671 GLint *params)
4672{
4673 if (!ValidateRobustEntryPoint(context, bufSize))
4674 {
4675 return false;
4676 }
4677
4678 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4679 {
4680 return false;
4681 }
4682
4683 if (!ValidateRobustBufferSize(context, bufSize, *length))
4684 {
4685 return false;
4686 }
4687
4688 return true;
4689}
4690
Geoff Lang0a9661f2016-10-20 10:59:20 -07004691bool ValidateGetInternalFormativ(Context *context,
4692 GLenum target,
4693 GLenum internalformat,
4694 GLenum pname,
4695 GLsizei bufSize,
4696 GLint *params)
4697{
4698 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4699 nullptr);
4700}
4701
4702bool ValidateGetInternalFormativRobustANGLE(Context *context,
4703 GLenum target,
4704 GLenum internalformat,
4705 GLenum pname,
4706 GLsizei bufSize,
4707 GLsizei *length,
4708 GLint *params)
4709{
4710 if (!ValidateRobustEntryPoint(context, bufSize))
4711 {
4712 return false;
4713 }
4714
4715 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4716 {
4717 return false;
4718 }
4719
4720 if (!ValidateRobustBufferSize(context, bufSize, *length))
4721 {
4722 return false;
4723 }
4724
4725 return true;
4726}
4727
Shao80957d92017-02-20 21:25:59 +08004728bool ValidateVertexFormatBase(ValidationContext *context,
4729 GLuint attribIndex,
4730 GLint size,
4731 GLenum type,
4732 GLboolean pureInteger)
4733{
4734 const Caps &caps = context->getCaps();
4735 if (attribIndex >= caps.maxVertexAttributes)
4736 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004737 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Shao80957d92017-02-20 21:25:59 +08004738 return false;
4739 }
4740
4741 if (size < 1 || size > 4)
4742 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004743 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004744 return false;
Shao80957d92017-02-20 21:25:59 +08004745 }
4746
4747 switch (type)
4748 {
4749 case GL_BYTE:
4750 case GL_UNSIGNED_BYTE:
4751 case GL_SHORT:
4752 case GL_UNSIGNED_SHORT:
4753 break;
4754
4755 case GL_INT:
4756 case GL_UNSIGNED_INT:
4757 if (context->getClientMajorVersion() < 3)
4758 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004759 context->handleError(InvalidEnum()
4760 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004761 return false;
4762 }
4763 break;
4764
4765 case GL_FIXED:
4766 case GL_FLOAT:
4767 if (pureInteger)
4768 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004769 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004770 return false;
4771 }
4772 break;
4773
4774 case GL_HALF_FLOAT:
4775 if (context->getClientMajorVersion() < 3)
4776 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004777 context->handleError(InvalidEnum()
4778 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004779 return false;
4780 }
4781 if (pureInteger)
4782 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004783 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004784 return false;
4785 }
4786 break;
4787
4788 case GL_INT_2_10_10_10_REV:
4789 case GL_UNSIGNED_INT_2_10_10_10_REV:
4790 if (context->getClientMajorVersion() < 3)
4791 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004792 context->handleError(InvalidEnum()
4793 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004794 return false;
4795 }
4796 if (pureInteger)
4797 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004798 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004799 return false;
4800 }
4801 if (size != 4)
4802 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004803 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4804 "UNSIGNED_INT_2_10_10_10_REV and "
4805 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004806 return false;
4807 }
4808 break;
4809
4810 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004811 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004812 return false;
4813 }
4814
4815 return true;
4816}
4817
Geoff Lang76e65652017-03-27 14:58:02 -04004818// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4819// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4820// specified clear value and the type of a buffer that is being cleared generates an
4821// INVALID_OPERATION error instead of producing undefined results
4822bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4823 GLint drawbuffer,
4824 const GLenum *validComponentTypes,
4825 size_t validComponentTypeCount)
4826{
4827 const FramebufferAttachment *attachment =
4828 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4829 if (attachment)
4830 {
4831 GLenum componentType = attachment->getFormat().info->componentType;
4832 const GLenum *end = validComponentTypes + validComponentTypeCount;
4833 if (std::find(validComponentTypes, end, componentType) == end)
4834 {
4835 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004836 InvalidOperation()
4837 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004838 return false;
4839 }
4840 }
4841
4842 return true;
4843}
4844
Corentin Wallezb2931602017-04-11 15:58:57 -04004845bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4846 GLsizei imageSize,
4847 GLsizei dataSize)
4848{
4849 if (!ValidateRobustEntryPoint(context, dataSize))
4850 {
4851 return false;
4852 }
4853
4854 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
4855 if (pixelUnpackBuffer == nullptr)
4856 {
4857 if (dataSize < imageSize)
4858 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004859 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004860 }
4861 }
4862 return true;
4863}
4864
Jamie Madillbe849e42017-05-02 15:49:00 -04004865bool ValidateGetBufferParameterBase(ValidationContext *context,
4866 GLenum target,
4867 GLenum pname,
4868 bool pointerVersion,
4869 GLsizei *numParams)
4870{
4871 if (numParams)
4872 {
4873 *numParams = 0;
4874 }
4875
4876 if (!ValidBufferTarget(context, target))
4877 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004878 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004879 return false;
4880 }
4881
4882 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4883 if (!buffer)
4884 {
4885 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004886 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004887 return false;
4888 }
4889
4890 const Extensions &extensions = context->getExtensions();
4891
4892 switch (pname)
4893 {
4894 case GL_BUFFER_USAGE:
4895 case GL_BUFFER_SIZE:
4896 break;
4897
4898 case GL_BUFFER_ACCESS_OES:
4899 if (!extensions.mapBuffer)
4900 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004901 context->handleError(InvalidEnum()
4902 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004903 return false;
4904 }
4905 break;
4906
4907 case GL_BUFFER_MAPPED:
4908 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4909 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4910 !extensions.mapBufferRange)
4911 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004912 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4913 "GL_OES_mapbuffer or "
4914 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004915 return false;
4916 }
4917 break;
4918
4919 case GL_BUFFER_MAP_POINTER:
4920 if (!pointerVersion)
4921 {
4922 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004923 InvalidEnum()
4924 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004925 return false;
4926 }
4927 break;
4928
4929 case GL_BUFFER_ACCESS_FLAGS:
4930 case GL_BUFFER_MAP_OFFSET:
4931 case GL_BUFFER_MAP_LENGTH:
4932 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4933 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004934 context->handleError(InvalidEnum()
4935 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004936 return false;
4937 }
4938 break;
4939
4940 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004941 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004942 return false;
4943 }
4944
4945 // All buffer parameter queries return one value.
4946 if (numParams)
4947 {
4948 *numParams = 1;
4949 }
4950
4951 return true;
4952}
4953
4954bool ValidateGetRenderbufferParameterivBase(Context *context,
4955 GLenum target,
4956 GLenum pname,
4957 GLsizei *length)
4958{
4959 if (length)
4960 {
4961 *length = 0;
4962 }
4963
4964 if (target != GL_RENDERBUFFER)
4965 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004966 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004967 return false;
4968 }
4969
4970 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4971 if (renderbuffer == nullptr)
4972 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004973 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004974 return false;
4975 }
4976
4977 switch (pname)
4978 {
4979 case GL_RENDERBUFFER_WIDTH:
4980 case GL_RENDERBUFFER_HEIGHT:
4981 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4982 case GL_RENDERBUFFER_RED_SIZE:
4983 case GL_RENDERBUFFER_GREEN_SIZE:
4984 case GL_RENDERBUFFER_BLUE_SIZE:
4985 case GL_RENDERBUFFER_ALPHA_SIZE:
4986 case GL_RENDERBUFFER_DEPTH_SIZE:
4987 case GL_RENDERBUFFER_STENCIL_SIZE:
4988 break;
4989
4990 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4991 if (!context->getExtensions().framebufferMultisample)
4992 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004993 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004994 return false;
4995 }
4996 break;
4997
4998 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004999 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005000 return false;
5001 }
5002
5003 if (length)
5004 {
5005 *length = 1;
5006 }
5007 return true;
5008}
5009
5010bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5011{
5012 if (length)
5013 {
5014 *length = 0;
5015 }
5016
5017 if (GetValidShader(context, shader) == nullptr)
5018 {
5019 return false;
5020 }
5021
5022 switch (pname)
5023 {
5024 case GL_SHADER_TYPE:
5025 case GL_DELETE_STATUS:
5026 case GL_COMPILE_STATUS:
5027 case GL_INFO_LOG_LENGTH:
5028 case GL_SHADER_SOURCE_LENGTH:
5029 break;
5030
5031 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5032 if (!context->getExtensions().translatedShaderSource)
5033 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005034 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005035 return false;
5036 }
5037 break;
5038
5039 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005040 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005041 return false;
5042 }
5043
5044 if (length)
5045 {
5046 *length = 1;
5047 }
5048 return true;
5049}
5050
5051bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
5052{
5053 if (length)
5054 {
5055 *length = 0;
5056 }
5057
5058 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5059 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005060 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005061 return false;
5062 }
5063
5064 if (context->getTargetTexture(target) == nullptr)
5065 {
5066 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005067 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005068 return false;
5069 }
5070
5071 switch (pname)
5072 {
5073 case GL_TEXTURE_MAG_FILTER:
5074 case GL_TEXTURE_MIN_FILTER:
5075 case GL_TEXTURE_WRAP_S:
5076 case GL_TEXTURE_WRAP_T:
5077 break;
5078
5079 case GL_TEXTURE_USAGE_ANGLE:
5080 if (!context->getExtensions().textureUsage)
5081 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005082 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005083 return false;
5084 }
5085 break;
5086
5087 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5088 if (!context->getExtensions().textureFilterAnisotropic)
5089 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005090 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005091 return false;
5092 }
5093 break;
5094
5095 case GL_TEXTURE_IMMUTABLE_FORMAT:
5096 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5097 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005098 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005099 return false;
5100 }
5101 break;
5102
5103 case GL_TEXTURE_WRAP_R:
5104 case GL_TEXTURE_IMMUTABLE_LEVELS:
5105 case GL_TEXTURE_SWIZZLE_R:
5106 case GL_TEXTURE_SWIZZLE_G:
5107 case GL_TEXTURE_SWIZZLE_B:
5108 case GL_TEXTURE_SWIZZLE_A:
5109 case GL_TEXTURE_BASE_LEVEL:
5110 case GL_TEXTURE_MAX_LEVEL:
5111 case GL_TEXTURE_MIN_LOD:
5112 case GL_TEXTURE_MAX_LOD:
5113 case GL_TEXTURE_COMPARE_MODE:
5114 case GL_TEXTURE_COMPARE_FUNC:
5115 if (context->getClientMajorVersion() < 3)
5116 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005117 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005118 return false;
5119 }
5120 break;
5121
5122 case GL_TEXTURE_SRGB_DECODE_EXT:
5123 if (!context->getExtensions().textureSRGBDecode)
5124 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005125 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005126 return false;
5127 }
5128 break;
5129
5130 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005131 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005132 return false;
5133 }
5134
5135 if (length)
5136 {
5137 *length = 1;
5138 }
5139 return true;
5140}
5141
5142bool ValidateGetVertexAttribBase(Context *context,
5143 GLuint index,
5144 GLenum pname,
5145 GLsizei *length,
5146 bool pointer,
5147 bool pureIntegerEntryPoint)
5148{
5149 if (length)
5150 {
5151 *length = 0;
5152 }
5153
5154 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5155 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005156 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005157 return false;
5158 }
5159
5160 if (index >= context->getCaps().maxVertexAttributes)
5161 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005162 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madillbe849e42017-05-02 15:49:00 -04005163 return false;
5164 }
5165
5166 if (pointer)
5167 {
5168 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5169 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005170 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005171 return false;
5172 }
5173 }
5174 else
5175 {
5176 switch (pname)
5177 {
5178 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5179 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5180 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5181 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5182 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5183 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5184 case GL_CURRENT_VERTEX_ATTRIB:
5185 break;
5186
5187 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5188 static_assert(
5189 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5190 "ANGLE extension enums not equal to GL enums.");
5191 if (context->getClientMajorVersion() < 3 &&
5192 !context->getExtensions().instancedArrays)
5193 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005194 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5195 "requires OpenGL ES 3.0 or "
5196 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005197 return false;
5198 }
5199 break;
5200
5201 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5202 if (context->getClientMajorVersion() < 3)
5203 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005204 context->handleError(
5205 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005206 return false;
5207 }
5208 break;
5209
5210 case GL_VERTEX_ATTRIB_BINDING:
5211 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5212 if (context->getClientVersion() < ES_3_1)
5213 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005214 context->handleError(InvalidEnum()
5215 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005216 return false;
5217 }
5218 break;
5219
5220 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005221 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005222 return false;
5223 }
5224 }
5225
5226 if (length)
5227 {
5228 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5229 {
5230 *length = 4;
5231 }
5232 else
5233 {
5234 *length = 1;
5235 }
5236 }
5237
5238 return true;
5239}
5240
Jamie Madill4928b7c2017-06-20 12:57:39 -04005241bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005242 GLint x,
5243 GLint y,
5244 GLsizei width,
5245 GLsizei height,
5246 GLenum format,
5247 GLenum type,
5248 GLsizei bufSize,
5249 GLsizei *length,
5250 GLsizei *columns,
5251 GLsizei *rows,
5252 void *pixels)
5253{
5254 if (length != nullptr)
5255 {
5256 *length = 0;
5257 }
5258 if (rows != nullptr)
5259 {
5260 *rows = 0;
5261 }
5262 if (columns != nullptr)
5263 {
5264 *columns = 0;
5265 }
5266
5267 if (width < 0 || height < 0)
5268 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005269 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005270 return false;
5271 }
5272
5273 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5274
5275 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5276 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005277 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005278 return false;
5279 }
5280
5281 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5282 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005283 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005284 return false;
5285 }
5286
5287 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5288 ASSERT(framebuffer);
5289
5290 if (framebuffer->getReadBufferState() == GL_NONE)
5291 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005292 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Jamie Madillbe849e42017-05-02 15:49:00 -04005293 return false;
5294 }
5295
5296 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5297 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5298 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5299 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5300 // situation is an application error that would lead to a crash in ANGLE.
5301 if (readBuffer == nullptr)
5302 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005303 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005304 return false;
5305 }
5306
Jamie Madill4928b7c2017-06-20 12:57:39 -04005307 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5308 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005309 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5310
5311 bool validFormatTypeCombination =
5312 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5313
5314 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5315 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005316 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005317 return false;
5318 }
5319
5320 // Check for pixel pack buffer related API errors
5321 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5322 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5323 {
5324 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005325 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005326 return false;
5327 }
5328
5329 // .. the data would be packed to the buffer object such that the memory writes required
5330 // would exceed the data store size.
5331 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5332 const gl::Extents size(width, height, 1);
5333 const auto &pack = context->getGLState().getPackState();
5334
5335 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5336 if (endByteOrErr.isError())
5337 {
5338 context->handleError(endByteOrErr.getError());
5339 return false;
5340 }
5341
5342 size_t endByte = endByteOrErr.getResult();
5343 if (bufSize >= 0)
5344 {
5345 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5346 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005347 context->handleError(InvalidOperation()
5348 << "bufSize must be at least " << endByte << " bytes.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005349 return false;
5350 }
5351 }
5352
5353 if (pixelPackBuffer != nullptr)
5354 {
5355 CheckedNumeric<size_t> checkedEndByte(endByte);
5356 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5357 checkedEndByte += checkedOffset;
5358
5359 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5360 {
5361 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005362 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005363 return false;
5364 }
5365 }
5366
5367 if (pixelPackBuffer == nullptr && length != nullptr)
5368 {
5369 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5370 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005371 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005372 return false;
5373 }
5374
5375 *length = static_cast<GLsizei>(endByte);
5376 }
5377
5378 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5379 angle::CheckedNumeric<int> clippedExtent(length);
5380 if (start < 0)
5381 {
5382 // "subtract" the area that is less than 0
5383 clippedExtent += start;
5384 }
5385
5386 const int readExtent = start + length;
5387 if (readExtent > bufferSize)
5388 {
5389 // Subtract the region to the right of the read buffer
5390 clippedExtent -= (readExtent - bufferSize);
5391 }
5392
5393 if (!clippedExtent.IsValid())
5394 {
5395 return 0;
5396 }
5397
5398 return std::max(clippedExtent.ValueOrDie(), 0);
5399 };
5400
5401 if (columns != nullptr)
5402 {
5403 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5404 }
5405
5406 if (rows != nullptr)
5407 {
5408 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5409 }
5410
5411 return true;
5412}
5413
5414template <typename ParamType>
5415bool ValidateTexParameterBase(Context *context,
5416 GLenum target,
5417 GLenum pname,
5418 GLsizei bufSize,
5419 const ParamType *params)
5420{
5421 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5422 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005423 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005424 return false;
5425 }
5426
5427 if (context->getTargetTexture(target) == nullptr)
5428 {
5429 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005430 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005431 return false;
5432 }
5433
5434 const GLsizei minBufSize = 1;
5435 if (bufSize >= 0 && bufSize < minBufSize)
5436 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005437 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005438 return false;
5439 }
5440
5441 switch (pname)
5442 {
5443 case GL_TEXTURE_WRAP_R:
5444 case GL_TEXTURE_SWIZZLE_R:
5445 case GL_TEXTURE_SWIZZLE_G:
5446 case GL_TEXTURE_SWIZZLE_B:
5447 case GL_TEXTURE_SWIZZLE_A:
5448 case GL_TEXTURE_BASE_LEVEL:
5449 case GL_TEXTURE_MAX_LEVEL:
5450 case GL_TEXTURE_COMPARE_MODE:
5451 case GL_TEXTURE_COMPARE_FUNC:
5452 case GL_TEXTURE_MIN_LOD:
5453 case GL_TEXTURE_MAX_LOD:
5454 if (context->getClientMajorVersion() < 3)
5455 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005456 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005457 return false;
5458 }
5459 if (target == GL_TEXTURE_EXTERNAL_OES &&
5460 !context->getExtensions().eglImageExternalEssl3)
5461 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005462 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5463 "available without "
5464 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005465 return false;
5466 }
5467 break;
5468
5469 default:
5470 break;
5471 }
5472
5473 switch (pname)
5474 {
5475 case GL_TEXTURE_WRAP_S:
5476 case GL_TEXTURE_WRAP_T:
5477 case GL_TEXTURE_WRAP_R:
5478 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
5479 {
5480 return false;
5481 }
5482 break;
5483
5484 case GL_TEXTURE_MIN_FILTER:
5485 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
5486 {
5487 return false;
5488 }
5489 break;
5490
5491 case GL_TEXTURE_MAG_FILTER:
5492 if (!ValidateTextureMagFilterValue(context, params))
5493 {
5494 return false;
5495 }
5496 break;
5497
5498 case GL_TEXTURE_USAGE_ANGLE:
5499 switch (ConvertToGLenum(params[0]))
5500 {
5501 case GL_NONE:
5502 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5503 break;
5504
5505 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005506 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005507 return false;
5508 }
5509 break;
5510
5511 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5512 if (!context->getExtensions().textureFilterAnisotropic)
5513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005514 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005515 return false;
5516 }
5517
5518 // we assume the parameter passed to this validation method is truncated, not rounded
5519 if (params[0] < 1)
5520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005521 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005522 return false;
5523 }
5524 break;
5525
5526 case GL_TEXTURE_MIN_LOD:
5527 case GL_TEXTURE_MAX_LOD:
5528 // any value is permissible
5529 break;
5530
5531 case GL_TEXTURE_COMPARE_MODE:
5532 if (!ValidateTextureCompareModeValue(context, params))
5533 {
5534 return false;
5535 }
5536 break;
5537
5538 case GL_TEXTURE_COMPARE_FUNC:
5539 if (!ValidateTextureCompareFuncValue(context, params))
5540 {
5541 return false;
5542 }
5543 break;
5544
5545 case GL_TEXTURE_SWIZZLE_R:
5546 case GL_TEXTURE_SWIZZLE_G:
5547 case GL_TEXTURE_SWIZZLE_B:
5548 case GL_TEXTURE_SWIZZLE_A:
5549 switch (ConvertToGLenum(params[0]))
5550 {
5551 case GL_RED:
5552 case GL_GREEN:
5553 case GL_BLUE:
5554 case GL_ALPHA:
5555 case GL_ZERO:
5556 case GL_ONE:
5557 break;
5558
5559 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005560 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005561 return false;
5562 }
5563 break;
5564
5565 case GL_TEXTURE_BASE_LEVEL:
5566 if (params[0] < 0)
5567 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005568 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005569 return false;
5570 }
5571 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5572 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005573 context->handleError(InvalidOperation()
5574 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005575 return false;
5576 }
5577 break;
5578
5579 case GL_TEXTURE_MAX_LEVEL:
5580 if (params[0] < 0)
5581 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005582 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005583 return false;
5584 }
5585 break;
5586
5587 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5588 if (context->getClientVersion() < Version(3, 1))
5589 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005590 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005591 return false;
5592 }
5593 switch (ConvertToGLenum(params[0]))
5594 {
5595 case GL_DEPTH_COMPONENT:
5596 case GL_STENCIL_INDEX:
5597 break;
5598
5599 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005600 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005601 return false;
5602 }
5603 break;
5604
5605 case GL_TEXTURE_SRGB_DECODE_EXT:
5606 if (!ValidateTextureSRGBDecodeValue(context, params))
5607 {
5608 return false;
5609 }
5610 break;
5611
5612 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005613 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005614 return false;
5615 }
5616
5617 return true;
5618}
5619
5620template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5621template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5622
Jamie Madillc29968b2016-01-20 11:17:23 -05005623} // namespace gl