blob: 36746cf533b63ec25ee75af02df9ff4334e3a211 [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"
Geoff Lang2b5420c2014-11-19 14:20:15 -050013#include "libANGLE/Framebuffer.h"
14#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040015#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050016#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040017#include "libANGLE/Query.h"
18#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050019#include "libANGLE/TransformFeedback.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040020#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050021#include "libANGLE/VertexArray.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040022#include "libANGLE/formatutils.h"
23#include "libANGLE/validationES2.h"
24#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025
26#include "common/mathutil.h"
27#include "common/utilities.h"
28
Jamie Madille2e406c2016-06-02 13:04:10 -040029using namespace angle;
30
Geoff Lange8ebe7f2013-08-05 15:03:13 -040031namespace gl
32{
Jamie Madille79b1e12015-11-04 16:36:37 -050033const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum element index.";
34
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
Corentin Wallez92db6942016-12-09 13:10:36 -050037bool ValidateDrawAttribs(ValidationContext *context,
38 GLint primcount,
39 GLint maxVertex,
40 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040041{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070042 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040043 const gl::Program *program = state.getProgram();
44
Corentin Wallez327411e2016-12-09 11:09:17 -050045 bool webglCompatibility = context->getExtensions().webglCompatibility;
46
Jamie Madill231c7f52017-04-26 13:45:37 -040047 const VertexArray *vao = state.getVertexArray();
48 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080049 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madill231c7f52017-04-26 13:45:37 -040050 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040051 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
52 {
53 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallezfd456442016-12-21 17:57:00 -050054 if (!program->isAttribLocationActive(attributeIndex) || !attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040055 {
Corentin Wallezfd456442016-12-21 17:57:00 -050056 continue;
57 }
Jamie Madill1ca74672015-07-21 15:14:11 -040058
Jiawei-Shao2597fb62016-12-09 16:38:02 +080059 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
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.
Jiawei-Shao2597fb62016-12-09 16:38:02 +080062 gl::Buffer *buffer = binding.buffer.get();
Corentin Wallezfd456442016-12-21 17:57:00 -050063 if (!buffer)
64 {
Geoff Langfeb8c682017-02-13 16:07:35 -050065 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050066 {
67 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050068 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
69 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
70 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
71 // error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050072 context->handleError(InvalidOperation()
73 << "An enabled vertex array has no buffer.");
Corentin Wallezfd456442016-12-21 17:57:00 -050074 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050075 }
Corentin Wallezfd456442016-12-21 17:57:00 -050076 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040077 {
78 // This is an application error that would normally result in a crash,
79 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050080 context->handleError(InvalidOperation()
81 << "An enabled vertex array has no buffer and no pointer.");
Jamie Madill1ca74672015-07-21 15:14:11 -040082 return false;
83 }
Corentin Wallezfd456442016-12-21 17:57:00 -050084 continue;
85 }
86
87 // If we're drawing zero vertices, we have enough data.
88 if (vertexCount <= 0 || primcount <= 0)
89 {
90 continue;
91 }
92
93 GLint maxVertexElement = 0;
Jiawei-Shao2597fb62016-12-09 16:38:02 +080094 if (binding.divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -050095 {
96 maxVertexElement = maxVertex;
97 }
98 else
99 {
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800100 maxVertexElement = (primcount - 1) / binding.divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500101 }
102
103 // We do manual overflow checks here instead of using safe_math.h because it was
104 // a bottleneck. Thanks to some properties of GL we know inequalities that can
105 // help us make the overflow checks faster.
106
107 // The max possible attribSize is 16 for a vector of 4 32 bit values.
108 constexpr uint64_t kMaxAttribSize = 16;
109 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
110 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
111
112 // We know attribStride is given as a GLsizei which is typedefed to int.
113 // We also know an upper bound for attribSize.
114 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800115 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500116 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
117 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
118
119 // Computing the max offset using uint64_t without attrib.offset is overflow
120 // safe. Note: Last vertex element does not take the full stride!
121 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
122 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
123
124 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800125 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
126 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500127 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500128 context->handleError(InvalidOperation() << "Integer overflow.");
Corentin Wallezfd456442016-12-21 17:57:00 -0500129 return false;
130 }
131 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
132
133 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
134 // We can return INVALID_OPERATION if our vertex attribute does not have
135 // enough backing data.
136 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
137 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500138 context->handleError(InvalidOperation()
139 << "Vertex buffer is not big enough for the draw call");
Corentin Wallezfd456442016-12-21 17:57:00 -0500140 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400141 }
142 }
143
144 return true;
145}
146
Geoff Langf607c602016-09-21 11:46:48 -0400147bool ValidReadPixelsFormatType(ValidationContext *context,
148 GLenum framebufferComponentType,
149 GLenum format,
150 GLenum type)
151{
152 switch (framebufferComponentType)
153 {
154 case GL_UNSIGNED_NORMALIZED:
155 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
156 // ReadPixels with BGRA even if the extension is not present
157 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
158 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
159 type == GL_UNSIGNED_BYTE);
160
161 case GL_SIGNED_NORMALIZED:
162 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
163
164 case GL_INT:
165 return (format == GL_RGBA_INTEGER && type == GL_INT);
166
167 case GL_UNSIGNED_INT:
168 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
169
170 case GL_FLOAT:
171 return (format == GL_RGBA && type == GL_FLOAT);
172
173 default:
174 UNREACHABLE();
175 return false;
176 }
177}
178
Geoff Langc1984ed2016-10-07 12:41:00 -0400179template <typename ParamType>
180bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
181{
182 switch (ConvertToGLenum(params[0]))
183 {
184 case GL_CLAMP_TO_EDGE:
185 break;
186
187 case GL_REPEAT:
188 case GL_MIRRORED_REPEAT:
189 if (isExternalTextureTarget)
190 {
191 // OES_EGL_image_external specifies this error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500192 context->handleError(InvalidEnum()
193 << "external textures only support CLAMP_TO_EDGE wrap mode");
Geoff Langc1984ed2016-10-07 12:41:00 -0400194 return false;
195 }
196 break;
197
198 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500199 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400200 return false;
201 }
202
203 return true;
204}
205
206template <typename ParamType>
207bool ValidateTextureMinFilterValue(Context *context,
208 ParamType *params,
209 bool isExternalTextureTarget)
210{
211 switch (ConvertToGLenum(params[0]))
212 {
213 case GL_NEAREST:
214 case GL_LINEAR:
215 break;
216
217 case GL_NEAREST_MIPMAP_NEAREST:
218 case GL_LINEAR_MIPMAP_NEAREST:
219 case GL_NEAREST_MIPMAP_LINEAR:
220 case GL_LINEAR_MIPMAP_LINEAR:
221 if (isExternalTextureTarget)
222 {
223 // OES_EGL_image_external specifies this error.
224 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500225 InvalidEnum() << "external textures only support NEAREST and LINEAR filtering");
Geoff Langc1984ed2016-10-07 12:41:00 -0400226 return false;
227 }
228 break;
229
230 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500231 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400232 return false;
233 }
234
235 return true;
236}
237
238template <typename ParamType>
239bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
240{
241 switch (ConvertToGLenum(params[0]))
242 {
243 case GL_NEAREST:
244 case GL_LINEAR:
245 break;
246
247 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500248 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400249 return false;
250 }
251
252 return true;
253}
254
255template <typename ParamType>
256bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
257{
258 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
259 switch (ConvertToGLenum(params[0]))
260 {
261 case GL_NONE:
262 case GL_COMPARE_REF_TO_TEXTURE:
263 break;
264
265 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500266 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400267 return false;
268 }
269
270 return true;
271}
272
273template <typename ParamType>
274bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
275{
276 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
277 switch (ConvertToGLenum(params[0]))
278 {
279 case GL_LEQUAL:
280 case GL_GEQUAL:
281 case GL_LESS:
282 case GL_GREATER:
283 case GL_EQUAL:
284 case GL_NOTEQUAL:
285 case GL_ALWAYS:
286 case GL_NEVER:
287 break;
288
289 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500290 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400291 return false;
292 }
293
294 return true;
295}
296
297template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700298bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
299{
300 if (!context->getExtensions().textureSRGBDecode)
301 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500302 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Geoff Lang81c6b572016-10-19 14:07:52 -0700303 return false;
304 }
305
306 switch (ConvertToGLenum(params[0]))
307 {
308 case GL_DECODE_EXT:
309 case GL_SKIP_DECODE_EXT:
310 break;
311
312 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500313 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Lang81c6b572016-10-19 14:07:52 -0700314 return false;
315 }
316
317 return true;
318}
319
320template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400321bool ValidateSamplerParameterBase(Context *context,
322 GLuint sampler,
323 GLenum pname,
324 GLsizei bufSize,
325 ParamType *params)
326{
327 if (context->getClientMajorVersion() < 3)
328 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500329 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400330 return false;
331 }
332
333 if (!context->isSampler(sampler))
334 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500335 context->handleError(InvalidOperation() << "Sampler is not valid.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400336 return false;
337 }
338
339 const GLsizei minBufSize = 1;
340 if (bufSize >= 0 && bufSize < minBufSize)
341 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500342 context->handleError(InvalidOperation() << "bufSize must be at least " << minBufSize);
Geoff Langc1984ed2016-10-07 12:41:00 -0400343 return false;
344 }
345
346 switch (pname)
347 {
348 case GL_TEXTURE_WRAP_S:
349 case GL_TEXTURE_WRAP_T:
350 case GL_TEXTURE_WRAP_R:
351 if (!ValidateTextureWrapModeValue(context, params, false))
352 {
353 return false;
354 }
355 break;
356
357 case GL_TEXTURE_MIN_FILTER:
358 if (!ValidateTextureMinFilterValue(context, params, false))
359 {
360 return false;
361 }
362 break;
363
364 case GL_TEXTURE_MAG_FILTER:
365 if (!ValidateTextureMagFilterValue(context, params))
366 {
367 return false;
368 }
369 break;
370
371 case GL_TEXTURE_MIN_LOD:
372 case GL_TEXTURE_MAX_LOD:
373 // any value is permissible
374 break;
375
376 case GL_TEXTURE_COMPARE_MODE:
377 if (!ValidateTextureCompareModeValue(context, params))
378 {
379 return false;
380 }
381 break;
382
383 case GL_TEXTURE_COMPARE_FUNC:
384 if (!ValidateTextureCompareFuncValue(context, params))
385 {
386 return false;
387 }
388 break;
389
Geoff Lang81c6b572016-10-19 14:07:52 -0700390 case GL_TEXTURE_SRGB_DECODE_EXT:
391 if (!ValidateTextureSRGBDecodeValue(context, params))
392 {
393 return false;
394 }
395 break;
396
Geoff Langc1984ed2016-10-07 12:41:00 -0400397 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500398 context->handleError(InvalidEnum() << "Unknown pname.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400399 return false;
400 }
401
402 return true;
403}
404
405bool ValidateGetSamplerParameterBase(Context *context,
406 GLuint sampler,
407 GLenum pname,
408 GLsizei *length)
409{
410 if (length)
411 {
412 *length = 0;
413 }
414
415 if (context->getClientMajorVersion() < 3)
416 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500417 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400418 return false;
419 }
420
421 if (!context->isSampler(sampler))
422 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500423 context->handleError(InvalidOperation() << "Sampler is not valid.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400424 return false;
425 }
426
427 switch (pname)
428 {
429 case GL_TEXTURE_WRAP_S:
430 case GL_TEXTURE_WRAP_T:
431 case GL_TEXTURE_WRAP_R:
432 case GL_TEXTURE_MIN_FILTER:
433 case GL_TEXTURE_MAG_FILTER:
434 case GL_TEXTURE_MIN_LOD:
435 case GL_TEXTURE_MAX_LOD:
436 case GL_TEXTURE_COMPARE_MODE:
437 case GL_TEXTURE_COMPARE_FUNC:
438 break;
439
Geoff Lang81c6b572016-10-19 14:07:52 -0700440 case GL_TEXTURE_SRGB_DECODE_EXT:
441 if (!context->getExtensions().textureSRGBDecode)
442 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500443 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Geoff Lang81c6b572016-10-19 14:07:52 -0700444 return false;
445 }
446 break;
447
Geoff Langc1984ed2016-10-07 12:41:00 -0400448 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500449 context->handleError(InvalidEnum() << "Unknown pname.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400450 return false;
451 }
452
453 if (length)
454 {
455 *length = 1;
456 }
457 return true;
458}
459
Geoff Lang6899b872016-10-14 11:30:13 -0400460bool ValidateGetActiveUniformBlockivBase(Context *context,
461 GLuint program,
462 GLuint uniformBlockIndex,
463 GLenum pname,
464 GLsizei *length)
465{
466 if (length)
467 {
468 *length = 0;
469 }
470
471 if (context->getClientMajorVersion() < 3)
472 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500473 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Lang6899b872016-10-14 11:30:13 -0400474 return false;
475 }
476
477 Program *programObject = GetValidProgram(context, program);
478 if (!programObject)
479 {
480 return false;
481 }
482
483 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
484 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500485 context->handleError(InvalidValue()
486 << "uniformBlockIndex exceeds active uniform block count.");
Geoff Lang6899b872016-10-14 11:30:13 -0400487 return false;
488 }
489
490 switch (pname)
491 {
492 case GL_UNIFORM_BLOCK_BINDING:
493 case GL_UNIFORM_BLOCK_DATA_SIZE:
494 case GL_UNIFORM_BLOCK_NAME_LENGTH:
495 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
496 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
497 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
498 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
499 break;
500
501 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500502 context->handleError(InvalidEnum() << "Unknown pname.");
Geoff Lang6899b872016-10-14 11:30:13 -0400503 return false;
504 }
505
506 if (length)
507 {
508 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
509 {
510 const UniformBlock &uniformBlock =
511 programObject->getUniformBlockByIndex(uniformBlockIndex);
512 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
513 }
514 else
515 {
516 *length = 1;
517 }
518 }
519
520 return true;
521}
522
Geoff Lang0a9661f2016-10-20 10:59:20 -0700523bool ValidateGetInternalFormativBase(Context *context,
524 GLenum target,
525 GLenum internalformat,
526 GLenum pname,
527 GLsizei bufSize,
528 GLsizei *numParams)
529{
530 if (numParams)
531 {
532 *numParams = 0;
533 }
534
535 if (context->getClientMajorVersion() < 3)
536 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500537 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700538 return false;
539 }
540
541 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
542 if (!formatCaps.renderable)
543 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500544 context->handleError(InvalidEnum() << "Internal format is not renderable.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700545 return false;
546 }
547
548 switch (target)
549 {
550 case GL_RENDERBUFFER:
551 break;
552
JiangYizhoubddc46b2016-12-09 09:50:51 +0800553 case GL_TEXTURE_2D_MULTISAMPLE:
554 if (context->getClientVersion() < ES_3_1)
555 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500556 context->handleError(InvalidOperation()
557 << "Texture target requires at least OpenGL ES 3.1.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800558 return false;
559 }
560 break;
561
Geoff Lang0a9661f2016-10-20 10:59:20 -0700562 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500563 context->handleError(InvalidEnum() << "Invalid target.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700564 return false;
565 }
566
567 if (bufSize < 0)
568 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500569 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700570 return false;
571 }
572
573 GLsizei maxWriteParams = 0;
574 switch (pname)
575 {
576 case GL_NUM_SAMPLE_COUNTS:
577 maxWriteParams = 1;
578 break;
579
580 case GL_SAMPLES:
581 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
582 break;
583
584 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500585 context->handleError(InvalidEnum() << "Unknown pname.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700586 return false;
587 }
588
589 if (numParams)
590 {
591 // glGetInternalFormativ will not overflow bufSize
592 *numParams = std::min(bufSize, maxWriteParams);
593 }
594
595 return true;
596}
597
Jamie Madillc1d770e2017-04-13 17:31:24 -0400598bool ValidateUniformCommonBase(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500599 gl::Program *program,
600 GLint location,
601 GLsizei count,
602 const LinkedUniform **uniformOut)
603{
604 // TODO(Jiajia): Add image uniform check in future.
605 if (count < 0)
606 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500607 context->handleError(InvalidValue());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500608 return false;
609 }
610
611 if (!program || !program->isLinked())
612 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500613 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500614 return false;
615 }
616
617 if (location == -1)
618 {
619 // Silently ignore the uniform command
620 return false;
621 }
622
623 const auto &uniformLocations = program->getUniformLocations();
Jamie Madillbe849e42017-05-02 15:49:00 -0400624 size_t castedLocation = static_cast<size_t>(location);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500625 if (castedLocation >= uniformLocations.size())
626 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500627 context->handleError(InvalidOperation() << "Invalid uniform location");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500628 return false;
629 }
630
631 const auto &uniformLocation = uniformLocations[castedLocation];
632 if (uniformLocation.ignored)
633 {
634 // Silently ignore the uniform command
635 return false;
636 }
637
638 if (!uniformLocation.used)
639 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500640 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500641 return false;
642 }
643
644 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
645
646 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
647 if (!uniform.isArray() && count > 1)
648 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500649 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500650 return false;
651 }
652
653 *uniformOut = &uniform;
654 return true;
655}
656
Frank Henigman999b0fd2017-02-02 21:45:55 -0500657bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -0500658 GLenum uniformType,
659 GLsizei count,
660 const GLint *value)
661{
662 // Value type is GL_INT, because we only get here from glUniform1i{v}.
663 // It is compatible with INT or BOOL.
664 // Do these cheap tests first, for a little extra speed.
665 if (GL_INT == uniformType || GL_BOOL == uniformType)
666 {
667 return true;
668 }
669
670 if (IsSamplerType(uniformType))
671 {
Frank Henigman999b0fd2017-02-02 21:45:55 -0500672 // Check that the values are in range.
673 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
674 for (GLsizei i = 0; i < count; ++i)
675 {
676 if (value[i] < 0 || value[i] >= max)
677 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500678 context->handleError(InvalidValue() << "sampler uniform value out of range");
Frank Henigman999b0fd2017-02-02 21:45:55 -0500679 return false;
680 }
681 }
Frank Henigmana98a6472017-02-02 21:38:32 -0500682 return true;
683 }
684
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500685 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmana98a6472017-02-02 21:38:32 -0500686 return false;
687}
688
Jamie Madillc1d770e2017-04-13 17:31:24 -0400689bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500690{
691 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -0500692 // Do the cheaper test first, for a little extra speed.
693 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500694 {
695 return true;
696 }
697
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500698 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500699 return false;
700}
701
Jamie Madillc1d770e2017-04-13 17:31:24 -0400702bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500703{
704 // Check that the value type is compatible with uniform type.
705 if (valueType == uniformType)
706 {
707 return true;
708 }
709
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500710 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500711 return false;
712}
713
Geoff Lange0cff192017-05-30 13:04:56 -0400714bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
715{
716 const Program *program = context->getGLState().getProgram();
717 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
718
719 const auto &programOutputTypes = program->getOutputVariableTypes();
720 for (size_t drawBufferIdx = 0; drawBufferIdx < programOutputTypes.size(); drawBufferIdx++)
721 {
722 GLenum outputType = programOutputTypes[drawBufferIdx];
723 GLenum inputType = framebuffer->getDrawbufferWriteType(drawBufferIdx);
724 if (outputType != GL_NONE && inputType != GL_NONE && inputType != outputType)
725 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500726 context->handleError(InvalidOperation() << "Fragment shader output type does not "
727 "match the bound framebuffer attachment "
728 "type.");
Geoff Lange0cff192017-05-30 13:04:56 -0400729 return false;
730 }
731 }
732
733 return true;
734}
735
Geoff Lang9ab5b822017-05-30 16:19:23 -0400736bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
737{
738 const Program *program = context->getGLState().getProgram();
739 const VertexArray *vao = context->getGLState().getVertexArray();
740
741 for (const auto &shaderAttribute : program->getAttributes())
742 {
743 GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
744
745 const auto &attrib = vao->getVertexAttribute(shaderAttribute.location);
746 const auto &currentValue =
747 context->getGLState().getVertexAttribCurrentValue(shaderAttribute.location);
748 GLenum vertexType = attrib.enabled ? GetVertexAttributeBaseType(attrib) : currentValue.Type;
749
750 if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
751 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500752 context->handleError(InvalidOperation() << "Vertex shader input type does not "
753 "match the type of the bound vertex "
754 "attribute.");
Geoff Lang9ab5b822017-05-30 16:19:23 -0400755 return false;
756 }
757 }
758
759 return true;
760}
761
Geoff Langf41a7152016-09-19 15:11:17 -0400762} // anonymous namespace
763
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500764bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400765{
Jamie Madilld7460c72014-01-21 16:38:14 -0500766 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400767 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800768 case GL_TEXTURE_2D:
769 case GL_TEXTURE_CUBE_MAP:
770 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400771
He Yunchaoced53ae2016-11-29 15:00:51 +0800772 case GL_TEXTURE_3D:
773 case GL_TEXTURE_2D_ARRAY:
774 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500775
He Yunchaoced53ae2016-11-29 15:00:51 +0800776 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800777 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400778
He Yunchaoced53ae2016-11-29 15:00:51 +0800779 default:
780 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500781 }
Jamie Madill35d15012013-10-07 10:46:37 -0400782}
783
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500784bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
785{
786 switch (target)
787 {
788 case GL_TEXTURE_2D:
789 case GL_TEXTURE_CUBE_MAP:
790 return true;
791
792 default:
793 return false;
794 }
795}
796
797bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
798{
799 switch (target)
800 {
801 case GL_TEXTURE_3D:
802 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300803 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500804
805 default:
806 return false;
807 }
808}
809
Ian Ewellbda75592016-04-18 17:25:54 -0400810// Most texture GL calls are not compatible with external textures, so we have a separate validation
811// function for use in the GL calls that do
812bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
813{
814 return (target == GL_TEXTURE_EXTERNAL_OES) &&
815 (context->getExtensions().eglImageExternal ||
816 context->getExtensions().eglStreamConsumerExternal);
817}
818
Shannon Woods4dfed832014-03-17 20:03:39 -0400819// This function differs from ValidTextureTarget in that the target must be
820// usable as the destination of a 2D operation-- so a cube face is valid, but
821// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400822// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500823bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400824{
825 switch (target)
826 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800827 case GL_TEXTURE_2D:
828 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
829 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
830 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
831 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
832 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
833 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
834 return true;
835 default:
836 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500837 }
838}
839
Jamie Madillbe849e42017-05-02 15:49:00 -0400840bool ValidateDrawElementsInstancedBase(ValidationContext *context,
841 GLenum mode,
842 GLsizei count,
843 GLenum type,
844 const GLvoid *indices,
845 GLsizei primcount)
846{
847 if (primcount < 0)
848 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500849 context->handleError(InvalidValue() << "primcount cannot be negative.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400850 return false;
851 }
852
853 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
854 {
855 return false;
856 }
857
858 // No-op zero primitive count
859 return (primcount > 0);
860}
861
862bool ValidateDrawArraysInstancedBase(Context *context,
863 GLenum mode,
864 GLint first,
865 GLsizei count,
866 GLsizei primcount)
867{
868 if (primcount < 0)
869 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500870 context->handleError(InvalidValue() << "primcount cannot be negative.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400871 return false;
872 }
873
874 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
875 {
876 return false;
877 }
878
879 // No-op if zero primitive count
880 return (primcount > 0);
881}
882
883bool ValidateDrawInstancedANGLEAndWebGL(ValidationContext *context)
884{
885 // Verify there is at least one active attribute with a divisor of zero
886 const State &state = context->getGLState();
887
888 Program *program = state.getProgram();
889
890 const auto &attribs = state.getVertexArray()->getVertexAttributes();
891 const auto &bindings = state.getVertexArray()->getVertexBindings();
892 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
893 {
894 const VertexAttribute &attrib = attribs[attributeIndex];
895 const VertexBinding &binding = bindings[attrib.bindingIndex];
896 if (program->isAttribLocationActive(attributeIndex) && binding.divisor == 0)
897 {
898 return true;
899 }
900 }
901
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500902 context->handleError(InvalidOperation()
903 << "At least one attribute must have a divisor of zero.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400904 return false;
905}
906
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500907bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
908{
909 switch (target)
910 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800911 case GL_TEXTURE_3D:
912 case GL_TEXTURE_2D_ARRAY:
913 return true;
914 default:
915 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400916 }
917}
918
He Yunchao11b038b2016-11-22 21:24:04 +0800919bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
920{
921 switch (target)
922 {
923 case GL_TEXTURE_2D:
924 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
925 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
926 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
927 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
928 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
929 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
930 case GL_TEXTURE_3D:
931 case GL_TEXTURE_2D_ARRAY:
932 case GL_TEXTURE_2D_MULTISAMPLE:
933 return true;
934 default:
935 return false;
936 }
937}
938
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500939bool ValidFramebufferTarget(GLenum target)
940{
He Yunchaoced53ae2016-11-29 15:00:51 +0800941 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
942 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400943 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500944
945 switch (target)
946 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800947 case GL_FRAMEBUFFER:
948 return true;
949 case GL_READ_FRAMEBUFFER:
950 return true;
951 case GL_DRAW_FRAMEBUFFER:
952 return true;
953 default:
954 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500955 }
956}
957
Jamie Madill29639852016-09-02 15:00:09 -0400958bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -0500959{
960 switch (target)
961 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800962 case GL_ARRAY_BUFFER:
963 case GL_ELEMENT_ARRAY_BUFFER:
964 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -0500965
He Yunchaoced53ae2016-11-29 15:00:51 +0800966 case GL_PIXEL_PACK_BUFFER:
967 case GL_PIXEL_UNPACK_BUFFER:
968 return (context->getExtensions().pixelBufferObject ||
969 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -0400970
He Yunchaoced53ae2016-11-29 15:00:51 +0800971 case GL_COPY_READ_BUFFER:
972 case GL_COPY_WRITE_BUFFER:
973 case GL_TRANSFORM_FEEDBACK_BUFFER:
974 case GL_UNIFORM_BUFFER:
975 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -0500976
He Yunchaoced53ae2016-11-29 15:00:51 +0800977 case GL_ATOMIC_COUNTER_BUFFER:
978 case GL_SHADER_STORAGE_BUFFER:
979 case GL_DRAW_INDIRECT_BUFFER:
980 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800981 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -0400982
He Yunchaoced53ae2016-11-29 15:00:51 +0800983 default:
984 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -0500985 }
986}
987
Jamie Madillc29968b2016-01-20 11:17:23 -0500988bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400989{
Jamie Madillc29968b2016-01-20 11:17:23 -0500990 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400991 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400992 switch (target)
993 {
Jamie Madillc29968b2016-01-20 11:17:23 -0500994 case GL_TEXTURE_2D:
995 maxDimension = caps.max2DTextureSize;
996 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800997 case GL_TEXTURE_CUBE_MAP:
998 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
999 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1000 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1001 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1002 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1003 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1004 maxDimension = caps.maxCubeMapTextureSize;
1005 break;
1006 case GL_TEXTURE_3D:
1007 maxDimension = caps.max3DTextureSize;
1008 break;
1009 case GL_TEXTURE_2D_ARRAY:
1010 maxDimension = caps.max2DTextureSize;
1011 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001012 case GL_TEXTURE_2D_MULTISAMPLE:
1013 maxDimension = caps.max2DTextureSize;
1014 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001015 default:
1016 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001017 }
1018
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001019 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001020}
1021
Geoff Langcc507aa2016-12-12 10:09:52 -05001022bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001023 GLenum target,
1024 GLint level,
1025 GLsizei width,
1026 GLsizei height,
1027 GLsizei depth,
1028 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001029{
1030 if (level < 0 || width < 0 || height < 0 || depth < 0)
1031 {
1032 return false;
1033 }
1034
Austin Kinross08528e12015-10-07 16:24:40 -07001035 // TexSubImage parameters can be NPOT without textureNPOT extension,
1036 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001037 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001038 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001039 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001040 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001041 {
1042 return false;
1043 }
1044
1045 if (!ValidMipLevel(context, target, level))
1046 {
1047 return false;
1048 }
1049
1050 return true;
1051}
1052
Geoff Lang0d8b7242015-09-09 14:56:53 -04001053bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1054{
1055 // List of compressed format that require that the texture size is smaller than or a multiple of
1056 // the compressed block size.
1057 switch (internalFormat)
1058 {
1059 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1060 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1061 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1062 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -04001063 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
1064 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
1065 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
1066 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -08001067 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001068 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1069 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1070 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1071 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1072 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
1073 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001074 return true;
1075
1076 default:
1077 return false;
1078 }
1079}
1080
Geoff Lang966c9402017-04-18 12:38:27 -04001081bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
1082{
1083 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
1084 (size % blockSize == 0);
1085}
1086
Jamie Madillc29968b2016-01-20 11:17:23 -05001087bool ValidCompressedImageSize(const ValidationContext *context,
1088 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -04001089 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -05001090 GLsizei width,
1091 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001092{
Geoff Langca271392017-04-05 12:30:00 -04001093 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -04001094 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001095 {
1096 return false;
1097 }
1098
Geoff Lang966c9402017-04-18 12:38:27 -04001099 if (width < 0 || height < 0)
1100 {
1101 return false;
1102 }
1103
1104 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1105 {
1106 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
1107 // block size for level 0 but WebGL disallows this.
1108 bool smallerThanBlockSizeAllowed =
1109 level > 0 || !context->getExtensions().webglCompatibility;
1110
1111 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
1112 smallerThanBlockSizeAllowed) ||
1113 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
1114 smallerThanBlockSizeAllowed))
1115 {
1116 return false;
1117 }
1118 }
1119
1120 return true;
1121}
1122
1123bool ValidCompressedSubImageSize(const ValidationContext *context,
1124 GLenum internalFormat,
1125 GLint xoffset,
1126 GLint yoffset,
1127 GLsizei width,
1128 GLsizei height,
1129 size_t textureWidth,
1130 size_t textureHeight)
1131{
1132 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
1133 if (!formatInfo.compressed)
1134 {
1135 return false;
1136 }
1137
Geoff Lang44ff5a72017-02-03 15:15:43 -05001138 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001139 {
1140 return false;
1141 }
1142
Geoff Lang0d8b7242015-09-09 14:56:53 -04001143 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1144 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05001145 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -04001146 yoffset % formatInfo.compressedBlockHeight != 0)
1147 {
1148 return false;
1149 }
1150
1151 // Allowed to either have data that is a multiple of block size or is smaller than the block
1152 // size but fills the entire mip
1153 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
1154 static_cast<size_t>(width) == textureWidth &&
1155 static_cast<size_t>(height) == textureHeight;
1156 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
1157 (height % formatInfo.compressedBlockHeight) == 0;
1158 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -04001159 {
1160 return false;
1161 }
1162 }
1163
Geoff Langd4f180b2013-09-24 13:57:44 -04001164 return true;
1165}
1166
Geoff Langff5b2d52016-09-07 11:32:23 -04001167bool ValidImageDataSize(ValidationContext *context,
1168 GLenum textureTarget,
1169 GLsizei width,
1170 GLsizei height,
1171 GLsizei depth,
1172 GLenum internalFormat,
1173 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001174 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001175 GLsizei imageSize)
1176{
1177 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1178 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1179 {
1180 // Checks are not required
1181 return true;
1182 }
1183
1184 // ...the data would be unpacked from the buffer object such that the memory reads required
1185 // would exceed the data store size.
Geoff Langca271392017-04-05 12:30:00 -04001186 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
Geoff Langff5b2d52016-09-07 11:32:23 -04001187 const gl::Extents size(width, height, depth);
1188 const auto &unpack = context->getGLState().getUnpackState();
1189
1190 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1191 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1192 if (endByteOrErr.isError())
1193 {
1194 context->handleError(endByteOrErr.getError());
1195 return false;
1196 }
1197
1198 GLuint endByte = endByteOrErr.getResult();
1199
1200 if (pixelUnpackBuffer)
1201 {
1202 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1203 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1204 checkedEndByte += checkedOffset;
1205
1206 if (!checkedEndByte.IsValid() ||
1207 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1208 {
1209 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001210 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04001211 return false;
1212 }
1213 }
1214 else
1215 {
1216 ASSERT(imageSize >= 0);
1217 if (pixels == nullptr && imageSize != 0)
1218 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001219 context->handleError(InvalidOperation()
1220 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001221 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001222 }
1223
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001224 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001225 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001226 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001227 return false;
1228 }
1229 }
1230
1231 return true;
1232}
1233
Geoff Lang37dde692014-01-31 16:34:54 -05001234bool ValidQueryType(const Context *context, GLenum queryType)
1235{
He Yunchaoced53ae2016-11-29 15:00:51 +08001236 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1237 "GL extension enums not equal.");
1238 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1239 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001240
1241 switch (queryType)
1242 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001243 case GL_ANY_SAMPLES_PASSED:
1244 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1245 return true;
1246 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1247 return (context->getClientMajorVersion() >= 3);
1248 case GL_TIME_ELAPSED_EXT:
1249 return context->getExtensions().disjointTimerQuery;
1250 case GL_COMMANDS_COMPLETED_CHROMIUM:
1251 return context->getExtensions().syncQuery;
1252 default:
1253 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001254 }
1255}
1256
Geoff Lang2d62ab72017-03-23 16:54:40 -04001257bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
1258 GLenum type,
1259 GLboolean normalized,
1260 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001261 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001262 bool pureInteger)
1263{
1264 ASSERT(context->getExtensions().webglCompatibility);
1265
1266 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1267 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1268 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1269 // parameter exceeds 255.
1270 constexpr GLsizei kMaxWebGLStride = 255;
1271 if (stride > kMaxWebGLStride)
1272 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001273 context->handleError(InvalidValue()
1274 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001275 return false;
1276 }
1277
1278 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1279 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1280 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1281 // or an INVALID_OPERATION error is generated.
1282 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1283 size_t typeSize = GetVertexFormatTypeSize(internalType);
1284
1285 ASSERT(isPow2(typeSize) && typeSize > 0);
1286 size_t sizeMask = (typeSize - 1);
1287 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1288 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001289 context->handleError(InvalidOperation() << "Offset is not a multiple of the type size.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001290 return false;
1291 }
1292
1293 if ((stride & sizeMask) != 0)
1294 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001295 context->handleError(InvalidOperation() << "Stride is not a multiple of the type size.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001296 return false;
1297 }
1298
1299 return true;
1300}
1301
Jamie Madillef300b12016-10-07 15:12:09 -04001302Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001303{
He Yunchaoced53ae2016-11-29 15:00:51 +08001304 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1305 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1306 // or program object and INVALID_OPERATION if the provided name identifies an object
1307 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001308
Dian Xiang769769a2015-09-09 15:20:08 -07001309 Program *validProgram = context->getProgram(id);
1310
1311 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001312 {
Dian Xiang769769a2015-09-09 15:20:08 -07001313 if (context->getShader(id))
1314 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001315 context->handleError(InvalidOperation()
1316 << "Expected a program name, but found a shader name");
Dian Xiang769769a2015-09-09 15:20:08 -07001317 }
1318 else
1319 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001320 context->handleError(InvalidValue() << "Program name is not valid");
Dian Xiang769769a2015-09-09 15:20:08 -07001321 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001322 }
Dian Xiang769769a2015-09-09 15:20:08 -07001323
1324 return validProgram;
1325}
1326
Jamie Madillef300b12016-10-07 15:12:09 -04001327Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001328{
1329 // See ValidProgram for spec details.
1330
1331 Shader *validShader = context->getShader(id);
1332
1333 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001334 {
Dian Xiang769769a2015-09-09 15:20:08 -07001335 if (context->getProgram(id))
1336 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001337 context->handleError(InvalidOperation()
1338 << "Expected a shader name, but found a program name");
Dian Xiang769769a2015-09-09 15:20:08 -07001339 }
1340 else
1341 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001342 context->handleError(InvalidValue() << "Shader name is invalid");
Dian Xiang769769a2015-09-09 15:20:08 -07001343 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001344 }
Dian Xiang769769a2015-09-09 15:20:08 -07001345
1346 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001347}
1348
Geoff Langb1196682014-07-23 13:47:29 -04001349bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001350{
1351 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1352 {
1353 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1354
Geoff Langaae65a42014-05-26 12:43:44 -04001355 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001356 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001357 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001358 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001359 }
1360 }
1361 else
1362 {
1363 switch (attachment)
1364 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001365 case GL_DEPTH_ATTACHMENT:
1366 case GL_STENCIL_ATTACHMENT:
1367 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001368
He Yunchaoced53ae2016-11-29 15:00:51 +08001369 case GL_DEPTH_STENCIL_ATTACHMENT:
1370 if (!context->getExtensions().webglCompatibility &&
1371 context->getClientMajorVersion() < 3)
1372 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001373 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001374 return false;
1375 }
1376 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001377
He Yunchaoced53ae2016-11-29 15:00:51 +08001378 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001379 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001380 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001381 }
1382 }
1383
1384 return true;
1385}
1386
Jamie Madille8fb6402017-02-14 17:56:40 -05001387bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001388 GLenum target,
1389 GLsizei samples,
1390 GLenum internalformat,
1391 GLsizei width,
1392 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001393{
1394 switch (target)
1395 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001396 case GL_RENDERBUFFER:
1397 break;
1398 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001399 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001400 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001401 }
1402
1403 if (width < 0 || height < 0 || samples < 0)
1404 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001405 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001406 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001407 }
1408
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001409 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1410 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1411
1412 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001413 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001414 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001415 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001416 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001417 }
1418
1419 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1420 // 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 -08001421 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001422 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1423 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001424 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001425 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001426 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001427 }
1428
Geoff Langaae65a42014-05-26 12:43:44 -04001429 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001430 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001431 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001432 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001433 }
1434
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001435 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001436 if (handle == 0)
1437 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001438 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001439 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001440 }
1441
1442 return true;
1443}
1444
He Yunchaoced53ae2016-11-29 15:00:51 +08001445bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1446 GLenum target,
1447 GLenum attachment,
1448 GLenum renderbuffertarget,
1449 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001450{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001451 if (!ValidFramebufferTarget(target))
1452 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001453 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001454 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001455 }
1456
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001457 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001458
Jamie Madill84115c92015-04-23 15:00:07 -04001459 ASSERT(framebuffer);
1460 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001461 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001462 context->handleError(InvalidOperation() << "Cannot change default FBO's attachments");
Geoff Langb1196682014-07-23 13:47:29 -04001463 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001464 }
1465
Jamie Madillb4472272014-07-03 10:38:55 -04001466 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001467 {
Jamie Madillb4472272014-07-03 10:38:55 -04001468 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001469 }
1470
Jamie Madillab9d82c2014-01-21 16:38:14 -05001471 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1472 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1473 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1474 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1475 if (renderbuffer != 0)
1476 {
1477 if (!context->getRenderbuffer(renderbuffer))
1478 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001479 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001480 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001481 }
1482 }
1483
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001484 return true;
1485}
1486
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001487bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001488 GLint srcX0,
1489 GLint srcY0,
1490 GLint srcX1,
1491 GLint srcY1,
1492 GLint dstX0,
1493 GLint dstY0,
1494 GLint dstX1,
1495 GLint dstY1,
1496 GLbitfield mask,
1497 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001498{
1499 switch (filter)
1500 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001501 case GL_NEAREST:
1502 break;
1503 case GL_LINEAR:
1504 break;
1505 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001506 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001507 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001508 }
1509
1510 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1511 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001512 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001513 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001514 }
1515
1516 if (mask == 0)
1517 {
1518 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1519 // buffers are copied.
1520 return false;
1521 }
1522
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001523 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1524 // color buffer, leaving only nearest being unfiltered from above
1525 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001527 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001528 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001529 }
1530
Jamie Madill51f40ec2016-06-15 14:06:00 -04001531 const auto &glState = context->getGLState();
1532 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1533 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001534
1535 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001536 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001537 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001538 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001539 }
1540
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001541 if (readFramebuffer->id() == drawFramebuffer->id())
1542 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001543 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001544 return false;
1545 }
1546
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001547 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001548 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001549 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001550 return false;
1551 }
1552
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001553 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001554 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001555 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001556 return false;
1557 }
1558
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001559 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001560 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001561 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001562 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001563 }
1564
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001565 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1566
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001567 if (mask & GL_COLOR_BUFFER_BIT)
1568 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001569 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001570 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001571
He Yunchao66a41a22016-12-15 16:45:05 +08001572 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001573 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001574 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001575
Geoff Langa15472a2015-08-11 11:48:03 -04001576 for (size_t drawbufferIdx = 0;
1577 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001578 {
Geoff Langa15472a2015-08-11 11:48:03 -04001579 const FramebufferAttachment *attachment =
1580 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1581 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001582 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001583 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001584
Geoff Langb2f3d052013-08-13 12:49:27 -04001585 // The GL ES 3.0.2 spec (pg 193) states that:
1586 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001587 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1588 // as well
1589 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1590 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001591 // Changes with EXT_color_buffer_float:
1592 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001593 GLenum readComponentType = readFormat.info->componentType;
1594 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001595 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001596 readComponentType == GL_SIGNED_NORMALIZED);
1597 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1598 drawComponentType == GL_SIGNED_NORMALIZED);
1599
1600 if (extensions.colorBufferFloat)
1601 {
1602 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1603 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1604
1605 if (readFixedOrFloat != drawFixedOrFloat)
1606 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001607 context->handleError(InvalidOperation()
1608 << "If the read buffer contains fixed-point or "
1609 "floating-point values, the draw buffer must "
1610 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001611 return false;
1612 }
1613 }
1614 else if (readFixedPoint != drawFixedPoint)
1615 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001616 context->handleError(InvalidOperation()
1617 << "If the read buffer contains fixed-point values, "
1618 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001619 return false;
1620 }
1621
1622 if (readComponentType == GL_UNSIGNED_INT &&
1623 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001625 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001626 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001627 }
1628
Jamie Madill6163c752015-12-07 16:32:59 -05001629 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001630 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001631 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001632 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001633 }
1634
Jamie Madilla3944d42016-07-22 22:13:26 -04001635 if (readColorBuffer->getSamples() > 0 &&
1636 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001637 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001638 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001639 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001640 }
Geoff Lange4915782017-04-12 15:19:07 -04001641
1642 if (context->getExtensions().webglCompatibility &&
1643 *readColorBuffer == *attachment)
1644 {
1645 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001646 InvalidOperation()
1647 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001648 return false;
1649 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001650 }
1651 }
1652
Jamie Madilla3944d42016-07-22 22:13:26 -04001653 if ((readFormat.info->componentType == GL_INT ||
1654 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1655 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001656 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001657 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001658 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001659 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001660 }
He Yunchao66a41a22016-12-15 16:45:05 +08001661 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1662 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1663 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1664 // situation is an application error that would lead to a crash in ANGLE.
1665 else if (drawFramebuffer->hasEnabledDrawBuffer())
1666 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001667 context->handleError(
1668 InvalidOperation()
1669 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001670 return false;
1671 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001672 }
1673
He Yunchaoced53ae2016-11-29 15:00:51 +08001674 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001675 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1676 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001677 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001678 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001679 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001680 const gl::FramebufferAttachment *readBuffer =
1681 readFramebuffer->getAttachment(attachments[i]);
1682 const gl::FramebufferAttachment *drawBuffer =
1683 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001684
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001685 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001686 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001687 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001688 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001689 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001690 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001691 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001692
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001693 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001694 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001695 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001696 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001697 }
Geoff Lange4915782017-04-12 15:19:07 -04001698
1699 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1700 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001701 context->handleError(
1702 InvalidOperation()
1703 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001704 return false;
1705 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001706 }
He Yunchao66a41a22016-12-15 16:45:05 +08001707 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1708 else if (drawBuffer)
1709 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001710 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1711 "depth/stencil attachment of a "
1712 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001713 return false;
1714 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001715 }
1716 }
1717
1718 return true;
1719}
1720
Geoff Lang62fce5b2016-09-30 10:46:35 -04001721bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
1722 GLint x,
1723 GLint y,
1724 GLsizei width,
1725 GLsizei height,
1726 GLenum format,
1727 GLenum type,
1728 GLsizei bufSize,
1729 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001730 GLsizei *columns,
1731 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001732 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001733{
1734 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001735 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001736 return false;
1737 }
1738
Geoff Lang62fce5b2016-09-30 10:46:35 -04001739 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001740 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001741 {
Geoff Langb1196682014-07-23 13:47:29 -04001742 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001743 }
1744
Geoff Lang62fce5b2016-09-30 10:46:35 -04001745 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001746 {
Geoff Langb1196682014-07-23 13:47:29 -04001747 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001748 }
1749
Jamie Madillc29968b2016-01-20 11:17:23 -05001750 return true;
1751}
1752
1753bool ValidateReadnPixelsEXT(Context *context,
1754 GLint x,
1755 GLint y,
1756 GLsizei width,
1757 GLsizei height,
1758 GLenum format,
1759 GLenum type,
1760 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001761 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001762{
1763 if (bufSize < 0)
1764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001765 context->handleError(InvalidValue() << "bufSize must be a positive number");
Jamie Madillc29968b2016-01-20 11:17:23 -05001766 return false;
1767 }
1768
Geoff Lang62fce5b2016-09-30 10:46:35 -04001769 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001770 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001771}
Jamie Madill26e91952014-03-05 15:01:27 -05001772
Geoff Lang62fce5b2016-09-30 10:46:35 -04001773bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
1774 GLint x,
1775 GLint y,
1776 GLsizei width,
1777 GLsizei height,
1778 GLenum format,
1779 GLenum type,
1780 GLsizei bufSize,
1781 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001782 GLsizei *columns,
1783 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001784 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001785{
1786 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001787 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001788 return false;
1789 }
1790
Geoff Lange93daba2017-03-30 13:54:40 -04001791 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1792 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001793 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001794 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001795 }
1796
Geoff Lang62fce5b2016-09-30 10:46:35 -04001797 if (!ValidateRobustBufferSize(context, bufSize, *length))
1798 {
1799 return false;
1800 }
1801
1802 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001803}
1804
Olli Etuaho41997e72016-03-10 13:38:39 +02001805bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001806{
1807 if (!context->getExtensions().occlusionQueryBoolean &&
1808 !context->getExtensions().disjointTimerQuery)
1809 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001810 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001811 return false;
1812 }
1813
Olli Etuaho41997e72016-03-10 13:38:39 +02001814 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001815}
1816
Olli Etuaho41997e72016-03-10 13:38:39 +02001817bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001818{
1819 if (!context->getExtensions().occlusionQueryBoolean &&
1820 !context->getExtensions().disjointTimerQuery)
1821 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001822 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001823 return false;
1824 }
1825
Olli Etuaho41997e72016-03-10 13:38:39 +02001826 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001827}
1828
1829bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001830{
1831 if (!ValidQueryType(context, target))
1832 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001833 context->handleError(InvalidEnum() << "Invalid query target");
Geoff Langb1196682014-07-23 13:47:29 -04001834 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001835 }
1836
1837 if (id == 0)
1838 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001839 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001840 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001841 }
1842
1843 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1844 // of zero, if the active query object name for <target> is non-zero (for the
1845 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1846 // the active query for either target is non-zero), if <id> is the name of an
1847 // existing query object whose type does not match <target>, or if <id> is the
1848 // active query object name for any query type, the error INVALID_OPERATION is
1849 // generated.
1850
1851 // Ensure no other queries are active
1852 // NOTE: If other queries than occlusion are supported, we will need to check
1853 // separately that:
1854 // a) The query ID passed is not the current active query for any target/type
1855 // b) There are no active queries for the requested target (and in the case
1856 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1857 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001858
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001859 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001860 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001861 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001862 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001863 }
1864
1865 Query *queryObject = context->getQuery(id, true, target);
1866
1867 // check that name was obtained with glGenQueries
1868 if (!queryObject)
1869 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001870 context->handleError(InvalidOperation() << "Invalid query id");
Geoff Langb1196682014-07-23 13:47:29 -04001871 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001872 }
1873
1874 // check for type mismatch
1875 if (queryObject->getType() != target)
1876 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001877 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001878 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001879 }
1880
1881 return true;
1882}
1883
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001884bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1885{
1886 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001887 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001888 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001889 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001890 return false;
1891 }
1892
1893 return ValidateBeginQueryBase(context, target, id);
1894}
1895
1896bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001897{
1898 if (!ValidQueryType(context, target))
1899 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001900 context->handleError(InvalidEnum() << "Invalid query target");
Geoff Langb1196682014-07-23 13:47:29 -04001901 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001902 }
1903
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001904 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001905
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001906 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001907 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001908 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001909 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001910 }
1911
Jamie Madill45c785d2014-05-13 14:09:34 -04001912 return true;
1913}
1914
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001915bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1916{
1917 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001918 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001919 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001920 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001921 return false;
1922 }
1923
1924 return ValidateEndQueryBase(context, target);
1925}
1926
1927bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1928{
1929 if (!context->getExtensions().disjointTimerQuery)
1930 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001931 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001932 return false;
1933 }
1934
1935 if (target != GL_TIMESTAMP_EXT)
1936 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001937 context->handleError(InvalidEnum() << "Invalid query target");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001938 return false;
1939 }
1940
1941 Query *queryObject = context->getQuery(id, true, target);
1942 if (queryObject == nullptr)
1943 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001944 context->handleError(InvalidOperation() << "Invalid query id");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001945 return false;
1946 }
1947
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001948 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001949 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001950 context->handleError(InvalidOperation() << "Query is active");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001951 return false;
1952 }
1953
1954 return true;
1955}
1956
Geoff Lang2186c382016-10-14 10:54:54 -04001957bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001958{
Geoff Lang2186c382016-10-14 10:54:54 -04001959 if (numParams)
1960 {
1961 *numParams = 0;
1962 }
1963
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001964 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1965 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001966 context->handleError(InvalidEnum() << "Invalid query type");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001967 return false;
1968 }
1969
1970 switch (pname)
1971 {
1972 case GL_CURRENT_QUERY_EXT:
1973 if (target == GL_TIMESTAMP_EXT)
1974 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001975 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001976 return false;
1977 }
1978 break;
1979 case GL_QUERY_COUNTER_BITS_EXT:
1980 if (!context->getExtensions().disjointTimerQuery ||
1981 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1982 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001983 context->handleError(InvalidEnum() << "Invalid pname");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001984 return false;
1985 }
1986 break;
1987 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001988 context->handleError(InvalidEnum() << "Invalid pname");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001989 return false;
1990 }
1991
Geoff Lang2186c382016-10-14 10:54:54 -04001992 if (numParams)
1993 {
1994 // All queries return only one value
1995 *numParams = 1;
1996 }
1997
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001998 return true;
1999}
2000
2001bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2002{
2003 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002004 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002006 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002007 return false;
2008 }
2009
Geoff Lang2186c382016-10-14 10:54:54 -04002010 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002011}
2012
Geoff Lang2186c382016-10-14 10:54:54 -04002013bool ValidateGetQueryivRobustANGLE(Context *context,
2014 GLenum target,
2015 GLenum pname,
2016 GLsizei bufSize,
2017 GLsizei *length,
2018 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002019{
Geoff Lang2186c382016-10-14 10:54:54 -04002020 if (!ValidateRobustEntryPoint(context, bufSize))
2021 {
2022 return false;
2023 }
2024
2025 if (!ValidateGetQueryivBase(context, target, pname, length))
2026 {
2027 return false;
2028 }
2029
2030 if (!ValidateRobustBufferSize(context, bufSize, *length))
2031 {
2032 return false;
2033 }
2034
2035 return true;
2036}
2037
2038bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2039{
2040 if (numParams)
2041 {
2042 *numParams = 0;
2043 }
2044
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002045 Query *queryObject = context->getQuery(id, false, GL_NONE);
2046
2047 if (!queryObject)
2048 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002049 context->handleError(InvalidOperation() << "Query does not exist");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002050 return false;
2051 }
2052
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002053 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002054 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002055 context->handleError(InvalidOperation() << "Query currently active");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002056 return false;
2057 }
2058
2059 switch (pname)
2060 {
2061 case GL_QUERY_RESULT_EXT:
2062 case GL_QUERY_RESULT_AVAILABLE_EXT:
2063 break;
2064
2065 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002066 context->handleError(InvalidEnum() << "Invalid pname enum");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002067 return false;
2068 }
2069
Geoff Lang2186c382016-10-14 10:54:54 -04002070 if (numParams)
2071 {
2072 *numParams = 1;
2073 }
2074
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002075 return true;
2076}
2077
2078bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2079{
2080 if (!context->getExtensions().disjointTimerQuery)
2081 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002082 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002083 return false;
2084 }
Geoff Lang2186c382016-10-14 10:54:54 -04002085 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2086}
2087
2088bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2089 GLuint id,
2090 GLenum pname,
2091 GLsizei bufSize,
2092 GLsizei *length,
2093 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");
Geoff Lang2186c382016-10-14 10:54:54 -04002098 return false;
2099 }
2100
2101 if (!ValidateRobustEntryPoint(context, bufSize))
2102 {
2103 return false;
2104 }
2105
2106 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2107 {
2108 return false;
2109 }
2110
2111 if (!ValidateRobustBufferSize(context, bufSize, *length))
2112 {
2113 return false;
2114 }
2115
2116 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002117}
2118
2119bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2120{
2121 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002122 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002123 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002124 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002125 return false;
2126 }
Geoff Lang2186c382016-10-14 10:54:54 -04002127 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2128}
2129
2130bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2131 GLuint id,
2132 GLenum pname,
2133 GLsizei bufSize,
2134 GLsizei *length,
2135 GLuint *params)
2136{
2137 if (!context->getExtensions().disjointTimerQuery &&
2138 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2139 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002140 context->handleError(InvalidOperation() << "Query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002141 return false;
2142 }
2143
2144 if (!ValidateRobustEntryPoint(context, bufSize))
2145 {
2146 return false;
2147 }
2148
2149 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2150 {
2151 return false;
2152 }
2153
2154 if (!ValidateRobustBufferSize(context, bufSize, *length))
2155 {
2156 return false;
2157 }
2158
2159 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002160}
2161
2162bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2163{
2164 if (!context->getExtensions().disjointTimerQuery)
2165 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002166 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002167 return false;
2168 }
Geoff Lang2186c382016-10-14 10:54:54 -04002169 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2170}
2171
2172bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2173 GLuint id,
2174 GLenum pname,
2175 GLsizei bufSize,
2176 GLsizei *length,
2177 GLint64 *params)
2178{
2179 if (!context->getExtensions().disjointTimerQuery)
2180 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002181 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002182 return false;
2183 }
2184
2185 if (!ValidateRobustEntryPoint(context, bufSize))
2186 {
2187 return false;
2188 }
2189
2190 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2191 {
2192 return false;
2193 }
2194
2195 if (!ValidateRobustBufferSize(context, bufSize, *length))
2196 {
2197 return false;
2198 }
2199
2200 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002201}
2202
2203bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2204{
2205 if (!context->getExtensions().disjointTimerQuery)
2206 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002207 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002208 return false;
2209 }
Geoff Lang2186c382016-10-14 10:54:54 -04002210 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2211}
2212
2213bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2214 GLuint id,
2215 GLenum pname,
2216 GLsizei bufSize,
2217 GLsizei *length,
2218 GLuint64 *params)
2219{
2220 if (!context->getExtensions().disjointTimerQuery)
2221 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002222 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002223 return false;
2224 }
2225
2226 if (!ValidateRobustEntryPoint(context, bufSize))
2227 {
2228 return false;
2229 }
2230
2231 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2232 {
2233 return false;
2234 }
2235
2236 if (!ValidateRobustBufferSize(context, bufSize, *length))
2237 {
2238 return false;
2239 }
2240
2241 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002242}
2243
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002244bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002245 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002246 GLuint program,
2247 GLint location,
2248 GLsizei count)
2249{
2250 // Check for ES31 program uniform entry points
2251 if (context->getClientVersion() < Version(3, 1))
2252 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002253 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002254 return false;
2255 }
2256
2257 const LinkedUniform *uniform = nullptr;
2258 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002259 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2260 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002261}
2262
Frank Henigmana98a6472017-02-02 21:38:32 -05002263bool ValidateProgramUniform1iv(gl::Context *context,
2264 GLuint program,
2265 GLint location,
2266 GLsizei count,
2267 const GLint *value)
2268{
2269 // Check for ES31 program uniform entry points
2270 if (context->getClientVersion() < Version(3, 1))
2271 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002272 context->handleError(InvalidOperation());
Frank Henigmana98a6472017-02-02 21:38:32 -05002273 return false;
2274 }
2275
2276 const LinkedUniform *uniform = nullptr;
2277 gl::Program *programObject = GetValidProgram(context, program);
2278 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2279 ValidateUniform1ivValue(context, uniform->type, count, value);
2280}
2281
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002282bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002283 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002284 GLuint program,
2285 GLint location,
2286 GLsizei count,
2287 GLboolean transpose)
2288{
2289 // Check for ES31 program uniform entry points
2290 if (context->getClientVersion() < Version(3, 1))
2291 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002292 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002293 return false;
2294 }
2295
2296 const LinkedUniform *uniform = nullptr;
2297 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002298 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2299 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002300}
2301
Jamie Madillc1d770e2017-04-13 17:31:24 -04002302bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002303{
2304 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002305 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002306 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002307 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002308 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002309 }
2310
Jamie Madill62d31cb2015-09-11 13:25:51 -04002311 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002312 gl::Program *programObject = context->getGLState().getProgram();
2313 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2314 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002315}
2316
Jamie Madillbe849e42017-05-02 15:49:00 -04002317bool ValidateUniform1iv(ValidationContext *context,
2318 GLint location,
2319 GLsizei count,
2320 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002321{
2322 const LinkedUniform *uniform = nullptr;
2323 gl::Program *programObject = context->getGLState().getProgram();
2324 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2325 ValidateUniform1ivValue(context, uniform->type, count, value);
2326}
2327
Jamie Madillc1d770e2017-04-13 17:31:24 -04002328bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002329 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002330 GLint location,
2331 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002332 GLboolean transpose)
2333{
2334 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002335 int rows = VariableRowCount(valueType);
2336 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002337 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002338 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002339 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002340 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002341 }
2342
Martin Radev1be913c2016-07-11 17:59:16 +03002343 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002344 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002345 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002346 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002347 }
2348
Jamie Madill62d31cb2015-09-11 13:25:51 -04002349 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002350 gl::Program *programObject = context->getGLState().getProgram();
2351 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2352 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002353}
2354
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002355bool ValidateStateQuery(ValidationContext *context,
2356 GLenum pname,
2357 GLenum *nativeType,
2358 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002359{
2360 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2361 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002362 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002363 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002364 }
2365
Jamie Madill0af26e12015-03-05 19:54:33 -05002366 const Caps &caps = context->getCaps();
2367
Jamie Madill893ab082014-05-16 16:56:10 -04002368 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2369 {
2370 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2371
Jamie Madill0af26e12015-03-05 19:54:33 -05002372 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002373 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002374 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002375 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002376 }
2377 }
2378
2379 switch (pname)
2380 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002381 case GL_TEXTURE_BINDING_2D:
2382 case GL_TEXTURE_BINDING_CUBE_MAP:
2383 case GL_TEXTURE_BINDING_3D:
2384 case GL_TEXTURE_BINDING_2D_ARRAY:
2385 break;
2386 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2387 if (!context->getExtensions().eglStreamConsumerExternal &&
2388 !context->getExtensions().eglImageExternal)
2389 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002390 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2391 "nor GL_OES_EGL_image_external "
2392 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002393 return false;
2394 }
2395 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002396
He Yunchaoced53ae2016-11-29 15:00:51 +08002397 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2398 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002399 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002400 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2401 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002403 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002404 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002405 }
2406
Jamie Madill51f40ec2016-06-15 14:06:00 -04002407 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2408 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002409
2410 if (framebuffer->getReadBufferState() == GL_NONE)
2411 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002412 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Martin Radev138064f2016-07-15 12:03:41 +03002413 return false;
2414 }
2415
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002416 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002417 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002418 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002419 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002420 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002421 }
2422 }
2423 break;
2424
He Yunchaoced53ae2016-11-29 15:00:51 +08002425 default:
2426 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002427 }
2428
2429 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002430 if (*numParams == 0)
2431 {
2432 return false;
2433 }
2434
2435 return true;
2436}
2437
2438bool ValidateRobustStateQuery(ValidationContext *context,
2439 GLenum pname,
2440 GLsizei bufSize,
2441 GLenum *nativeType,
2442 unsigned int *numParams)
2443{
2444 if (!ValidateRobustEntryPoint(context, bufSize))
2445 {
2446 return false;
2447 }
2448
2449 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2450 {
2451 return false;
2452 }
2453
2454 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002455 {
2456 return false;
2457 }
2458
2459 return true;
2460}
2461
Jamie Madillc29968b2016-01-20 11:17:23 -05002462bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2463 GLenum target,
2464 GLint level,
2465 GLenum internalformat,
2466 bool isSubImage,
2467 GLint xoffset,
2468 GLint yoffset,
2469 GLint zoffset,
2470 GLint x,
2471 GLint y,
2472 GLsizei width,
2473 GLsizei height,
2474 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002475 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002476{
Jamie Madill560a8d82014-05-21 13:06:20 -04002477 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2478 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002479 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002480 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002481 }
2482
He Yunchaoced53ae2016-11-29 15:00:51 +08002483 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2484 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002485 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002486 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002487 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002488 }
2489
2490 if (border != 0)
2491 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002492 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002493 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002494 }
2495
2496 if (!ValidMipLevel(context, target, level))
2497 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002498 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002499 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002500 }
2501
Jamie Madill51f40ec2016-06-15 14:06:00 -04002502 const auto &state = context->getGLState();
2503 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002504 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002505 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002506 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002507 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002508 }
2509
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002510 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002511 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002512 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002513 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002514 }
2515
Martin Radev138064f2016-07-15 12:03:41 +03002516 if (readFramebuffer->getReadBufferState() == GL_NONE)
2517 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002518 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Martin Radev138064f2016-07-15 12:03:41 +03002519 return false;
2520 }
2521
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002522 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2523 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002524 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002525 // situation is an application error that would lead to a crash in ANGLE.
2526 if (readFramebuffer->getReadColorbuffer() == nullptr)
2527 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002528 context->handleError(InvalidOperation() << "Missing read attachment");
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002529 return false;
2530 }
2531
Geoff Langaae65a42014-05-26 12:43:44 -04002532 const gl::Caps &caps = context->getCaps();
2533
Geoff Langaae65a42014-05-26 12:43:44 -04002534 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002535 switch (target)
2536 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002537 case GL_TEXTURE_2D:
2538 maxDimension = caps.max2DTextureSize;
2539 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002540
He Yunchaoced53ae2016-11-29 15:00:51 +08002541 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2542 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2543 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2544 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2545 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2546 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2547 maxDimension = caps.maxCubeMapTextureSize;
2548 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002549
He Yunchaoced53ae2016-11-29 15:00:51 +08002550 case GL_TEXTURE_2D_ARRAY:
2551 maxDimension = caps.max2DTextureSize;
2552 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002553
He Yunchaoced53ae2016-11-29 15:00:51 +08002554 case GL_TEXTURE_3D:
2555 maxDimension = caps.max3DTextureSize;
2556 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002557
He Yunchaoced53ae2016-11-29 15:00:51 +08002558 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002559 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002560 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002561 }
2562
Jamie Madillc29968b2016-01-20 11:17:23 -05002563 gl::Texture *texture =
2564 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002565 if (!texture)
2566 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002567 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002568 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002569 }
2570
Geoff Lang69cce582015-09-17 13:20:36 -04002571 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002572 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002573 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002574 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002575 }
2576
Geoff Langca271392017-04-05 12:30:00 -04002577 const gl::InternalFormat &formatInfo =
2578 gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002579
Geoff Lang966c9402017-04-18 12:38:27 -04002580 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002581 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002582 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002583 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002584 }
2585
2586 if (isSubImage)
2587 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002588 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2589 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2590 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002591 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002592 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002593 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002594 }
2595 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002596 else
2597 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002598 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002599 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002600 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002601 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002602 }
2603
Geoff Langeb66a6e2016-10-31 13:06:12 -04002604 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002605 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002606 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002607 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002608 }
2609
2610 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002611 if (static_cast<int>(width) > maxLevelDimension ||
2612 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002613 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002614 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002615 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002616 }
2617 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002618
Jamie Madill0c8abca2016-07-22 20:21:26 -04002619 if (textureFormatOut)
2620 {
2621 *textureFormatOut = texture->getFormat(target, level);
2622 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002623
2624 // Detect texture copying feedback loops for WebGL.
2625 if (context->getExtensions().webglCompatibility)
2626 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002627 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002628 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002629 context->handleError(InvalidOperation() << "Texture copying feedback loop formed "
2630 "between Framebuffer and specified "
2631 "Texture level.");
Jamie Madillf695a3a2017-01-11 17:36:35 -05002632 return false;
2633 }
2634 }
2635
Jamie Madill560a8d82014-05-21 13:06:20 -04002636 return true;
2637}
2638
Jiajia Qind9671222016-11-29 16:30:31 +08002639bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002640{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002641 switch (mode)
2642 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002643 case GL_POINTS:
2644 case GL_LINES:
2645 case GL_LINE_LOOP:
2646 case GL_LINE_STRIP:
2647 case GL_TRIANGLES:
2648 case GL_TRIANGLE_STRIP:
2649 case GL_TRIANGLE_FAN:
2650 break;
2651 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002652 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002653 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002654 }
2655
Jamie Madill250d33f2014-06-06 17:09:03 -04002656 if (count < 0)
2657 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002658 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002659 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002660 }
2661
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002662 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002663
Jamie Madill250d33f2014-06-06 17:09:03 -04002664 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002665 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002666 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002667 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002668 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002669 }
2670
Jamie Madillcbcde722017-01-06 14:50:00 -05002671 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2672 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002673 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002674 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
2675 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002676 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002677 const FramebufferAttachment *dsAttachment =
2678 framebuffer->getStencilOrDepthStencilAttachment();
2679 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002680 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002681 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002682
2683 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2684 bool differentWritemasks =
2685 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2686 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2687 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2688 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2689
2690 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002691 {
Jamie Madillcbcde722017-01-06 14:50:00 -05002692 if (!context->getExtensions().webglCompatibility)
2693 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002694 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2695 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002696 }
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002697 context->handleError(InvalidOperation());
Geoff Lang3a86ad32015-09-01 11:47:05 -04002698 return false;
2699 }
Jamie Madillac528012014-06-20 13:21:23 -04002700 }
2701
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002702 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002703 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002704 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002705 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002706 }
2707
Geoff Lang7dd2e102014-11-10 15:19:26 -05002708 gl::Program *program = state.getProgram();
2709 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002710 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002711 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002712 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002713 }
2714
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002715 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002716 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002717 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002718 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002719 }
2720
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002721 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002722 for (unsigned int uniformBlockIndex = 0;
2723 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002724 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002725 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002726 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002727 const OffsetBindingPointer<Buffer> &uniformBuffer =
2728 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002729
Geoff Lang5d124a62015-09-15 13:03:27 -04002730 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002731 {
2732 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002733 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002734 InvalidOperation()
2735 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002736 return false;
2737 }
2738
Geoff Lang5d124a62015-09-15 13:03:27 -04002739 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002740 if (uniformBufferSize == 0)
2741 {
2742 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002743 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002744 }
2745
Jamie Madill62d31cb2015-09-11 13:25:51 -04002746 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002747 {
2748 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002749 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002750 InvalidOperation()
2751 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002752 return false;
2753 }
2754 }
2755
Geoff Lange0cff192017-05-30 13:04:56 -04002756 // Do some additonal WebGL-specific validation
Jamie Madilla4595b82017-01-11 17:36:34 -05002757 if (context->getExtensions().webglCompatibility)
2758 {
Geoff Lange0cff192017-05-30 13:04:56 -04002759 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002760 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2761 {
2762 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002763 InvalidOperation()
2764 << "Rendering feedback loop formed between Framebuffer and active Texture.");
Jamie Madilla4595b82017-01-11 17:36:34 -05002765 return false;
2766 }
Geoff Lange0cff192017-05-30 13:04:56 -04002767
Geoff Lang9ab5b822017-05-30 16:19:23 -04002768 // Detect that the vertex shader input types match the attribute types
2769 if (!ValidateVertexShaderAttributeTypeMatch(context))
2770 {
2771 return false;
2772 }
2773
Geoff Lange0cff192017-05-30 13:04:56 -04002774 // Detect that the color buffer types match the fragment shader output types
2775 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2776 {
2777 return false;
2778 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002779 }
2780
Jamie Madill250d33f2014-06-06 17:09:03 -04002781 // No-op if zero count
2782 return (count > 0);
2783}
2784
Jamie Madillc1d770e2017-04-13 17:31:24 -04002785bool ValidateDrawArraysCommon(ValidationContext *context,
2786 GLenum mode,
2787 GLint first,
2788 GLsizei count,
2789 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002790{
Jamie Madillfd716582014-06-06 17:09:04 -04002791 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002792 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002793 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002794 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002795 }
2796
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002797 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002798 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002799 if (curTransformFeedback && curTransformFeedback->isActive() &&
2800 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002801 {
2802 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002803 // that does not match the current transform feedback object's draw mode (if transform
2804 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002805 // is active), (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002806 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002807 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002808 }
2809
Jiajia Qind9671222016-11-29 16:30:31 +08002810 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002811 {
2812 return false;
2813 }
2814
Corentin Wallez71168a02016-12-19 15:11:18 -08002815 // Check the computation of maxVertex doesn't overflow.
2816 // - first < 0 or count < 0 have been checked as an error condition
2817 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2818 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2819 ASSERT(count > 0 && first >= 0);
2820 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2821 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002822 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002823 context->handleError(InvalidOperation() << "Integer overflow.");
Corentin Wallez92db6942016-12-09 13:10:36 -05002824 return false;
2825 }
2826
Corentin Wallez71168a02016-12-19 15:11:18 -08002827 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002828 {
2829 return false;
2830 }
2831
2832 return true;
2833}
2834
He Yunchaoced53ae2016-11-29 15:00:51 +08002835bool ValidateDrawArraysInstanced(Context *context,
2836 GLenum mode,
2837 GLint first,
2838 GLsizei count,
2839 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002840{
Corentin Wallez170efbf2017-05-02 13:45:01 -04002841 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04002842 {
2843 return false;
2844 }
2845
Corentin Wallez170efbf2017-05-02 13:45:01 -04002846 return !context->getExtensions().webglCompatibility ||
2847 ValidateDrawInstancedANGLEAndWebGL(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002848}
2849
He Yunchaoced53ae2016-11-29 15:00:51 +08002850bool ValidateDrawArraysInstancedANGLE(Context *context,
2851 GLenum mode,
2852 GLint first,
2853 GLsizei count,
2854 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002855{
Corentin Wallez170efbf2017-05-02 13:45:01 -04002856 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002857 {
2858 return false;
2859 }
2860
Corentin Wallez170efbf2017-05-02 13:45:01 -04002861 return ValidateDrawInstancedANGLEAndWebGL(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002862}
2863
Jiajia Qind9671222016-11-29 16:30:31 +08002864bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002865{
Jamie Madill250d33f2014-06-06 17:09:03 -04002866 switch (type)
2867 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002868 case GL_UNSIGNED_BYTE:
2869 case GL_UNSIGNED_SHORT:
2870 break;
2871 case GL_UNSIGNED_INT:
2872 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2873 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002874 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002875 return false;
2876 }
2877 break;
2878 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002879 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002880 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002881 }
2882
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002883 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002884
2885 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002886 if (curTransformFeedback && curTransformFeedback->isActive() &&
2887 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002888 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002889 // It is an invalid operation to call DrawElements, DrawRangeElements or
2890 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002891 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002892 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002893 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002894 }
2895
Jiajia Qind9671222016-11-29 16:30:31 +08002896 return true;
2897}
2898
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002899bool ValidateDrawElementsCommon(ValidationContext *context,
2900 GLenum mode,
2901 GLsizei count,
2902 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002903 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002904 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002905{
2906 if (!ValidateDrawElementsBase(context, type))
2907 return false;
2908
2909 const State &state = context->getGLState();
2910
Corentin Wallez170efbf2017-05-02 13:45:01 -04002911 if (!ValidateDrawBase(context, mode, count))
2912 {
2913 return false;
2914 }
2915
Jamie Madill250d33f2014-06-06 17:09:03 -04002916 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002917 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002918 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002919 context->handleError(InvalidOperation() << "Index buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -04002920 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002921 }
2922
He Yunchaoced53ae2016-11-29 15:00:51 +08002923 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002924 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002925
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002926 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2927
2928 if (context->getExtensions().webglCompatibility)
2929 {
2930 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2931 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2932 {
2933 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2934 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2935 // data type passed to the call, or an INVALID_OPERATION error is generated.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002936 context->handleError(InvalidOperation()
2937 << "indices must be a multiple of the element type size.");
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002938 return false;
2939 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002940
2941 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2942 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2943 // error is generated.
2944 if (reinterpret_cast<intptr_t>(indices) < 0)
2945 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002946 context->handleError(InvalidValue() << "Offset < 0.");
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002947 return false;
2948 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002949 }
2950
2951 if (context->getExtensions().webglCompatibility ||
2952 !context->getGLState().areClientArraysEnabled())
2953 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002954 if (!elementArrayBuffer && count > 0)
2955 {
2956 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2957 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2958 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002959 context->handleError(InvalidOperation()
2960 << "There is no element array buffer bound and count > 0.");
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002961 return false;
2962 }
2963 }
2964
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002965 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002966 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002967 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002968 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002969 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2970 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2971 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2972 constexpr uint64_t kMaxTypeSize = 8;
2973 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2974 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2975 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002976
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002977 uint64_t typeSize = typeBytes;
2978 uint64_t elementCount = static_cast<uint64_t>(count);
2979 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2980
2981 // Doing the multiplication here is overflow-safe
2982 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2983
2984 // The offset can be any value, check for overflows
2985 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2986 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002987 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002988 context->handleError(InvalidOperation() << "Integer overflow.");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002989 return false;
2990 }
2991
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002992 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2993 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002994 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002995 context->handleError(InvalidOperation()
2996 << "Index buffer is not big enough for the draw.");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002997 return false;
2998 }
2999 }
3000 else if (!indices)
3001 {
3002 // This is an application error that would normally result in a crash,
3003 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003004 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04003005 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003006 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003007 }
3008
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003009 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill2b976812014-08-25 15:47:49 -04003010 // TODO: offer fast path, with disabled index validation.
3011 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003012 const auto &params = context->getParams<HasIndexRange>();
3013 const auto &indexRangeOpt = params.getIndexRange();
3014 if (!indexRangeOpt.valid())
Jamie Madill2b976812014-08-25 15:47:49 -04003015 {
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003016 // Unexpected error.
3017 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003018 }
3019
Jamie Madille79b1e12015-11-04 16:36:37 -05003020 // If we use an index greater than our maximum supported index range, return an error.
3021 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3022 // return an error if possible here.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003023 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
Jamie Madille79b1e12015-11-04 16:36:37 -05003024 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003025 context->handleError(InvalidOperation() << g_ExceedsMaxElementErrorMessage);
Jamie Madille79b1e12015-11-04 16:36:37 -05003026 return false;
3027 }
3028
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003029 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
3030 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003031 {
3032 return false;
3033 }
3034
Geoff Lang3edfe032015-09-04 16:38:24 -04003035 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003036 return (indexRangeOpt.value().vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003037}
3038
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003039bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
3040 GLenum mode,
3041 GLsizei count,
3042 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003043 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003044 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003045{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003046 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003047 {
3048 return false;
3049 }
3050
Corentin Wallez170efbf2017-05-02 13:45:01 -04003051 return !context->getExtensions().webglCompatibility ||
3052 ValidateDrawInstancedANGLEAndWebGL(context);
Jamie Madill250d33f2014-06-06 17:09:03 -04003053}
3054
Geoff Lang3edfe032015-09-04 16:38:24 -04003055bool ValidateDrawElementsInstancedANGLE(Context *context,
3056 GLenum mode,
3057 GLsizei count,
3058 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003059 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003060 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003061{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003062 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003063 {
3064 return false;
3065 }
3066
Corentin Wallez170efbf2017-05-02 13:45:01 -04003067 return ValidateDrawInstancedANGLEAndWebGL(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003068}
3069
He Yunchaoced53ae2016-11-29 15:00:51 +08003070bool ValidateFramebufferTextureBase(Context *context,
3071 GLenum target,
3072 GLenum attachment,
3073 GLuint texture,
3074 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003075{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003076 if (!ValidFramebufferTarget(target))
3077 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003078 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04003079 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003080 }
3081
3082 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003083 {
3084 return false;
3085 }
3086
Jamie Madill55ec3b12014-07-03 10:38:57 -04003087 if (texture != 0)
3088 {
3089 gl::Texture *tex = context->getTexture(texture);
3090
Jamie Madillbe849e42017-05-02 15:49:00 -04003091 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003092 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003093 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003094 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003095 }
3096
3097 if (level < 0)
3098 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003099 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003100 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003101 }
3102 }
3103
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003104 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003105 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003106
Jamie Madill84115c92015-04-23 15:00:07 -04003107 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003108 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003109 context->handleError(InvalidOperation() << "Cannot change default FBO's attachments");
Geoff Langb1196682014-07-23 13:47:29 -04003110 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003111 }
3112
3113 return true;
3114}
3115
Geoff Langb1196682014-07-23 13:47:29 -04003116bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003117{
3118 if (program == 0)
3119 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003120 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003121 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003122 }
3123
Dian Xiang769769a2015-09-09 15:20:08 -07003124 gl::Program *programObject = GetValidProgram(context, program);
3125 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003126 {
3127 return false;
3128 }
3129
Jamie Madill0063c512014-08-25 15:47:53 -04003130 if (!programObject || !programObject->isLinked())
3131 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003132 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003133 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003134 }
3135
Geoff Lang7dd2e102014-11-10 15:19:26 -05003136 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003137 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003138 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003139 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003140 }
3141
Jamie Madill0063c512014-08-25 15:47:53 -04003142 return true;
3143}
3144
Geoff Langf41d0ee2016-10-07 13:04:23 -04003145static bool ValidateSizedGetUniform(Context *context,
3146 GLuint program,
3147 GLint location,
3148 GLsizei bufSize,
3149 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003150{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003151 if (length)
3152 {
3153 *length = 0;
3154 }
3155
Jamie Madill78f41802014-08-25 15:47:55 -04003156 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003157 {
Jamie Madill78f41802014-08-25 15:47:55 -04003158 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003159 }
3160
Geoff Langf41d0ee2016-10-07 13:04:23 -04003161 if (bufSize < 0)
3162 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003163 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003164 return false;
3165 }
3166
Jamie Madilla502c742014-08-28 17:19:13 -04003167 gl::Program *programObject = context->getProgram(program);
3168 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003169
Jamie Madill78f41802014-08-25 15:47:55 -04003170 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003171 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003172 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003173 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003174 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003175 context->handleError(InvalidOperation()
3176 << "bufSize of at least " << requiredBytes << " is required.");
Geoff Langb1196682014-07-23 13:47:29 -04003177 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003178 }
3179
Geoff Langf41d0ee2016-10-07 13:04:23 -04003180 if (length)
3181 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003182 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003183 }
3184
Jamie Madill0063c512014-08-25 15:47:53 -04003185 return true;
3186}
3187
He Yunchaoced53ae2016-11-29 15:00:51 +08003188bool ValidateGetnUniformfvEXT(Context *context,
3189 GLuint program,
3190 GLint location,
3191 GLsizei bufSize,
3192 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003193{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003194 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003195}
3196
He Yunchaoced53ae2016-11-29 15:00:51 +08003197bool ValidateGetnUniformivEXT(Context *context,
3198 GLuint program,
3199 GLint location,
3200 GLsizei bufSize,
3201 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003202{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003203 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3204}
3205
3206bool ValidateGetUniformfvRobustANGLE(Context *context,
3207 GLuint program,
3208 GLint location,
3209 GLsizei bufSize,
3210 GLsizei *length,
3211 GLfloat *params)
3212{
3213 if (!ValidateRobustEntryPoint(context, bufSize))
3214 {
3215 return false;
3216 }
3217
3218 // bufSize is validated in ValidateSizedGetUniform
3219 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3220}
3221
3222bool ValidateGetUniformivRobustANGLE(Context *context,
3223 GLuint program,
3224 GLint location,
3225 GLsizei bufSize,
3226 GLsizei *length,
3227 GLint *params)
3228{
3229 if (!ValidateRobustEntryPoint(context, bufSize))
3230 {
3231 return false;
3232 }
3233
3234 // bufSize is validated in ValidateSizedGetUniform
3235 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3236}
3237
3238bool ValidateGetUniformuivRobustANGLE(Context *context,
3239 GLuint program,
3240 GLint location,
3241 GLsizei bufSize,
3242 GLsizei *length,
3243 GLuint *params)
3244{
3245 if (!ValidateRobustEntryPoint(context, bufSize))
3246 {
3247 return false;
3248 }
3249
3250 if (context->getClientMajorVersion() < 3)
3251 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003252 context->handleError(InvalidOperation() << "Entry point requires at least OpenGL ES 3.0.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003253 return false;
3254 }
3255
3256 // bufSize is validated in ValidateSizedGetUniform
3257 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003258}
3259
He Yunchaoced53ae2016-11-29 15:00:51 +08003260bool ValidateDiscardFramebufferBase(Context *context,
3261 GLenum target,
3262 GLsizei numAttachments,
3263 const GLenum *attachments,
3264 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003265{
3266 if (numAttachments < 0)
3267 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003268 context->handleError(InvalidValue() << "numAttachments must not be less than zero");
Austin Kinross08332632015-05-05 13:35:47 -07003269 return false;
3270 }
3271
3272 for (GLsizei i = 0; i < numAttachments; ++i)
3273 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003274 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003275 {
3276 if (defaultFramebuffer)
3277 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003278 context->handleError(InvalidEnum()
3279 << "Invalid attachment when the default framebuffer is bound");
Austin Kinross08332632015-05-05 13:35:47 -07003280 return false;
3281 }
3282
3283 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3284 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003285 context->handleError(InvalidOperation() << "Requested color attachment is "
3286 "greater than the maximum supported "
3287 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003288 return false;
3289 }
3290 }
3291 else
3292 {
3293 switch (attachments[i])
3294 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003295 case GL_DEPTH_ATTACHMENT:
3296 case GL_STENCIL_ATTACHMENT:
3297 case GL_DEPTH_STENCIL_ATTACHMENT:
3298 if (defaultFramebuffer)
3299 {
3300 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003301 InvalidEnum()
3302 << "Invalid attachment when the default framebuffer is bound");
He Yunchaoced53ae2016-11-29 15:00:51 +08003303 return false;
3304 }
3305 break;
3306 case GL_COLOR:
3307 case GL_DEPTH:
3308 case GL_STENCIL:
3309 if (!defaultFramebuffer)
3310 {
3311 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003312 InvalidEnum()
3313 << "Invalid attachment when the default framebuffer is not bound");
He Yunchaoced53ae2016-11-29 15:00:51 +08003314 return false;
3315 }
3316 break;
3317 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003318 context->handleError(InvalidEnum() << "Invalid attachment");
Austin Kinross08332632015-05-05 13:35:47 -07003319 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003320 }
3321 }
3322 }
3323
3324 return true;
3325}
3326
Austin Kinross6ee1e782015-05-29 17:05:37 -07003327bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3328{
3329 // Note that debug marker calls must not set error state
3330
3331 if (length < 0)
3332 {
3333 return false;
3334 }
3335
3336 if (marker == nullptr)
3337 {
3338 return false;
3339 }
3340
3341 return true;
3342}
3343
3344bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3345{
3346 // Note that debug marker calls must not set error state
3347
3348 if (length < 0)
3349 {
3350 return false;
3351 }
3352
3353 if (length > 0 && marker == nullptr)
3354 {
3355 return false;
3356 }
3357
3358 return true;
3359}
3360
Geoff Langdcab33b2015-07-21 13:03:16 -04003361bool ValidateEGLImageTargetTexture2DOES(Context *context,
3362 egl::Display *display,
3363 GLenum target,
3364 egl::Image *image)
3365{
Geoff Langa8406172015-07-21 16:53:39 -04003366 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3367 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003368 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003369 return false;
3370 }
3371
3372 switch (target)
3373 {
3374 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003375 if (!context->getExtensions().eglImage)
3376 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003377 context->handleError(InvalidEnum()
3378 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003379 }
3380 break;
3381
3382 case GL_TEXTURE_EXTERNAL_OES:
3383 if (!context->getExtensions().eglImageExternal)
3384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003385 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3386 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003387 }
Geoff Langa8406172015-07-21 16:53:39 -04003388 break;
3389
3390 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003391 context->handleError(InvalidEnum() << "invalid texture target.");
Geoff Langa8406172015-07-21 16:53:39 -04003392 return false;
3393 }
3394
3395 if (!display->isValidImage(image))
3396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003397 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003398 return false;
3399 }
3400
3401 if (image->getSamples() > 0)
3402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003403 context->handleError(InvalidOperation()
3404 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003405 return false;
3406 }
3407
Geoff Langca271392017-04-05 12:30:00 -04003408 const TextureCaps &textureCaps =
3409 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003410 if (!textureCaps.texturable)
3411 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003412 context->handleError(InvalidOperation()
3413 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003414 return false;
3415 }
3416
Geoff Langdcab33b2015-07-21 13:03:16 -04003417 return true;
3418}
3419
3420bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3421 egl::Display *display,
3422 GLenum target,
3423 egl::Image *image)
3424{
Geoff Langa8406172015-07-21 16:53:39 -04003425 if (!context->getExtensions().eglImage)
3426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003427 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003428 return false;
3429 }
3430
3431 switch (target)
3432 {
3433 case GL_RENDERBUFFER:
3434 break;
3435
3436 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003437 context->handleError(InvalidEnum() << "invalid renderbuffer target.");
Geoff Langa8406172015-07-21 16:53:39 -04003438 return false;
3439 }
3440
3441 if (!display->isValidImage(image))
3442 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003443 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003444 return false;
3445 }
3446
Geoff Langca271392017-04-05 12:30:00 -04003447 const TextureCaps &textureCaps =
3448 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003449 if (!textureCaps.renderable)
3450 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003451 context->handleError(InvalidOperation()
3452 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003453 return false;
3454 }
3455
Geoff Langdcab33b2015-07-21 13:03:16 -04003456 return true;
3457}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003458
3459bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3460{
Geoff Lang36167ab2015-12-07 10:27:14 -05003461 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003462 {
3463 // The default VAO should always exist
3464 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003465 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003466 return false;
3467 }
3468
3469 return true;
3470}
3471
Geoff Langc5629752015-12-07 16:29:04 -05003472bool ValidateProgramBinaryBase(Context *context,
3473 GLuint program,
3474 GLenum binaryFormat,
3475 const void *binary,
3476 GLint length)
3477{
3478 Program *programObject = GetValidProgram(context, program);
3479 if (programObject == nullptr)
3480 {
3481 return false;
3482 }
3483
3484 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3485 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3486 programBinaryFormats.end())
3487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003488 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003489 return false;
3490 }
3491
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003492 if (context->hasActiveTransformFeedback(program))
3493 {
3494 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003495 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3496 "is associated with an active transform "
3497 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003498 return false;
3499 }
3500
Geoff Langc5629752015-12-07 16:29:04 -05003501 return true;
3502}
3503
3504bool ValidateGetProgramBinaryBase(Context *context,
3505 GLuint program,
3506 GLsizei bufSize,
3507 GLsizei *length,
3508 GLenum *binaryFormat,
3509 void *binary)
3510{
3511 Program *programObject = GetValidProgram(context, program);
3512 if (programObject == nullptr)
3513 {
3514 return false;
3515 }
3516
3517 if (!programObject->isLinked())
3518 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003519 context->handleError(InvalidOperation() << "Program is not linked.");
Geoff Langc5629752015-12-07 16:29:04 -05003520 return false;
3521 }
3522
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003523 if (context->getCaps().programBinaryFormats.empty())
3524 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003525 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003526 return false;
3527 }
3528
Geoff Langc5629752015-12-07 16:29:04 -05003529 return true;
3530}
Jamie Madillc29968b2016-01-20 11:17:23 -05003531
Jamie Madillc29968b2016-01-20 11:17:23 -05003532bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3533{
3534 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3535 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3536 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003537 context->handleError(InvalidValue()
3538 << "n must be non-negative and no greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003539 return false;
3540 }
3541
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003542 ASSERT(context->getGLState().getDrawFramebuffer());
3543 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003544 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3545
3546 // This should come first before the check for the default frame buffer
3547 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3548 // rather than INVALID_OPERATION
3549 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3550 {
3551 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3552
3553 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003554 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3555 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003556 {
3557 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003558 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3559 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3560 // 3.1 is still a bit ambiguous about the error, but future specs are
3561 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003562 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003563 return false;
3564 }
3565 else if (bufs[colorAttachment] >= maxColorAttachment)
3566 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003567 context->handleError(InvalidOperation()
3568 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003569 return false;
3570 }
3571 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3572 frameBufferId != 0)
3573 {
3574 // INVALID_OPERATION-GL is bound to buffer and ith argument
3575 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003576 context->handleError(InvalidOperation()
3577 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003578 return false;
3579 }
3580 }
3581
3582 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3583 // and n is not 1 or bufs is bound to value other than BACK and NONE
3584 if (frameBufferId == 0)
3585 {
3586 if (n != 1)
3587 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003588 context->handleError(InvalidOperation()
3589 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003590 return false;
3591 }
3592
3593 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3594 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003595 context->handleError(
3596 InvalidOperation()
3597 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003598 return false;
3599 }
3600 }
3601
3602 return true;
3603}
3604
Geoff Lang496c02d2016-10-20 11:38:11 -07003605bool ValidateGetBufferPointervBase(Context *context,
3606 GLenum target,
3607 GLenum pname,
3608 GLsizei *length,
3609 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003610{
Geoff Lang496c02d2016-10-20 11:38:11 -07003611 if (length)
3612 {
3613 *length = 0;
3614 }
3615
3616 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3617 {
3618 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003619 InvalidOperation()
3620 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003621 return false;
3622 }
3623
Olli Etuaho4f667482016-03-30 15:56:35 +03003624 if (!ValidBufferTarget(context, target))
3625 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003626 context->handleError(InvalidEnum() << "Buffer target not valid: 0x" << std::hex
3627 << std::uppercase << target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003628 return false;
3629 }
3630
Geoff Lang496c02d2016-10-20 11:38:11 -07003631 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003632 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003633 case GL_BUFFER_MAP_POINTER:
3634 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003635
Geoff Lang496c02d2016-10-20 11:38:11 -07003636 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003637 context->handleError(InvalidEnum() << "Unknown pname.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003638 return false;
3639 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003640
3641 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3642 // target bound to zero generate an INVALID_OPERATION error."
3643 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003644 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003646 context->handleError(InvalidOperation()
3647 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003648 return false;
3649 }
3650
Geoff Lang496c02d2016-10-20 11:38:11 -07003651 if (length)
3652 {
3653 *length = 1;
3654 }
3655
Olli Etuaho4f667482016-03-30 15:56:35 +03003656 return true;
3657}
3658
3659bool ValidateUnmapBufferBase(Context *context, GLenum target)
3660{
3661 if (!ValidBufferTarget(context, target))
3662 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003663 context->handleError(InvalidEnum() << "Invalid buffer target.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003664 return false;
3665 }
3666
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003667 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003668
3669 if (buffer == nullptr || !buffer->isMapped())
3670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003671 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003672 return false;
3673 }
3674
3675 return true;
3676}
3677
3678bool ValidateMapBufferRangeBase(Context *context,
3679 GLenum target,
3680 GLintptr offset,
3681 GLsizeiptr length,
3682 GLbitfield access)
3683{
3684 if (!ValidBufferTarget(context, target))
3685 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003686 context->handleError(InvalidEnum() << "Invalid buffer target.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003687 return false;
3688 }
3689
3690 if (offset < 0 || length < 0)
3691 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003692 context->handleError(InvalidValue() << "Invalid offset or length.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003693 return false;
3694 }
3695
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003696 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003697
3698 if (!buffer)
3699 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003700 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003701 return false;
3702 }
3703
3704 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003705 CheckedNumeric<size_t> checkedOffset(offset);
3706 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003707
Jamie Madille2e406c2016-06-02 13:04:10 -04003708 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003709 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003710 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003711 return false;
3712 }
3713
3714 // Check for invalid bits in the mask
3715 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3716 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3717 GL_MAP_UNSYNCHRONIZED_BIT;
3718
3719 if (access & ~(allAccessBits))
3720 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003721 context->handleError(InvalidValue()
3722 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003723 return false;
3724 }
3725
3726 if (length == 0)
3727 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003728 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003729 return false;
3730 }
3731
3732 if (buffer->isMapped())
3733 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003734 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003735 return false;
3736 }
3737
3738 // Check for invalid bit combinations
3739 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3740 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003741 context->handleError(InvalidOperation()
3742 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003743 return false;
3744 }
3745
3746 GLbitfield writeOnlyBits =
3747 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3748
3749 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3750 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003751 context->handleError(InvalidOperation()
3752 << "Invalid access bits when mapping buffer for reading: 0x"
3753 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003754 return false;
3755 }
3756
3757 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3758 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003759 context->handleError(
3760 InvalidOperation()
3761 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003762 return false;
3763 }
3764 return true;
3765}
3766
3767bool ValidateFlushMappedBufferRangeBase(Context *context,
3768 GLenum target,
3769 GLintptr offset,
3770 GLsizeiptr length)
3771{
3772 if (offset < 0 || length < 0)
3773 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003774 context->handleError(InvalidValue() << "Invalid offset/length parameters.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003775 return false;
3776 }
3777
3778 if (!ValidBufferTarget(context, target))
3779 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003780 context->handleError(InvalidEnum() << "Invalid buffer target.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003781 return false;
3782 }
3783
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003784 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003785
3786 if (buffer == nullptr)
3787 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003788 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003789 return false;
3790 }
3791
3792 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3793 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003794 context->handleError(InvalidOperation()
3795 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003796 return false;
3797 }
3798
3799 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003800 CheckedNumeric<size_t> checkedOffset(offset);
3801 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003802
Jamie Madille2e406c2016-06-02 13:04:10 -04003803 if (!checkedSize.IsValid() ||
3804 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003805 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003806 context->handleError(InvalidValue()
3807 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003808 return false;
3809 }
3810
3811 return true;
3812}
3813
Olli Etuaho41997e72016-03-10 13:38:39 +02003814bool ValidateGenOrDelete(Context *context, GLint n)
3815{
3816 if (n < 0)
3817 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003818 context->handleError(InvalidValue() << "n < 0");
Olli Etuaho41997e72016-03-10 13:38:39 +02003819 return false;
3820 }
3821 return true;
3822}
3823
Geoff Langff5b2d52016-09-07 11:32:23 -04003824bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3825{
3826 if (!context->getExtensions().robustClientMemory)
3827 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003828 context->handleError(InvalidOperation()
3829 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003830 return false;
3831 }
3832
3833 if (bufSize < 0)
3834 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003835 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003836 return false;
3837 }
3838
3839 return true;
3840}
3841
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003842bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3843{
3844 if (bufSize < numParams)
3845 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003846 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3847 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003848 return false;
3849 }
3850
3851 return true;
3852}
3853
Jamie Madillbe849e42017-05-02 15:49:00 -04003854bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3855 GLenum target,
3856 GLenum attachment,
3857 GLenum pname,
3858 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003859{
3860 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
Yunchao He33151a52017-04-13 09:58:17 +08003861 if (numParams)
3862 {
3863 *numParams = 1;
3864 }
Geoff Langff5b2d52016-09-07 11:32:23 -04003865
3866 if (!ValidFramebufferTarget(target))
3867 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003868 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003869 return false;
3870 }
3871
3872 int clientVersion = context->getClientMajorVersion();
3873
3874 switch (pname)
3875 {
3876 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3877 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3878 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3879 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3880 break;
3881
3882 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3883 if (clientVersion < 3 && !context->getExtensions().sRGB)
3884 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003885 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003886 return false;
3887 }
3888 break;
3889
3890 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3891 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3892 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3893 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3894 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3895 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3896 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3897 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3898 if (clientVersion < 3)
3899 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003900 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003901 return false;
3902 }
3903 break;
3904
3905 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003906 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003907 return false;
3908 }
3909
3910 // Determine if the attachment is a valid enum
3911 switch (attachment)
3912 {
3913 case GL_BACK:
3914 case GL_FRONT:
3915 case GL_DEPTH:
3916 case GL_STENCIL:
3917 case GL_DEPTH_STENCIL_ATTACHMENT:
3918 if (clientVersion < 3)
3919 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003920 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003921 return false;
3922 }
3923 break;
3924
3925 case GL_DEPTH_ATTACHMENT:
3926 case GL_STENCIL_ATTACHMENT:
3927 break;
3928
3929 default:
3930 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
3931 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3932 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003933 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003934 return false;
3935 }
3936 break;
3937 }
3938
3939 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3940 ASSERT(framebuffer);
3941
3942 if (framebuffer->id() == 0)
3943 {
3944 if (clientVersion < 3)
3945 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003946 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003947 return false;
3948 }
3949
3950 switch (attachment)
3951 {
3952 case GL_BACK:
3953 case GL_DEPTH:
3954 case GL_STENCIL:
3955 break;
3956
3957 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003958 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003959 return false;
3960 }
3961 }
3962 else
3963 {
3964 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3965 {
3966 // Valid attachment query
3967 }
3968 else
3969 {
3970 switch (attachment)
3971 {
3972 case GL_DEPTH_ATTACHMENT:
3973 case GL_STENCIL_ATTACHMENT:
3974 break;
3975
3976 case GL_DEPTH_STENCIL_ATTACHMENT:
3977 if (!framebuffer->hasValidDepthStencil())
3978 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003979 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003980 return false;
3981 }
3982 break;
3983
3984 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003985 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003986 return false;
3987 }
3988 }
3989 }
3990
3991 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3992 if (attachmentObject)
3993 {
3994 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3995 attachmentObject->type() == GL_TEXTURE ||
3996 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3997
3998 switch (pname)
3999 {
4000 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4001 if (attachmentObject->type() != GL_RENDERBUFFER &&
4002 attachmentObject->type() != GL_TEXTURE)
4003 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004004 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004005 return false;
4006 }
4007 break;
4008
4009 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4010 if (attachmentObject->type() != GL_TEXTURE)
4011 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004012 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004013 return false;
4014 }
4015 break;
4016
4017 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4018 if (attachmentObject->type() != GL_TEXTURE)
4019 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004020 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004021 return false;
4022 }
4023 break;
4024
4025 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4026 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4027 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004028 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004029 return false;
4030 }
4031 break;
4032
4033 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4034 if (attachmentObject->type() != GL_TEXTURE)
4035 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004036 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004037 return false;
4038 }
4039 break;
4040
4041 default:
4042 break;
4043 }
4044 }
4045 else
4046 {
4047 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4048 // is NONE, then querying any other pname will generate INVALID_ENUM.
4049
4050 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4051 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4052 // INVALID_OPERATION for all other pnames
4053
4054 switch (pname)
4055 {
4056 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4057 break;
4058
4059 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4060 if (clientVersion < 3)
4061 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004062 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004063 return false;
4064 }
4065 break;
4066
4067 default:
4068 if (clientVersion < 3)
4069 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004070 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004071 return false;
4072 }
4073 else
4074 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004075 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004076 return false;
4077 }
4078 }
4079 }
4080
4081 return true;
4082}
4083
4084bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4085 GLenum target,
4086 GLenum attachment,
4087 GLenum pname,
4088 GLsizei bufSize,
4089 GLsizei *numParams)
4090{
4091 if (!ValidateRobustEntryPoint(context, bufSize))
4092 {
4093 return false;
4094 }
4095
Jamie Madillbe849e42017-05-02 15:49:00 -04004096 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4097 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004098 {
4099 return false;
4100 }
4101
4102 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4103 {
4104 return false;
4105 }
4106
4107 return true;
4108}
4109
Geoff Langff5b2d52016-09-07 11:32:23 -04004110bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4111 GLenum target,
4112 GLenum pname,
4113 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004114 GLsizei *length,
4115 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004116{
4117 if (!ValidateRobustEntryPoint(context, bufSize))
4118 {
4119 return false;
4120 }
4121
Geoff Langebebe1c2016-10-14 12:01:31 -04004122 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004123 {
4124 return false;
4125 }
4126
Geoff Langebebe1c2016-10-14 12:01:31 -04004127 if (!ValidateRobustBufferSize(context, bufSize, *length))
4128 {
4129 return false;
4130 }
4131
4132 return true;
4133}
4134
4135bool ValidateGetBufferParameteri64v(ValidationContext *context,
4136 GLenum target,
4137 GLenum pname,
4138 GLint64 *params)
4139{
4140 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4141}
4142
4143bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4144 GLenum target,
4145 GLenum pname,
4146 GLsizei bufSize,
4147 GLsizei *length,
4148 GLint64 *params)
4149{
4150 if (!ValidateRobustEntryPoint(context, bufSize))
4151 {
4152 return false;
4153 }
4154
4155 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4156 {
4157 return false;
4158 }
4159
4160 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004161 {
4162 return false;
4163 }
4164
4165 return true;
4166}
4167
Jamie Madillbe849e42017-05-02 15:49:00 -04004168bool ValidateGetProgramivBase(ValidationContext *context,
4169 GLuint program,
4170 GLenum pname,
4171 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004172{
4173 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004174 if (numParams)
4175 {
4176 *numParams = 1;
4177 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004178
4179 Program *programObject = GetValidProgram(context, program);
4180 if (!programObject)
4181 {
4182 return false;
4183 }
4184
4185 switch (pname)
4186 {
4187 case GL_DELETE_STATUS:
4188 case GL_LINK_STATUS:
4189 case GL_VALIDATE_STATUS:
4190 case GL_INFO_LOG_LENGTH:
4191 case GL_ATTACHED_SHADERS:
4192 case GL_ACTIVE_ATTRIBUTES:
4193 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4194 case GL_ACTIVE_UNIFORMS:
4195 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4196 break;
4197
4198 case GL_PROGRAM_BINARY_LENGTH:
4199 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4200 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004201 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4202 "requires GL_OES_get_program_binary or "
4203 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004204 return false;
4205 }
4206 break;
4207
4208 case GL_ACTIVE_UNIFORM_BLOCKS:
4209 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4210 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4211 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4212 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4213 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4214 if (context->getClientMajorVersion() < 3)
4215 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004216 context->handleError(InvalidEnum() << "Querying requires at least ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004217 return false;
4218 }
4219 break;
4220
Yunchao He61afff12017-03-14 15:34:03 +08004221 case GL_PROGRAM_SEPARABLE:
4222 if (context->getClientVersion() < Version(3, 1))
4223 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004224 context->handleError(InvalidEnum() << "Querying requires at least ES 3.1.");
Yunchao He61afff12017-03-14 15:34:03 +08004225 return false;
4226 }
4227 break;
4228
Geoff Langff5b2d52016-09-07 11:32:23 -04004229 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004230 context->handleError(InvalidEnum() << "Unknown parameter name.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004231 return false;
4232 }
4233
4234 return true;
4235}
4236
4237bool ValidateGetProgramivRobustANGLE(Context *context,
4238 GLuint program,
4239 GLenum pname,
4240 GLsizei bufSize,
4241 GLsizei *numParams)
4242{
4243 if (!ValidateRobustEntryPoint(context, bufSize))
4244 {
4245 return false;
4246 }
4247
Jamie Madillbe849e42017-05-02 15:49:00 -04004248 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004249 {
4250 return false;
4251 }
4252
4253 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4254 {
4255 return false;
4256 }
4257
4258 return true;
4259}
4260
Geoff Lang740d9022016-10-07 11:20:52 -04004261bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4262 GLenum target,
4263 GLenum pname,
4264 GLsizei bufSize,
4265 GLsizei *length,
4266 GLint *params)
4267{
4268 if (!ValidateRobustEntryPoint(context, bufSize))
4269 {
4270 return false;
4271 }
4272
4273 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4274 {
4275 return false;
4276 }
4277
4278 if (!ValidateRobustBufferSize(context, bufSize, *length))
4279 {
4280 return false;
4281 }
4282
4283 return true;
4284}
4285
Geoff Langd7d0ed32016-10-07 11:33:51 -04004286bool ValidateGetShaderivRobustANGLE(Context *context,
4287 GLuint shader,
4288 GLenum pname,
4289 GLsizei bufSize,
4290 GLsizei *length,
4291 GLint *params)
4292{
4293 if (!ValidateRobustEntryPoint(context, bufSize))
4294 {
4295 return false;
4296 }
4297
4298 if (!ValidateGetShaderivBase(context, shader, pname, length))
4299 {
4300 return false;
4301 }
4302
4303 if (!ValidateRobustBufferSize(context, bufSize, *length))
4304 {
4305 return false;
4306 }
4307
4308 return true;
4309}
4310
Geoff Langc1984ed2016-10-07 12:41:00 -04004311bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4312 GLenum target,
4313 GLenum pname,
4314 GLsizei bufSize,
4315 GLsizei *length,
4316 GLfloat *params)
4317{
4318 if (!ValidateRobustEntryPoint(context, bufSize))
4319 {
4320 return false;
4321 }
4322
4323 if (!ValidateGetTexParameterBase(context, target, pname, length))
4324 {
4325 return false;
4326 }
4327
4328 if (!ValidateRobustBufferSize(context, bufSize, *length))
4329 {
4330 return false;
4331 }
4332
4333 return true;
4334}
4335
Geoff Langc1984ed2016-10-07 12:41:00 -04004336bool ValidateGetTexParameterivRobustANGLE(Context *context,
4337 GLenum target,
4338 GLenum pname,
4339 GLsizei bufSize,
4340 GLsizei *length,
4341 GLint *params)
4342{
4343 if (!ValidateRobustEntryPoint(context, bufSize))
4344 {
4345 return false;
4346 }
4347
4348 if (!ValidateGetTexParameterBase(context, target, pname, length))
4349 {
4350 return false;
4351 }
4352
4353 if (!ValidateRobustBufferSize(context, bufSize, *length))
4354 {
4355 return false;
4356 }
4357
4358 return true;
4359}
4360
Geoff Langc1984ed2016-10-07 12:41:00 -04004361bool ValidateTexParameterfvRobustANGLE(Context *context,
4362 GLenum target,
4363 GLenum pname,
4364 GLsizei bufSize,
4365 const GLfloat *params)
4366{
4367 if (!ValidateRobustEntryPoint(context, bufSize))
4368 {
4369 return false;
4370 }
4371
4372 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4373}
4374
Geoff Langc1984ed2016-10-07 12:41:00 -04004375bool ValidateTexParameterivRobustANGLE(Context *context,
4376 GLenum target,
4377 GLenum pname,
4378 GLsizei bufSize,
4379 const GLint *params)
4380{
4381 if (!ValidateRobustEntryPoint(context, bufSize))
4382 {
4383 return false;
4384 }
4385
4386 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4387}
4388
4389bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4390{
4391 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4392}
4393
4394bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4395 GLuint sampler,
4396 GLenum pname,
4397 GLuint bufSize,
4398 GLsizei *length,
4399 GLfloat *params)
4400{
4401 if (!ValidateRobustEntryPoint(context, bufSize))
4402 {
4403 return false;
4404 }
4405
4406 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4407 {
4408 return false;
4409 }
4410
4411 if (!ValidateRobustBufferSize(context, bufSize, *length))
4412 {
4413 return false;
4414 }
4415
4416 return true;
4417}
4418
4419bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4420{
4421 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4422}
4423
4424bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4425 GLuint sampler,
4426 GLenum pname,
4427 GLuint bufSize,
4428 GLsizei *length,
4429 GLint *params)
4430{
4431 if (!ValidateRobustEntryPoint(context, bufSize))
4432 {
4433 return false;
4434 }
4435
4436 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4437 {
4438 return false;
4439 }
4440
4441 if (!ValidateRobustBufferSize(context, bufSize, *length))
4442 {
4443 return false;
4444 }
4445
4446 return true;
4447}
4448
4449bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4450{
4451 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4452}
4453
4454bool ValidateSamplerParameterfv(Context *context,
4455 GLuint sampler,
4456 GLenum pname,
4457 const GLfloat *params)
4458{
4459 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4460}
4461
4462bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4463 GLuint sampler,
4464 GLenum pname,
4465 GLsizei bufSize,
4466 const GLfloat *params)
4467{
4468 if (!ValidateRobustEntryPoint(context, bufSize))
4469 {
4470 return false;
4471 }
4472
4473 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4474}
4475
4476bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4477{
4478 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4479}
4480
4481bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4482{
4483 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4484}
4485
4486bool ValidateSamplerParameterivRobustANGLE(Context *context,
4487 GLuint sampler,
4488 GLenum pname,
4489 GLsizei bufSize,
4490 const GLint *params)
4491{
4492 if (!ValidateRobustEntryPoint(context, bufSize))
4493 {
4494 return false;
4495 }
4496
4497 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4498}
4499
Geoff Lang0b031062016-10-13 14:30:04 -04004500bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4501 GLuint index,
4502 GLenum pname,
4503 GLsizei bufSize,
4504 GLsizei *length,
4505 GLfloat *params)
4506{
4507 if (!ValidateRobustEntryPoint(context, bufSize))
4508 {
4509 return false;
4510 }
4511
4512 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4513 {
4514 return false;
4515 }
4516
4517 if (!ValidateRobustBufferSize(context, bufSize, *length))
4518 {
4519 return false;
4520 }
4521
4522 return true;
4523}
4524
Geoff Lang0b031062016-10-13 14:30:04 -04004525bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4526 GLuint index,
4527 GLenum pname,
4528 GLsizei bufSize,
4529 GLsizei *length,
4530 GLint *params)
4531{
4532 if (!ValidateRobustEntryPoint(context, bufSize))
4533 {
4534 return false;
4535 }
4536
4537 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4538 {
4539 return false;
4540 }
4541
4542 if (!ValidateRobustBufferSize(context, bufSize, *length))
4543 {
4544 return false;
4545 }
4546
4547 return true;
4548}
4549
Geoff Lang0b031062016-10-13 14:30:04 -04004550bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4551 GLuint index,
4552 GLenum pname,
4553 GLsizei bufSize,
4554 GLsizei *length,
4555 void **pointer)
4556{
4557 if (!ValidateRobustEntryPoint(context, bufSize))
4558 {
4559 return false;
4560 }
4561
4562 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4563 {
4564 return false;
4565 }
4566
4567 if (!ValidateRobustBufferSize(context, bufSize, *length))
4568 {
4569 return false;
4570 }
4571
4572 return true;
4573}
4574
4575bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4576{
4577 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4578}
4579
4580bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4581 GLuint index,
4582 GLenum pname,
4583 GLsizei bufSize,
4584 GLsizei *length,
4585 GLint *params)
4586{
4587 if (!ValidateRobustEntryPoint(context, bufSize))
4588 {
4589 return false;
4590 }
4591
4592 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4593 {
4594 return false;
4595 }
4596
4597 if (!ValidateRobustBufferSize(context, bufSize, *length))
4598 {
4599 return false;
4600 }
4601
4602 return true;
4603}
4604
4605bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4606{
4607 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4608}
4609
4610bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4611 GLuint index,
4612 GLenum pname,
4613 GLsizei bufSize,
4614 GLsizei *length,
4615 GLuint *params)
4616{
4617 if (!ValidateRobustEntryPoint(context, bufSize))
4618 {
4619 return false;
4620 }
4621
4622 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4623 {
4624 return false;
4625 }
4626
4627 if (!ValidateRobustBufferSize(context, bufSize, *length))
4628 {
4629 return false;
4630 }
4631
4632 return true;
4633}
4634
Geoff Lang6899b872016-10-14 11:30:13 -04004635bool ValidateGetActiveUniformBlockiv(Context *context,
4636 GLuint program,
4637 GLuint uniformBlockIndex,
4638 GLenum pname,
4639 GLint *params)
4640{
4641 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
4642}
4643
4644bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4645 GLuint program,
4646 GLuint uniformBlockIndex,
4647 GLenum pname,
4648 GLsizei bufSize,
4649 GLsizei *length,
4650 GLint *params)
4651{
4652 if (!ValidateRobustEntryPoint(context, bufSize))
4653 {
4654 return false;
4655 }
4656
4657 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4658 {
4659 return false;
4660 }
4661
4662 if (!ValidateRobustBufferSize(context, bufSize, *length))
4663 {
4664 return false;
4665 }
4666
4667 return true;
4668}
4669
Geoff Lang0a9661f2016-10-20 10:59:20 -07004670bool ValidateGetInternalFormativ(Context *context,
4671 GLenum target,
4672 GLenum internalformat,
4673 GLenum pname,
4674 GLsizei bufSize,
4675 GLint *params)
4676{
4677 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4678 nullptr);
4679}
4680
4681bool ValidateGetInternalFormativRobustANGLE(Context *context,
4682 GLenum target,
4683 GLenum internalformat,
4684 GLenum pname,
4685 GLsizei bufSize,
4686 GLsizei *length,
4687 GLint *params)
4688{
4689 if (!ValidateRobustEntryPoint(context, bufSize))
4690 {
4691 return false;
4692 }
4693
4694 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4695 {
4696 return false;
4697 }
4698
4699 if (!ValidateRobustBufferSize(context, bufSize, *length))
4700 {
4701 return false;
4702 }
4703
4704 return true;
4705}
4706
Shao80957d92017-02-20 21:25:59 +08004707bool ValidateVertexFormatBase(ValidationContext *context,
4708 GLuint attribIndex,
4709 GLint size,
4710 GLenum type,
4711 GLboolean pureInteger)
4712{
4713 const Caps &caps = context->getCaps();
4714 if (attribIndex >= caps.maxVertexAttributes)
4715 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004716 context->handleError(InvalidValue()
4717 << "attribindex must be smaller than MAX_VERTEX_ATTRIBS.");
Shao80957d92017-02-20 21:25:59 +08004718 return false;
4719 }
4720
4721 if (size < 1 || size > 4)
4722 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004723 context->handleError(InvalidValue() << "size must be between one and four.");
Shao80957d92017-02-20 21:25:59 +08004724 }
4725
4726 switch (type)
4727 {
4728 case GL_BYTE:
4729 case GL_UNSIGNED_BYTE:
4730 case GL_SHORT:
4731 case GL_UNSIGNED_SHORT:
4732 break;
4733
4734 case GL_INT:
4735 case GL_UNSIGNED_INT:
4736 if (context->getClientMajorVersion() < 3)
4737 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004738 context->handleError(InvalidEnum()
4739 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004740 return false;
4741 }
4742 break;
4743
4744 case GL_FIXED:
4745 case GL_FLOAT:
4746 if (pureInteger)
4747 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004748 context->handleError(InvalidEnum() << "Type is not integer.");
Shao80957d92017-02-20 21:25:59 +08004749 return false;
4750 }
4751 break;
4752
4753 case GL_HALF_FLOAT:
4754 if (context->getClientMajorVersion() < 3)
4755 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004756 context->handleError(InvalidEnum()
4757 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004758 return false;
4759 }
4760 if (pureInteger)
4761 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004762 context->handleError(InvalidEnum() << "Type is not integer.");
Shao80957d92017-02-20 21:25:59 +08004763 return false;
4764 }
4765 break;
4766
4767 case GL_INT_2_10_10_10_REV:
4768 case GL_UNSIGNED_INT_2_10_10_10_REV:
4769 if (context->getClientMajorVersion() < 3)
4770 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004771 context->handleError(InvalidEnum()
4772 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004773 return false;
4774 }
4775 if (pureInteger)
4776 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004777 context->handleError(InvalidEnum() << "Type is not integer.");
Shao80957d92017-02-20 21:25:59 +08004778 return false;
4779 }
4780 if (size != 4)
4781 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004782 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4783 "UNSIGNED_INT_2_10_10_10_REV and "
4784 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004785 return false;
4786 }
4787 break;
4788
4789 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004790 context->handleError(InvalidEnum() << "Invalid vertex type.");
Shao80957d92017-02-20 21:25:59 +08004791 return false;
4792 }
4793
4794 return true;
4795}
4796
Geoff Lang76e65652017-03-27 14:58:02 -04004797// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4798// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4799// specified clear value and the type of a buffer that is being cleared generates an
4800// INVALID_OPERATION error instead of producing undefined results
4801bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4802 GLint drawbuffer,
4803 const GLenum *validComponentTypes,
4804 size_t validComponentTypeCount)
4805{
4806 const FramebufferAttachment *attachment =
4807 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4808 if (attachment)
4809 {
4810 GLenum componentType = attachment->getFormat().info->componentType;
4811 const GLenum *end = validComponentTypes + validComponentTypeCount;
4812 if (std::find(validComponentTypes, end, componentType) == end)
4813 {
4814 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004815 InvalidOperation()
4816 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004817 return false;
4818 }
4819 }
4820
4821 return true;
4822}
4823
Corentin Wallezb2931602017-04-11 15:58:57 -04004824bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4825 GLsizei imageSize,
4826 GLsizei dataSize)
4827{
4828 if (!ValidateRobustEntryPoint(context, dataSize))
4829 {
4830 return false;
4831 }
4832
4833 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
4834 if (pixelUnpackBuffer == nullptr)
4835 {
4836 if (dataSize < imageSize)
4837 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004838 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004839 }
4840 }
4841 return true;
4842}
4843
Jamie Madillbe849e42017-05-02 15:49:00 -04004844bool ValidateGetBufferParameterBase(ValidationContext *context,
4845 GLenum target,
4846 GLenum pname,
4847 bool pointerVersion,
4848 GLsizei *numParams)
4849{
4850 if (numParams)
4851 {
4852 *numParams = 0;
4853 }
4854
4855 if (!ValidBufferTarget(context, target))
4856 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004857 context->handleError(InvalidEnum() << "Invalid buffer target.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004858 return false;
4859 }
4860
4861 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4862 if (!buffer)
4863 {
4864 // A null buffer means that "0" is bound to the requested buffer target
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004865 context->handleError(InvalidOperation() << "No buffer bound.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004866 return false;
4867 }
4868
4869 const Extensions &extensions = context->getExtensions();
4870
4871 switch (pname)
4872 {
4873 case GL_BUFFER_USAGE:
4874 case GL_BUFFER_SIZE:
4875 break;
4876
4877 case GL_BUFFER_ACCESS_OES:
4878 if (!extensions.mapBuffer)
4879 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004880 context->handleError(InvalidEnum()
4881 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004882 return false;
4883 }
4884 break;
4885
4886 case GL_BUFFER_MAPPED:
4887 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4888 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4889 !extensions.mapBufferRange)
4890 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004891 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4892 "GL_OES_mapbuffer or "
4893 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004894 return false;
4895 }
4896 break;
4897
4898 case GL_BUFFER_MAP_POINTER:
4899 if (!pointerVersion)
4900 {
4901 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004902 InvalidEnum()
4903 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004904 return false;
4905 }
4906 break;
4907
4908 case GL_BUFFER_ACCESS_FLAGS:
4909 case GL_BUFFER_MAP_OFFSET:
4910 case GL_BUFFER_MAP_LENGTH:
4911 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4912 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004913 context->handleError(InvalidEnum()
4914 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004915 return false;
4916 }
4917 break;
4918
4919 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004920 context->handleError(InvalidEnum() << "Unknown pname.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004921 return false;
4922 }
4923
4924 // All buffer parameter queries return one value.
4925 if (numParams)
4926 {
4927 *numParams = 1;
4928 }
4929
4930 return true;
4931}
4932
4933bool ValidateGetRenderbufferParameterivBase(Context *context,
4934 GLenum target,
4935 GLenum pname,
4936 GLsizei *length)
4937{
4938 if (length)
4939 {
4940 *length = 0;
4941 }
4942
4943 if (target != GL_RENDERBUFFER)
4944 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004945 context->handleError(InvalidEnum() << "Invalid target.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004946 return false;
4947 }
4948
4949 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4950 if (renderbuffer == nullptr)
4951 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004952 context->handleError(InvalidOperation() << "No renderbuffer bound.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004953 return false;
4954 }
4955
4956 switch (pname)
4957 {
4958 case GL_RENDERBUFFER_WIDTH:
4959 case GL_RENDERBUFFER_HEIGHT:
4960 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4961 case GL_RENDERBUFFER_RED_SIZE:
4962 case GL_RENDERBUFFER_GREEN_SIZE:
4963 case GL_RENDERBUFFER_BLUE_SIZE:
4964 case GL_RENDERBUFFER_ALPHA_SIZE:
4965 case GL_RENDERBUFFER_DEPTH_SIZE:
4966 case GL_RENDERBUFFER_STENCIL_SIZE:
4967 break;
4968
4969 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4970 if (!context->getExtensions().framebufferMultisample)
4971 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004972 context->handleError(InvalidEnum()
4973 << "GL_ANGLE_framebuffer_multisample is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004974 return false;
4975 }
4976 break;
4977
4978 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004979 context->handleError(InvalidEnum() << "Unknown pname.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004980 return false;
4981 }
4982
4983 if (length)
4984 {
4985 *length = 1;
4986 }
4987 return true;
4988}
4989
4990bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4991{
4992 if (length)
4993 {
4994 *length = 0;
4995 }
4996
4997 if (GetValidShader(context, shader) == nullptr)
4998 {
4999 return false;
5000 }
5001
5002 switch (pname)
5003 {
5004 case GL_SHADER_TYPE:
5005 case GL_DELETE_STATUS:
5006 case GL_COMPILE_STATUS:
5007 case GL_INFO_LOG_LENGTH:
5008 case GL_SHADER_SOURCE_LENGTH:
5009 break;
5010
5011 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5012 if (!context->getExtensions().translatedShaderSource)
5013 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005014 context->handleError(InvalidEnum()
5015 << "GL_ANGLE_translated_shader_source is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005016 return false;
5017 }
5018 break;
5019
5020 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005021 context->handleError(InvalidEnum() << "Unknown pname.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005022 return false;
5023 }
5024
5025 if (length)
5026 {
5027 *length = 1;
5028 }
5029 return true;
5030}
5031
5032bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
5033{
5034 if (length)
5035 {
5036 *length = 0;
5037 }
5038
5039 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5040 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005041 context->handleError(InvalidEnum() << "Invalid texture target");
Jamie Madillbe849e42017-05-02 15:49:00 -04005042 return false;
5043 }
5044
5045 if (context->getTargetTexture(target) == nullptr)
5046 {
5047 // Should only be possible for external textures
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005048 context->handleError(InvalidEnum() << "No texture bound.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005049 return false;
5050 }
5051
5052 switch (pname)
5053 {
5054 case GL_TEXTURE_MAG_FILTER:
5055 case GL_TEXTURE_MIN_FILTER:
5056 case GL_TEXTURE_WRAP_S:
5057 case GL_TEXTURE_WRAP_T:
5058 break;
5059
5060 case GL_TEXTURE_USAGE_ANGLE:
5061 if (!context->getExtensions().textureUsage)
5062 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005063 context->handleError(InvalidEnum() << "GL_ANGLE_texture_usage is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005064 return false;
5065 }
5066 break;
5067
5068 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5069 if (!context->getExtensions().textureFilterAnisotropic)
5070 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005071 context->handleError(InvalidEnum()
5072 << "GL_EXT_texture_filter_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005073 return false;
5074 }
5075 break;
5076
5077 case GL_TEXTURE_IMMUTABLE_FORMAT:
5078 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5079 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005080 context->handleError(InvalidEnum() << "GL_EXT_texture_storage is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005081 return false;
5082 }
5083 break;
5084
5085 case GL_TEXTURE_WRAP_R:
5086 case GL_TEXTURE_IMMUTABLE_LEVELS:
5087 case GL_TEXTURE_SWIZZLE_R:
5088 case GL_TEXTURE_SWIZZLE_G:
5089 case GL_TEXTURE_SWIZZLE_B:
5090 case GL_TEXTURE_SWIZZLE_A:
5091 case GL_TEXTURE_BASE_LEVEL:
5092 case GL_TEXTURE_MAX_LEVEL:
5093 case GL_TEXTURE_MIN_LOD:
5094 case GL_TEXTURE_MAX_LOD:
5095 case GL_TEXTURE_COMPARE_MODE:
5096 case GL_TEXTURE_COMPARE_FUNC:
5097 if (context->getClientMajorVersion() < 3)
5098 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005099 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005100 return false;
5101 }
5102 break;
5103
5104 case GL_TEXTURE_SRGB_DECODE_EXT:
5105 if (!context->getExtensions().textureSRGBDecode)
5106 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005107 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005108 return false;
5109 }
5110 break;
5111
5112 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005113 context->handleError(InvalidEnum() << "Unknown pname.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005114 return false;
5115 }
5116
5117 if (length)
5118 {
5119 *length = 1;
5120 }
5121 return true;
5122}
5123
5124bool ValidateGetVertexAttribBase(Context *context,
5125 GLuint index,
5126 GLenum pname,
5127 GLsizei *length,
5128 bool pointer,
5129 bool pureIntegerEntryPoint)
5130{
5131 if (length)
5132 {
5133 *length = 0;
5134 }
5135
5136 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5137 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005138 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005139 return false;
5140 }
5141
5142 if (index >= context->getCaps().maxVertexAttributes)
5143 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005144 context->handleError(InvalidValue()
5145 << "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005146 return false;
5147 }
5148
5149 if (pointer)
5150 {
5151 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5152 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005153 context->handleError(InvalidEnum() << "Unknown pname.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005154 return false;
5155 }
5156 }
5157 else
5158 {
5159 switch (pname)
5160 {
5161 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5162 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5163 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5164 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5165 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5166 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5167 case GL_CURRENT_VERTEX_ATTRIB:
5168 break;
5169
5170 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5171 static_assert(
5172 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5173 "ANGLE extension enums not equal to GL enums.");
5174 if (context->getClientMajorVersion() < 3 &&
5175 !context->getExtensions().instancedArrays)
5176 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005177 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5178 "requires OpenGL ES 3.0 or "
5179 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005180 return false;
5181 }
5182 break;
5183
5184 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5185 if (context->getClientMajorVersion() < 3)
5186 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005187 context->handleError(
5188 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005189 return false;
5190 }
5191 break;
5192
5193 case GL_VERTEX_ATTRIB_BINDING:
5194 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5195 if (context->getClientVersion() < ES_3_1)
5196 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005197 context->handleError(InvalidEnum()
5198 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005199 return false;
5200 }
5201 break;
5202
5203 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005204 context->handleError(InvalidEnum() << "Unknown pname.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005205 return false;
5206 }
5207 }
5208
5209 if (length)
5210 {
5211 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5212 {
5213 *length = 4;
5214 }
5215 else
5216 {
5217 *length = 1;
5218 }
5219 }
5220
5221 return true;
5222}
5223
5224bool ValidateReadPixelsBase(ValidationContext *context,
5225 GLint x,
5226 GLint y,
5227 GLsizei width,
5228 GLsizei height,
5229 GLenum format,
5230 GLenum type,
5231 GLsizei bufSize,
5232 GLsizei *length,
5233 GLsizei *columns,
5234 GLsizei *rows,
5235 void *pixels)
5236{
5237 if (length != nullptr)
5238 {
5239 *length = 0;
5240 }
5241 if (rows != nullptr)
5242 {
5243 *rows = 0;
5244 }
5245 if (columns != nullptr)
5246 {
5247 *columns = 0;
5248 }
5249
5250 if (width < 0 || height < 0)
5251 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005252 context->handleError(InvalidValue() << "width and height must be positive");
Jamie Madillbe849e42017-05-02 15:49:00 -04005253 return false;
5254 }
5255
5256 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5257
5258 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5259 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005260 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005261 return false;
5262 }
5263
5264 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5265 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005266 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005267 return false;
5268 }
5269
5270 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5271 ASSERT(framebuffer);
5272
5273 if (framebuffer->getReadBufferState() == GL_NONE)
5274 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005275 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Jamie Madillbe849e42017-05-02 15:49:00 -04005276 return false;
5277 }
5278
5279 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5280 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5281 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5282 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5283 // situation is an application error that would lead to a crash in ANGLE.
5284 if (readBuffer == nullptr)
5285 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005286 context->handleError(InvalidOperation() << "Missing read attachment");
Jamie Madillbe849e42017-05-02 15:49:00 -04005287 return false;
5288 }
5289
5290 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
5291 GLenum currentType = framebuffer->getImplementationColorReadType();
5292 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5293
5294 bool validFormatTypeCombination =
5295 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5296
5297 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5298 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005299 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005300 return false;
5301 }
5302
5303 // Check for pixel pack buffer related API errors
5304 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5305 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5306 {
5307 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005308 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005309 return false;
5310 }
5311
5312 // .. the data would be packed to the buffer object such that the memory writes required
5313 // would exceed the data store size.
5314 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5315 const gl::Extents size(width, height, 1);
5316 const auto &pack = context->getGLState().getPackState();
5317
5318 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5319 if (endByteOrErr.isError())
5320 {
5321 context->handleError(endByteOrErr.getError());
5322 return false;
5323 }
5324
5325 size_t endByte = endByteOrErr.getResult();
5326 if (bufSize >= 0)
5327 {
5328 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5329 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005330 context->handleError(InvalidOperation()
5331 << "bufSize must be at least " << endByte << " bytes.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005332 return false;
5333 }
5334 }
5335
5336 if (pixelPackBuffer != nullptr)
5337 {
5338 CheckedNumeric<size_t> checkedEndByte(endByte);
5339 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5340 checkedEndByte += checkedOffset;
5341
5342 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5343 {
5344 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005345 context->handleError(InvalidOperation()
5346 << "Writes would overflow the pixel pack buffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005347 return false;
5348 }
5349 }
5350
5351 if (pixelPackBuffer == nullptr && length != nullptr)
5352 {
5353 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5354 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005355 context->handleError(InvalidOperation() << "length would overflow GLsizei.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005356 return false;
5357 }
5358
5359 *length = static_cast<GLsizei>(endByte);
5360 }
5361
5362 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5363 angle::CheckedNumeric<int> clippedExtent(length);
5364 if (start < 0)
5365 {
5366 // "subtract" the area that is less than 0
5367 clippedExtent += start;
5368 }
5369
5370 const int readExtent = start + length;
5371 if (readExtent > bufferSize)
5372 {
5373 // Subtract the region to the right of the read buffer
5374 clippedExtent -= (readExtent - bufferSize);
5375 }
5376
5377 if (!clippedExtent.IsValid())
5378 {
5379 return 0;
5380 }
5381
5382 return std::max(clippedExtent.ValueOrDie(), 0);
5383 };
5384
5385 if (columns != nullptr)
5386 {
5387 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5388 }
5389
5390 if (rows != nullptr)
5391 {
5392 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5393 }
5394
5395 return true;
5396}
5397
5398template <typename ParamType>
5399bool ValidateTexParameterBase(Context *context,
5400 GLenum target,
5401 GLenum pname,
5402 GLsizei bufSize,
5403 const ParamType *params)
5404{
5405 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5406 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005407 context->handleError(InvalidEnum() << "Invalid texture target");
Jamie Madillbe849e42017-05-02 15:49:00 -04005408 return false;
5409 }
5410
5411 if (context->getTargetTexture(target) == nullptr)
5412 {
5413 // Should only be possible for external textures
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005414 context->handleError(InvalidEnum() << "No texture bound.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005415 return false;
5416 }
5417
5418 const GLsizei minBufSize = 1;
5419 if (bufSize >= 0 && bufSize < minBufSize)
5420 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005421 context->handleError(InvalidOperation() << "bufSize must be at least " << minBufSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005422 return false;
5423 }
5424
5425 switch (pname)
5426 {
5427 case GL_TEXTURE_WRAP_R:
5428 case GL_TEXTURE_SWIZZLE_R:
5429 case GL_TEXTURE_SWIZZLE_G:
5430 case GL_TEXTURE_SWIZZLE_B:
5431 case GL_TEXTURE_SWIZZLE_A:
5432 case GL_TEXTURE_BASE_LEVEL:
5433 case GL_TEXTURE_MAX_LEVEL:
5434 case GL_TEXTURE_COMPARE_MODE:
5435 case GL_TEXTURE_COMPARE_FUNC:
5436 case GL_TEXTURE_MIN_LOD:
5437 case GL_TEXTURE_MAX_LOD:
5438 if (context->getClientMajorVersion() < 3)
5439 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005440 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005441 return false;
5442 }
5443 if (target == GL_TEXTURE_EXTERNAL_OES &&
5444 !context->getExtensions().eglImageExternalEssl3)
5445 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005446 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5447 "available without "
5448 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005449 return false;
5450 }
5451 break;
5452
5453 default:
5454 break;
5455 }
5456
5457 switch (pname)
5458 {
5459 case GL_TEXTURE_WRAP_S:
5460 case GL_TEXTURE_WRAP_T:
5461 case GL_TEXTURE_WRAP_R:
5462 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
5463 {
5464 return false;
5465 }
5466 break;
5467
5468 case GL_TEXTURE_MIN_FILTER:
5469 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
5470 {
5471 return false;
5472 }
5473 break;
5474
5475 case GL_TEXTURE_MAG_FILTER:
5476 if (!ValidateTextureMagFilterValue(context, params))
5477 {
5478 return false;
5479 }
5480 break;
5481
5482 case GL_TEXTURE_USAGE_ANGLE:
5483 switch (ConvertToGLenum(params[0]))
5484 {
5485 case GL_NONE:
5486 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5487 break;
5488
5489 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005490 context->handleError(InvalidEnum() << "Unknown param value.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005491 return false;
5492 }
5493 break;
5494
5495 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5496 if (!context->getExtensions().textureFilterAnisotropic)
5497 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005498 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005499 return false;
5500 }
5501
5502 // we assume the parameter passed to this validation method is truncated, not rounded
5503 if (params[0] < 1)
5504 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005505 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005506 return false;
5507 }
5508 break;
5509
5510 case GL_TEXTURE_MIN_LOD:
5511 case GL_TEXTURE_MAX_LOD:
5512 // any value is permissible
5513 break;
5514
5515 case GL_TEXTURE_COMPARE_MODE:
5516 if (!ValidateTextureCompareModeValue(context, params))
5517 {
5518 return false;
5519 }
5520 break;
5521
5522 case GL_TEXTURE_COMPARE_FUNC:
5523 if (!ValidateTextureCompareFuncValue(context, params))
5524 {
5525 return false;
5526 }
5527 break;
5528
5529 case GL_TEXTURE_SWIZZLE_R:
5530 case GL_TEXTURE_SWIZZLE_G:
5531 case GL_TEXTURE_SWIZZLE_B:
5532 case GL_TEXTURE_SWIZZLE_A:
5533 switch (ConvertToGLenum(params[0]))
5534 {
5535 case GL_RED:
5536 case GL_GREEN:
5537 case GL_BLUE:
5538 case GL_ALPHA:
5539 case GL_ZERO:
5540 case GL_ONE:
5541 break;
5542
5543 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005544 context->handleError(InvalidEnum() << "Unknown param value.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005545 return false;
5546 }
5547 break;
5548
5549 case GL_TEXTURE_BASE_LEVEL:
5550 if (params[0] < 0)
5551 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005552 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005553 return false;
5554 }
5555 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5556 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005557 context->handleError(InvalidOperation()
5558 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005559 return false;
5560 }
5561 break;
5562
5563 case GL_TEXTURE_MAX_LEVEL:
5564 if (params[0] < 0)
5565 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005566 context->handleError(InvalidValue() << "Max level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005567 return false;
5568 }
5569 break;
5570
5571 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5572 if (context->getClientVersion() < Version(3, 1))
5573 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005574 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005575 return false;
5576 }
5577 switch (ConvertToGLenum(params[0]))
5578 {
5579 case GL_DEPTH_COMPONENT:
5580 case GL_STENCIL_INDEX:
5581 break;
5582
5583 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005584 context->handleError(InvalidEnum() << "Unknown param value.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005585 return false;
5586 }
5587 break;
5588
5589 case GL_TEXTURE_SRGB_DECODE_EXT:
5590 if (!ValidateTextureSRGBDecodeValue(context, params))
5591 {
5592 return false;
5593 }
5594 break;
5595
5596 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005597 context->handleError(InvalidEnum() << "Unknown pname.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005598 return false;
5599 }
5600
5601 return true;
5602}
5603
5604template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5605template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5606
Jamie Madillc29968b2016-01-20 11:17:23 -05005607} // namespace gl