blob: 1cc388233b0242617e39914b09546db488bb99f5 [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.
Martin Radevdd5f27e2017-06-07 10:17:09 +030062 gl::Buffer *buffer = binding.getBuffer().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;
Martin Radevdd5f27e2017-06-07 10:17:09 +030094 GLuint divisor = binding.getDivisor();
95 if (divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -050096 {
97 maxVertexElement = maxVertex;
98 }
99 else
100 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300101 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500102 }
103
104 // We do manual overflow checks here instead of using safe_math.h because it was
105 // a bottleneck. Thanks to some properties of GL we know inequalities that can
106 // help us make the overflow checks faster.
107
108 // The max possible attribSize is 16 for a vector of 4 32 bit values.
109 constexpr uint64_t kMaxAttribSize = 16;
110 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
111 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
112
113 // We know attribStride is given as a GLsizei which is typedefed to int.
114 // We also know an upper bound for attribSize.
115 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800116 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500117 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
118 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
119
120 // Computing the max offset using uint64_t without attrib.offset is overflow
121 // safe. Note: Last vertex element does not take the full stride!
122 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
123 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
124
125 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800126 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
127 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500128 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500129 context->handleError(InvalidOperation() << "Integer overflow.");
Corentin Wallezfd456442016-12-21 17:57:00 -0500130 return false;
131 }
132 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
133
134 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
135 // We can return INVALID_OPERATION if our vertex attribute does not have
136 // enough backing data.
137 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
138 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500139 context->handleError(InvalidOperation()
140 << "Vertex buffer is not big enough for the draw call");
Corentin Wallezfd456442016-12-21 17:57:00 -0500141 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400142 }
143 }
144
145 return true;
146}
147
Geoff Langf607c602016-09-21 11:46:48 -0400148bool ValidReadPixelsFormatType(ValidationContext *context,
149 GLenum framebufferComponentType,
150 GLenum format,
151 GLenum type)
152{
153 switch (framebufferComponentType)
154 {
155 case GL_UNSIGNED_NORMALIZED:
156 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
157 // ReadPixels with BGRA even if the extension is not present
158 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
159 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
160 type == GL_UNSIGNED_BYTE);
161
162 case GL_SIGNED_NORMALIZED:
163 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
164
165 case GL_INT:
166 return (format == GL_RGBA_INTEGER && type == GL_INT);
167
168 case GL_UNSIGNED_INT:
169 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
170
171 case GL_FLOAT:
172 return (format == GL_RGBA && type == GL_FLOAT);
173
174 default:
175 UNREACHABLE();
176 return false;
177 }
178}
179
Geoff Langc1984ed2016-10-07 12:41:00 -0400180template <typename ParamType>
181bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
182{
183 switch (ConvertToGLenum(params[0]))
184 {
185 case GL_CLAMP_TO_EDGE:
186 break;
187
188 case GL_REPEAT:
189 case GL_MIRRORED_REPEAT:
190 if (isExternalTextureTarget)
191 {
192 // OES_EGL_image_external specifies this error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500193 context->handleError(InvalidEnum()
194 << "external textures only support CLAMP_TO_EDGE wrap mode");
Geoff Langc1984ed2016-10-07 12:41:00 -0400195 return false;
196 }
197 break;
198
199 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500200 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400201 return false;
202 }
203
204 return true;
205}
206
207template <typename ParamType>
208bool ValidateTextureMinFilterValue(Context *context,
209 ParamType *params,
210 bool isExternalTextureTarget)
211{
212 switch (ConvertToGLenum(params[0]))
213 {
214 case GL_NEAREST:
215 case GL_LINEAR:
216 break;
217
218 case GL_NEAREST_MIPMAP_NEAREST:
219 case GL_LINEAR_MIPMAP_NEAREST:
220 case GL_NEAREST_MIPMAP_LINEAR:
221 case GL_LINEAR_MIPMAP_LINEAR:
222 if (isExternalTextureTarget)
223 {
224 // OES_EGL_image_external specifies this error.
225 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500226 InvalidEnum() << "external textures only support NEAREST and LINEAR filtering");
Geoff Langc1984ed2016-10-07 12:41:00 -0400227 return false;
228 }
229 break;
230
231 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500232 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400233 return false;
234 }
235
236 return true;
237}
238
239template <typename ParamType>
240bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
241{
242 switch (ConvertToGLenum(params[0]))
243 {
244 case GL_NEAREST:
245 case GL_LINEAR:
246 break;
247
248 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500249 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400250 return false;
251 }
252
253 return true;
254}
255
256template <typename ParamType>
257bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
258{
259 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
260 switch (ConvertToGLenum(params[0]))
261 {
262 case GL_NONE:
263 case GL_COMPARE_REF_TO_TEXTURE:
264 break;
265
266 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500267 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400268 return false;
269 }
270
271 return true;
272}
273
274template <typename ParamType>
275bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
276{
277 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
278 switch (ConvertToGLenum(params[0]))
279 {
280 case GL_LEQUAL:
281 case GL_GEQUAL:
282 case GL_LESS:
283 case GL_GREATER:
284 case GL_EQUAL:
285 case GL_NOTEQUAL:
286 case GL_ALWAYS:
287 case GL_NEVER:
288 break;
289
290 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500291 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400292 return false;
293 }
294
295 return true;
296}
297
298template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700299bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
300{
301 if (!context->getExtensions().textureSRGBDecode)
302 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500303 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Geoff Lang81c6b572016-10-19 14:07:52 -0700304 return false;
305 }
306
307 switch (ConvertToGLenum(params[0]))
308 {
309 case GL_DECODE_EXT:
310 case GL_SKIP_DECODE_EXT:
311 break;
312
313 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500314 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Lang81c6b572016-10-19 14:07:52 -0700315 return false;
316 }
317
318 return true;
319}
320
321template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400322bool ValidateSamplerParameterBase(Context *context,
323 GLuint sampler,
324 GLenum pname,
325 GLsizei bufSize,
326 ParamType *params)
327{
328 if (context->getClientMajorVersion() < 3)
329 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500330 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400331 return false;
332 }
333
334 if (!context->isSampler(sampler))
335 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500336 context->handleError(InvalidOperation() << "Sampler is not valid.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400337 return false;
338 }
339
340 const GLsizei minBufSize = 1;
341 if (bufSize >= 0 && bufSize < minBufSize)
342 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500343 context->handleError(InvalidOperation() << "bufSize must be at least " << minBufSize);
Geoff Langc1984ed2016-10-07 12:41:00 -0400344 return false;
345 }
346
347 switch (pname)
348 {
349 case GL_TEXTURE_WRAP_S:
350 case GL_TEXTURE_WRAP_T:
351 case GL_TEXTURE_WRAP_R:
352 if (!ValidateTextureWrapModeValue(context, params, false))
353 {
354 return false;
355 }
356 break;
357
358 case GL_TEXTURE_MIN_FILTER:
359 if (!ValidateTextureMinFilterValue(context, params, false))
360 {
361 return false;
362 }
363 break;
364
365 case GL_TEXTURE_MAG_FILTER:
366 if (!ValidateTextureMagFilterValue(context, params))
367 {
368 return false;
369 }
370 break;
371
372 case GL_TEXTURE_MIN_LOD:
373 case GL_TEXTURE_MAX_LOD:
374 // any value is permissible
375 break;
376
377 case GL_TEXTURE_COMPARE_MODE:
378 if (!ValidateTextureCompareModeValue(context, params))
379 {
380 return false;
381 }
382 break;
383
384 case GL_TEXTURE_COMPARE_FUNC:
385 if (!ValidateTextureCompareFuncValue(context, params))
386 {
387 return false;
388 }
389 break;
390
Geoff Lang81c6b572016-10-19 14:07:52 -0700391 case GL_TEXTURE_SRGB_DECODE_EXT:
392 if (!ValidateTextureSRGBDecodeValue(context, params))
393 {
394 return false;
395 }
396 break;
397
Geoff Langc1984ed2016-10-07 12:41:00 -0400398 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500399 context->handleError(InvalidEnum() << "Unknown pname.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400400 return false;
401 }
402
403 return true;
404}
405
406bool ValidateGetSamplerParameterBase(Context *context,
407 GLuint sampler,
408 GLenum pname,
409 GLsizei *length)
410{
411 if (length)
412 {
413 *length = 0;
414 }
415
416 if (context->getClientMajorVersion() < 3)
417 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500418 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400419 return false;
420 }
421
422 if (!context->isSampler(sampler))
423 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500424 context->handleError(InvalidOperation() << "Sampler is not valid.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400425 return false;
426 }
427
428 switch (pname)
429 {
430 case GL_TEXTURE_WRAP_S:
431 case GL_TEXTURE_WRAP_T:
432 case GL_TEXTURE_WRAP_R:
433 case GL_TEXTURE_MIN_FILTER:
434 case GL_TEXTURE_MAG_FILTER:
435 case GL_TEXTURE_MIN_LOD:
436 case GL_TEXTURE_MAX_LOD:
437 case GL_TEXTURE_COMPARE_MODE:
438 case GL_TEXTURE_COMPARE_FUNC:
439 break;
440
Geoff Lang81c6b572016-10-19 14:07:52 -0700441 case GL_TEXTURE_SRGB_DECODE_EXT:
442 if (!context->getExtensions().textureSRGBDecode)
443 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500444 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Geoff Lang81c6b572016-10-19 14:07:52 -0700445 return false;
446 }
447 break;
448
Geoff Langc1984ed2016-10-07 12:41:00 -0400449 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500450 context->handleError(InvalidEnum() << "Unknown pname.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400451 return false;
452 }
453
454 if (length)
455 {
456 *length = 1;
457 }
458 return true;
459}
460
Geoff Lang6899b872016-10-14 11:30:13 -0400461bool ValidateGetActiveUniformBlockivBase(Context *context,
462 GLuint program,
463 GLuint uniformBlockIndex,
464 GLenum pname,
465 GLsizei *length)
466{
467 if (length)
468 {
469 *length = 0;
470 }
471
472 if (context->getClientMajorVersion() < 3)
473 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500474 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Lang6899b872016-10-14 11:30:13 -0400475 return false;
476 }
477
478 Program *programObject = GetValidProgram(context, program);
479 if (!programObject)
480 {
481 return false;
482 }
483
484 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
485 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500486 context->handleError(InvalidValue()
487 << "uniformBlockIndex exceeds active uniform block count.");
Geoff Lang6899b872016-10-14 11:30:13 -0400488 return false;
489 }
490
491 switch (pname)
492 {
493 case GL_UNIFORM_BLOCK_BINDING:
494 case GL_UNIFORM_BLOCK_DATA_SIZE:
495 case GL_UNIFORM_BLOCK_NAME_LENGTH:
496 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
497 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
498 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
499 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
500 break;
501
502 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500503 context->handleError(InvalidEnum() << "Unknown pname.");
Geoff Lang6899b872016-10-14 11:30:13 -0400504 return false;
505 }
506
507 if (length)
508 {
509 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
510 {
511 const UniformBlock &uniformBlock =
512 programObject->getUniformBlockByIndex(uniformBlockIndex);
513 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
514 }
515 else
516 {
517 *length = 1;
518 }
519 }
520
521 return true;
522}
523
Geoff Lang0a9661f2016-10-20 10:59:20 -0700524bool ValidateGetInternalFormativBase(Context *context,
525 GLenum target,
526 GLenum internalformat,
527 GLenum pname,
528 GLsizei bufSize,
529 GLsizei *numParams)
530{
531 if (numParams)
532 {
533 *numParams = 0;
534 }
535
536 if (context->getClientMajorVersion() < 3)
537 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500538 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700539 return false;
540 }
541
542 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
543 if (!formatCaps.renderable)
544 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500545 context->handleError(InvalidEnum() << "Internal format is not renderable.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700546 return false;
547 }
548
549 switch (target)
550 {
551 case GL_RENDERBUFFER:
552 break;
553
JiangYizhoubddc46b2016-12-09 09:50:51 +0800554 case GL_TEXTURE_2D_MULTISAMPLE:
555 if (context->getClientVersion() < ES_3_1)
556 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500557 context->handleError(InvalidOperation()
558 << "Texture target requires at least OpenGL ES 3.1.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800559 return false;
560 }
561 break;
562
Geoff Lang0a9661f2016-10-20 10:59:20 -0700563 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500564 context->handleError(InvalidEnum() << "Invalid target.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700565 return false;
566 }
567
568 if (bufSize < 0)
569 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500570 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700571 return false;
572 }
573
574 GLsizei maxWriteParams = 0;
575 switch (pname)
576 {
577 case GL_NUM_SAMPLE_COUNTS:
578 maxWriteParams = 1;
579 break;
580
581 case GL_SAMPLES:
582 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
583 break;
584
585 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500586 context->handleError(InvalidEnum() << "Unknown pname.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700587 return false;
588 }
589
590 if (numParams)
591 {
592 // glGetInternalFormativ will not overflow bufSize
593 *numParams = std::min(bufSize, maxWriteParams);
594 }
595
596 return true;
597}
598
Jamie Madillc1d770e2017-04-13 17:31:24 -0400599bool ValidateUniformCommonBase(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500600 gl::Program *program,
601 GLint location,
602 GLsizei count,
603 const LinkedUniform **uniformOut)
604{
605 // TODO(Jiajia): Add image uniform check in future.
606 if (count < 0)
607 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500608 context->handleError(InvalidValue());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500609 return false;
610 }
611
612 if (!program || !program->isLinked())
613 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500614 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500615 return false;
616 }
617
618 if (location == -1)
619 {
620 // Silently ignore the uniform command
621 return false;
622 }
623
624 const auto &uniformLocations = program->getUniformLocations();
Jamie Madillbe849e42017-05-02 15:49:00 -0400625 size_t castedLocation = static_cast<size_t>(location);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500626 if (castedLocation >= uniformLocations.size())
627 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500628 context->handleError(InvalidOperation() << "Invalid uniform location");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500629 return false;
630 }
631
632 const auto &uniformLocation = uniformLocations[castedLocation];
633 if (uniformLocation.ignored)
634 {
635 // Silently ignore the uniform command
636 return false;
637 }
638
639 if (!uniformLocation.used)
640 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500641 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500642 return false;
643 }
644
645 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
646
647 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
648 if (!uniform.isArray() && count > 1)
649 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500650 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500651 return false;
652 }
653
654 *uniformOut = &uniform;
655 return true;
656}
657
Frank Henigman999b0fd2017-02-02 21:45:55 -0500658bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -0500659 GLenum uniformType,
660 GLsizei count,
661 const GLint *value)
662{
663 // Value type is GL_INT, because we only get here from glUniform1i{v}.
664 // It is compatible with INT or BOOL.
665 // Do these cheap tests first, for a little extra speed.
666 if (GL_INT == uniformType || GL_BOOL == uniformType)
667 {
668 return true;
669 }
670
671 if (IsSamplerType(uniformType))
672 {
Frank Henigman999b0fd2017-02-02 21:45:55 -0500673 // Check that the values are in range.
674 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
675 for (GLsizei i = 0; i < count; ++i)
676 {
677 if (value[i] < 0 || value[i] >= max)
678 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500679 context->handleError(InvalidValue() << "sampler uniform value out of range");
Frank Henigman999b0fd2017-02-02 21:45:55 -0500680 return false;
681 }
682 }
Frank Henigmana98a6472017-02-02 21:38:32 -0500683 return true;
684 }
685
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500686 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmana98a6472017-02-02 21:38:32 -0500687 return false;
688}
689
Jamie Madillc1d770e2017-04-13 17:31:24 -0400690bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500691{
692 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -0500693 // Do the cheaper test first, for a little extra speed.
694 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500695 {
696 return true;
697 }
698
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500699 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500700 return false;
701}
702
Jamie Madillc1d770e2017-04-13 17:31:24 -0400703bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500704{
705 // Check that the value type is compatible with uniform type.
706 if (valueType == uniformType)
707 {
708 return true;
709 }
710
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500711 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500712 return false;
713}
714
Geoff Lange0cff192017-05-30 13:04:56 -0400715bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
716{
717 const Program *program = context->getGLState().getProgram();
718 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
719
720 const auto &programOutputTypes = program->getOutputVariableTypes();
721 for (size_t drawBufferIdx = 0; drawBufferIdx < programOutputTypes.size(); drawBufferIdx++)
722 {
723 GLenum outputType = programOutputTypes[drawBufferIdx];
724 GLenum inputType = framebuffer->getDrawbufferWriteType(drawBufferIdx);
725 if (outputType != GL_NONE && inputType != GL_NONE && inputType != outputType)
726 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500727 context->handleError(InvalidOperation() << "Fragment shader output type does not "
728 "match the bound framebuffer attachment "
729 "type.");
Geoff Lange0cff192017-05-30 13:04:56 -0400730 return false;
731 }
732 }
733
734 return true;
735}
736
Geoff Lang9ab5b822017-05-30 16:19:23 -0400737bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
738{
739 const Program *program = context->getGLState().getProgram();
740 const VertexArray *vao = context->getGLState().getVertexArray();
741
742 for (const auto &shaderAttribute : program->getAttributes())
743 {
744 GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
745
746 const auto &attrib = vao->getVertexAttribute(shaderAttribute.location);
747 const auto &currentValue =
748 context->getGLState().getVertexAttribCurrentValue(shaderAttribute.location);
749 GLenum vertexType = attrib.enabled ? GetVertexAttributeBaseType(attrib) : currentValue.Type;
750
751 if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
752 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500753 context->handleError(InvalidOperation() << "Vertex shader input type does not "
754 "match the type of the bound vertex "
755 "attribute.");
Geoff Lang9ab5b822017-05-30 16:19:23 -0400756 return false;
757 }
758 }
759
760 return true;
761}
762
Geoff Langf41a7152016-09-19 15:11:17 -0400763} // anonymous namespace
764
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500765bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400766{
Jamie Madilld7460c72014-01-21 16:38:14 -0500767 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400768 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800769 case GL_TEXTURE_2D:
770 case GL_TEXTURE_CUBE_MAP:
771 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400772
He Yunchaoced53ae2016-11-29 15:00:51 +0800773 case GL_TEXTURE_3D:
774 case GL_TEXTURE_2D_ARRAY:
775 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500776
He Yunchaoced53ae2016-11-29 15:00:51 +0800777 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800778 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400779
He Yunchaoced53ae2016-11-29 15:00:51 +0800780 default:
781 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500782 }
Jamie Madill35d15012013-10-07 10:46:37 -0400783}
784
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500785bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
786{
787 switch (target)
788 {
789 case GL_TEXTURE_2D:
790 case GL_TEXTURE_CUBE_MAP:
791 return true;
792
793 default:
794 return false;
795 }
796}
797
798bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
799{
800 switch (target)
801 {
802 case GL_TEXTURE_3D:
803 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300804 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500805
806 default:
807 return false;
808 }
809}
810
Ian Ewellbda75592016-04-18 17:25:54 -0400811// Most texture GL calls are not compatible with external textures, so we have a separate validation
812// function for use in the GL calls that do
813bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
814{
815 return (target == GL_TEXTURE_EXTERNAL_OES) &&
816 (context->getExtensions().eglImageExternal ||
817 context->getExtensions().eglStreamConsumerExternal);
818}
819
Shannon Woods4dfed832014-03-17 20:03:39 -0400820// This function differs from ValidTextureTarget in that the target must be
821// usable as the destination of a 2D operation-- so a cube face is valid, but
822// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400823// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500824bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400825{
826 switch (target)
827 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800828 case GL_TEXTURE_2D:
829 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
830 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
831 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
832 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
833 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
834 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
835 return true;
836 default:
837 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500838 }
839}
840
Jamie Madillbe849e42017-05-02 15:49:00 -0400841bool ValidateDrawElementsInstancedBase(ValidationContext *context,
842 GLenum mode,
843 GLsizei count,
844 GLenum type,
845 const GLvoid *indices,
846 GLsizei primcount)
847{
848 if (primcount < 0)
849 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500850 context->handleError(InvalidValue() << "primcount cannot be negative.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400851 return false;
852 }
853
854 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
855 {
856 return false;
857 }
858
859 // No-op zero primitive count
860 return (primcount > 0);
861}
862
863bool ValidateDrawArraysInstancedBase(Context *context,
864 GLenum mode,
865 GLint first,
866 GLsizei count,
867 GLsizei primcount)
868{
869 if (primcount < 0)
870 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500871 context->handleError(InvalidValue() << "primcount cannot be negative.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400872 return false;
873 }
874
875 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
876 {
877 return false;
878 }
879
880 // No-op if zero primitive count
881 return (primcount > 0);
882}
883
884bool ValidateDrawInstancedANGLEAndWebGL(ValidationContext *context)
885{
886 // Verify there is at least one active attribute with a divisor of zero
887 const State &state = context->getGLState();
888
889 Program *program = state.getProgram();
890
891 const auto &attribs = state.getVertexArray()->getVertexAttributes();
892 const auto &bindings = state.getVertexArray()->getVertexBindings();
893 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
894 {
895 const VertexAttribute &attrib = attribs[attributeIndex];
896 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300897 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400898 {
899 return true;
900 }
901 }
902
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500903 context->handleError(InvalidOperation()
904 << "At least one attribute must have a divisor of zero.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400905 return false;
906}
907
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500908bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
909{
910 switch (target)
911 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800912 case GL_TEXTURE_3D:
913 case GL_TEXTURE_2D_ARRAY:
914 return true;
915 default:
916 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400917 }
918}
919
He Yunchao11b038b2016-11-22 21:24:04 +0800920bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
921{
922 switch (target)
923 {
924 case GL_TEXTURE_2D:
925 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
926 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
927 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
928 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
929 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
930 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
931 case GL_TEXTURE_3D:
932 case GL_TEXTURE_2D_ARRAY:
933 case GL_TEXTURE_2D_MULTISAMPLE:
934 return true;
935 default:
936 return false;
937 }
938}
939
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500940bool ValidFramebufferTarget(GLenum target)
941{
He Yunchaoced53ae2016-11-29 15:00:51 +0800942 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
943 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400944 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500945
946 switch (target)
947 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800948 case GL_FRAMEBUFFER:
949 return true;
950 case GL_READ_FRAMEBUFFER:
951 return true;
952 case GL_DRAW_FRAMEBUFFER:
953 return true;
954 default:
955 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500956 }
957}
958
Jamie Madill29639852016-09-02 15:00:09 -0400959bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -0500960{
961 switch (target)
962 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800963 case GL_ARRAY_BUFFER:
964 case GL_ELEMENT_ARRAY_BUFFER:
965 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -0500966
He Yunchaoced53ae2016-11-29 15:00:51 +0800967 case GL_PIXEL_PACK_BUFFER:
968 case GL_PIXEL_UNPACK_BUFFER:
969 return (context->getExtensions().pixelBufferObject ||
970 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -0400971
He Yunchaoced53ae2016-11-29 15:00:51 +0800972 case GL_COPY_READ_BUFFER:
973 case GL_COPY_WRITE_BUFFER:
974 case GL_TRANSFORM_FEEDBACK_BUFFER:
975 case GL_UNIFORM_BUFFER:
976 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -0500977
He Yunchaoced53ae2016-11-29 15:00:51 +0800978 case GL_ATOMIC_COUNTER_BUFFER:
979 case GL_SHADER_STORAGE_BUFFER:
980 case GL_DRAW_INDIRECT_BUFFER:
981 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800982 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -0400983
He Yunchaoced53ae2016-11-29 15:00:51 +0800984 default:
985 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -0500986 }
987}
988
Jamie Madillc29968b2016-01-20 11:17:23 -0500989bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400990{
Jamie Madillc29968b2016-01-20 11:17:23 -0500991 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400992 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400993 switch (target)
994 {
Jamie Madillc29968b2016-01-20 11:17:23 -0500995 case GL_TEXTURE_2D:
996 maxDimension = caps.max2DTextureSize;
997 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800998 case GL_TEXTURE_CUBE_MAP:
999 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1000 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1001 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1002 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1003 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1004 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1005 maxDimension = caps.maxCubeMapTextureSize;
1006 break;
1007 case GL_TEXTURE_3D:
1008 maxDimension = caps.max3DTextureSize;
1009 break;
1010 case GL_TEXTURE_2D_ARRAY:
1011 maxDimension = caps.max2DTextureSize;
1012 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001013 case GL_TEXTURE_2D_MULTISAMPLE:
1014 maxDimension = caps.max2DTextureSize;
1015 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001016 default:
1017 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001018 }
1019
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001020 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001021}
1022
Geoff Langcc507aa2016-12-12 10:09:52 -05001023bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001024 GLenum target,
1025 GLint level,
1026 GLsizei width,
1027 GLsizei height,
1028 GLsizei depth,
1029 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001030{
1031 if (level < 0 || width < 0 || height < 0 || depth < 0)
1032 {
1033 return false;
1034 }
1035
Austin Kinross08528e12015-10-07 16:24:40 -07001036 // TexSubImage parameters can be NPOT without textureNPOT extension,
1037 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001038 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001039 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001040 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001041 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001042 {
1043 return false;
1044 }
1045
1046 if (!ValidMipLevel(context, target, level))
1047 {
1048 return false;
1049 }
1050
1051 return true;
1052}
1053
Geoff Lang0d8b7242015-09-09 14:56:53 -04001054bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1055{
1056 // List of compressed format that require that the texture size is smaller than or a multiple of
1057 // the compressed block size.
1058 switch (internalFormat)
1059 {
1060 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1061 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1062 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1063 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -04001064 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
1065 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
1066 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
1067 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -08001068 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001069 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1070 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1071 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1072 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1073 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
1074 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001075 return true;
1076
1077 default:
1078 return false;
1079 }
1080}
1081
Geoff Lang966c9402017-04-18 12:38:27 -04001082bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
1083{
1084 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
1085 (size % blockSize == 0);
1086}
1087
Jamie Madillc29968b2016-01-20 11:17:23 -05001088bool ValidCompressedImageSize(const ValidationContext *context,
1089 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -04001090 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -05001091 GLsizei width,
1092 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001093{
Geoff Langca271392017-04-05 12:30:00 -04001094 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -04001095 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001096 {
1097 return false;
1098 }
1099
Geoff Lang966c9402017-04-18 12:38:27 -04001100 if (width < 0 || height < 0)
1101 {
1102 return false;
1103 }
1104
1105 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1106 {
1107 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
1108 // block size for level 0 but WebGL disallows this.
1109 bool smallerThanBlockSizeAllowed =
1110 level > 0 || !context->getExtensions().webglCompatibility;
1111
1112 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
1113 smallerThanBlockSizeAllowed) ||
1114 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
1115 smallerThanBlockSizeAllowed))
1116 {
1117 return false;
1118 }
1119 }
1120
1121 return true;
1122}
1123
1124bool ValidCompressedSubImageSize(const ValidationContext *context,
1125 GLenum internalFormat,
1126 GLint xoffset,
1127 GLint yoffset,
1128 GLsizei width,
1129 GLsizei height,
1130 size_t textureWidth,
1131 size_t textureHeight)
1132{
1133 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
1134 if (!formatInfo.compressed)
1135 {
1136 return false;
1137 }
1138
Geoff Lang44ff5a72017-02-03 15:15:43 -05001139 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001140 {
1141 return false;
1142 }
1143
Geoff Lang0d8b7242015-09-09 14:56:53 -04001144 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1145 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05001146 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -04001147 yoffset % formatInfo.compressedBlockHeight != 0)
1148 {
1149 return false;
1150 }
1151
1152 // Allowed to either have data that is a multiple of block size or is smaller than the block
1153 // size but fills the entire mip
1154 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
1155 static_cast<size_t>(width) == textureWidth &&
1156 static_cast<size_t>(height) == textureHeight;
1157 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
1158 (height % formatInfo.compressedBlockHeight) == 0;
1159 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -04001160 {
1161 return false;
1162 }
1163 }
1164
Geoff Langd4f180b2013-09-24 13:57:44 -04001165 return true;
1166}
1167
Geoff Langff5b2d52016-09-07 11:32:23 -04001168bool ValidImageDataSize(ValidationContext *context,
1169 GLenum textureTarget,
1170 GLsizei width,
1171 GLsizei height,
1172 GLsizei depth,
1173 GLenum internalFormat,
1174 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001175 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001176 GLsizei imageSize)
1177{
1178 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1179 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1180 {
1181 // Checks are not required
1182 return true;
1183 }
1184
1185 // ...the data would be unpacked from the buffer object such that the memory reads required
1186 // would exceed the data store size.
Geoff Langca271392017-04-05 12:30:00 -04001187 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
Geoff Langff5b2d52016-09-07 11:32:23 -04001188 const gl::Extents size(width, height, depth);
1189 const auto &unpack = context->getGLState().getUnpackState();
1190
1191 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1192 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1193 if (endByteOrErr.isError())
1194 {
1195 context->handleError(endByteOrErr.getError());
1196 return false;
1197 }
1198
1199 GLuint endByte = endByteOrErr.getResult();
1200
1201 if (pixelUnpackBuffer)
1202 {
1203 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1204 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1205 checkedEndByte += checkedOffset;
1206
1207 if (!checkedEndByte.IsValid() ||
1208 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1209 {
1210 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001211 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04001212 return false;
1213 }
1214 }
1215 else
1216 {
1217 ASSERT(imageSize >= 0);
1218 if (pixels == nullptr && imageSize != 0)
1219 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001220 context->handleError(InvalidOperation()
1221 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001222 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001223 }
1224
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001225 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001226 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001227 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001228 return false;
1229 }
1230 }
1231
1232 return true;
1233}
1234
Geoff Lang37dde692014-01-31 16:34:54 -05001235bool ValidQueryType(const Context *context, GLenum queryType)
1236{
He Yunchaoced53ae2016-11-29 15:00:51 +08001237 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1238 "GL extension enums not equal.");
1239 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1240 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001241
1242 switch (queryType)
1243 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001244 case GL_ANY_SAMPLES_PASSED:
1245 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1246 return true;
1247 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1248 return (context->getClientMajorVersion() >= 3);
1249 case GL_TIME_ELAPSED_EXT:
1250 return context->getExtensions().disjointTimerQuery;
1251 case GL_COMMANDS_COMPLETED_CHROMIUM:
1252 return context->getExtensions().syncQuery;
1253 default:
1254 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001255 }
1256}
1257
Geoff Lang2d62ab72017-03-23 16:54:40 -04001258bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
1259 GLenum type,
1260 GLboolean normalized,
1261 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001262 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001263 bool pureInteger)
1264{
1265 ASSERT(context->getExtensions().webglCompatibility);
1266
1267 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1268 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1269 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1270 // parameter exceeds 255.
1271 constexpr GLsizei kMaxWebGLStride = 255;
1272 if (stride > kMaxWebGLStride)
1273 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001274 context->handleError(InvalidValue()
1275 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001276 return false;
1277 }
1278
1279 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1280 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1281 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1282 // or an INVALID_OPERATION error is generated.
1283 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1284 size_t typeSize = GetVertexFormatTypeSize(internalType);
1285
1286 ASSERT(isPow2(typeSize) && typeSize > 0);
1287 size_t sizeMask = (typeSize - 1);
1288 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1289 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001290 context->handleError(InvalidOperation() << "Offset is not a multiple of the type size.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001291 return false;
1292 }
1293
1294 if ((stride & sizeMask) != 0)
1295 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001296 context->handleError(InvalidOperation() << "Stride is not a multiple of the type size.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001297 return false;
1298 }
1299
1300 return true;
1301}
1302
Jamie Madillef300b12016-10-07 15:12:09 -04001303Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001304{
He Yunchaoced53ae2016-11-29 15:00:51 +08001305 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1306 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1307 // or program object and INVALID_OPERATION if the provided name identifies an object
1308 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001309
Dian Xiang769769a2015-09-09 15:20:08 -07001310 Program *validProgram = context->getProgram(id);
1311
1312 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001313 {
Dian Xiang769769a2015-09-09 15:20:08 -07001314 if (context->getShader(id))
1315 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001316 context->handleError(InvalidOperation()
1317 << "Expected a program name, but found a shader name");
Dian Xiang769769a2015-09-09 15:20:08 -07001318 }
1319 else
1320 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001321 context->handleError(InvalidValue() << "Program name is not valid");
Dian Xiang769769a2015-09-09 15:20:08 -07001322 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001323 }
Dian Xiang769769a2015-09-09 15:20:08 -07001324
1325 return validProgram;
1326}
1327
Jamie Madillef300b12016-10-07 15:12:09 -04001328Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001329{
1330 // See ValidProgram for spec details.
1331
1332 Shader *validShader = context->getShader(id);
1333
1334 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001335 {
Dian Xiang769769a2015-09-09 15:20:08 -07001336 if (context->getProgram(id))
1337 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001338 context->handleError(InvalidOperation()
1339 << "Expected a shader name, but found a program name");
Dian Xiang769769a2015-09-09 15:20:08 -07001340 }
1341 else
1342 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001343 context->handleError(InvalidValue() << "Shader name is invalid");
Dian Xiang769769a2015-09-09 15:20:08 -07001344 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001345 }
Dian Xiang769769a2015-09-09 15:20:08 -07001346
1347 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001348}
1349
Geoff Langb1196682014-07-23 13:47:29 -04001350bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001351{
1352 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1353 {
1354 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1355
Geoff Langaae65a42014-05-26 12:43:44 -04001356 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001357 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001358 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001359 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001360 }
1361 }
1362 else
1363 {
1364 switch (attachment)
1365 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001366 case GL_DEPTH_ATTACHMENT:
1367 case GL_STENCIL_ATTACHMENT:
1368 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001369
He Yunchaoced53ae2016-11-29 15:00:51 +08001370 case GL_DEPTH_STENCIL_ATTACHMENT:
1371 if (!context->getExtensions().webglCompatibility &&
1372 context->getClientMajorVersion() < 3)
1373 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001374 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001375 return false;
1376 }
1377 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001378
He Yunchaoced53ae2016-11-29 15:00:51 +08001379 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001380 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001381 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001382 }
1383 }
1384
1385 return true;
1386}
1387
Jamie Madille8fb6402017-02-14 17:56:40 -05001388bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001389 GLenum target,
1390 GLsizei samples,
1391 GLenum internalformat,
1392 GLsizei width,
1393 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001394{
1395 switch (target)
1396 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001397 case GL_RENDERBUFFER:
1398 break;
1399 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001400 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001401 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001402 }
1403
1404 if (width < 0 || height < 0 || samples < 0)
1405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001406 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001407 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001408 }
1409
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001410 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1411 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1412
1413 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001414 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001415 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001416 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001417 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001418 }
1419
1420 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1421 // 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 -08001422 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001423 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1424 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001425 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001426 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001427 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001428 }
1429
Geoff Langaae65a42014-05-26 12:43:44 -04001430 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001431 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001432 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001433 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001434 }
1435
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001436 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001437 if (handle == 0)
1438 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001439 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001440 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001441 }
1442
1443 return true;
1444}
1445
He Yunchaoced53ae2016-11-29 15:00:51 +08001446bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1447 GLenum target,
1448 GLenum attachment,
1449 GLenum renderbuffertarget,
1450 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001451{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001452 if (!ValidFramebufferTarget(target))
1453 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001454 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001455 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001456 }
1457
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001458 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001459
Jamie Madill84115c92015-04-23 15:00:07 -04001460 ASSERT(framebuffer);
1461 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001463 context->handleError(InvalidOperation() << "Cannot change default FBO's attachments");
Geoff Langb1196682014-07-23 13:47:29 -04001464 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001465 }
1466
Jamie Madillb4472272014-07-03 10:38:55 -04001467 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001468 {
Jamie Madillb4472272014-07-03 10:38:55 -04001469 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001470 }
1471
Jamie Madillab9d82c2014-01-21 16:38:14 -05001472 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1473 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1474 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1475 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1476 if (renderbuffer != 0)
1477 {
1478 if (!context->getRenderbuffer(renderbuffer))
1479 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001480 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001481 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001482 }
1483 }
1484
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001485 return true;
1486}
1487
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001488bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001489 GLint srcX0,
1490 GLint srcY0,
1491 GLint srcX1,
1492 GLint srcY1,
1493 GLint dstX0,
1494 GLint dstY0,
1495 GLint dstX1,
1496 GLint dstY1,
1497 GLbitfield mask,
1498 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001499{
1500 switch (filter)
1501 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001502 case GL_NEAREST:
1503 break;
1504 case GL_LINEAR:
1505 break;
1506 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001507 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001508 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001509 }
1510
1511 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001513 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001514 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001515 }
1516
1517 if (mask == 0)
1518 {
1519 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1520 // buffers are copied.
1521 return false;
1522 }
1523
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001524 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1525 // color buffer, leaving only nearest being unfiltered from above
1526 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1527 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001528 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001529 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001530 }
1531
Jamie Madill51f40ec2016-06-15 14:06:00 -04001532 const auto &glState = context->getGLState();
1533 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1534 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001535
1536 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001537 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001538 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001539 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001540 }
1541
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001542 if (readFramebuffer->id() == drawFramebuffer->id())
1543 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001544 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001545 return false;
1546 }
1547
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001548 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001549 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001550 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001551 return false;
1552 }
1553
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001554 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001555 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001556 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001557 return false;
1558 }
1559
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001560 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001561 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001562 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001563 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001564 }
1565
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001566 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1567
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001568 if (mask & GL_COLOR_BUFFER_BIT)
1569 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001570 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001571 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001572
He Yunchao66a41a22016-12-15 16:45:05 +08001573 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001574 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001575 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001576
Geoff Langa15472a2015-08-11 11:48:03 -04001577 for (size_t drawbufferIdx = 0;
1578 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001579 {
Geoff Langa15472a2015-08-11 11:48:03 -04001580 const FramebufferAttachment *attachment =
1581 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1582 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001583 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001584 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001585
Geoff Langb2f3d052013-08-13 12:49:27 -04001586 // The GL ES 3.0.2 spec (pg 193) states that:
1587 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001588 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1589 // as well
1590 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1591 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001592 // Changes with EXT_color_buffer_float:
1593 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001594 GLenum readComponentType = readFormat.info->componentType;
1595 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001596 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001597 readComponentType == GL_SIGNED_NORMALIZED);
1598 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1599 drawComponentType == GL_SIGNED_NORMALIZED);
1600
1601 if (extensions.colorBufferFloat)
1602 {
1603 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1604 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1605
1606 if (readFixedOrFloat != drawFixedOrFloat)
1607 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001608 context->handleError(InvalidOperation()
1609 << "If the read buffer contains fixed-point or "
1610 "floating-point values, the draw buffer must "
1611 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001612 return false;
1613 }
1614 }
1615 else if (readFixedPoint != drawFixedPoint)
1616 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001617 context->handleError(InvalidOperation()
1618 << "If the read buffer contains fixed-point values, "
1619 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001620 return false;
1621 }
1622
1623 if (readComponentType == GL_UNSIGNED_INT &&
1624 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001625 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001626 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001627 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001628 }
1629
Jamie Madill6163c752015-12-07 16:32:59 -05001630 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001631 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001632 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001633 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001634 }
1635
Jamie Madilla3944d42016-07-22 22:13:26 -04001636 if (readColorBuffer->getSamples() > 0 &&
1637 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001638 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001639 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001640 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001641 }
Geoff Lange4915782017-04-12 15:19:07 -04001642
1643 if (context->getExtensions().webglCompatibility &&
1644 *readColorBuffer == *attachment)
1645 {
1646 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001647 InvalidOperation()
1648 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001649 return false;
1650 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001651 }
1652 }
1653
Jamie Madilla3944d42016-07-22 22:13:26 -04001654 if ((readFormat.info->componentType == GL_INT ||
1655 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1656 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001657 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001658 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001659 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001660 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001661 }
He Yunchao66a41a22016-12-15 16:45:05 +08001662 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1663 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1664 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1665 // situation is an application error that would lead to a crash in ANGLE.
1666 else if (drawFramebuffer->hasEnabledDrawBuffer())
1667 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001668 context->handleError(
1669 InvalidOperation()
1670 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001671 return false;
1672 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001673 }
1674
He Yunchaoced53ae2016-11-29 15:00:51 +08001675 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001676 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1677 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001678 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001679 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001680 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001681 const gl::FramebufferAttachment *readBuffer =
1682 readFramebuffer->getAttachment(attachments[i]);
1683 const gl::FramebufferAttachment *drawBuffer =
1684 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001685
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001686 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001687 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001688 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001689 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001690 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001691 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001692 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001693
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001694 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001695 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001696 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001697 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001698 }
Geoff Lange4915782017-04-12 15:19:07 -04001699
1700 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1701 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001702 context->handleError(
1703 InvalidOperation()
1704 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001705 return false;
1706 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001707 }
He Yunchao66a41a22016-12-15 16:45:05 +08001708 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1709 else if (drawBuffer)
1710 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001711 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1712 "depth/stencil attachment of a "
1713 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001714 return false;
1715 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001716 }
1717 }
1718
1719 return true;
1720}
1721
Geoff Lang62fce5b2016-09-30 10:46:35 -04001722bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
1723 GLint x,
1724 GLint y,
1725 GLsizei width,
1726 GLsizei height,
1727 GLenum format,
1728 GLenum type,
1729 GLsizei bufSize,
1730 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001731 GLsizei *columns,
1732 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001733 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001734{
1735 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001736 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001737 return false;
1738 }
1739
Geoff Lang62fce5b2016-09-30 10:46:35 -04001740 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001741 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001742 {
Geoff Langb1196682014-07-23 13:47:29 -04001743 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001744 }
1745
Geoff Lang62fce5b2016-09-30 10:46:35 -04001746 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001747 {
Geoff Langb1196682014-07-23 13:47:29 -04001748 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001749 }
1750
Jamie Madillc29968b2016-01-20 11:17:23 -05001751 return true;
1752}
1753
1754bool ValidateReadnPixelsEXT(Context *context,
1755 GLint x,
1756 GLint y,
1757 GLsizei width,
1758 GLsizei height,
1759 GLenum format,
1760 GLenum type,
1761 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001762 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001763{
1764 if (bufSize < 0)
1765 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001766 context->handleError(InvalidValue() << "bufSize must be a positive number");
Jamie Madillc29968b2016-01-20 11:17:23 -05001767 return false;
1768 }
1769
Geoff Lang62fce5b2016-09-30 10:46:35 -04001770 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001771 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001772}
Jamie Madill26e91952014-03-05 15:01:27 -05001773
Geoff Lang62fce5b2016-09-30 10:46:35 -04001774bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
1775 GLint x,
1776 GLint y,
1777 GLsizei width,
1778 GLsizei height,
1779 GLenum format,
1780 GLenum type,
1781 GLsizei bufSize,
1782 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001783 GLsizei *columns,
1784 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001785 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001786{
1787 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001788 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001789 return false;
1790 }
1791
Geoff Lange93daba2017-03-30 13:54:40 -04001792 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1793 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001794 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001795 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001796 }
1797
Geoff Lang62fce5b2016-09-30 10:46:35 -04001798 if (!ValidateRobustBufferSize(context, bufSize, *length))
1799 {
1800 return false;
1801 }
1802
1803 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001804}
1805
Olli Etuaho41997e72016-03-10 13:38:39 +02001806bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001807{
1808 if (!context->getExtensions().occlusionQueryBoolean &&
1809 !context->getExtensions().disjointTimerQuery)
1810 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001811 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001812 return false;
1813 }
1814
Olli Etuaho41997e72016-03-10 13:38:39 +02001815 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001816}
1817
Olli Etuaho41997e72016-03-10 13:38:39 +02001818bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001819{
1820 if (!context->getExtensions().occlusionQueryBoolean &&
1821 !context->getExtensions().disjointTimerQuery)
1822 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001823 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001824 return false;
1825 }
1826
Olli Etuaho41997e72016-03-10 13:38:39 +02001827 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001828}
1829
1830bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001831{
1832 if (!ValidQueryType(context, target))
1833 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001834 context->handleError(InvalidEnum() << "Invalid query target");
Geoff Langb1196682014-07-23 13:47:29 -04001835 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001836 }
1837
1838 if (id == 0)
1839 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001840 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001841 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001842 }
1843
1844 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1845 // of zero, if the active query object name for <target> is non-zero (for the
1846 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1847 // the active query for either target is non-zero), if <id> is the name of an
1848 // existing query object whose type does not match <target>, or if <id> is the
1849 // active query object name for any query type, the error INVALID_OPERATION is
1850 // generated.
1851
1852 // Ensure no other queries are active
1853 // NOTE: If other queries than occlusion are supported, we will need to check
1854 // separately that:
1855 // a) The query ID passed is not the current active query for any target/type
1856 // b) There are no active queries for the requested target (and in the case
1857 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1858 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001859
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001860 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001861 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001862 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001863 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001864 }
1865
1866 Query *queryObject = context->getQuery(id, true, target);
1867
1868 // check that name was obtained with glGenQueries
1869 if (!queryObject)
1870 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001871 context->handleError(InvalidOperation() << "Invalid query id");
Geoff Langb1196682014-07-23 13:47:29 -04001872 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001873 }
1874
1875 // check for type mismatch
1876 if (queryObject->getType() != target)
1877 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001878 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001879 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001880 }
1881
1882 return true;
1883}
1884
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001885bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1886{
1887 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001888 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001889 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001890 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001891 return false;
1892 }
1893
1894 return ValidateBeginQueryBase(context, target, id);
1895}
1896
1897bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001898{
1899 if (!ValidQueryType(context, target))
1900 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001901 context->handleError(InvalidEnum() << "Invalid query target");
Geoff Langb1196682014-07-23 13:47:29 -04001902 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001903 }
1904
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001905 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001906
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001907 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001908 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001909 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001910 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001911 }
1912
Jamie Madill45c785d2014-05-13 14:09:34 -04001913 return true;
1914}
1915
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001916bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1917{
1918 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001919 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001920 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001921 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001922 return false;
1923 }
1924
1925 return ValidateEndQueryBase(context, target);
1926}
1927
1928bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1929{
1930 if (!context->getExtensions().disjointTimerQuery)
1931 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001932 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001933 return false;
1934 }
1935
1936 if (target != GL_TIMESTAMP_EXT)
1937 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001938 context->handleError(InvalidEnum() << "Invalid query target");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001939 return false;
1940 }
1941
1942 Query *queryObject = context->getQuery(id, true, target);
1943 if (queryObject == nullptr)
1944 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001945 context->handleError(InvalidOperation() << "Invalid query id");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001946 return false;
1947 }
1948
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001949 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001950 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001951 context->handleError(InvalidOperation() << "Query is active");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001952 return false;
1953 }
1954
1955 return true;
1956}
1957
Geoff Lang2186c382016-10-14 10:54:54 -04001958bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001959{
Geoff Lang2186c382016-10-14 10:54:54 -04001960 if (numParams)
1961 {
1962 *numParams = 0;
1963 }
1964
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001965 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1966 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001967 context->handleError(InvalidEnum() << "Invalid query type");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001968 return false;
1969 }
1970
1971 switch (pname)
1972 {
1973 case GL_CURRENT_QUERY_EXT:
1974 if (target == GL_TIMESTAMP_EXT)
1975 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001976 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001977 return false;
1978 }
1979 break;
1980 case GL_QUERY_COUNTER_BITS_EXT:
1981 if (!context->getExtensions().disjointTimerQuery ||
1982 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1983 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001984 context->handleError(InvalidEnum() << "Invalid pname");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001985 return false;
1986 }
1987 break;
1988 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001989 context->handleError(InvalidEnum() << "Invalid pname");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001990 return false;
1991 }
1992
Geoff Lang2186c382016-10-14 10:54:54 -04001993 if (numParams)
1994 {
1995 // All queries return only one value
1996 *numParams = 1;
1997 }
1998
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001999 return true;
2000}
2001
2002bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2003{
2004 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002005 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002006 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002007 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002008 return false;
2009 }
2010
Geoff Lang2186c382016-10-14 10:54:54 -04002011 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002012}
2013
Geoff Lang2186c382016-10-14 10:54:54 -04002014bool ValidateGetQueryivRobustANGLE(Context *context,
2015 GLenum target,
2016 GLenum pname,
2017 GLsizei bufSize,
2018 GLsizei *length,
2019 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002020{
Geoff Lang2186c382016-10-14 10:54:54 -04002021 if (!ValidateRobustEntryPoint(context, bufSize))
2022 {
2023 return false;
2024 }
2025
2026 if (!ValidateGetQueryivBase(context, target, pname, length))
2027 {
2028 return false;
2029 }
2030
2031 if (!ValidateRobustBufferSize(context, bufSize, *length))
2032 {
2033 return false;
2034 }
2035
2036 return true;
2037}
2038
2039bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2040{
2041 if (numParams)
2042 {
2043 *numParams = 0;
2044 }
2045
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002046 Query *queryObject = context->getQuery(id, false, GL_NONE);
2047
2048 if (!queryObject)
2049 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002050 context->handleError(InvalidOperation() << "Query does not exist");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002051 return false;
2052 }
2053
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002054 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002055 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002056 context->handleError(InvalidOperation() << "Query currently active");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002057 return false;
2058 }
2059
2060 switch (pname)
2061 {
2062 case GL_QUERY_RESULT_EXT:
2063 case GL_QUERY_RESULT_AVAILABLE_EXT:
2064 break;
2065
2066 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002067 context->handleError(InvalidEnum() << "Invalid pname enum");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002068 return false;
2069 }
2070
Geoff Lang2186c382016-10-14 10:54:54 -04002071 if (numParams)
2072 {
2073 *numParams = 1;
2074 }
2075
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002076 return true;
2077}
2078
2079bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2080{
2081 if (!context->getExtensions().disjointTimerQuery)
2082 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002083 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002084 return false;
2085 }
Geoff Lang2186c382016-10-14 10:54:54 -04002086 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2087}
2088
2089bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2090 GLuint id,
2091 GLenum pname,
2092 GLsizei bufSize,
2093 GLsizei *length,
2094 GLint *params)
2095{
2096 if (!context->getExtensions().disjointTimerQuery)
2097 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002098 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002099 return false;
2100 }
2101
2102 if (!ValidateRobustEntryPoint(context, bufSize))
2103 {
2104 return false;
2105 }
2106
2107 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2108 {
2109 return false;
2110 }
2111
2112 if (!ValidateRobustBufferSize(context, bufSize, *length))
2113 {
2114 return false;
2115 }
2116
2117 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002118}
2119
2120bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2121{
2122 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002123 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002124 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002125 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002126 return false;
2127 }
Geoff Lang2186c382016-10-14 10:54:54 -04002128 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2129}
2130
2131bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2132 GLuint id,
2133 GLenum pname,
2134 GLsizei bufSize,
2135 GLsizei *length,
2136 GLuint *params)
2137{
2138 if (!context->getExtensions().disjointTimerQuery &&
2139 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2140 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002141 context->handleError(InvalidOperation() << "Query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002142 return false;
2143 }
2144
2145 if (!ValidateRobustEntryPoint(context, bufSize))
2146 {
2147 return false;
2148 }
2149
2150 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2151 {
2152 return false;
2153 }
2154
2155 if (!ValidateRobustBufferSize(context, bufSize, *length))
2156 {
2157 return false;
2158 }
2159
2160 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002161}
2162
2163bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2164{
2165 if (!context->getExtensions().disjointTimerQuery)
2166 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002167 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002168 return false;
2169 }
Geoff Lang2186c382016-10-14 10:54:54 -04002170 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2171}
2172
2173bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2174 GLuint id,
2175 GLenum pname,
2176 GLsizei bufSize,
2177 GLsizei *length,
2178 GLint64 *params)
2179{
2180 if (!context->getExtensions().disjointTimerQuery)
2181 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002182 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002183 return false;
2184 }
2185
2186 if (!ValidateRobustEntryPoint(context, bufSize))
2187 {
2188 return false;
2189 }
2190
2191 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2192 {
2193 return false;
2194 }
2195
2196 if (!ValidateRobustBufferSize(context, bufSize, *length))
2197 {
2198 return false;
2199 }
2200
2201 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002202}
2203
2204bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2205{
2206 if (!context->getExtensions().disjointTimerQuery)
2207 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002208 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002209 return false;
2210 }
Geoff Lang2186c382016-10-14 10:54:54 -04002211 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2212}
2213
2214bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2215 GLuint id,
2216 GLenum pname,
2217 GLsizei bufSize,
2218 GLsizei *length,
2219 GLuint64 *params)
2220{
2221 if (!context->getExtensions().disjointTimerQuery)
2222 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002223 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002224 return false;
2225 }
2226
2227 if (!ValidateRobustEntryPoint(context, bufSize))
2228 {
2229 return false;
2230 }
2231
2232 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2233 {
2234 return false;
2235 }
2236
2237 if (!ValidateRobustBufferSize(context, bufSize, *length))
2238 {
2239 return false;
2240 }
2241
2242 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002243}
2244
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002245bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002246 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002247 GLuint program,
2248 GLint location,
2249 GLsizei count)
2250{
2251 // Check for ES31 program uniform entry points
2252 if (context->getClientVersion() < Version(3, 1))
2253 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002254 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002255 return false;
2256 }
2257
2258 const LinkedUniform *uniform = nullptr;
2259 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002260 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2261 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002262}
2263
Frank Henigmana98a6472017-02-02 21:38:32 -05002264bool ValidateProgramUniform1iv(gl::Context *context,
2265 GLuint program,
2266 GLint location,
2267 GLsizei count,
2268 const GLint *value)
2269{
2270 // Check for ES31 program uniform entry points
2271 if (context->getClientVersion() < Version(3, 1))
2272 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002273 context->handleError(InvalidOperation());
Frank Henigmana98a6472017-02-02 21:38:32 -05002274 return false;
2275 }
2276
2277 const LinkedUniform *uniform = nullptr;
2278 gl::Program *programObject = GetValidProgram(context, program);
2279 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2280 ValidateUniform1ivValue(context, uniform->type, count, value);
2281}
2282
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002283bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002284 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002285 GLuint program,
2286 GLint location,
2287 GLsizei count,
2288 GLboolean transpose)
2289{
2290 // Check for ES31 program uniform entry points
2291 if (context->getClientVersion() < Version(3, 1))
2292 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002293 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002294 return false;
2295 }
2296
2297 const LinkedUniform *uniform = nullptr;
2298 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002299 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2300 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002301}
2302
Jamie Madillc1d770e2017-04-13 17:31:24 -04002303bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002304{
2305 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002306 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002307 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002308 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002309 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002310 }
2311
Jamie Madill62d31cb2015-09-11 13:25:51 -04002312 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002313 gl::Program *programObject = context->getGLState().getProgram();
2314 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2315 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002316}
2317
Jamie Madillbe849e42017-05-02 15:49:00 -04002318bool ValidateUniform1iv(ValidationContext *context,
2319 GLint location,
2320 GLsizei count,
2321 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002322{
2323 const LinkedUniform *uniform = nullptr;
2324 gl::Program *programObject = context->getGLState().getProgram();
2325 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2326 ValidateUniform1ivValue(context, uniform->type, count, value);
2327}
2328
Jamie Madillc1d770e2017-04-13 17:31:24 -04002329bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002330 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002331 GLint location,
2332 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002333 GLboolean transpose)
2334{
2335 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002336 int rows = VariableRowCount(valueType);
2337 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002338 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002339 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002340 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002341 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002342 }
2343
Martin Radev1be913c2016-07-11 17:59:16 +03002344 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002345 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002346 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002347 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002348 }
2349
Jamie Madill62d31cb2015-09-11 13:25:51 -04002350 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002351 gl::Program *programObject = context->getGLState().getProgram();
2352 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2353 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002354}
2355
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002356bool ValidateStateQuery(ValidationContext *context,
2357 GLenum pname,
2358 GLenum *nativeType,
2359 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002360{
2361 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002363 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002364 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002365 }
2366
Jamie Madill0af26e12015-03-05 19:54:33 -05002367 const Caps &caps = context->getCaps();
2368
Jamie Madill893ab082014-05-16 16:56:10 -04002369 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2370 {
2371 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2372
Jamie Madill0af26e12015-03-05 19:54:33 -05002373 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002374 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002375 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002376 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002377 }
2378 }
2379
2380 switch (pname)
2381 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002382 case GL_TEXTURE_BINDING_2D:
2383 case GL_TEXTURE_BINDING_CUBE_MAP:
2384 case GL_TEXTURE_BINDING_3D:
2385 case GL_TEXTURE_BINDING_2D_ARRAY:
2386 break;
2387 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2388 if (!context->getExtensions().eglStreamConsumerExternal &&
2389 !context->getExtensions().eglImageExternal)
2390 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002391 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2392 "nor GL_OES_EGL_image_external "
2393 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002394 return false;
2395 }
2396 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002397
He Yunchaoced53ae2016-11-29 15:00:51 +08002398 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2399 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002400 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002401 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2402 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002404 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002405 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002406 }
2407
Jamie Madill51f40ec2016-06-15 14:06:00 -04002408 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2409 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002410
2411 if (framebuffer->getReadBufferState() == GL_NONE)
2412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002413 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Martin Radev138064f2016-07-15 12:03:41 +03002414 return false;
2415 }
2416
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002417 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002418 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002419 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002420 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002421 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002422 }
2423 }
2424 break;
2425
He Yunchaoced53ae2016-11-29 15:00:51 +08002426 default:
2427 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002428 }
2429
2430 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002431 if (*numParams == 0)
2432 {
2433 return false;
2434 }
2435
2436 return true;
2437}
2438
2439bool ValidateRobustStateQuery(ValidationContext *context,
2440 GLenum pname,
2441 GLsizei bufSize,
2442 GLenum *nativeType,
2443 unsigned int *numParams)
2444{
2445 if (!ValidateRobustEntryPoint(context, bufSize))
2446 {
2447 return false;
2448 }
2449
2450 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2451 {
2452 return false;
2453 }
2454
2455 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002456 {
2457 return false;
2458 }
2459
2460 return true;
2461}
2462
Jamie Madillc29968b2016-01-20 11:17:23 -05002463bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2464 GLenum target,
2465 GLint level,
2466 GLenum internalformat,
2467 bool isSubImage,
2468 GLint xoffset,
2469 GLint yoffset,
2470 GLint zoffset,
2471 GLint x,
2472 GLint y,
2473 GLsizei width,
2474 GLsizei height,
2475 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002476 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002477{
Jamie Madill560a8d82014-05-21 13:06:20 -04002478 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2479 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002480 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002481 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002482 }
2483
He Yunchaoced53ae2016-11-29 15:00:51 +08002484 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2485 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002486 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002487 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002488 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002489 }
2490
2491 if (border != 0)
2492 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002493 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002494 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002495 }
2496
2497 if (!ValidMipLevel(context, target, level))
2498 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002499 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002500 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002501 }
2502
Jamie Madill51f40ec2016-06-15 14:06:00 -04002503 const auto &state = context->getGLState();
2504 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002505 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002506 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002507 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002508 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002509 }
2510
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002511 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002513 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002514 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002515 }
2516
Martin Radev138064f2016-07-15 12:03:41 +03002517 if (readFramebuffer->getReadBufferState() == GL_NONE)
2518 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002519 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Martin Radev138064f2016-07-15 12:03:41 +03002520 return false;
2521 }
2522
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002523 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2524 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002525 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002526 // situation is an application error that would lead to a crash in ANGLE.
2527 if (readFramebuffer->getReadColorbuffer() == nullptr)
2528 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002529 context->handleError(InvalidOperation() << "Missing read attachment");
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002530 return false;
2531 }
2532
Geoff Langaae65a42014-05-26 12:43:44 -04002533 const gl::Caps &caps = context->getCaps();
2534
Geoff Langaae65a42014-05-26 12:43:44 -04002535 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002536 switch (target)
2537 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002538 case GL_TEXTURE_2D:
2539 maxDimension = caps.max2DTextureSize;
2540 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002541
He Yunchaoced53ae2016-11-29 15:00:51 +08002542 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2543 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2544 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2545 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2546 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2547 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2548 maxDimension = caps.maxCubeMapTextureSize;
2549 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002550
He Yunchaoced53ae2016-11-29 15:00:51 +08002551 case GL_TEXTURE_2D_ARRAY:
2552 maxDimension = caps.max2DTextureSize;
2553 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002554
He Yunchaoced53ae2016-11-29 15:00:51 +08002555 case GL_TEXTURE_3D:
2556 maxDimension = caps.max3DTextureSize;
2557 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002558
He Yunchaoced53ae2016-11-29 15:00:51 +08002559 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002560 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002561 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002562 }
2563
Jamie Madillc29968b2016-01-20 11:17:23 -05002564 gl::Texture *texture =
2565 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002566 if (!texture)
2567 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002568 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002569 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002570 }
2571
Geoff Lang69cce582015-09-17 13:20:36 -04002572 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002573 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002574 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002575 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002576 }
2577
Geoff Langca271392017-04-05 12:30:00 -04002578 const gl::InternalFormat &formatInfo =
2579 gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002580
Geoff Lang966c9402017-04-18 12:38:27 -04002581 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002582 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002583 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002584 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002585 }
2586
2587 if (isSubImage)
2588 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002589 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2590 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2591 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002592 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002593 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002594 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002595 }
2596 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002597 else
2598 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002599 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002600 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002601 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002602 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002603 }
2604
Geoff Langeb66a6e2016-10-31 13:06:12 -04002605 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002606 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002607 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002608 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002609 }
2610
2611 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002612 if (static_cast<int>(width) > maxLevelDimension ||
2613 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002615 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002616 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002617 }
2618 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002619
Jamie Madill0c8abca2016-07-22 20:21:26 -04002620 if (textureFormatOut)
2621 {
2622 *textureFormatOut = texture->getFormat(target, level);
2623 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002624
2625 // Detect texture copying feedback loops for WebGL.
2626 if (context->getExtensions().webglCompatibility)
2627 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002628 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002629 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002630 context->handleError(InvalidOperation() << "Texture copying feedback loop formed "
2631 "between Framebuffer and specified "
2632 "Texture level.");
Jamie Madillf695a3a2017-01-11 17:36:35 -05002633 return false;
2634 }
2635 }
2636
Jamie Madill560a8d82014-05-21 13:06:20 -04002637 return true;
2638}
2639
Jiajia Qind9671222016-11-29 16:30:31 +08002640bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002641{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002642 switch (mode)
2643 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002644 case GL_POINTS:
2645 case GL_LINES:
2646 case GL_LINE_LOOP:
2647 case GL_LINE_STRIP:
2648 case GL_TRIANGLES:
2649 case GL_TRIANGLE_STRIP:
2650 case GL_TRIANGLE_FAN:
2651 break;
2652 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002653 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002654 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002655 }
2656
Jamie Madill250d33f2014-06-06 17:09:03 -04002657 if (count < 0)
2658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002659 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002660 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002661 }
2662
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002663 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002664
Jamie Madill250d33f2014-06-06 17:09:03 -04002665 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002666 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002667 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002668 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002669 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002670 }
2671
Jamie Madillcbcde722017-01-06 14:50:00 -05002672 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2673 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002674 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002675 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
2676 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002677 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002678 const FramebufferAttachment *dsAttachment =
2679 framebuffer->getStencilOrDepthStencilAttachment();
2680 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002681 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002682 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002683
2684 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2685 bool differentWritemasks =
2686 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2687 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2688 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2689 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2690
2691 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002692 {
Jamie Madillcbcde722017-01-06 14:50:00 -05002693 if (!context->getExtensions().webglCompatibility)
2694 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002695 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2696 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002697 }
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002698 context->handleError(InvalidOperation());
Geoff Lang3a86ad32015-09-01 11:47:05 -04002699 return false;
2700 }
Jamie Madillac528012014-06-20 13:21:23 -04002701 }
2702
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002703 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002705 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002706 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002707 }
2708
Geoff Lang7dd2e102014-11-10 15:19:26 -05002709 gl::Program *program = state.getProgram();
2710 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002711 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002712 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002713 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002714 }
2715
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002716 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002717 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002718 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002719 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002720 }
2721
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002722 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002723 for (unsigned int uniformBlockIndex = 0;
2724 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002725 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002726 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002727 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002728 const OffsetBindingPointer<Buffer> &uniformBuffer =
2729 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002730
Geoff Lang5d124a62015-09-15 13:03:27 -04002731 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002732 {
2733 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002734 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002735 InvalidOperation()
2736 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002737 return false;
2738 }
2739
Geoff Lang5d124a62015-09-15 13:03:27 -04002740 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002741 if (uniformBufferSize == 0)
2742 {
2743 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002744 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002745 }
2746
Jamie Madill62d31cb2015-09-11 13:25:51 -04002747 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002748 {
2749 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002750 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002751 InvalidOperation()
2752 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002753 return false;
2754 }
2755 }
2756
Geoff Lange0cff192017-05-30 13:04:56 -04002757 // Do some additonal WebGL-specific validation
Jamie Madilla4595b82017-01-11 17:36:34 -05002758 if (context->getExtensions().webglCompatibility)
2759 {
Geoff Lange0cff192017-05-30 13:04:56 -04002760 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002761 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2762 {
2763 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002764 InvalidOperation()
2765 << "Rendering feedback loop formed between Framebuffer and active Texture.");
Jamie Madilla4595b82017-01-11 17:36:34 -05002766 return false;
2767 }
Geoff Lange0cff192017-05-30 13:04:56 -04002768
Geoff Lang9ab5b822017-05-30 16:19:23 -04002769 // Detect that the vertex shader input types match the attribute types
2770 if (!ValidateVertexShaderAttributeTypeMatch(context))
2771 {
2772 return false;
2773 }
2774
Geoff Lange0cff192017-05-30 13:04:56 -04002775 // Detect that the color buffer types match the fragment shader output types
2776 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2777 {
2778 return false;
2779 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002780 }
2781
Jamie Madill250d33f2014-06-06 17:09:03 -04002782 // No-op if zero count
2783 return (count > 0);
2784}
2785
Jamie Madillc1d770e2017-04-13 17:31:24 -04002786bool ValidateDrawArraysCommon(ValidationContext *context,
2787 GLenum mode,
2788 GLint first,
2789 GLsizei count,
2790 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002791{
Jamie Madillfd716582014-06-06 17:09:04 -04002792 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002793 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002794 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002795 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002796 }
2797
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002798 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002799 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002800 if (curTransformFeedback && curTransformFeedback->isActive() &&
2801 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002802 {
2803 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002804 // that does not match the current transform feedback object's draw mode (if transform
2805 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002806 // is active), (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002807 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002808 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002809 }
2810
Jiajia Qind9671222016-11-29 16:30:31 +08002811 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002812 {
2813 return false;
2814 }
2815
Corentin Wallez71168a02016-12-19 15:11:18 -08002816 // Check the computation of maxVertex doesn't overflow.
2817 // - first < 0 or count < 0 have been checked as an error condition
2818 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2819 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2820 ASSERT(count > 0 && first >= 0);
2821 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2822 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002823 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002824 context->handleError(InvalidOperation() << "Integer overflow.");
Corentin Wallez92db6942016-12-09 13:10:36 -05002825 return false;
2826 }
2827
Corentin Wallez71168a02016-12-19 15:11:18 -08002828 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002829 {
2830 return false;
2831 }
2832
2833 return true;
2834}
2835
He Yunchaoced53ae2016-11-29 15:00:51 +08002836bool ValidateDrawArraysInstanced(Context *context,
2837 GLenum mode,
2838 GLint first,
2839 GLsizei count,
2840 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002841{
Corentin Wallez170efbf2017-05-02 13:45:01 -04002842 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04002843 {
2844 return false;
2845 }
2846
Corentin Wallez170efbf2017-05-02 13:45:01 -04002847 return !context->getExtensions().webglCompatibility ||
2848 ValidateDrawInstancedANGLEAndWebGL(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002849}
2850
He Yunchaoced53ae2016-11-29 15:00:51 +08002851bool ValidateDrawArraysInstancedANGLE(Context *context,
2852 GLenum mode,
2853 GLint first,
2854 GLsizei count,
2855 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002856{
Corentin Wallez170efbf2017-05-02 13:45:01 -04002857 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002858 {
2859 return false;
2860 }
2861
Corentin Wallez170efbf2017-05-02 13:45:01 -04002862 return ValidateDrawInstancedANGLEAndWebGL(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002863}
2864
Jiajia Qind9671222016-11-29 16:30:31 +08002865bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002866{
Jamie Madill250d33f2014-06-06 17:09:03 -04002867 switch (type)
2868 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002869 case GL_UNSIGNED_BYTE:
2870 case GL_UNSIGNED_SHORT:
2871 break;
2872 case GL_UNSIGNED_INT:
2873 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2874 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002875 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002876 return false;
2877 }
2878 break;
2879 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002880 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002881 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002882 }
2883
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002884 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002885
2886 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002887 if (curTransformFeedback && curTransformFeedback->isActive() &&
2888 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002889 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002890 // It is an invalid operation to call DrawElements, DrawRangeElements or
2891 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002892 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002893 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002894 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002895 }
2896
Jiajia Qind9671222016-11-29 16:30:31 +08002897 return true;
2898}
2899
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002900bool ValidateDrawElementsCommon(ValidationContext *context,
2901 GLenum mode,
2902 GLsizei count,
2903 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002904 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002905 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002906{
2907 if (!ValidateDrawElementsBase(context, type))
2908 return false;
2909
2910 const State &state = context->getGLState();
2911
Corentin Wallez170efbf2017-05-02 13:45:01 -04002912 if (!ValidateDrawBase(context, mode, count))
2913 {
2914 return false;
2915 }
2916
Jamie Madill250d33f2014-06-06 17:09:03 -04002917 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002918 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002919 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002920 context->handleError(InvalidOperation() << "Index buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -04002921 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002922 }
2923
He Yunchaoced53ae2016-11-29 15:00:51 +08002924 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002925 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002926
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002927 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2928
2929 if (context->getExtensions().webglCompatibility)
2930 {
2931 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2932 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2933 {
2934 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2935 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2936 // data type passed to the call, or an INVALID_OPERATION error is generated.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002937 context->handleError(InvalidOperation()
2938 << "indices must be a multiple of the element type size.");
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002939 return false;
2940 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002941
2942 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2943 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2944 // error is generated.
2945 if (reinterpret_cast<intptr_t>(indices) < 0)
2946 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002947 context->handleError(InvalidValue() << "Offset < 0.");
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002948 return false;
2949 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002950 }
2951
2952 if (context->getExtensions().webglCompatibility ||
2953 !context->getGLState().areClientArraysEnabled())
2954 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002955 if (!elementArrayBuffer && count > 0)
2956 {
2957 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2958 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2959 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002960 context->handleError(InvalidOperation()
2961 << "There is no element array buffer bound and count > 0.");
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002962 return false;
2963 }
2964 }
2965
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002966 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002967 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002968 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002969 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002970 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2971 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2972 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2973 constexpr uint64_t kMaxTypeSize = 8;
2974 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2975 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2976 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002977
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002978 uint64_t typeSize = typeBytes;
2979 uint64_t elementCount = static_cast<uint64_t>(count);
2980 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2981
2982 // Doing the multiplication here is overflow-safe
2983 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2984
2985 // The offset can be any value, check for overflows
2986 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2987 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002988 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002989 context->handleError(InvalidOperation() << "Integer overflow.");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002990 return false;
2991 }
2992
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002993 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2994 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002995 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002996 context->handleError(InvalidOperation()
2997 << "Index buffer is not big enough for the draw.");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002998 return false;
2999 }
3000 }
3001 else if (!indices)
3002 {
3003 // This is an application error that would normally result in a crash,
3004 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003005 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04003006 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003007 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003008 }
3009
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003010 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill2b976812014-08-25 15:47:49 -04003011 // TODO: offer fast path, with disabled index validation.
3012 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003013 const auto &params = context->getParams<HasIndexRange>();
3014 const auto &indexRangeOpt = params.getIndexRange();
3015 if (!indexRangeOpt.valid())
Jamie Madill2b976812014-08-25 15:47:49 -04003016 {
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003017 // Unexpected error.
3018 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003019 }
3020
Jamie Madille79b1e12015-11-04 16:36:37 -05003021 // If we use an index greater than our maximum supported index range, return an error.
3022 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3023 // return an error if possible here.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003024 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
Jamie Madille79b1e12015-11-04 16:36:37 -05003025 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003026 context->handleError(InvalidOperation() << g_ExceedsMaxElementErrorMessage);
Jamie Madille79b1e12015-11-04 16:36:37 -05003027 return false;
3028 }
3029
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003030 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
3031 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003032 {
3033 return false;
3034 }
3035
Geoff Lang3edfe032015-09-04 16:38:24 -04003036 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003037 return (indexRangeOpt.value().vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003038}
3039
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003040bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
3041 GLenum mode,
3042 GLsizei count,
3043 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003044 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003045 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003046{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003047 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003048 {
3049 return false;
3050 }
3051
Corentin Wallez170efbf2017-05-02 13:45:01 -04003052 return !context->getExtensions().webglCompatibility ||
3053 ValidateDrawInstancedANGLEAndWebGL(context);
Jamie Madill250d33f2014-06-06 17:09:03 -04003054}
3055
Geoff Lang3edfe032015-09-04 16:38:24 -04003056bool ValidateDrawElementsInstancedANGLE(Context *context,
3057 GLenum mode,
3058 GLsizei count,
3059 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003060 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003061 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003062{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003063 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003064 {
3065 return false;
3066 }
3067
Corentin Wallez170efbf2017-05-02 13:45:01 -04003068 return ValidateDrawInstancedANGLEAndWebGL(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003069}
3070
He Yunchaoced53ae2016-11-29 15:00:51 +08003071bool ValidateFramebufferTextureBase(Context *context,
3072 GLenum target,
3073 GLenum attachment,
3074 GLuint texture,
3075 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003076{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003077 if (!ValidFramebufferTarget(target))
3078 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003079 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04003080 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003081 }
3082
3083 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003084 {
3085 return false;
3086 }
3087
Jamie Madill55ec3b12014-07-03 10:38:57 -04003088 if (texture != 0)
3089 {
3090 gl::Texture *tex = context->getTexture(texture);
3091
Jamie Madillbe849e42017-05-02 15:49:00 -04003092 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003093 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003094 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003095 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003096 }
3097
3098 if (level < 0)
3099 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003100 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003101 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003102 }
3103 }
3104
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003105 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003106 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003107
Jamie Madill84115c92015-04-23 15:00:07 -04003108 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003109 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003110 context->handleError(InvalidOperation() << "Cannot change default FBO's attachments");
Geoff Langb1196682014-07-23 13:47:29 -04003111 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003112 }
3113
3114 return true;
3115}
3116
Geoff Langb1196682014-07-23 13:47:29 -04003117bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003118{
3119 if (program == 0)
3120 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003121 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003122 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003123 }
3124
Dian Xiang769769a2015-09-09 15:20:08 -07003125 gl::Program *programObject = GetValidProgram(context, program);
3126 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003127 {
3128 return false;
3129 }
3130
Jamie Madill0063c512014-08-25 15:47:53 -04003131 if (!programObject || !programObject->isLinked())
3132 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003133 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003134 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003135 }
3136
Geoff Lang7dd2e102014-11-10 15:19:26 -05003137 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003138 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003139 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003140 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003141 }
3142
Jamie Madill0063c512014-08-25 15:47:53 -04003143 return true;
3144}
3145
Geoff Langf41d0ee2016-10-07 13:04:23 -04003146static bool ValidateSizedGetUniform(Context *context,
3147 GLuint program,
3148 GLint location,
3149 GLsizei bufSize,
3150 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003151{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003152 if (length)
3153 {
3154 *length = 0;
3155 }
3156
Jamie Madill78f41802014-08-25 15:47:55 -04003157 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003158 {
Jamie Madill78f41802014-08-25 15:47:55 -04003159 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003160 }
3161
Geoff Langf41d0ee2016-10-07 13:04:23 -04003162 if (bufSize < 0)
3163 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003164 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003165 return false;
3166 }
3167
Jamie Madilla502c742014-08-28 17:19:13 -04003168 gl::Program *programObject = context->getProgram(program);
3169 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003170
Jamie Madill78f41802014-08-25 15:47:55 -04003171 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003172 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003173 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003174 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003176 context->handleError(InvalidOperation()
3177 << "bufSize of at least " << requiredBytes << " is required.");
Geoff Langb1196682014-07-23 13:47:29 -04003178 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003179 }
3180
Geoff Langf41d0ee2016-10-07 13:04:23 -04003181 if (length)
3182 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003183 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003184 }
3185
Jamie Madill0063c512014-08-25 15:47:53 -04003186 return true;
3187}
3188
He Yunchaoced53ae2016-11-29 15:00:51 +08003189bool ValidateGetnUniformfvEXT(Context *context,
3190 GLuint program,
3191 GLint location,
3192 GLsizei bufSize,
3193 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003194{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003195 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003196}
3197
He Yunchaoced53ae2016-11-29 15:00:51 +08003198bool ValidateGetnUniformivEXT(Context *context,
3199 GLuint program,
3200 GLint location,
3201 GLsizei bufSize,
3202 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003203{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003204 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3205}
3206
3207bool ValidateGetUniformfvRobustANGLE(Context *context,
3208 GLuint program,
3209 GLint location,
3210 GLsizei bufSize,
3211 GLsizei *length,
3212 GLfloat *params)
3213{
3214 if (!ValidateRobustEntryPoint(context, bufSize))
3215 {
3216 return false;
3217 }
3218
3219 // bufSize is validated in ValidateSizedGetUniform
3220 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3221}
3222
3223bool ValidateGetUniformivRobustANGLE(Context *context,
3224 GLuint program,
3225 GLint location,
3226 GLsizei bufSize,
3227 GLsizei *length,
3228 GLint *params)
3229{
3230 if (!ValidateRobustEntryPoint(context, bufSize))
3231 {
3232 return false;
3233 }
3234
3235 // bufSize is validated in ValidateSizedGetUniform
3236 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3237}
3238
3239bool ValidateGetUniformuivRobustANGLE(Context *context,
3240 GLuint program,
3241 GLint location,
3242 GLsizei bufSize,
3243 GLsizei *length,
3244 GLuint *params)
3245{
3246 if (!ValidateRobustEntryPoint(context, bufSize))
3247 {
3248 return false;
3249 }
3250
3251 if (context->getClientMajorVersion() < 3)
3252 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003253 context->handleError(InvalidOperation() << "Entry point requires at least OpenGL ES 3.0.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003254 return false;
3255 }
3256
3257 // bufSize is validated in ValidateSizedGetUniform
3258 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003259}
3260
He Yunchaoced53ae2016-11-29 15:00:51 +08003261bool ValidateDiscardFramebufferBase(Context *context,
3262 GLenum target,
3263 GLsizei numAttachments,
3264 const GLenum *attachments,
3265 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003266{
3267 if (numAttachments < 0)
3268 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003269 context->handleError(InvalidValue() << "numAttachments must not be less than zero");
Austin Kinross08332632015-05-05 13:35:47 -07003270 return false;
3271 }
3272
3273 for (GLsizei i = 0; i < numAttachments; ++i)
3274 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003275 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003276 {
3277 if (defaultFramebuffer)
3278 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003279 context->handleError(InvalidEnum()
3280 << "Invalid attachment when the default framebuffer is bound");
Austin Kinross08332632015-05-05 13:35:47 -07003281 return false;
3282 }
3283
3284 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3285 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003286 context->handleError(InvalidOperation() << "Requested color attachment is "
3287 "greater than the maximum supported "
3288 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003289 return false;
3290 }
3291 }
3292 else
3293 {
3294 switch (attachments[i])
3295 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003296 case GL_DEPTH_ATTACHMENT:
3297 case GL_STENCIL_ATTACHMENT:
3298 case GL_DEPTH_STENCIL_ATTACHMENT:
3299 if (defaultFramebuffer)
3300 {
3301 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003302 InvalidEnum()
3303 << "Invalid attachment when the default framebuffer is bound");
He Yunchaoced53ae2016-11-29 15:00:51 +08003304 return false;
3305 }
3306 break;
3307 case GL_COLOR:
3308 case GL_DEPTH:
3309 case GL_STENCIL:
3310 if (!defaultFramebuffer)
3311 {
3312 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003313 InvalidEnum()
3314 << "Invalid attachment when the default framebuffer is not bound");
He Yunchaoced53ae2016-11-29 15:00:51 +08003315 return false;
3316 }
3317 break;
3318 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003319 context->handleError(InvalidEnum() << "Invalid attachment");
Austin Kinross08332632015-05-05 13:35:47 -07003320 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003321 }
3322 }
3323 }
3324
3325 return true;
3326}
3327
Austin Kinross6ee1e782015-05-29 17:05:37 -07003328bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3329{
3330 // Note that debug marker calls must not set error state
3331
3332 if (length < 0)
3333 {
3334 return false;
3335 }
3336
3337 if (marker == nullptr)
3338 {
3339 return false;
3340 }
3341
3342 return true;
3343}
3344
3345bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3346{
3347 // Note that debug marker calls must not set error state
3348
3349 if (length < 0)
3350 {
3351 return false;
3352 }
3353
3354 if (length > 0 && marker == nullptr)
3355 {
3356 return false;
3357 }
3358
3359 return true;
3360}
3361
Geoff Langdcab33b2015-07-21 13:03:16 -04003362bool ValidateEGLImageTargetTexture2DOES(Context *context,
3363 egl::Display *display,
3364 GLenum target,
3365 egl::Image *image)
3366{
Geoff Langa8406172015-07-21 16:53:39 -04003367 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3368 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003369 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003370 return false;
3371 }
3372
3373 switch (target)
3374 {
3375 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003376 if (!context->getExtensions().eglImage)
3377 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003378 context->handleError(InvalidEnum()
3379 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003380 }
3381 break;
3382
3383 case GL_TEXTURE_EXTERNAL_OES:
3384 if (!context->getExtensions().eglImageExternal)
3385 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003386 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3387 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003388 }
Geoff Langa8406172015-07-21 16:53:39 -04003389 break;
3390
3391 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003392 context->handleError(InvalidEnum() << "invalid texture target.");
Geoff Langa8406172015-07-21 16:53:39 -04003393 return false;
3394 }
3395
3396 if (!display->isValidImage(image))
3397 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003398 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003399 return false;
3400 }
3401
3402 if (image->getSamples() > 0)
3403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003404 context->handleError(InvalidOperation()
3405 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003406 return false;
3407 }
3408
Geoff Langca271392017-04-05 12:30:00 -04003409 const TextureCaps &textureCaps =
3410 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003411 if (!textureCaps.texturable)
3412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003413 context->handleError(InvalidOperation()
3414 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003415 return false;
3416 }
3417
Geoff Langdcab33b2015-07-21 13:03:16 -04003418 return true;
3419}
3420
3421bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3422 egl::Display *display,
3423 GLenum target,
3424 egl::Image *image)
3425{
Geoff Langa8406172015-07-21 16:53:39 -04003426 if (!context->getExtensions().eglImage)
3427 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003428 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003429 return false;
3430 }
3431
3432 switch (target)
3433 {
3434 case GL_RENDERBUFFER:
3435 break;
3436
3437 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003438 context->handleError(InvalidEnum() << "invalid renderbuffer target.");
Geoff Langa8406172015-07-21 16:53:39 -04003439 return false;
3440 }
3441
3442 if (!display->isValidImage(image))
3443 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003444 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003445 return false;
3446 }
3447
Geoff Langca271392017-04-05 12:30:00 -04003448 const TextureCaps &textureCaps =
3449 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003450 if (!textureCaps.renderable)
3451 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003452 context->handleError(InvalidOperation()
3453 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003454 return false;
3455 }
3456
Geoff Langdcab33b2015-07-21 13:03:16 -04003457 return true;
3458}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003459
3460bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3461{
Geoff Lang36167ab2015-12-07 10:27:14 -05003462 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003463 {
3464 // The default VAO should always exist
3465 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003466 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003467 return false;
3468 }
3469
3470 return true;
3471}
3472
Geoff Langc5629752015-12-07 16:29:04 -05003473bool ValidateProgramBinaryBase(Context *context,
3474 GLuint program,
3475 GLenum binaryFormat,
3476 const void *binary,
3477 GLint length)
3478{
3479 Program *programObject = GetValidProgram(context, program);
3480 if (programObject == nullptr)
3481 {
3482 return false;
3483 }
3484
3485 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3486 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3487 programBinaryFormats.end())
3488 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003489 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003490 return false;
3491 }
3492
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003493 if (context->hasActiveTransformFeedback(program))
3494 {
3495 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003496 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3497 "is associated with an active transform "
3498 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003499 return false;
3500 }
3501
Geoff Langc5629752015-12-07 16:29:04 -05003502 return true;
3503}
3504
3505bool ValidateGetProgramBinaryBase(Context *context,
3506 GLuint program,
3507 GLsizei bufSize,
3508 GLsizei *length,
3509 GLenum *binaryFormat,
3510 void *binary)
3511{
3512 Program *programObject = GetValidProgram(context, program);
3513 if (programObject == nullptr)
3514 {
3515 return false;
3516 }
3517
3518 if (!programObject->isLinked())
3519 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003520 context->handleError(InvalidOperation() << "Program is not linked.");
Geoff Langc5629752015-12-07 16:29:04 -05003521 return false;
3522 }
3523
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003524 if (context->getCaps().programBinaryFormats.empty())
3525 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003526 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003527 return false;
3528 }
3529
Geoff Langc5629752015-12-07 16:29:04 -05003530 return true;
3531}
Jamie Madillc29968b2016-01-20 11:17:23 -05003532
Jamie Madillc29968b2016-01-20 11:17:23 -05003533bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3534{
3535 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3536 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3537 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003538 context->handleError(InvalidValue()
3539 << "n must be non-negative and no greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003540 return false;
3541 }
3542
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003543 ASSERT(context->getGLState().getDrawFramebuffer());
3544 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003545 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3546
3547 // This should come first before the check for the default frame buffer
3548 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3549 // rather than INVALID_OPERATION
3550 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3551 {
3552 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3553
3554 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003555 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3556 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003557 {
3558 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003559 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3560 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3561 // 3.1 is still a bit ambiguous about the error, but future specs are
3562 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003563 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003564 return false;
3565 }
3566 else if (bufs[colorAttachment] >= maxColorAttachment)
3567 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003568 context->handleError(InvalidOperation()
3569 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003570 return false;
3571 }
3572 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3573 frameBufferId != 0)
3574 {
3575 // INVALID_OPERATION-GL is bound to buffer and ith argument
3576 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003577 context->handleError(InvalidOperation()
3578 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003579 return false;
3580 }
3581 }
3582
3583 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3584 // and n is not 1 or bufs is bound to value other than BACK and NONE
3585 if (frameBufferId == 0)
3586 {
3587 if (n != 1)
3588 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003589 context->handleError(InvalidOperation()
3590 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003591 return false;
3592 }
3593
3594 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3595 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003596 context->handleError(
3597 InvalidOperation()
3598 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003599 return false;
3600 }
3601 }
3602
3603 return true;
3604}
3605
Geoff Lang496c02d2016-10-20 11:38:11 -07003606bool ValidateGetBufferPointervBase(Context *context,
3607 GLenum target,
3608 GLenum pname,
3609 GLsizei *length,
3610 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003611{
Geoff Lang496c02d2016-10-20 11:38:11 -07003612 if (length)
3613 {
3614 *length = 0;
3615 }
3616
3617 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3618 {
3619 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003620 InvalidOperation()
3621 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003622 return false;
3623 }
3624
Olli Etuaho4f667482016-03-30 15:56:35 +03003625 if (!ValidBufferTarget(context, target))
3626 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003627 context->handleError(InvalidEnum() << "Buffer target not valid: 0x" << std::hex
3628 << std::uppercase << target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003629 return false;
3630 }
3631
Geoff Lang496c02d2016-10-20 11:38:11 -07003632 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003633 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003634 case GL_BUFFER_MAP_POINTER:
3635 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003636
Geoff Lang496c02d2016-10-20 11:38:11 -07003637 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003638 context->handleError(InvalidEnum() << "Unknown pname.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003639 return false;
3640 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003641
3642 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3643 // target bound to zero generate an INVALID_OPERATION error."
3644 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003645 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003647 context->handleError(InvalidOperation()
3648 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003649 return false;
3650 }
3651
Geoff Lang496c02d2016-10-20 11:38:11 -07003652 if (length)
3653 {
3654 *length = 1;
3655 }
3656
Olli Etuaho4f667482016-03-30 15:56:35 +03003657 return true;
3658}
3659
3660bool ValidateUnmapBufferBase(Context *context, GLenum target)
3661{
3662 if (!ValidBufferTarget(context, target))
3663 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003664 context->handleError(InvalidEnum() << "Invalid buffer target.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003665 return false;
3666 }
3667
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003668 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003669
3670 if (buffer == nullptr || !buffer->isMapped())
3671 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003672 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003673 return false;
3674 }
3675
3676 return true;
3677}
3678
3679bool ValidateMapBufferRangeBase(Context *context,
3680 GLenum target,
3681 GLintptr offset,
3682 GLsizeiptr length,
3683 GLbitfield access)
3684{
3685 if (!ValidBufferTarget(context, target))
3686 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003687 context->handleError(InvalidEnum() << "Invalid buffer target.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003688 return false;
3689 }
3690
3691 if (offset < 0 || length < 0)
3692 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003693 context->handleError(InvalidValue() << "Invalid offset or length.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003694 return false;
3695 }
3696
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003697 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003698
3699 if (!buffer)
3700 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003701 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003702 return false;
3703 }
3704
3705 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003706 CheckedNumeric<size_t> checkedOffset(offset);
3707 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003708
Jamie Madille2e406c2016-06-02 13:04:10 -04003709 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003710 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003711 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003712 return false;
3713 }
3714
3715 // Check for invalid bits in the mask
3716 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3717 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3718 GL_MAP_UNSYNCHRONIZED_BIT;
3719
3720 if (access & ~(allAccessBits))
3721 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003722 context->handleError(InvalidValue()
3723 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003724 return false;
3725 }
3726
3727 if (length == 0)
3728 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003729 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003730 return false;
3731 }
3732
3733 if (buffer->isMapped())
3734 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003735 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003736 return false;
3737 }
3738
3739 // Check for invalid bit combinations
3740 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3741 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003742 context->handleError(InvalidOperation()
3743 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003744 return false;
3745 }
3746
3747 GLbitfield writeOnlyBits =
3748 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3749
3750 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3751 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003752 context->handleError(InvalidOperation()
3753 << "Invalid access bits when mapping buffer for reading: 0x"
3754 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003755 return false;
3756 }
3757
3758 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3759 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003760 context->handleError(
3761 InvalidOperation()
3762 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003763 return false;
3764 }
3765 return true;
3766}
3767
3768bool ValidateFlushMappedBufferRangeBase(Context *context,
3769 GLenum target,
3770 GLintptr offset,
3771 GLsizeiptr length)
3772{
3773 if (offset < 0 || length < 0)
3774 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003775 context->handleError(InvalidValue() << "Invalid offset/length parameters.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003776 return false;
3777 }
3778
3779 if (!ValidBufferTarget(context, target))
3780 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003781 context->handleError(InvalidEnum() << "Invalid buffer target.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003782 return false;
3783 }
3784
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003785 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003786
3787 if (buffer == nullptr)
3788 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003789 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003790 return false;
3791 }
3792
3793 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3794 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003795 context->handleError(InvalidOperation()
3796 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003797 return false;
3798 }
3799
3800 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003801 CheckedNumeric<size_t> checkedOffset(offset);
3802 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003803
Jamie Madille2e406c2016-06-02 13:04:10 -04003804 if (!checkedSize.IsValid() ||
3805 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003806 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003807 context->handleError(InvalidValue()
3808 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003809 return false;
3810 }
3811
3812 return true;
3813}
3814
Olli Etuaho41997e72016-03-10 13:38:39 +02003815bool ValidateGenOrDelete(Context *context, GLint n)
3816{
3817 if (n < 0)
3818 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003819 context->handleError(InvalidValue() << "n < 0");
Olli Etuaho41997e72016-03-10 13:38:39 +02003820 return false;
3821 }
3822 return true;
3823}
3824
Geoff Langff5b2d52016-09-07 11:32:23 -04003825bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3826{
3827 if (!context->getExtensions().robustClientMemory)
3828 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003829 context->handleError(InvalidOperation()
3830 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003831 return false;
3832 }
3833
3834 if (bufSize < 0)
3835 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003836 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003837 return false;
3838 }
3839
3840 return true;
3841}
3842
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003843bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3844{
3845 if (bufSize < numParams)
3846 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003847 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3848 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003849 return false;
3850 }
3851
3852 return true;
3853}
3854
Jamie Madillbe849e42017-05-02 15:49:00 -04003855bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3856 GLenum target,
3857 GLenum attachment,
3858 GLenum pname,
3859 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003860{
3861 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
Yunchao He33151a52017-04-13 09:58:17 +08003862 if (numParams)
3863 {
3864 *numParams = 1;
3865 }
Geoff Langff5b2d52016-09-07 11:32:23 -04003866
3867 if (!ValidFramebufferTarget(target))
3868 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003869 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003870 return false;
3871 }
3872
3873 int clientVersion = context->getClientMajorVersion();
3874
3875 switch (pname)
3876 {
3877 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3878 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3879 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3880 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3881 break;
3882
3883 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3884 if (clientVersion < 3 && !context->getExtensions().sRGB)
3885 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003886 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003887 return false;
3888 }
3889 break;
3890
3891 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3892 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3893 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3894 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3895 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3896 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3897 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3898 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3899 if (clientVersion < 3)
3900 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003901 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003902 return false;
3903 }
3904 break;
3905
3906 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003907 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003908 return false;
3909 }
3910
3911 // Determine if the attachment is a valid enum
3912 switch (attachment)
3913 {
3914 case GL_BACK:
3915 case GL_FRONT:
3916 case GL_DEPTH:
3917 case GL_STENCIL:
3918 case GL_DEPTH_STENCIL_ATTACHMENT:
3919 if (clientVersion < 3)
3920 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003921 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003922 return false;
3923 }
3924 break;
3925
3926 case GL_DEPTH_ATTACHMENT:
3927 case GL_STENCIL_ATTACHMENT:
3928 break;
3929
3930 default:
3931 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
3932 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3933 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003934 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003935 return false;
3936 }
3937 break;
3938 }
3939
3940 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3941 ASSERT(framebuffer);
3942
3943 if (framebuffer->id() == 0)
3944 {
3945 if (clientVersion < 3)
3946 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003947 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003948 return false;
3949 }
3950
3951 switch (attachment)
3952 {
3953 case GL_BACK:
3954 case GL_DEPTH:
3955 case GL_STENCIL:
3956 break;
3957
3958 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003959 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003960 return false;
3961 }
3962 }
3963 else
3964 {
3965 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3966 {
3967 // Valid attachment query
3968 }
3969 else
3970 {
3971 switch (attachment)
3972 {
3973 case GL_DEPTH_ATTACHMENT:
3974 case GL_STENCIL_ATTACHMENT:
3975 break;
3976
3977 case GL_DEPTH_STENCIL_ATTACHMENT:
3978 if (!framebuffer->hasValidDepthStencil())
3979 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003980 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003981 return false;
3982 }
3983 break;
3984
3985 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003986 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003987 return false;
3988 }
3989 }
3990 }
3991
3992 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3993 if (attachmentObject)
3994 {
3995 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3996 attachmentObject->type() == GL_TEXTURE ||
3997 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3998
3999 switch (pname)
4000 {
4001 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4002 if (attachmentObject->type() != GL_RENDERBUFFER &&
4003 attachmentObject->type() != GL_TEXTURE)
4004 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004005 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004006 return false;
4007 }
4008 break;
4009
4010 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4011 if (attachmentObject->type() != GL_TEXTURE)
4012 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004013 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004014 return false;
4015 }
4016 break;
4017
4018 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4019 if (attachmentObject->type() != GL_TEXTURE)
4020 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004021 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004022 return false;
4023 }
4024 break;
4025
4026 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4027 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4028 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004029 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004030 return false;
4031 }
4032 break;
4033
4034 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4035 if (attachmentObject->type() != GL_TEXTURE)
4036 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004037 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004038 return false;
4039 }
4040 break;
4041
4042 default:
4043 break;
4044 }
4045 }
4046 else
4047 {
4048 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4049 // is NONE, then querying any other pname will generate INVALID_ENUM.
4050
4051 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4052 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4053 // INVALID_OPERATION for all other pnames
4054
4055 switch (pname)
4056 {
4057 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4058 break;
4059
4060 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4061 if (clientVersion < 3)
4062 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004063 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004064 return false;
4065 }
4066 break;
4067
4068 default:
4069 if (clientVersion < 3)
4070 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004071 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004072 return false;
4073 }
4074 else
4075 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004076 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004077 return false;
4078 }
4079 }
4080 }
4081
4082 return true;
4083}
4084
4085bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4086 GLenum target,
4087 GLenum attachment,
4088 GLenum pname,
4089 GLsizei bufSize,
4090 GLsizei *numParams)
4091{
4092 if (!ValidateRobustEntryPoint(context, bufSize))
4093 {
4094 return false;
4095 }
4096
Jamie Madillbe849e42017-05-02 15:49:00 -04004097 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4098 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004099 {
4100 return false;
4101 }
4102
4103 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4104 {
4105 return false;
4106 }
4107
4108 return true;
4109}
4110
Geoff Langff5b2d52016-09-07 11:32:23 -04004111bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4112 GLenum target,
4113 GLenum pname,
4114 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004115 GLsizei *length,
4116 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004117{
4118 if (!ValidateRobustEntryPoint(context, bufSize))
4119 {
4120 return false;
4121 }
4122
Geoff Langebebe1c2016-10-14 12:01:31 -04004123 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004124 {
4125 return false;
4126 }
4127
Geoff Langebebe1c2016-10-14 12:01:31 -04004128 if (!ValidateRobustBufferSize(context, bufSize, *length))
4129 {
4130 return false;
4131 }
4132
4133 return true;
4134}
4135
4136bool ValidateGetBufferParameteri64v(ValidationContext *context,
4137 GLenum target,
4138 GLenum pname,
4139 GLint64 *params)
4140{
4141 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4142}
4143
4144bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4145 GLenum target,
4146 GLenum pname,
4147 GLsizei bufSize,
4148 GLsizei *length,
4149 GLint64 *params)
4150{
4151 if (!ValidateRobustEntryPoint(context, bufSize))
4152 {
4153 return false;
4154 }
4155
4156 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4157 {
4158 return false;
4159 }
4160
4161 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004162 {
4163 return false;
4164 }
4165
4166 return true;
4167}
4168
Jamie Madillbe849e42017-05-02 15:49:00 -04004169bool ValidateGetProgramivBase(ValidationContext *context,
4170 GLuint program,
4171 GLenum pname,
4172 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004173{
4174 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004175 if (numParams)
4176 {
4177 *numParams = 1;
4178 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004179
4180 Program *programObject = GetValidProgram(context, program);
4181 if (!programObject)
4182 {
4183 return false;
4184 }
4185
4186 switch (pname)
4187 {
4188 case GL_DELETE_STATUS:
4189 case GL_LINK_STATUS:
4190 case GL_VALIDATE_STATUS:
4191 case GL_INFO_LOG_LENGTH:
4192 case GL_ATTACHED_SHADERS:
4193 case GL_ACTIVE_ATTRIBUTES:
4194 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4195 case GL_ACTIVE_UNIFORMS:
4196 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4197 break;
4198
4199 case GL_PROGRAM_BINARY_LENGTH:
4200 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4201 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004202 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4203 "requires GL_OES_get_program_binary or "
4204 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004205 return false;
4206 }
4207 break;
4208
4209 case GL_ACTIVE_UNIFORM_BLOCKS:
4210 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4211 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4212 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4213 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4214 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4215 if (context->getClientMajorVersion() < 3)
4216 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004217 context->handleError(InvalidEnum() << "Querying requires at least ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004218 return false;
4219 }
4220 break;
4221
Yunchao He61afff12017-03-14 15:34:03 +08004222 case GL_PROGRAM_SEPARABLE:
4223 if (context->getClientVersion() < Version(3, 1))
4224 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004225 context->handleError(InvalidEnum() << "Querying requires at least ES 3.1.");
Yunchao He61afff12017-03-14 15:34:03 +08004226 return false;
4227 }
4228 break;
4229
Geoff Langff5b2d52016-09-07 11:32:23 -04004230 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004231 context->handleError(InvalidEnum() << "Unknown parameter name.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004232 return false;
4233 }
4234
4235 return true;
4236}
4237
4238bool ValidateGetProgramivRobustANGLE(Context *context,
4239 GLuint program,
4240 GLenum pname,
4241 GLsizei bufSize,
4242 GLsizei *numParams)
4243{
4244 if (!ValidateRobustEntryPoint(context, bufSize))
4245 {
4246 return false;
4247 }
4248
Jamie Madillbe849e42017-05-02 15:49:00 -04004249 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004250 {
4251 return false;
4252 }
4253
4254 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4255 {
4256 return false;
4257 }
4258
4259 return true;
4260}
4261
Geoff Lang740d9022016-10-07 11:20:52 -04004262bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4263 GLenum target,
4264 GLenum pname,
4265 GLsizei bufSize,
4266 GLsizei *length,
4267 GLint *params)
4268{
4269 if (!ValidateRobustEntryPoint(context, bufSize))
4270 {
4271 return false;
4272 }
4273
4274 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4275 {
4276 return false;
4277 }
4278
4279 if (!ValidateRobustBufferSize(context, bufSize, *length))
4280 {
4281 return false;
4282 }
4283
4284 return true;
4285}
4286
Geoff Langd7d0ed32016-10-07 11:33:51 -04004287bool ValidateGetShaderivRobustANGLE(Context *context,
4288 GLuint shader,
4289 GLenum pname,
4290 GLsizei bufSize,
4291 GLsizei *length,
4292 GLint *params)
4293{
4294 if (!ValidateRobustEntryPoint(context, bufSize))
4295 {
4296 return false;
4297 }
4298
4299 if (!ValidateGetShaderivBase(context, shader, pname, length))
4300 {
4301 return false;
4302 }
4303
4304 if (!ValidateRobustBufferSize(context, bufSize, *length))
4305 {
4306 return false;
4307 }
4308
4309 return true;
4310}
4311
Geoff Langc1984ed2016-10-07 12:41:00 -04004312bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4313 GLenum target,
4314 GLenum pname,
4315 GLsizei bufSize,
4316 GLsizei *length,
4317 GLfloat *params)
4318{
4319 if (!ValidateRobustEntryPoint(context, bufSize))
4320 {
4321 return false;
4322 }
4323
4324 if (!ValidateGetTexParameterBase(context, target, pname, length))
4325 {
4326 return false;
4327 }
4328
4329 if (!ValidateRobustBufferSize(context, bufSize, *length))
4330 {
4331 return false;
4332 }
4333
4334 return true;
4335}
4336
Geoff Langc1984ed2016-10-07 12:41:00 -04004337bool ValidateGetTexParameterivRobustANGLE(Context *context,
4338 GLenum target,
4339 GLenum pname,
4340 GLsizei bufSize,
4341 GLsizei *length,
4342 GLint *params)
4343{
4344 if (!ValidateRobustEntryPoint(context, bufSize))
4345 {
4346 return false;
4347 }
4348
4349 if (!ValidateGetTexParameterBase(context, target, pname, length))
4350 {
4351 return false;
4352 }
4353
4354 if (!ValidateRobustBufferSize(context, bufSize, *length))
4355 {
4356 return false;
4357 }
4358
4359 return true;
4360}
4361
Geoff Langc1984ed2016-10-07 12:41:00 -04004362bool ValidateTexParameterfvRobustANGLE(Context *context,
4363 GLenum target,
4364 GLenum pname,
4365 GLsizei bufSize,
4366 const GLfloat *params)
4367{
4368 if (!ValidateRobustEntryPoint(context, bufSize))
4369 {
4370 return false;
4371 }
4372
4373 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4374}
4375
Geoff Langc1984ed2016-10-07 12:41:00 -04004376bool ValidateTexParameterivRobustANGLE(Context *context,
4377 GLenum target,
4378 GLenum pname,
4379 GLsizei bufSize,
4380 const GLint *params)
4381{
4382 if (!ValidateRobustEntryPoint(context, bufSize))
4383 {
4384 return false;
4385 }
4386
4387 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4388}
4389
4390bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4391{
4392 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4393}
4394
4395bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4396 GLuint sampler,
4397 GLenum pname,
4398 GLuint bufSize,
4399 GLsizei *length,
4400 GLfloat *params)
4401{
4402 if (!ValidateRobustEntryPoint(context, bufSize))
4403 {
4404 return false;
4405 }
4406
4407 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4408 {
4409 return false;
4410 }
4411
4412 if (!ValidateRobustBufferSize(context, bufSize, *length))
4413 {
4414 return false;
4415 }
4416
4417 return true;
4418}
4419
4420bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4421{
4422 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4423}
4424
4425bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4426 GLuint sampler,
4427 GLenum pname,
4428 GLuint bufSize,
4429 GLsizei *length,
4430 GLint *params)
4431{
4432 if (!ValidateRobustEntryPoint(context, bufSize))
4433 {
4434 return false;
4435 }
4436
4437 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4438 {
4439 return false;
4440 }
4441
4442 if (!ValidateRobustBufferSize(context, bufSize, *length))
4443 {
4444 return false;
4445 }
4446
4447 return true;
4448}
4449
4450bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4451{
4452 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4453}
4454
4455bool ValidateSamplerParameterfv(Context *context,
4456 GLuint sampler,
4457 GLenum pname,
4458 const GLfloat *params)
4459{
4460 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4461}
4462
4463bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4464 GLuint sampler,
4465 GLenum pname,
4466 GLsizei bufSize,
4467 const GLfloat *params)
4468{
4469 if (!ValidateRobustEntryPoint(context, bufSize))
4470 {
4471 return false;
4472 }
4473
4474 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4475}
4476
4477bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4478{
4479 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4480}
4481
4482bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4483{
4484 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4485}
4486
4487bool ValidateSamplerParameterivRobustANGLE(Context *context,
4488 GLuint sampler,
4489 GLenum pname,
4490 GLsizei bufSize,
4491 const GLint *params)
4492{
4493 if (!ValidateRobustEntryPoint(context, bufSize))
4494 {
4495 return false;
4496 }
4497
4498 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4499}
4500
Geoff Lang0b031062016-10-13 14:30:04 -04004501bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4502 GLuint index,
4503 GLenum pname,
4504 GLsizei bufSize,
4505 GLsizei *length,
4506 GLfloat *params)
4507{
4508 if (!ValidateRobustEntryPoint(context, bufSize))
4509 {
4510 return false;
4511 }
4512
4513 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4514 {
4515 return false;
4516 }
4517
4518 if (!ValidateRobustBufferSize(context, bufSize, *length))
4519 {
4520 return false;
4521 }
4522
4523 return true;
4524}
4525
Geoff Lang0b031062016-10-13 14:30:04 -04004526bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4527 GLuint index,
4528 GLenum pname,
4529 GLsizei bufSize,
4530 GLsizei *length,
4531 GLint *params)
4532{
4533 if (!ValidateRobustEntryPoint(context, bufSize))
4534 {
4535 return false;
4536 }
4537
4538 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4539 {
4540 return false;
4541 }
4542
4543 if (!ValidateRobustBufferSize(context, bufSize, *length))
4544 {
4545 return false;
4546 }
4547
4548 return true;
4549}
4550
Geoff Lang0b031062016-10-13 14:30:04 -04004551bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4552 GLuint index,
4553 GLenum pname,
4554 GLsizei bufSize,
4555 GLsizei *length,
4556 void **pointer)
4557{
4558 if (!ValidateRobustEntryPoint(context, bufSize))
4559 {
4560 return false;
4561 }
4562
4563 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4564 {
4565 return false;
4566 }
4567
4568 if (!ValidateRobustBufferSize(context, bufSize, *length))
4569 {
4570 return false;
4571 }
4572
4573 return true;
4574}
4575
4576bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4577{
4578 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4579}
4580
4581bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4582 GLuint index,
4583 GLenum pname,
4584 GLsizei bufSize,
4585 GLsizei *length,
4586 GLint *params)
4587{
4588 if (!ValidateRobustEntryPoint(context, bufSize))
4589 {
4590 return false;
4591 }
4592
4593 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4594 {
4595 return false;
4596 }
4597
4598 if (!ValidateRobustBufferSize(context, bufSize, *length))
4599 {
4600 return false;
4601 }
4602
4603 return true;
4604}
4605
4606bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4607{
4608 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4609}
4610
4611bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4612 GLuint index,
4613 GLenum pname,
4614 GLsizei bufSize,
4615 GLsizei *length,
4616 GLuint *params)
4617{
4618 if (!ValidateRobustEntryPoint(context, bufSize))
4619 {
4620 return false;
4621 }
4622
4623 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4624 {
4625 return false;
4626 }
4627
4628 if (!ValidateRobustBufferSize(context, bufSize, *length))
4629 {
4630 return false;
4631 }
4632
4633 return true;
4634}
4635
Geoff Lang6899b872016-10-14 11:30:13 -04004636bool ValidateGetActiveUniformBlockiv(Context *context,
4637 GLuint program,
4638 GLuint uniformBlockIndex,
4639 GLenum pname,
4640 GLint *params)
4641{
4642 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
4643}
4644
4645bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4646 GLuint program,
4647 GLuint uniformBlockIndex,
4648 GLenum pname,
4649 GLsizei bufSize,
4650 GLsizei *length,
4651 GLint *params)
4652{
4653 if (!ValidateRobustEntryPoint(context, bufSize))
4654 {
4655 return false;
4656 }
4657
4658 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4659 {
4660 return false;
4661 }
4662
4663 if (!ValidateRobustBufferSize(context, bufSize, *length))
4664 {
4665 return false;
4666 }
4667
4668 return true;
4669}
4670
Geoff Lang0a9661f2016-10-20 10:59:20 -07004671bool ValidateGetInternalFormativ(Context *context,
4672 GLenum target,
4673 GLenum internalformat,
4674 GLenum pname,
4675 GLsizei bufSize,
4676 GLint *params)
4677{
4678 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4679 nullptr);
4680}
4681
4682bool ValidateGetInternalFormativRobustANGLE(Context *context,
4683 GLenum target,
4684 GLenum internalformat,
4685 GLenum pname,
4686 GLsizei bufSize,
4687 GLsizei *length,
4688 GLint *params)
4689{
4690 if (!ValidateRobustEntryPoint(context, bufSize))
4691 {
4692 return false;
4693 }
4694
4695 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4696 {
4697 return false;
4698 }
4699
4700 if (!ValidateRobustBufferSize(context, bufSize, *length))
4701 {
4702 return false;
4703 }
4704
4705 return true;
4706}
4707
Shao80957d92017-02-20 21:25:59 +08004708bool ValidateVertexFormatBase(ValidationContext *context,
4709 GLuint attribIndex,
4710 GLint size,
4711 GLenum type,
4712 GLboolean pureInteger)
4713{
4714 const Caps &caps = context->getCaps();
4715 if (attribIndex >= caps.maxVertexAttributes)
4716 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004717 context->handleError(InvalidValue()
4718 << "attribindex must be smaller than MAX_VERTEX_ATTRIBS.");
Shao80957d92017-02-20 21:25:59 +08004719 return false;
4720 }
4721
4722 if (size < 1 || size > 4)
4723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004724 context->handleError(InvalidValue() << "size must be between one and four.");
Shao80957d92017-02-20 21:25:59 +08004725 }
4726
4727 switch (type)
4728 {
4729 case GL_BYTE:
4730 case GL_UNSIGNED_BYTE:
4731 case GL_SHORT:
4732 case GL_UNSIGNED_SHORT:
4733 break;
4734
4735 case GL_INT:
4736 case GL_UNSIGNED_INT:
4737 if (context->getClientMajorVersion() < 3)
4738 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004739 context->handleError(InvalidEnum()
4740 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004741 return false;
4742 }
4743 break;
4744
4745 case GL_FIXED:
4746 case GL_FLOAT:
4747 if (pureInteger)
4748 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004749 context->handleError(InvalidEnum() << "Type is not integer.");
Shao80957d92017-02-20 21:25:59 +08004750 return false;
4751 }
4752 break;
4753
4754 case GL_HALF_FLOAT:
4755 if (context->getClientMajorVersion() < 3)
4756 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004757 context->handleError(InvalidEnum()
4758 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004759 return false;
4760 }
4761 if (pureInteger)
4762 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004763 context->handleError(InvalidEnum() << "Type is not integer.");
Shao80957d92017-02-20 21:25:59 +08004764 return false;
4765 }
4766 break;
4767
4768 case GL_INT_2_10_10_10_REV:
4769 case GL_UNSIGNED_INT_2_10_10_10_REV:
4770 if (context->getClientMajorVersion() < 3)
4771 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004772 context->handleError(InvalidEnum()
4773 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004774 return false;
4775 }
4776 if (pureInteger)
4777 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004778 context->handleError(InvalidEnum() << "Type is not integer.");
Shao80957d92017-02-20 21:25:59 +08004779 return false;
4780 }
4781 if (size != 4)
4782 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004783 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4784 "UNSIGNED_INT_2_10_10_10_REV and "
4785 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004786 return false;
4787 }
4788 break;
4789
4790 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004791 context->handleError(InvalidEnum() << "Invalid vertex type.");
Shao80957d92017-02-20 21:25:59 +08004792 return false;
4793 }
4794
4795 return true;
4796}
4797
Geoff Lang76e65652017-03-27 14:58:02 -04004798// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4799// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4800// specified clear value and the type of a buffer that is being cleared generates an
4801// INVALID_OPERATION error instead of producing undefined results
4802bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4803 GLint drawbuffer,
4804 const GLenum *validComponentTypes,
4805 size_t validComponentTypeCount)
4806{
4807 const FramebufferAttachment *attachment =
4808 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4809 if (attachment)
4810 {
4811 GLenum componentType = attachment->getFormat().info->componentType;
4812 const GLenum *end = validComponentTypes + validComponentTypeCount;
4813 if (std::find(validComponentTypes, end, componentType) == end)
4814 {
4815 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004816 InvalidOperation()
4817 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004818 return false;
4819 }
4820 }
4821
4822 return true;
4823}
4824
Corentin Wallezb2931602017-04-11 15:58:57 -04004825bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4826 GLsizei imageSize,
4827 GLsizei dataSize)
4828{
4829 if (!ValidateRobustEntryPoint(context, dataSize))
4830 {
4831 return false;
4832 }
4833
4834 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
4835 if (pixelUnpackBuffer == nullptr)
4836 {
4837 if (dataSize < imageSize)
4838 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004839 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004840 }
4841 }
4842 return true;
4843}
4844
Jamie Madillbe849e42017-05-02 15:49:00 -04004845bool ValidateGetBufferParameterBase(ValidationContext *context,
4846 GLenum target,
4847 GLenum pname,
4848 bool pointerVersion,
4849 GLsizei *numParams)
4850{
4851 if (numParams)
4852 {
4853 *numParams = 0;
4854 }
4855
4856 if (!ValidBufferTarget(context, target))
4857 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004858 context->handleError(InvalidEnum() << "Invalid buffer target.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004859 return false;
4860 }
4861
4862 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4863 if (!buffer)
4864 {
4865 // A null buffer means that "0" is bound to the requested buffer target
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004866 context->handleError(InvalidOperation() << "No buffer bound.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004867 return false;
4868 }
4869
4870 const Extensions &extensions = context->getExtensions();
4871
4872 switch (pname)
4873 {
4874 case GL_BUFFER_USAGE:
4875 case GL_BUFFER_SIZE:
4876 break;
4877
4878 case GL_BUFFER_ACCESS_OES:
4879 if (!extensions.mapBuffer)
4880 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004881 context->handleError(InvalidEnum()
4882 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004883 return false;
4884 }
4885 break;
4886
4887 case GL_BUFFER_MAPPED:
4888 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4889 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4890 !extensions.mapBufferRange)
4891 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004892 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4893 "GL_OES_mapbuffer or "
4894 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004895 return false;
4896 }
4897 break;
4898
4899 case GL_BUFFER_MAP_POINTER:
4900 if (!pointerVersion)
4901 {
4902 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004903 InvalidEnum()
4904 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004905 return false;
4906 }
4907 break;
4908
4909 case GL_BUFFER_ACCESS_FLAGS:
4910 case GL_BUFFER_MAP_OFFSET:
4911 case GL_BUFFER_MAP_LENGTH:
4912 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4913 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004914 context->handleError(InvalidEnum()
4915 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004916 return false;
4917 }
4918 break;
4919
4920 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004921 context->handleError(InvalidEnum() << "Unknown pname.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004922 return false;
4923 }
4924
4925 // All buffer parameter queries return one value.
4926 if (numParams)
4927 {
4928 *numParams = 1;
4929 }
4930
4931 return true;
4932}
4933
4934bool ValidateGetRenderbufferParameterivBase(Context *context,
4935 GLenum target,
4936 GLenum pname,
4937 GLsizei *length)
4938{
4939 if (length)
4940 {
4941 *length = 0;
4942 }
4943
4944 if (target != GL_RENDERBUFFER)
4945 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004946 context->handleError(InvalidEnum() << "Invalid target.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004947 return false;
4948 }
4949
4950 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4951 if (renderbuffer == nullptr)
4952 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004953 context->handleError(InvalidOperation() << "No renderbuffer bound.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004954 return false;
4955 }
4956
4957 switch (pname)
4958 {
4959 case GL_RENDERBUFFER_WIDTH:
4960 case GL_RENDERBUFFER_HEIGHT:
4961 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4962 case GL_RENDERBUFFER_RED_SIZE:
4963 case GL_RENDERBUFFER_GREEN_SIZE:
4964 case GL_RENDERBUFFER_BLUE_SIZE:
4965 case GL_RENDERBUFFER_ALPHA_SIZE:
4966 case GL_RENDERBUFFER_DEPTH_SIZE:
4967 case GL_RENDERBUFFER_STENCIL_SIZE:
4968 break;
4969
4970 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4971 if (!context->getExtensions().framebufferMultisample)
4972 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004973 context->handleError(InvalidEnum()
4974 << "GL_ANGLE_framebuffer_multisample is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004975 return false;
4976 }
4977 break;
4978
4979 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004980 context->handleError(InvalidEnum() << "Unknown pname.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004981 return false;
4982 }
4983
4984 if (length)
4985 {
4986 *length = 1;
4987 }
4988 return true;
4989}
4990
4991bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4992{
4993 if (length)
4994 {
4995 *length = 0;
4996 }
4997
4998 if (GetValidShader(context, shader) == nullptr)
4999 {
5000 return false;
5001 }
5002
5003 switch (pname)
5004 {
5005 case GL_SHADER_TYPE:
5006 case GL_DELETE_STATUS:
5007 case GL_COMPILE_STATUS:
5008 case GL_INFO_LOG_LENGTH:
5009 case GL_SHADER_SOURCE_LENGTH:
5010 break;
5011
5012 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5013 if (!context->getExtensions().translatedShaderSource)
5014 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005015 context->handleError(InvalidEnum()
5016 << "GL_ANGLE_translated_shader_source is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005017 return false;
5018 }
5019 break;
5020
5021 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005022 context->handleError(InvalidEnum() << "Unknown pname.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005023 return false;
5024 }
5025
5026 if (length)
5027 {
5028 *length = 1;
5029 }
5030 return true;
5031}
5032
5033bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
5034{
5035 if (length)
5036 {
5037 *length = 0;
5038 }
5039
5040 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5041 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005042 context->handleError(InvalidEnum() << "Invalid texture target");
Jamie Madillbe849e42017-05-02 15:49:00 -04005043 return false;
5044 }
5045
5046 if (context->getTargetTexture(target) == nullptr)
5047 {
5048 // Should only be possible for external textures
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005049 context->handleError(InvalidEnum() << "No texture bound.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005050 return false;
5051 }
5052
5053 switch (pname)
5054 {
5055 case GL_TEXTURE_MAG_FILTER:
5056 case GL_TEXTURE_MIN_FILTER:
5057 case GL_TEXTURE_WRAP_S:
5058 case GL_TEXTURE_WRAP_T:
5059 break;
5060
5061 case GL_TEXTURE_USAGE_ANGLE:
5062 if (!context->getExtensions().textureUsage)
5063 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005064 context->handleError(InvalidEnum() << "GL_ANGLE_texture_usage is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005065 return false;
5066 }
5067 break;
5068
5069 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5070 if (!context->getExtensions().textureFilterAnisotropic)
5071 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005072 context->handleError(InvalidEnum()
5073 << "GL_EXT_texture_filter_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005074 return false;
5075 }
5076 break;
5077
5078 case GL_TEXTURE_IMMUTABLE_FORMAT:
5079 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5080 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005081 context->handleError(InvalidEnum() << "GL_EXT_texture_storage is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005082 return false;
5083 }
5084 break;
5085
5086 case GL_TEXTURE_WRAP_R:
5087 case GL_TEXTURE_IMMUTABLE_LEVELS:
5088 case GL_TEXTURE_SWIZZLE_R:
5089 case GL_TEXTURE_SWIZZLE_G:
5090 case GL_TEXTURE_SWIZZLE_B:
5091 case GL_TEXTURE_SWIZZLE_A:
5092 case GL_TEXTURE_BASE_LEVEL:
5093 case GL_TEXTURE_MAX_LEVEL:
5094 case GL_TEXTURE_MIN_LOD:
5095 case GL_TEXTURE_MAX_LOD:
5096 case GL_TEXTURE_COMPARE_MODE:
5097 case GL_TEXTURE_COMPARE_FUNC:
5098 if (context->getClientMajorVersion() < 3)
5099 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005100 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005101 return false;
5102 }
5103 break;
5104
5105 case GL_TEXTURE_SRGB_DECODE_EXT:
5106 if (!context->getExtensions().textureSRGBDecode)
5107 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005108 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005109 return false;
5110 }
5111 break;
5112
5113 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005114 context->handleError(InvalidEnum() << "Unknown pname.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005115 return false;
5116 }
5117
5118 if (length)
5119 {
5120 *length = 1;
5121 }
5122 return true;
5123}
5124
5125bool ValidateGetVertexAttribBase(Context *context,
5126 GLuint index,
5127 GLenum pname,
5128 GLsizei *length,
5129 bool pointer,
5130 bool pureIntegerEntryPoint)
5131{
5132 if (length)
5133 {
5134 *length = 0;
5135 }
5136
5137 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5138 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005139 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005140 return false;
5141 }
5142
5143 if (index >= context->getCaps().maxVertexAttributes)
5144 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005145 context->handleError(InvalidValue()
5146 << "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005147 return false;
5148 }
5149
5150 if (pointer)
5151 {
5152 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5153 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005154 context->handleError(InvalidEnum() << "Unknown pname.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005155 return false;
5156 }
5157 }
5158 else
5159 {
5160 switch (pname)
5161 {
5162 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5163 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5164 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5165 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5166 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5167 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5168 case GL_CURRENT_VERTEX_ATTRIB:
5169 break;
5170
5171 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5172 static_assert(
5173 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5174 "ANGLE extension enums not equal to GL enums.");
5175 if (context->getClientMajorVersion() < 3 &&
5176 !context->getExtensions().instancedArrays)
5177 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005178 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5179 "requires OpenGL ES 3.0 or "
5180 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005181 return false;
5182 }
5183 break;
5184
5185 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5186 if (context->getClientMajorVersion() < 3)
5187 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005188 context->handleError(
5189 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005190 return false;
5191 }
5192 break;
5193
5194 case GL_VERTEX_ATTRIB_BINDING:
5195 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5196 if (context->getClientVersion() < ES_3_1)
5197 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005198 context->handleError(InvalidEnum()
5199 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005200 return false;
5201 }
5202 break;
5203
5204 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005205 context->handleError(InvalidEnum() << "Unknown pname.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005206 return false;
5207 }
5208 }
5209
5210 if (length)
5211 {
5212 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5213 {
5214 *length = 4;
5215 }
5216 else
5217 {
5218 *length = 1;
5219 }
5220 }
5221
5222 return true;
5223}
5224
5225bool ValidateReadPixelsBase(ValidationContext *context,
5226 GLint x,
5227 GLint y,
5228 GLsizei width,
5229 GLsizei height,
5230 GLenum format,
5231 GLenum type,
5232 GLsizei bufSize,
5233 GLsizei *length,
5234 GLsizei *columns,
5235 GLsizei *rows,
5236 void *pixels)
5237{
5238 if (length != nullptr)
5239 {
5240 *length = 0;
5241 }
5242 if (rows != nullptr)
5243 {
5244 *rows = 0;
5245 }
5246 if (columns != nullptr)
5247 {
5248 *columns = 0;
5249 }
5250
5251 if (width < 0 || height < 0)
5252 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005253 context->handleError(InvalidValue() << "width and height must be positive");
Jamie Madillbe849e42017-05-02 15:49:00 -04005254 return false;
5255 }
5256
5257 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5258
5259 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5260 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005261 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005262 return false;
5263 }
5264
5265 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5266 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005267 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005268 return false;
5269 }
5270
5271 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5272 ASSERT(framebuffer);
5273
5274 if (framebuffer->getReadBufferState() == GL_NONE)
5275 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005276 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Jamie Madillbe849e42017-05-02 15:49:00 -04005277 return false;
5278 }
5279
5280 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5281 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5282 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5283 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5284 // situation is an application error that would lead to a crash in ANGLE.
5285 if (readBuffer == nullptr)
5286 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005287 context->handleError(InvalidOperation() << "Missing read attachment");
Jamie Madillbe849e42017-05-02 15:49:00 -04005288 return false;
5289 }
5290
5291 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
5292 GLenum currentType = framebuffer->getImplementationColorReadType();
5293 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5294
5295 bool validFormatTypeCombination =
5296 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5297
5298 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5299 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005300 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005301 return false;
5302 }
5303
5304 // Check for pixel pack buffer related API errors
5305 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5306 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5307 {
5308 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005309 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005310 return false;
5311 }
5312
5313 // .. the data would be packed to the buffer object such that the memory writes required
5314 // would exceed the data store size.
5315 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5316 const gl::Extents size(width, height, 1);
5317 const auto &pack = context->getGLState().getPackState();
5318
5319 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5320 if (endByteOrErr.isError())
5321 {
5322 context->handleError(endByteOrErr.getError());
5323 return false;
5324 }
5325
5326 size_t endByte = endByteOrErr.getResult();
5327 if (bufSize >= 0)
5328 {
5329 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5330 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005331 context->handleError(InvalidOperation()
5332 << "bufSize must be at least " << endByte << " bytes.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005333 return false;
5334 }
5335 }
5336
5337 if (pixelPackBuffer != nullptr)
5338 {
5339 CheckedNumeric<size_t> checkedEndByte(endByte);
5340 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5341 checkedEndByte += checkedOffset;
5342
5343 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5344 {
5345 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005346 context->handleError(InvalidOperation()
5347 << "Writes would overflow the pixel pack buffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005348 return false;
5349 }
5350 }
5351
5352 if (pixelPackBuffer == nullptr && length != nullptr)
5353 {
5354 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5355 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005356 context->handleError(InvalidOperation() << "length would overflow GLsizei.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005357 return false;
5358 }
5359
5360 *length = static_cast<GLsizei>(endByte);
5361 }
5362
5363 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5364 angle::CheckedNumeric<int> clippedExtent(length);
5365 if (start < 0)
5366 {
5367 // "subtract" the area that is less than 0
5368 clippedExtent += start;
5369 }
5370
5371 const int readExtent = start + length;
5372 if (readExtent > bufferSize)
5373 {
5374 // Subtract the region to the right of the read buffer
5375 clippedExtent -= (readExtent - bufferSize);
5376 }
5377
5378 if (!clippedExtent.IsValid())
5379 {
5380 return 0;
5381 }
5382
5383 return std::max(clippedExtent.ValueOrDie(), 0);
5384 };
5385
5386 if (columns != nullptr)
5387 {
5388 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5389 }
5390
5391 if (rows != nullptr)
5392 {
5393 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5394 }
5395
5396 return true;
5397}
5398
5399template <typename ParamType>
5400bool ValidateTexParameterBase(Context *context,
5401 GLenum target,
5402 GLenum pname,
5403 GLsizei bufSize,
5404 const ParamType *params)
5405{
5406 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5407 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005408 context->handleError(InvalidEnum() << "Invalid texture target");
Jamie Madillbe849e42017-05-02 15:49:00 -04005409 return false;
5410 }
5411
5412 if (context->getTargetTexture(target) == nullptr)
5413 {
5414 // Should only be possible for external textures
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005415 context->handleError(InvalidEnum() << "No texture bound.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005416 return false;
5417 }
5418
5419 const GLsizei minBufSize = 1;
5420 if (bufSize >= 0 && bufSize < minBufSize)
5421 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005422 context->handleError(InvalidOperation() << "bufSize must be at least " << minBufSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005423 return false;
5424 }
5425
5426 switch (pname)
5427 {
5428 case GL_TEXTURE_WRAP_R:
5429 case GL_TEXTURE_SWIZZLE_R:
5430 case GL_TEXTURE_SWIZZLE_G:
5431 case GL_TEXTURE_SWIZZLE_B:
5432 case GL_TEXTURE_SWIZZLE_A:
5433 case GL_TEXTURE_BASE_LEVEL:
5434 case GL_TEXTURE_MAX_LEVEL:
5435 case GL_TEXTURE_COMPARE_MODE:
5436 case GL_TEXTURE_COMPARE_FUNC:
5437 case GL_TEXTURE_MIN_LOD:
5438 case GL_TEXTURE_MAX_LOD:
5439 if (context->getClientMajorVersion() < 3)
5440 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005441 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005442 return false;
5443 }
5444 if (target == GL_TEXTURE_EXTERNAL_OES &&
5445 !context->getExtensions().eglImageExternalEssl3)
5446 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005447 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5448 "available without "
5449 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005450 return false;
5451 }
5452 break;
5453
5454 default:
5455 break;
5456 }
5457
5458 switch (pname)
5459 {
5460 case GL_TEXTURE_WRAP_S:
5461 case GL_TEXTURE_WRAP_T:
5462 case GL_TEXTURE_WRAP_R:
5463 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
5464 {
5465 return false;
5466 }
5467 break;
5468
5469 case GL_TEXTURE_MIN_FILTER:
5470 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
5471 {
5472 return false;
5473 }
5474 break;
5475
5476 case GL_TEXTURE_MAG_FILTER:
5477 if (!ValidateTextureMagFilterValue(context, params))
5478 {
5479 return false;
5480 }
5481 break;
5482
5483 case GL_TEXTURE_USAGE_ANGLE:
5484 switch (ConvertToGLenum(params[0]))
5485 {
5486 case GL_NONE:
5487 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5488 break;
5489
5490 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005491 context->handleError(InvalidEnum() << "Unknown param value.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005492 return false;
5493 }
5494 break;
5495
5496 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5497 if (!context->getExtensions().textureFilterAnisotropic)
5498 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005499 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005500 return false;
5501 }
5502
5503 // we assume the parameter passed to this validation method is truncated, not rounded
5504 if (params[0] < 1)
5505 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005506 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005507 return false;
5508 }
5509 break;
5510
5511 case GL_TEXTURE_MIN_LOD:
5512 case GL_TEXTURE_MAX_LOD:
5513 // any value is permissible
5514 break;
5515
5516 case GL_TEXTURE_COMPARE_MODE:
5517 if (!ValidateTextureCompareModeValue(context, params))
5518 {
5519 return false;
5520 }
5521 break;
5522
5523 case GL_TEXTURE_COMPARE_FUNC:
5524 if (!ValidateTextureCompareFuncValue(context, params))
5525 {
5526 return false;
5527 }
5528 break;
5529
5530 case GL_TEXTURE_SWIZZLE_R:
5531 case GL_TEXTURE_SWIZZLE_G:
5532 case GL_TEXTURE_SWIZZLE_B:
5533 case GL_TEXTURE_SWIZZLE_A:
5534 switch (ConvertToGLenum(params[0]))
5535 {
5536 case GL_RED:
5537 case GL_GREEN:
5538 case GL_BLUE:
5539 case GL_ALPHA:
5540 case GL_ZERO:
5541 case GL_ONE:
5542 break;
5543
5544 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005545 context->handleError(InvalidEnum() << "Unknown param value.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005546 return false;
5547 }
5548 break;
5549
5550 case GL_TEXTURE_BASE_LEVEL:
5551 if (params[0] < 0)
5552 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005553 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005554 return false;
5555 }
5556 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5557 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005558 context->handleError(InvalidOperation()
5559 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005560 return false;
5561 }
5562 break;
5563
5564 case GL_TEXTURE_MAX_LEVEL:
5565 if (params[0] < 0)
5566 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005567 context->handleError(InvalidValue() << "Max level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005568 return false;
5569 }
5570 break;
5571
5572 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5573 if (context->getClientVersion() < Version(3, 1))
5574 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005575 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005576 return false;
5577 }
5578 switch (ConvertToGLenum(params[0]))
5579 {
5580 case GL_DEPTH_COMPONENT:
5581 case GL_STENCIL_INDEX:
5582 break;
5583
5584 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005585 context->handleError(InvalidEnum() << "Unknown param value.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005586 return false;
5587 }
5588 break;
5589
5590 case GL_TEXTURE_SRGB_DECODE_EXT:
5591 if (!ValidateTextureSRGBDecodeValue(context, params))
5592 {
5593 return false;
5594 }
5595 break;
5596
5597 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005598 context->handleError(InvalidEnum() << "Unknown pname.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005599 return false;
5600 }
5601
5602 return true;
5603}
5604
5605template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5606template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5607
Jamie Madillc29968b2016-01-20 11:17:23 -05005608} // namespace gl