blob: 2fdb17e5acda56e231a589054b7456f46cd7370b [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,
Geoff Langdbcced82017-06-06 15:55:54 -04001173 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -04001174 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 Langdbcced82017-06-06 15:55:54 -04001187 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
1188 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -04001189 const gl::Extents size(width, height, depth);
1190 const auto &unpack = context->getGLState().getUnpackState();
1191
1192 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1193 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1194 if (endByteOrErr.isError())
1195 {
1196 context->handleError(endByteOrErr.getError());
1197 return false;
1198 }
1199
1200 GLuint endByte = endByteOrErr.getResult();
1201
1202 if (pixelUnpackBuffer)
1203 {
1204 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1205 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1206 checkedEndByte += checkedOffset;
1207
1208 if (!checkedEndByte.IsValid() ||
1209 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1210 {
1211 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001212 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04001213 return false;
1214 }
1215 }
1216 else
1217 {
1218 ASSERT(imageSize >= 0);
1219 if (pixels == nullptr && imageSize != 0)
1220 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001221 context->handleError(InvalidOperation()
1222 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001223 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001224 }
1225
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001226 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001227 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001228 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001229 return false;
1230 }
1231 }
1232
1233 return true;
1234}
1235
Geoff Lang37dde692014-01-31 16:34:54 -05001236bool ValidQueryType(const Context *context, GLenum queryType)
1237{
He Yunchaoced53ae2016-11-29 15:00:51 +08001238 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1239 "GL extension enums not equal.");
1240 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1241 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001242
1243 switch (queryType)
1244 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001245 case GL_ANY_SAMPLES_PASSED:
1246 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1247 return true;
1248 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1249 return (context->getClientMajorVersion() >= 3);
1250 case GL_TIME_ELAPSED_EXT:
1251 return context->getExtensions().disjointTimerQuery;
1252 case GL_COMMANDS_COMPLETED_CHROMIUM:
1253 return context->getExtensions().syncQuery;
1254 default:
1255 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001256 }
1257}
1258
Geoff Lang2d62ab72017-03-23 16:54:40 -04001259bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
1260 GLenum type,
1261 GLboolean normalized,
1262 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001263 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001264 bool pureInteger)
1265{
1266 ASSERT(context->getExtensions().webglCompatibility);
1267
1268 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1269 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1270 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1271 // parameter exceeds 255.
1272 constexpr GLsizei kMaxWebGLStride = 255;
1273 if (stride > kMaxWebGLStride)
1274 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001275 context->handleError(InvalidValue()
1276 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001277 return false;
1278 }
1279
1280 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1281 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1282 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1283 // or an INVALID_OPERATION error is generated.
1284 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1285 size_t typeSize = GetVertexFormatTypeSize(internalType);
1286
1287 ASSERT(isPow2(typeSize) && typeSize > 0);
1288 size_t sizeMask = (typeSize - 1);
1289 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1290 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001291 context->handleError(InvalidOperation() << "Offset is not a multiple of the type size.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001292 return false;
1293 }
1294
1295 if ((stride & sizeMask) != 0)
1296 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001297 context->handleError(InvalidOperation() << "Stride is not a multiple of the type size.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001298 return false;
1299 }
1300
1301 return true;
1302}
1303
Jamie Madillef300b12016-10-07 15:12:09 -04001304Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001305{
He Yunchaoced53ae2016-11-29 15:00:51 +08001306 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1307 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1308 // or program object and INVALID_OPERATION if the provided name identifies an object
1309 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001310
Dian Xiang769769a2015-09-09 15:20:08 -07001311 Program *validProgram = context->getProgram(id);
1312
1313 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001314 {
Dian Xiang769769a2015-09-09 15:20:08 -07001315 if (context->getShader(id))
1316 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001317 context->handleError(InvalidOperation()
1318 << "Expected a program name, but found a shader name");
Dian Xiang769769a2015-09-09 15:20:08 -07001319 }
1320 else
1321 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001322 context->handleError(InvalidValue() << "Program name is not valid");
Dian Xiang769769a2015-09-09 15:20:08 -07001323 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001324 }
Dian Xiang769769a2015-09-09 15:20:08 -07001325
1326 return validProgram;
1327}
1328
Jamie Madillef300b12016-10-07 15:12:09 -04001329Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001330{
1331 // See ValidProgram for spec details.
1332
1333 Shader *validShader = context->getShader(id);
1334
1335 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001336 {
Dian Xiang769769a2015-09-09 15:20:08 -07001337 if (context->getProgram(id))
1338 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001339 context->handleError(InvalidOperation()
1340 << "Expected a shader name, but found a program name");
Dian Xiang769769a2015-09-09 15:20:08 -07001341 }
1342 else
1343 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001344 context->handleError(InvalidValue() << "Shader name is invalid");
Dian Xiang769769a2015-09-09 15:20:08 -07001345 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001346 }
Dian Xiang769769a2015-09-09 15:20:08 -07001347
1348 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001349}
1350
Geoff Langb1196682014-07-23 13:47:29 -04001351bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001352{
1353 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1354 {
1355 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1356
Geoff Langaae65a42014-05-26 12:43:44 -04001357 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001358 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001359 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001360 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001361 }
1362 }
1363 else
1364 {
1365 switch (attachment)
1366 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001367 case GL_DEPTH_ATTACHMENT:
1368 case GL_STENCIL_ATTACHMENT:
1369 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001370
He Yunchaoced53ae2016-11-29 15:00:51 +08001371 case GL_DEPTH_STENCIL_ATTACHMENT:
1372 if (!context->getExtensions().webglCompatibility &&
1373 context->getClientMajorVersion() < 3)
1374 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001375 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001376 return false;
1377 }
1378 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001379
He Yunchaoced53ae2016-11-29 15:00:51 +08001380 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001381 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001382 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001383 }
1384 }
1385
1386 return true;
1387}
1388
Jamie Madille8fb6402017-02-14 17:56:40 -05001389bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001390 GLenum target,
1391 GLsizei samples,
1392 GLenum internalformat,
1393 GLsizei width,
1394 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001395{
1396 switch (target)
1397 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001398 case GL_RENDERBUFFER:
1399 break;
1400 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001401 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001402 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001403 }
1404
1405 if (width < 0 || height < 0 || samples < 0)
1406 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001407 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001408 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001409 }
1410
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001411 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1412 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1413
1414 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001415 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001416 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001417 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001418 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001419 }
1420
1421 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1422 // 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 -08001423 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001424 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1425 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001427 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001428 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001429 }
1430
Geoff Langaae65a42014-05-26 12:43:44 -04001431 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001432 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001433 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001434 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001435 }
1436
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001437 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001438 if (handle == 0)
1439 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001440 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001441 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001442 }
1443
1444 return true;
1445}
1446
He Yunchaoced53ae2016-11-29 15:00:51 +08001447bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1448 GLenum target,
1449 GLenum attachment,
1450 GLenum renderbuffertarget,
1451 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001452{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001453 if (!ValidFramebufferTarget(target))
1454 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001455 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001456 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001457 }
1458
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001459 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001460
Jamie Madill84115c92015-04-23 15:00:07 -04001461 ASSERT(framebuffer);
1462 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001463 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001464 context->handleError(InvalidOperation() << "Cannot change default FBO's attachments");
Geoff Langb1196682014-07-23 13:47:29 -04001465 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001466 }
1467
Jamie Madillb4472272014-07-03 10:38:55 -04001468 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001469 {
Jamie Madillb4472272014-07-03 10:38:55 -04001470 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001471 }
1472
Jamie Madillab9d82c2014-01-21 16:38:14 -05001473 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1474 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1475 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1476 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1477 if (renderbuffer != 0)
1478 {
1479 if (!context->getRenderbuffer(renderbuffer))
1480 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001481 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001482 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001483 }
1484 }
1485
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001486 return true;
1487}
1488
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001489bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001490 GLint srcX0,
1491 GLint srcY0,
1492 GLint srcX1,
1493 GLint srcY1,
1494 GLint dstX0,
1495 GLint dstY0,
1496 GLint dstX1,
1497 GLint dstY1,
1498 GLbitfield mask,
1499 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001500{
1501 switch (filter)
1502 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001503 case GL_NEAREST:
1504 break;
1505 case GL_LINEAR:
1506 break;
1507 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001508 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001509 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001510 }
1511
1512 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001514 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001515 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001516 }
1517
1518 if (mask == 0)
1519 {
1520 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1521 // buffers are copied.
1522 return false;
1523 }
1524
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001525 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1526 // color buffer, leaving only nearest being unfiltered from above
1527 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1528 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001529 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001530 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001531 }
1532
Jamie Madill51f40ec2016-06-15 14:06:00 -04001533 const auto &glState = context->getGLState();
1534 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1535 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001536
1537 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001538 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001539 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001540 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001541 }
1542
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001543 if (readFramebuffer->id() == drawFramebuffer->id())
1544 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001545 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001546 return false;
1547 }
1548
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001549 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001550 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001551 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001552 return false;
1553 }
1554
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001555 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001556 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001557 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001558 return false;
1559 }
1560
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001561 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001562 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001563 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001564 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001565 }
1566
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001567 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1568
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001569 if (mask & GL_COLOR_BUFFER_BIT)
1570 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001571 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001572 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001573
He Yunchao66a41a22016-12-15 16:45:05 +08001574 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001575 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001576 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001577
Geoff Langa15472a2015-08-11 11:48:03 -04001578 for (size_t drawbufferIdx = 0;
1579 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001580 {
Geoff Langa15472a2015-08-11 11:48:03 -04001581 const FramebufferAttachment *attachment =
1582 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1583 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001584 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001585 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001586
Geoff Langb2f3d052013-08-13 12:49:27 -04001587 // The GL ES 3.0.2 spec (pg 193) states that:
1588 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001589 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1590 // as well
1591 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1592 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001593 // Changes with EXT_color_buffer_float:
1594 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001595 GLenum readComponentType = readFormat.info->componentType;
1596 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001597 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001598 readComponentType == GL_SIGNED_NORMALIZED);
1599 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1600 drawComponentType == GL_SIGNED_NORMALIZED);
1601
1602 if (extensions.colorBufferFloat)
1603 {
1604 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1605 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1606
1607 if (readFixedOrFloat != drawFixedOrFloat)
1608 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001609 context->handleError(InvalidOperation()
1610 << "If the read buffer contains fixed-point or "
1611 "floating-point values, the draw buffer must "
1612 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001613 return false;
1614 }
1615 }
1616 else if (readFixedPoint != drawFixedPoint)
1617 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001618 context->handleError(InvalidOperation()
1619 << "If the read buffer contains fixed-point values, "
1620 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001621 return false;
1622 }
1623
1624 if (readComponentType == GL_UNSIGNED_INT &&
1625 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001626 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001627 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001628 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001629 }
1630
Jamie Madill6163c752015-12-07 16:32:59 -05001631 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001632 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001633 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001634 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001635 }
1636
Jamie Madilla3944d42016-07-22 22:13:26 -04001637 if (readColorBuffer->getSamples() > 0 &&
1638 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001639 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001640 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001641 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001642 }
Geoff Lange4915782017-04-12 15:19:07 -04001643
1644 if (context->getExtensions().webglCompatibility &&
1645 *readColorBuffer == *attachment)
1646 {
1647 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001648 InvalidOperation()
1649 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001650 return false;
1651 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001652 }
1653 }
1654
Jamie Madilla3944d42016-07-22 22:13:26 -04001655 if ((readFormat.info->componentType == GL_INT ||
1656 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1657 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001659 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001660 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001661 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001662 }
He Yunchao66a41a22016-12-15 16:45:05 +08001663 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1664 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1665 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1666 // situation is an application error that would lead to a crash in ANGLE.
1667 else if (drawFramebuffer->hasEnabledDrawBuffer())
1668 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001669 context->handleError(
1670 InvalidOperation()
1671 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001672 return false;
1673 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001674 }
1675
He Yunchaoced53ae2016-11-29 15:00:51 +08001676 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001677 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1678 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001679 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001680 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001681 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001682 const gl::FramebufferAttachment *readBuffer =
1683 readFramebuffer->getAttachment(attachments[i]);
1684 const gl::FramebufferAttachment *drawBuffer =
1685 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001686
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001687 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001688 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001689 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001690 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001691 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001692 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001693 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001694
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001695 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001696 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001697 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001698 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001699 }
Geoff Lange4915782017-04-12 15:19:07 -04001700
1701 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1702 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001703 context->handleError(
1704 InvalidOperation()
1705 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001706 return false;
1707 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001708 }
He Yunchao66a41a22016-12-15 16:45:05 +08001709 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1710 else if (drawBuffer)
1711 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001712 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1713 "depth/stencil attachment of a "
1714 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001715 return false;
1716 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001717 }
1718 }
1719
1720 return true;
1721}
1722
Geoff Lang62fce5b2016-09-30 10:46:35 -04001723bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
1724 GLint x,
1725 GLint y,
1726 GLsizei width,
1727 GLsizei height,
1728 GLenum format,
1729 GLenum type,
1730 GLsizei bufSize,
1731 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001732 GLsizei *columns,
1733 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001734 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001735{
1736 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001737 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001738 return false;
1739 }
1740
Geoff Lang62fce5b2016-09-30 10:46:35 -04001741 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001742 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001743 {
Geoff Langb1196682014-07-23 13:47:29 -04001744 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001745 }
1746
Geoff Lang62fce5b2016-09-30 10:46:35 -04001747 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001748 {
Geoff Langb1196682014-07-23 13:47:29 -04001749 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001750 }
1751
Jamie Madillc29968b2016-01-20 11:17:23 -05001752 return true;
1753}
1754
1755bool ValidateReadnPixelsEXT(Context *context,
1756 GLint x,
1757 GLint y,
1758 GLsizei width,
1759 GLsizei height,
1760 GLenum format,
1761 GLenum type,
1762 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001763 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001764{
1765 if (bufSize < 0)
1766 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001767 context->handleError(InvalidValue() << "bufSize must be a positive number");
Jamie Madillc29968b2016-01-20 11:17:23 -05001768 return false;
1769 }
1770
Geoff Lang62fce5b2016-09-30 10:46:35 -04001771 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001772 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001773}
Jamie Madill26e91952014-03-05 15:01:27 -05001774
Geoff Lang62fce5b2016-09-30 10:46:35 -04001775bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
1776 GLint x,
1777 GLint y,
1778 GLsizei width,
1779 GLsizei height,
1780 GLenum format,
1781 GLenum type,
1782 GLsizei bufSize,
1783 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001784 GLsizei *columns,
1785 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001786 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001787{
1788 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001789 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001790 return false;
1791 }
1792
Geoff Lange93daba2017-03-30 13:54:40 -04001793 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1794 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001795 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001796 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001797 }
1798
Geoff Lang62fce5b2016-09-30 10:46:35 -04001799 if (!ValidateRobustBufferSize(context, bufSize, *length))
1800 {
1801 return false;
1802 }
1803
1804 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001805}
1806
Olli Etuaho41997e72016-03-10 13:38:39 +02001807bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001808{
1809 if (!context->getExtensions().occlusionQueryBoolean &&
1810 !context->getExtensions().disjointTimerQuery)
1811 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001812 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001813 return false;
1814 }
1815
Olli Etuaho41997e72016-03-10 13:38:39 +02001816 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001817}
1818
Olli Etuaho41997e72016-03-10 13:38:39 +02001819bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001820{
1821 if (!context->getExtensions().occlusionQueryBoolean &&
1822 !context->getExtensions().disjointTimerQuery)
1823 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001824 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001825 return false;
1826 }
1827
Olli Etuaho41997e72016-03-10 13:38:39 +02001828 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001829}
1830
1831bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001832{
1833 if (!ValidQueryType(context, target))
1834 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001835 context->handleError(InvalidEnum() << "Invalid query target");
Geoff Langb1196682014-07-23 13:47:29 -04001836 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001837 }
1838
1839 if (id == 0)
1840 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001841 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001842 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001843 }
1844
1845 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1846 // of zero, if the active query object name for <target> is non-zero (for the
1847 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1848 // the active query for either target is non-zero), if <id> is the name of an
1849 // existing query object whose type does not match <target>, or if <id> is the
1850 // active query object name for any query type, the error INVALID_OPERATION is
1851 // generated.
1852
1853 // Ensure no other queries are active
1854 // NOTE: If other queries than occlusion are supported, we will need to check
1855 // separately that:
1856 // a) The query ID passed is not the current active query for any target/type
1857 // b) There are no active queries for the requested target (and in the case
1858 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1859 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001860
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001861 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001862 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001863 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001864 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001865 }
1866
1867 Query *queryObject = context->getQuery(id, true, target);
1868
1869 // check that name was obtained with glGenQueries
1870 if (!queryObject)
1871 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001872 context->handleError(InvalidOperation() << "Invalid query id");
Geoff Langb1196682014-07-23 13:47:29 -04001873 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001874 }
1875
1876 // check for type mismatch
1877 if (queryObject->getType() != target)
1878 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001879 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001880 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001881 }
1882
1883 return true;
1884}
1885
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001886bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1887{
1888 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001889 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001890 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001891 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001892 return false;
1893 }
1894
1895 return ValidateBeginQueryBase(context, target, id);
1896}
1897
1898bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001899{
1900 if (!ValidQueryType(context, target))
1901 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001902 context->handleError(InvalidEnum() << "Invalid query target");
Geoff Langb1196682014-07-23 13:47:29 -04001903 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001904 }
1905
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001906 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001907
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001908 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001909 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001910 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001911 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001912 }
1913
Jamie Madill45c785d2014-05-13 14:09:34 -04001914 return true;
1915}
1916
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001917bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1918{
1919 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001920 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001921 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001922 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001923 return false;
1924 }
1925
1926 return ValidateEndQueryBase(context, target);
1927}
1928
1929bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1930{
1931 if (!context->getExtensions().disjointTimerQuery)
1932 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001933 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001934 return false;
1935 }
1936
1937 if (target != GL_TIMESTAMP_EXT)
1938 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001939 context->handleError(InvalidEnum() << "Invalid query target");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001940 return false;
1941 }
1942
1943 Query *queryObject = context->getQuery(id, true, target);
1944 if (queryObject == nullptr)
1945 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001946 context->handleError(InvalidOperation() << "Invalid query id");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001947 return false;
1948 }
1949
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001950 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001951 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001952 context->handleError(InvalidOperation() << "Query is active");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001953 return false;
1954 }
1955
1956 return true;
1957}
1958
Geoff Lang2186c382016-10-14 10:54:54 -04001959bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001960{
Geoff Lang2186c382016-10-14 10:54:54 -04001961 if (numParams)
1962 {
1963 *numParams = 0;
1964 }
1965
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001966 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1967 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001968 context->handleError(InvalidEnum() << "Invalid query type");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001969 return false;
1970 }
1971
1972 switch (pname)
1973 {
1974 case GL_CURRENT_QUERY_EXT:
1975 if (target == GL_TIMESTAMP_EXT)
1976 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001977 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001978 return false;
1979 }
1980 break;
1981 case GL_QUERY_COUNTER_BITS_EXT:
1982 if (!context->getExtensions().disjointTimerQuery ||
1983 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1984 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001985 context->handleError(InvalidEnum() << "Invalid pname");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001986 return false;
1987 }
1988 break;
1989 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001990 context->handleError(InvalidEnum() << "Invalid pname");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001991 return false;
1992 }
1993
Geoff Lang2186c382016-10-14 10:54:54 -04001994 if (numParams)
1995 {
1996 // All queries return only one value
1997 *numParams = 1;
1998 }
1999
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002000 return true;
2001}
2002
2003bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2004{
2005 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002006 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002007 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002008 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002009 return false;
2010 }
2011
Geoff Lang2186c382016-10-14 10:54:54 -04002012 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002013}
2014
Geoff Lang2186c382016-10-14 10:54:54 -04002015bool ValidateGetQueryivRobustANGLE(Context *context,
2016 GLenum target,
2017 GLenum pname,
2018 GLsizei bufSize,
2019 GLsizei *length,
2020 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002021{
Geoff Lang2186c382016-10-14 10:54:54 -04002022 if (!ValidateRobustEntryPoint(context, bufSize))
2023 {
2024 return false;
2025 }
2026
2027 if (!ValidateGetQueryivBase(context, target, pname, length))
2028 {
2029 return false;
2030 }
2031
2032 if (!ValidateRobustBufferSize(context, bufSize, *length))
2033 {
2034 return false;
2035 }
2036
2037 return true;
2038}
2039
2040bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2041{
2042 if (numParams)
2043 {
2044 *numParams = 0;
2045 }
2046
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002047 Query *queryObject = context->getQuery(id, false, GL_NONE);
2048
2049 if (!queryObject)
2050 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002051 context->handleError(InvalidOperation() << "Query does not exist");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002052 return false;
2053 }
2054
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002055 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002056 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002057 context->handleError(InvalidOperation() << "Query currently active");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002058 return false;
2059 }
2060
2061 switch (pname)
2062 {
2063 case GL_QUERY_RESULT_EXT:
2064 case GL_QUERY_RESULT_AVAILABLE_EXT:
2065 break;
2066
2067 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002068 context->handleError(InvalidEnum() << "Invalid pname enum");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002069 return false;
2070 }
2071
Geoff Lang2186c382016-10-14 10:54:54 -04002072 if (numParams)
2073 {
2074 *numParams = 1;
2075 }
2076
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002077 return true;
2078}
2079
2080bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2081{
2082 if (!context->getExtensions().disjointTimerQuery)
2083 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002084 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002085 return false;
2086 }
Geoff Lang2186c382016-10-14 10:54:54 -04002087 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2088}
2089
2090bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2091 GLuint id,
2092 GLenum pname,
2093 GLsizei bufSize,
2094 GLsizei *length,
2095 GLint *params)
2096{
2097 if (!context->getExtensions().disjointTimerQuery)
2098 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002099 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002100 return false;
2101 }
2102
2103 if (!ValidateRobustEntryPoint(context, bufSize))
2104 {
2105 return false;
2106 }
2107
2108 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2109 {
2110 return false;
2111 }
2112
2113 if (!ValidateRobustBufferSize(context, bufSize, *length))
2114 {
2115 return false;
2116 }
2117
2118 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002119}
2120
2121bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2122{
2123 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002124 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002125 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002126 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002127 return false;
2128 }
Geoff Lang2186c382016-10-14 10:54:54 -04002129 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2130}
2131
2132bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2133 GLuint id,
2134 GLenum pname,
2135 GLsizei bufSize,
2136 GLsizei *length,
2137 GLuint *params)
2138{
2139 if (!context->getExtensions().disjointTimerQuery &&
2140 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2141 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002142 context->handleError(InvalidOperation() << "Query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002143 return false;
2144 }
2145
2146 if (!ValidateRobustEntryPoint(context, bufSize))
2147 {
2148 return false;
2149 }
2150
2151 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2152 {
2153 return false;
2154 }
2155
2156 if (!ValidateRobustBufferSize(context, bufSize, *length))
2157 {
2158 return false;
2159 }
2160
2161 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002162}
2163
2164bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2165{
2166 if (!context->getExtensions().disjointTimerQuery)
2167 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002168 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002169 return false;
2170 }
Geoff Lang2186c382016-10-14 10:54:54 -04002171 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2172}
2173
2174bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2175 GLuint id,
2176 GLenum pname,
2177 GLsizei bufSize,
2178 GLsizei *length,
2179 GLint64 *params)
2180{
2181 if (!context->getExtensions().disjointTimerQuery)
2182 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002183 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002184 return false;
2185 }
2186
2187 if (!ValidateRobustEntryPoint(context, bufSize))
2188 {
2189 return false;
2190 }
2191
2192 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2193 {
2194 return false;
2195 }
2196
2197 if (!ValidateRobustBufferSize(context, bufSize, *length))
2198 {
2199 return false;
2200 }
2201
2202 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002203}
2204
2205bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2206{
2207 if (!context->getExtensions().disjointTimerQuery)
2208 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002209 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002210 return false;
2211 }
Geoff Lang2186c382016-10-14 10:54:54 -04002212 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2213}
2214
2215bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2216 GLuint id,
2217 GLenum pname,
2218 GLsizei bufSize,
2219 GLsizei *length,
2220 GLuint64 *params)
2221{
2222 if (!context->getExtensions().disjointTimerQuery)
2223 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002224 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002225 return false;
2226 }
2227
2228 if (!ValidateRobustEntryPoint(context, bufSize))
2229 {
2230 return false;
2231 }
2232
2233 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2234 {
2235 return false;
2236 }
2237
2238 if (!ValidateRobustBufferSize(context, bufSize, *length))
2239 {
2240 return false;
2241 }
2242
2243 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002244}
2245
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002246bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002247 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002248 GLuint program,
2249 GLint location,
2250 GLsizei count)
2251{
2252 // Check for ES31 program uniform entry points
2253 if (context->getClientVersion() < Version(3, 1))
2254 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002255 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002256 return false;
2257 }
2258
2259 const LinkedUniform *uniform = nullptr;
2260 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002261 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2262 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002263}
2264
Frank Henigmana98a6472017-02-02 21:38:32 -05002265bool ValidateProgramUniform1iv(gl::Context *context,
2266 GLuint program,
2267 GLint location,
2268 GLsizei count,
2269 const GLint *value)
2270{
2271 // Check for ES31 program uniform entry points
2272 if (context->getClientVersion() < Version(3, 1))
2273 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002274 context->handleError(InvalidOperation());
Frank Henigmana98a6472017-02-02 21:38:32 -05002275 return false;
2276 }
2277
2278 const LinkedUniform *uniform = nullptr;
2279 gl::Program *programObject = GetValidProgram(context, program);
2280 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2281 ValidateUniform1ivValue(context, uniform->type, count, value);
2282}
2283
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002284bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002285 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002286 GLuint program,
2287 GLint location,
2288 GLsizei count,
2289 GLboolean transpose)
2290{
2291 // Check for ES31 program uniform entry points
2292 if (context->getClientVersion() < Version(3, 1))
2293 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002294 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002295 return false;
2296 }
2297
2298 const LinkedUniform *uniform = nullptr;
2299 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002300 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2301 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002302}
2303
Jamie Madillc1d770e2017-04-13 17:31:24 -04002304bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002305{
2306 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002307 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002308 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002309 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002310 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002311 }
2312
Jamie Madill62d31cb2015-09-11 13:25:51 -04002313 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002314 gl::Program *programObject = context->getGLState().getProgram();
2315 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2316 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002317}
2318
Jamie Madillbe849e42017-05-02 15:49:00 -04002319bool ValidateUniform1iv(ValidationContext *context,
2320 GLint location,
2321 GLsizei count,
2322 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002323{
2324 const LinkedUniform *uniform = nullptr;
2325 gl::Program *programObject = context->getGLState().getProgram();
2326 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2327 ValidateUniform1ivValue(context, uniform->type, count, value);
2328}
2329
Jamie Madillc1d770e2017-04-13 17:31:24 -04002330bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002331 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002332 GLint location,
2333 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002334 GLboolean transpose)
2335{
2336 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002337 int rows = VariableRowCount(valueType);
2338 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002339 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002340 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002341 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002342 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002343 }
2344
Martin Radev1be913c2016-07-11 17:59:16 +03002345 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002346 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002347 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002348 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002349 }
2350
Jamie Madill62d31cb2015-09-11 13:25:51 -04002351 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002352 gl::Program *programObject = context->getGLState().getProgram();
2353 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2354 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002355}
2356
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002357bool ValidateStateQuery(ValidationContext *context,
2358 GLenum pname,
2359 GLenum *nativeType,
2360 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002361{
2362 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2363 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002364 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002365 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002366 }
2367
Jamie Madill0af26e12015-03-05 19:54:33 -05002368 const Caps &caps = context->getCaps();
2369
Jamie Madill893ab082014-05-16 16:56:10 -04002370 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2371 {
2372 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2373
Jamie Madill0af26e12015-03-05 19:54:33 -05002374 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002375 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002376 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002377 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002378 }
2379 }
2380
2381 switch (pname)
2382 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002383 case GL_TEXTURE_BINDING_2D:
2384 case GL_TEXTURE_BINDING_CUBE_MAP:
2385 case GL_TEXTURE_BINDING_3D:
2386 case GL_TEXTURE_BINDING_2D_ARRAY:
2387 break;
2388 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2389 if (!context->getExtensions().eglStreamConsumerExternal &&
2390 !context->getExtensions().eglImageExternal)
2391 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002392 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2393 "nor GL_OES_EGL_image_external "
2394 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002395 return false;
2396 }
2397 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002398
He Yunchaoced53ae2016-11-29 15:00:51 +08002399 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2400 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002401 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002402 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2403 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002404 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002405 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002406 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002407 }
2408
Jamie Madill51f40ec2016-06-15 14:06:00 -04002409 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2410 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002411
2412 if (framebuffer->getReadBufferState() == GL_NONE)
2413 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002414 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Martin Radev138064f2016-07-15 12:03:41 +03002415 return false;
2416 }
2417
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002418 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002419 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002420 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002421 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002422 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002423 }
2424 }
2425 break;
2426
He Yunchaoced53ae2016-11-29 15:00:51 +08002427 default:
2428 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002429 }
2430
2431 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002432 if (*numParams == 0)
2433 {
2434 return false;
2435 }
2436
2437 return true;
2438}
2439
2440bool ValidateRobustStateQuery(ValidationContext *context,
2441 GLenum pname,
2442 GLsizei bufSize,
2443 GLenum *nativeType,
2444 unsigned int *numParams)
2445{
2446 if (!ValidateRobustEntryPoint(context, bufSize))
2447 {
2448 return false;
2449 }
2450
2451 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2452 {
2453 return false;
2454 }
2455
2456 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002457 {
2458 return false;
2459 }
2460
2461 return true;
2462}
2463
Jamie Madillc29968b2016-01-20 11:17:23 -05002464bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2465 GLenum target,
2466 GLint level,
2467 GLenum internalformat,
2468 bool isSubImage,
2469 GLint xoffset,
2470 GLint yoffset,
2471 GLint zoffset,
2472 GLint x,
2473 GLint y,
2474 GLsizei width,
2475 GLsizei height,
2476 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002477 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002478{
Jamie Madill560a8d82014-05-21 13:06:20 -04002479 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2480 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002481 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002482 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002483 }
2484
He Yunchaoced53ae2016-11-29 15:00:51 +08002485 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2486 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002488 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002489 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002490 }
2491
2492 if (border != 0)
2493 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002494 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002495 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002496 }
2497
2498 if (!ValidMipLevel(context, target, level))
2499 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002500 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002501 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002502 }
2503
Jamie Madill51f40ec2016-06-15 14:06:00 -04002504 const auto &state = context->getGLState();
2505 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002506 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002507 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002508 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002509 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002510 }
2511
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002512 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002514 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002515 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002516 }
2517
Martin Radev138064f2016-07-15 12:03:41 +03002518 if (readFramebuffer->getReadBufferState() == GL_NONE)
2519 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002520 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Martin Radev138064f2016-07-15 12:03:41 +03002521 return false;
2522 }
2523
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002524 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2525 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002526 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002527 // situation is an application error that would lead to a crash in ANGLE.
2528 if (readFramebuffer->getReadColorbuffer() == nullptr)
2529 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002530 context->handleError(InvalidOperation() << "Missing read attachment");
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002531 return false;
2532 }
2533
Geoff Langaae65a42014-05-26 12:43:44 -04002534 const gl::Caps &caps = context->getCaps();
2535
Geoff Langaae65a42014-05-26 12:43:44 -04002536 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002537 switch (target)
2538 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002539 case GL_TEXTURE_2D:
2540 maxDimension = caps.max2DTextureSize;
2541 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002542
He Yunchaoced53ae2016-11-29 15:00:51 +08002543 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2544 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2545 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2546 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2547 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2548 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2549 maxDimension = caps.maxCubeMapTextureSize;
2550 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002551
He Yunchaoced53ae2016-11-29 15:00:51 +08002552 case GL_TEXTURE_2D_ARRAY:
2553 maxDimension = caps.max2DTextureSize;
2554 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002555
He Yunchaoced53ae2016-11-29 15:00:51 +08002556 case GL_TEXTURE_3D:
2557 maxDimension = caps.max3DTextureSize;
2558 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002559
He Yunchaoced53ae2016-11-29 15:00:51 +08002560 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002561 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002562 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002563 }
2564
Jamie Madillc29968b2016-01-20 11:17:23 -05002565 gl::Texture *texture =
2566 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002567 if (!texture)
2568 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002569 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002570 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002571 }
2572
Geoff Lang69cce582015-09-17 13:20:36 -04002573 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002574 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002575 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002576 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002577 }
2578
Geoff Langca271392017-04-05 12:30:00 -04002579 const gl::InternalFormat &formatInfo =
2580 gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002581
Geoff Lang966c9402017-04-18 12:38:27 -04002582 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002583 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002584 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002585 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002586 }
2587
2588 if (isSubImage)
2589 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002590 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2591 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2592 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002593 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002594 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002595 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002596 }
2597 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002598 else
2599 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002600 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002601 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002602 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002603 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002604 }
2605
Geoff Langeb66a6e2016-10-31 13:06:12 -04002606 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002607 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002608 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002609 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002610 }
2611
2612 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002613 if (static_cast<int>(width) > maxLevelDimension ||
2614 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002615 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002616 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002617 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002618 }
2619 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002620
Jamie Madill0c8abca2016-07-22 20:21:26 -04002621 if (textureFormatOut)
2622 {
2623 *textureFormatOut = texture->getFormat(target, level);
2624 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002625
2626 // Detect texture copying feedback loops for WebGL.
2627 if (context->getExtensions().webglCompatibility)
2628 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002629 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002630 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002631 context->handleError(InvalidOperation() << "Texture copying feedback loop formed "
2632 "between Framebuffer and specified "
2633 "Texture level.");
Jamie Madillf695a3a2017-01-11 17:36:35 -05002634 return false;
2635 }
2636 }
2637
Jamie Madill560a8d82014-05-21 13:06:20 -04002638 return true;
2639}
2640
Jiajia Qind9671222016-11-29 16:30:31 +08002641bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002642{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002643 switch (mode)
2644 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002645 case GL_POINTS:
2646 case GL_LINES:
2647 case GL_LINE_LOOP:
2648 case GL_LINE_STRIP:
2649 case GL_TRIANGLES:
2650 case GL_TRIANGLE_STRIP:
2651 case GL_TRIANGLE_FAN:
2652 break;
2653 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002654 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002655 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002656 }
2657
Jamie Madill250d33f2014-06-06 17:09:03 -04002658 if (count < 0)
2659 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002660 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002661 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002662 }
2663
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002664 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002665
Jamie Madill250d33f2014-06-06 17:09:03 -04002666 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002667 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002668 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002669 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002670 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002671 }
2672
Jamie Madillcbcde722017-01-06 14:50:00 -05002673 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2674 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002675 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002676 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
2677 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002678 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002679 const FramebufferAttachment *dsAttachment =
2680 framebuffer->getStencilOrDepthStencilAttachment();
2681 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002682 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002683 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002684
2685 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2686 bool differentWritemasks =
2687 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2688 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2689 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2690 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2691
2692 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002693 {
Jamie Madillcbcde722017-01-06 14:50:00 -05002694 if (!context->getExtensions().webglCompatibility)
2695 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002696 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2697 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002698 }
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002699 context->handleError(InvalidOperation());
Geoff Lang3a86ad32015-09-01 11:47:05 -04002700 return false;
2701 }
Jamie Madillac528012014-06-20 13:21:23 -04002702 }
2703
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002704 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002705 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002706 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002707 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002708 }
2709
Geoff Lang7dd2e102014-11-10 15:19:26 -05002710 gl::Program *program = state.getProgram();
2711 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002712 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002713 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002714 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002715 }
2716
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002717 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002719 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002720 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002721 }
2722
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002723 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002724 for (unsigned int uniformBlockIndex = 0;
2725 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002726 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002727 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002728 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002729 const OffsetBindingPointer<Buffer> &uniformBuffer =
2730 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002731
Geoff Lang5d124a62015-09-15 13:03:27 -04002732 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002733 {
2734 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002735 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002736 InvalidOperation()
2737 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002738 return false;
2739 }
2740
Geoff Lang5d124a62015-09-15 13:03:27 -04002741 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002742 if (uniformBufferSize == 0)
2743 {
2744 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002745 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002746 }
2747
Jamie Madill62d31cb2015-09-11 13:25:51 -04002748 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002749 {
2750 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002751 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002752 InvalidOperation()
2753 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002754 return false;
2755 }
2756 }
2757
Geoff Lange0cff192017-05-30 13:04:56 -04002758 // Do some additonal WebGL-specific validation
Jamie Madilla4595b82017-01-11 17:36:34 -05002759 if (context->getExtensions().webglCompatibility)
2760 {
Geoff Lange0cff192017-05-30 13:04:56 -04002761 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002762 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2763 {
2764 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002765 InvalidOperation()
2766 << "Rendering feedback loop formed between Framebuffer and active Texture.");
Jamie Madilla4595b82017-01-11 17:36:34 -05002767 return false;
2768 }
Geoff Lange0cff192017-05-30 13:04:56 -04002769
Geoff Lang9ab5b822017-05-30 16:19:23 -04002770 // Detect that the vertex shader input types match the attribute types
2771 if (!ValidateVertexShaderAttributeTypeMatch(context))
2772 {
2773 return false;
2774 }
2775
Geoff Lange0cff192017-05-30 13:04:56 -04002776 // Detect that the color buffer types match the fragment shader output types
2777 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2778 {
2779 return false;
2780 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002781 }
2782
Jamie Madill250d33f2014-06-06 17:09:03 -04002783 // No-op if zero count
2784 return (count > 0);
2785}
2786
Jamie Madillc1d770e2017-04-13 17:31:24 -04002787bool ValidateDrawArraysCommon(ValidationContext *context,
2788 GLenum mode,
2789 GLint first,
2790 GLsizei count,
2791 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002792{
Jamie Madillfd716582014-06-06 17:09:04 -04002793 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002794 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002795 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002796 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002797 }
2798
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002799 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002800 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002801 if (curTransformFeedback && curTransformFeedback->isActive() &&
2802 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002803 {
2804 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002805 // that does not match the current transform feedback object's draw mode (if transform
2806 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002807 // is active), (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002808 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002809 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002810 }
2811
Jiajia Qind9671222016-11-29 16:30:31 +08002812 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002813 {
2814 return false;
2815 }
2816
Corentin Wallez71168a02016-12-19 15:11:18 -08002817 // Check the computation of maxVertex doesn't overflow.
2818 // - first < 0 or count < 0 have been checked as an error condition
2819 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2820 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2821 ASSERT(count > 0 && first >= 0);
2822 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2823 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002824 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002825 context->handleError(InvalidOperation() << "Integer overflow.");
Corentin Wallez92db6942016-12-09 13:10:36 -05002826 return false;
2827 }
2828
Corentin Wallez71168a02016-12-19 15:11:18 -08002829 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002830 {
2831 return false;
2832 }
2833
2834 return true;
2835}
2836
He Yunchaoced53ae2016-11-29 15:00:51 +08002837bool ValidateDrawArraysInstanced(Context *context,
2838 GLenum mode,
2839 GLint first,
2840 GLsizei count,
2841 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002842{
Corentin Wallez170efbf2017-05-02 13:45:01 -04002843 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04002844 {
2845 return false;
2846 }
2847
Corentin Wallez170efbf2017-05-02 13:45:01 -04002848 return !context->getExtensions().webglCompatibility ||
2849 ValidateDrawInstancedANGLEAndWebGL(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002850}
2851
He Yunchaoced53ae2016-11-29 15:00:51 +08002852bool ValidateDrawArraysInstancedANGLE(Context *context,
2853 GLenum mode,
2854 GLint first,
2855 GLsizei count,
2856 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002857{
Corentin Wallez170efbf2017-05-02 13:45:01 -04002858 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002859 {
2860 return false;
2861 }
2862
Corentin Wallez170efbf2017-05-02 13:45:01 -04002863 return ValidateDrawInstancedANGLEAndWebGL(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002864}
2865
Jiajia Qind9671222016-11-29 16:30:31 +08002866bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002867{
Jamie Madill250d33f2014-06-06 17:09:03 -04002868 switch (type)
2869 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002870 case GL_UNSIGNED_BYTE:
2871 case GL_UNSIGNED_SHORT:
2872 break;
2873 case GL_UNSIGNED_INT:
2874 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2875 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002876 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002877 return false;
2878 }
2879 break;
2880 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002881 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002882 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002883 }
2884
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002885 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002886
2887 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002888 if (curTransformFeedback && curTransformFeedback->isActive() &&
2889 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002890 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002891 // It is an invalid operation to call DrawElements, DrawRangeElements or
2892 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002893 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002894 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002895 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002896 }
2897
Jiajia Qind9671222016-11-29 16:30:31 +08002898 return true;
2899}
2900
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002901bool ValidateDrawElementsCommon(ValidationContext *context,
2902 GLenum mode,
2903 GLsizei count,
2904 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002905 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002906 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002907{
2908 if (!ValidateDrawElementsBase(context, type))
2909 return false;
2910
2911 const State &state = context->getGLState();
2912
Corentin Wallez170efbf2017-05-02 13:45:01 -04002913 if (!ValidateDrawBase(context, mode, count))
2914 {
2915 return false;
2916 }
2917
Jamie Madill250d33f2014-06-06 17:09:03 -04002918 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002919 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002920 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002921 context->handleError(InvalidOperation() << "Index buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -04002922 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002923 }
2924
He Yunchaoced53ae2016-11-29 15:00:51 +08002925 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002926 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002927
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002928 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2929
2930 if (context->getExtensions().webglCompatibility)
2931 {
2932 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2933 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2934 {
2935 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2936 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2937 // data type passed to the call, or an INVALID_OPERATION error is generated.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002938 context->handleError(InvalidOperation()
2939 << "indices must be a multiple of the element type size.");
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002940 return false;
2941 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002942
2943 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2944 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2945 // error is generated.
2946 if (reinterpret_cast<intptr_t>(indices) < 0)
2947 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002948 context->handleError(InvalidValue() << "Offset < 0.");
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002949 return false;
2950 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002951 }
2952
2953 if (context->getExtensions().webglCompatibility ||
2954 !context->getGLState().areClientArraysEnabled())
2955 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002956 if (!elementArrayBuffer && count > 0)
2957 {
2958 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2959 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2960 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002961 context->handleError(InvalidOperation()
2962 << "There is no element array buffer bound and count > 0.");
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002963 return false;
2964 }
2965 }
2966
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002967 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002968 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002969 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002970 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002971 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2972 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2973 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2974 constexpr uint64_t kMaxTypeSize = 8;
2975 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2976 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2977 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002978
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002979 uint64_t typeSize = typeBytes;
2980 uint64_t elementCount = static_cast<uint64_t>(count);
2981 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2982
2983 // Doing the multiplication here is overflow-safe
2984 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2985
2986 // The offset can be any value, check for overflows
2987 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2988 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002989 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002990 context->handleError(InvalidOperation() << "Integer overflow.");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002991 return false;
2992 }
2993
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002994 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2995 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002996 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002997 context->handleError(InvalidOperation()
2998 << "Index buffer is not big enough for the draw.");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002999 return false;
3000 }
3001 }
3002 else if (!indices)
3003 {
3004 // This is an application error that would normally result in a crash,
3005 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003006 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04003007 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003008 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003009 }
3010
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003011 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill2b976812014-08-25 15:47:49 -04003012 // TODO: offer fast path, with disabled index validation.
3013 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003014 const auto &params = context->getParams<HasIndexRange>();
3015 const auto &indexRangeOpt = params.getIndexRange();
3016 if (!indexRangeOpt.valid())
Jamie Madill2b976812014-08-25 15:47:49 -04003017 {
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003018 // Unexpected error.
3019 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003020 }
3021
Jamie Madille79b1e12015-11-04 16:36:37 -05003022 // If we use an index greater than our maximum supported index range, return an error.
3023 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3024 // return an error if possible here.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003025 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
Jamie Madille79b1e12015-11-04 16:36:37 -05003026 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003027 context->handleError(InvalidOperation() << g_ExceedsMaxElementErrorMessage);
Jamie Madille79b1e12015-11-04 16:36:37 -05003028 return false;
3029 }
3030
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003031 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
3032 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003033 {
3034 return false;
3035 }
3036
Geoff Lang3edfe032015-09-04 16:38:24 -04003037 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003038 return (indexRangeOpt.value().vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003039}
3040
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003041bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
3042 GLenum mode,
3043 GLsizei count,
3044 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003045 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003046 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003047{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003048 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003049 {
3050 return false;
3051 }
3052
Corentin Wallez170efbf2017-05-02 13:45:01 -04003053 return !context->getExtensions().webglCompatibility ||
3054 ValidateDrawInstancedANGLEAndWebGL(context);
Jamie Madill250d33f2014-06-06 17:09:03 -04003055}
3056
Geoff Lang3edfe032015-09-04 16:38:24 -04003057bool ValidateDrawElementsInstancedANGLE(Context *context,
3058 GLenum mode,
3059 GLsizei count,
3060 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003061 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003062 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003063{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003064 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003065 {
3066 return false;
3067 }
3068
Corentin Wallez170efbf2017-05-02 13:45:01 -04003069 return ValidateDrawInstancedANGLEAndWebGL(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003070}
3071
He Yunchaoced53ae2016-11-29 15:00:51 +08003072bool ValidateFramebufferTextureBase(Context *context,
3073 GLenum target,
3074 GLenum attachment,
3075 GLuint texture,
3076 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003077{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003078 if (!ValidFramebufferTarget(target))
3079 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003080 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04003081 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003082 }
3083
3084 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003085 {
3086 return false;
3087 }
3088
Jamie Madill55ec3b12014-07-03 10:38:57 -04003089 if (texture != 0)
3090 {
3091 gl::Texture *tex = context->getTexture(texture);
3092
Jamie Madillbe849e42017-05-02 15:49:00 -04003093 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003094 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003095 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003096 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003097 }
3098
3099 if (level < 0)
3100 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003101 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003102 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003103 }
3104 }
3105
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003106 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003107 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003108
Jamie Madill84115c92015-04-23 15:00:07 -04003109 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003110 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003111 context->handleError(InvalidOperation() << "Cannot change default FBO's attachments");
Geoff Langb1196682014-07-23 13:47:29 -04003112 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003113 }
3114
3115 return true;
3116}
3117
Geoff Langb1196682014-07-23 13:47:29 -04003118bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003119{
3120 if (program == 0)
3121 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003122 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003123 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003124 }
3125
Dian Xiang769769a2015-09-09 15:20:08 -07003126 gl::Program *programObject = GetValidProgram(context, program);
3127 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003128 {
3129 return false;
3130 }
3131
Jamie Madill0063c512014-08-25 15:47:53 -04003132 if (!programObject || !programObject->isLinked())
3133 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003134 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003135 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003136 }
3137
Geoff Lang7dd2e102014-11-10 15:19:26 -05003138 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003139 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003140 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003141 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003142 }
3143
Jamie Madill0063c512014-08-25 15:47:53 -04003144 return true;
3145}
3146
Geoff Langf41d0ee2016-10-07 13:04:23 -04003147static bool ValidateSizedGetUniform(Context *context,
3148 GLuint program,
3149 GLint location,
3150 GLsizei bufSize,
3151 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003152{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003153 if (length)
3154 {
3155 *length = 0;
3156 }
3157
Jamie Madill78f41802014-08-25 15:47:55 -04003158 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003159 {
Jamie Madill78f41802014-08-25 15:47:55 -04003160 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003161 }
3162
Geoff Langf41d0ee2016-10-07 13:04:23 -04003163 if (bufSize < 0)
3164 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003165 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003166 return false;
3167 }
3168
Jamie Madilla502c742014-08-28 17:19:13 -04003169 gl::Program *programObject = context->getProgram(program);
3170 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003171
Jamie Madill78f41802014-08-25 15:47:55 -04003172 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003173 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003174 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003175 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003176 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003177 context->handleError(InvalidOperation()
3178 << "bufSize of at least " << requiredBytes << " is required.");
Geoff Langb1196682014-07-23 13:47:29 -04003179 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003180 }
3181
Geoff Langf41d0ee2016-10-07 13:04:23 -04003182 if (length)
3183 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003184 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003185 }
3186
Jamie Madill0063c512014-08-25 15:47:53 -04003187 return true;
3188}
3189
He Yunchaoced53ae2016-11-29 15:00:51 +08003190bool ValidateGetnUniformfvEXT(Context *context,
3191 GLuint program,
3192 GLint location,
3193 GLsizei bufSize,
3194 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003195{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003196 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003197}
3198
He Yunchaoced53ae2016-11-29 15:00:51 +08003199bool ValidateGetnUniformivEXT(Context *context,
3200 GLuint program,
3201 GLint location,
3202 GLsizei bufSize,
3203 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003204{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003205 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3206}
3207
3208bool ValidateGetUniformfvRobustANGLE(Context *context,
3209 GLuint program,
3210 GLint location,
3211 GLsizei bufSize,
3212 GLsizei *length,
3213 GLfloat *params)
3214{
3215 if (!ValidateRobustEntryPoint(context, bufSize))
3216 {
3217 return false;
3218 }
3219
3220 // bufSize is validated in ValidateSizedGetUniform
3221 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3222}
3223
3224bool ValidateGetUniformivRobustANGLE(Context *context,
3225 GLuint program,
3226 GLint location,
3227 GLsizei bufSize,
3228 GLsizei *length,
3229 GLint *params)
3230{
3231 if (!ValidateRobustEntryPoint(context, bufSize))
3232 {
3233 return false;
3234 }
3235
3236 // bufSize is validated in ValidateSizedGetUniform
3237 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3238}
3239
3240bool ValidateGetUniformuivRobustANGLE(Context *context,
3241 GLuint program,
3242 GLint location,
3243 GLsizei bufSize,
3244 GLsizei *length,
3245 GLuint *params)
3246{
3247 if (!ValidateRobustEntryPoint(context, bufSize))
3248 {
3249 return false;
3250 }
3251
3252 if (context->getClientMajorVersion() < 3)
3253 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003254 context->handleError(InvalidOperation() << "Entry point requires at least OpenGL ES 3.0.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003255 return false;
3256 }
3257
3258 // bufSize is validated in ValidateSizedGetUniform
3259 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003260}
3261
He Yunchaoced53ae2016-11-29 15:00:51 +08003262bool ValidateDiscardFramebufferBase(Context *context,
3263 GLenum target,
3264 GLsizei numAttachments,
3265 const GLenum *attachments,
3266 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003267{
3268 if (numAttachments < 0)
3269 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003270 context->handleError(InvalidValue() << "numAttachments must not be less than zero");
Austin Kinross08332632015-05-05 13:35:47 -07003271 return false;
3272 }
3273
3274 for (GLsizei i = 0; i < numAttachments; ++i)
3275 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003276 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003277 {
3278 if (defaultFramebuffer)
3279 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003280 context->handleError(InvalidEnum()
3281 << "Invalid attachment when the default framebuffer is bound");
Austin Kinross08332632015-05-05 13:35:47 -07003282 return false;
3283 }
3284
3285 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3286 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003287 context->handleError(InvalidOperation() << "Requested color attachment is "
3288 "greater than the maximum supported "
3289 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003290 return false;
3291 }
3292 }
3293 else
3294 {
3295 switch (attachments[i])
3296 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003297 case GL_DEPTH_ATTACHMENT:
3298 case GL_STENCIL_ATTACHMENT:
3299 case GL_DEPTH_STENCIL_ATTACHMENT:
3300 if (defaultFramebuffer)
3301 {
3302 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003303 InvalidEnum()
3304 << "Invalid attachment when the default framebuffer is bound");
He Yunchaoced53ae2016-11-29 15:00:51 +08003305 return false;
3306 }
3307 break;
3308 case GL_COLOR:
3309 case GL_DEPTH:
3310 case GL_STENCIL:
3311 if (!defaultFramebuffer)
3312 {
3313 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003314 InvalidEnum()
3315 << "Invalid attachment when the default framebuffer is not bound");
He Yunchaoced53ae2016-11-29 15:00:51 +08003316 return false;
3317 }
3318 break;
3319 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003320 context->handleError(InvalidEnum() << "Invalid attachment");
Austin Kinross08332632015-05-05 13:35:47 -07003321 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003322 }
3323 }
3324 }
3325
3326 return true;
3327}
3328
Austin Kinross6ee1e782015-05-29 17:05:37 -07003329bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3330{
3331 // Note that debug marker calls must not set error state
3332
3333 if (length < 0)
3334 {
3335 return false;
3336 }
3337
3338 if (marker == nullptr)
3339 {
3340 return false;
3341 }
3342
3343 return true;
3344}
3345
3346bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3347{
3348 // Note that debug marker calls must not set error state
3349
3350 if (length < 0)
3351 {
3352 return false;
3353 }
3354
3355 if (length > 0 && marker == nullptr)
3356 {
3357 return false;
3358 }
3359
3360 return true;
3361}
3362
Geoff Langdcab33b2015-07-21 13:03:16 -04003363bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003364 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
Jamie Madill61e16b42017-06-19 11:13:23 -04003396 ASSERT(context->getCurrentDisplay());
3397 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003398 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003399 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003400 return false;
3401 }
3402
3403 if (image->getSamples() > 0)
3404 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003405 context->handleError(InvalidOperation()
3406 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003407 return false;
3408 }
3409
Geoff Langca271392017-04-05 12:30:00 -04003410 const TextureCaps &textureCaps =
3411 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003412 if (!textureCaps.texturable)
3413 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003414 context->handleError(InvalidOperation()
3415 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003416 return false;
3417 }
3418
Geoff Langdcab33b2015-07-21 13:03:16 -04003419 return true;
3420}
3421
3422bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003423 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
Jamie Madill61e16b42017-06-19 11:13:23 -04003442 ASSERT(context->getCurrentDisplay());
3443 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003444 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003445 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003446 return false;
3447 }
3448
Geoff Langca271392017-04-05 12:30:00 -04003449 const TextureCaps &textureCaps =
3450 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003451 if (!textureCaps.renderable)
3452 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003453 context->handleError(InvalidOperation()
3454 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003455 return false;
3456 }
3457
Geoff Langdcab33b2015-07-21 13:03:16 -04003458 return true;
3459}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003460
3461bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3462{
Geoff Lang36167ab2015-12-07 10:27:14 -05003463 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003464 {
3465 // The default VAO should always exist
3466 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003467 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003468 return false;
3469 }
3470
3471 return true;
3472}
3473
Geoff Langc5629752015-12-07 16:29:04 -05003474bool ValidateProgramBinaryBase(Context *context,
3475 GLuint program,
3476 GLenum binaryFormat,
3477 const void *binary,
3478 GLint length)
3479{
3480 Program *programObject = GetValidProgram(context, program);
3481 if (programObject == nullptr)
3482 {
3483 return false;
3484 }
3485
3486 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3487 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3488 programBinaryFormats.end())
3489 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003490 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003491 return false;
3492 }
3493
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003494 if (context->hasActiveTransformFeedback(program))
3495 {
3496 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003497 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3498 "is associated with an active transform "
3499 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003500 return false;
3501 }
3502
Geoff Langc5629752015-12-07 16:29:04 -05003503 return true;
3504}
3505
3506bool ValidateGetProgramBinaryBase(Context *context,
3507 GLuint program,
3508 GLsizei bufSize,
3509 GLsizei *length,
3510 GLenum *binaryFormat,
3511 void *binary)
3512{
3513 Program *programObject = GetValidProgram(context, program);
3514 if (programObject == nullptr)
3515 {
3516 return false;
3517 }
3518
3519 if (!programObject->isLinked())
3520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003521 context->handleError(InvalidOperation() << "Program is not linked.");
Geoff Langc5629752015-12-07 16:29:04 -05003522 return false;
3523 }
3524
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003525 if (context->getCaps().programBinaryFormats.empty())
3526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003527 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003528 return false;
3529 }
3530
Geoff Langc5629752015-12-07 16:29:04 -05003531 return true;
3532}
Jamie Madillc29968b2016-01-20 11:17:23 -05003533
Jamie Madillc29968b2016-01-20 11:17:23 -05003534bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3535{
3536 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3537 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3538 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003539 context->handleError(InvalidValue()
3540 << "n must be non-negative and no greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003541 return false;
3542 }
3543
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003544 ASSERT(context->getGLState().getDrawFramebuffer());
3545 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003546 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3547
3548 // This should come first before the check for the default frame buffer
3549 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3550 // rather than INVALID_OPERATION
3551 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3552 {
3553 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3554
3555 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003556 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3557 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003558 {
3559 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003560 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3561 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3562 // 3.1 is still a bit ambiguous about the error, but future specs are
3563 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003564 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003565 return false;
3566 }
3567 else if (bufs[colorAttachment] >= maxColorAttachment)
3568 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003569 context->handleError(InvalidOperation()
3570 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003571 return false;
3572 }
3573 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3574 frameBufferId != 0)
3575 {
3576 // INVALID_OPERATION-GL is bound to buffer and ith argument
3577 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003578 context->handleError(InvalidOperation()
3579 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003580 return false;
3581 }
3582 }
3583
3584 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3585 // and n is not 1 or bufs is bound to value other than BACK and NONE
3586 if (frameBufferId == 0)
3587 {
3588 if (n != 1)
3589 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003590 context->handleError(InvalidOperation()
3591 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003592 return false;
3593 }
3594
3595 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3596 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003597 context->handleError(
3598 InvalidOperation()
3599 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003600 return false;
3601 }
3602 }
3603
3604 return true;
3605}
3606
Geoff Lang496c02d2016-10-20 11:38:11 -07003607bool ValidateGetBufferPointervBase(Context *context,
3608 GLenum target,
3609 GLenum pname,
3610 GLsizei *length,
3611 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003612{
Geoff Lang496c02d2016-10-20 11:38:11 -07003613 if (length)
3614 {
3615 *length = 0;
3616 }
3617
3618 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3619 {
3620 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003621 InvalidOperation()
3622 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003623 return false;
3624 }
3625
Olli Etuaho4f667482016-03-30 15:56:35 +03003626 if (!ValidBufferTarget(context, target))
3627 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003628 context->handleError(InvalidEnum() << "Buffer target not valid: 0x" << std::hex
3629 << std::uppercase << target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003630 return false;
3631 }
3632
Geoff Lang496c02d2016-10-20 11:38:11 -07003633 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003634 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003635 case GL_BUFFER_MAP_POINTER:
3636 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003637
Geoff Lang496c02d2016-10-20 11:38:11 -07003638 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003639 context->handleError(InvalidEnum() << "Unknown pname.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003640 return false;
3641 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003642
3643 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3644 // target bound to zero generate an INVALID_OPERATION error."
3645 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003646 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003647 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003648 context->handleError(InvalidOperation()
3649 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003650 return false;
3651 }
3652
Geoff Lang496c02d2016-10-20 11:38:11 -07003653 if (length)
3654 {
3655 *length = 1;
3656 }
3657
Olli Etuaho4f667482016-03-30 15:56:35 +03003658 return true;
3659}
3660
3661bool ValidateUnmapBufferBase(Context *context, GLenum target)
3662{
3663 if (!ValidBufferTarget(context, target))
3664 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003665 context->handleError(InvalidEnum() << "Invalid buffer target.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003666 return false;
3667 }
3668
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003669 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003670
3671 if (buffer == nullptr || !buffer->isMapped())
3672 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003673 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003674 return false;
3675 }
3676
3677 return true;
3678}
3679
3680bool ValidateMapBufferRangeBase(Context *context,
3681 GLenum target,
3682 GLintptr offset,
3683 GLsizeiptr length,
3684 GLbitfield access)
3685{
3686 if (!ValidBufferTarget(context, target))
3687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003688 context->handleError(InvalidEnum() << "Invalid buffer target.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003689 return false;
3690 }
3691
3692 if (offset < 0 || length < 0)
3693 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003694 context->handleError(InvalidValue() << "Invalid offset or length.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003695 return false;
3696 }
3697
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003698 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003699
3700 if (!buffer)
3701 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003702 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003703 return false;
3704 }
3705
3706 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003707 CheckedNumeric<size_t> checkedOffset(offset);
3708 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003709
Jamie Madille2e406c2016-06-02 13:04:10 -04003710 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003711 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003712 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003713 return false;
3714 }
3715
3716 // Check for invalid bits in the mask
3717 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3718 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3719 GL_MAP_UNSYNCHRONIZED_BIT;
3720
3721 if (access & ~(allAccessBits))
3722 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003723 context->handleError(InvalidValue()
3724 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003725 return false;
3726 }
3727
3728 if (length == 0)
3729 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003730 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003731 return false;
3732 }
3733
3734 if (buffer->isMapped())
3735 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003736 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003737 return false;
3738 }
3739
3740 // Check for invalid bit combinations
3741 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003743 context->handleError(InvalidOperation()
3744 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003745 return false;
3746 }
3747
3748 GLbitfield writeOnlyBits =
3749 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3750
3751 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3752 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003753 context->handleError(InvalidOperation()
3754 << "Invalid access bits when mapping buffer for reading: 0x"
3755 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003756 return false;
3757 }
3758
3759 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3760 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003761 context->handleError(
3762 InvalidOperation()
3763 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003764 return false;
3765 }
3766 return true;
3767}
3768
3769bool ValidateFlushMappedBufferRangeBase(Context *context,
3770 GLenum target,
3771 GLintptr offset,
3772 GLsizeiptr length)
3773{
3774 if (offset < 0 || length < 0)
3775 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003776 context->handleError(InvalidValue() << "Invalid offset/length parameters.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003777 return false;
3778 }
3779
3780 if (!ValidBufferTarget(context, target))
3781 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003782 context->handleError(InvalidEnum() << "Invalid buffer target.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003783 return false;
3784 }
3785
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003786 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003787
3788 if (buffer == nullptr)
3789 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003790 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003791 return false;
3792 }
3793
3794 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3795 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003796 context->handleError(InvalidOperation()
3797 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003798 return false;
3799 }
3800
3801 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003802 CheckedNumeric<size_t> checkedOffset(offset);
3803 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003804
Jamie Madille2e406c2016-06-02 13:04:10 -04003805 if (!checkedSize.IsValid() ||
3806 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003807 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003808 context->handleError(InvalidValue()
3809 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003810 return false;
3811 }
3812
3813 return true;
3814}
3815
Olli Etuaho41997e72016-03-10 13:38:39 +02003816bool ValidateGenOrDelete(Context *context, GLint n)
3817{
3818 if (n < 0)
3819 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003820 context->handleError(InvalidValue() << "n < 0");
Olli Etuaho41997e72016-03-10 13:38:39 +02003821 return false;
3822 }
3823 return true;
3824}
3825
Geoff Langff5b2d52016-09-07 11:32:23 -04003826bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3827{
3828 if (!context->getExtensions().robustClientMemory)
3829 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003830 context->handleError(InvalidOperation()
3831 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003832 return false;
3833 }
3834
3835 if (bufSize < 0)
3836 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003837 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003838 return false;
3839 }
3840
3841 return true;
3842}
3843
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003844bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3845{
3846 if (bufSize < numParams)
3847 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003848 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3849 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003850 return false;
3851 }
3852
3853 return true;
3854}
3855
Jamie Madillbe849e42017-05-02 15:49:00 -04003856bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3857 GLenum target,
3858 GLenum attachment,
3859 GLenum pname,
3860 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003861{
3862 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
Yunchao He33151a52017-04-13 09:58:17 +08003863 if (numParams)
3864 {
3865 *numParams = 1;
3866 }
Geoff Langff5b2d52016-09-07 11:32:23 -04003867
3868 if (!ValidFramebufferTarget(target))
3869 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003870 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003871 return false;
3872 }
3873
3874 int clientVersion = context->getClientMajorVersion();
3875
3876 switch (pname)
3877 {
3878 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3879 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3880 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3881 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3882 break;
3883
3884 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3885 if (clientVersion < 3 && !context->getExtensions().sRGB)
3886 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003887 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003888 return false;
3889 }
3890 break;
3891
3892 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3893 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3894 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3895 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3896 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3897 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3898 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3899 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3900 if (clientVersion < 3)
3901 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003902 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003903 return false;
3904 }
3905 break;
3906
3907 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003908 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003909 return false;
3910 }
3911
3912 // Determine if the attachment is a valid enum
3913 switch (attachment)
3914 {
3915 case GL_BACK:
3916 case GL_FRONT:
3917 case GL_DEPTH:
3918 case GL_STENCIL:
3919 case GL_DEPTH_STENCIL_ATTACHMENT:
3920 if (clientVersion < 3)
3921 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003922 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003923 return false;
3924 }
3925 break;
3926
3927 case GL_DEPTH_ATTACHMENT:
3928 case GL_STENCIL_ATTACHMENT:
3929 break;
3930
3931 default:
3932 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
3933 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3934 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003935 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003936 return false;
3937 }
3938 break;
3939 }
3940
3941 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3942 ASSERT(framebuffer);
3943
3944 if (framebuffer->id() == 0)
3945 {
3946 if (clientVersion < 3)
3947 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003948 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003949 return false;
3950 }
3951
3952 switch (attachment)
3953 {
3954 case GL_BACK:
3955 case GL_DEPTH:
3956 case GL_STENCIL:
3957 break;
3958
3959 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003960 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003961 return false;
3962 }
3963 }
3964 else
3965 {
3966 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3967 {
3968 // Valid attachment query
3969 }
3970 else
3971 {
3972 switch (attachment)
3973 {
3974 case GL_DEPTH_ATTACHMENT:
3975 case GL_STENCIL_ATTACHMENT:
3976 break;
3977
3978 case GL_DEPTH_STENCIL_ATTACHMENT:
3979 if (!framebuffer->hasValidDepthStencil())
3980 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003981 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003982 return false;
3983 }
3984 break;
3985
3986 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003987 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003988 return false;
3989 }
3990 }
3991 }
3992
3993 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3994 if (attachmentObject)
3995 {
3996 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3997 attachmentObject->type() == GL_TEXTURE ||
3998 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3999
4000 switch (pname)
4001 {
4002 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4003 if (attachmentObject->type() != GL_RENDERBUFFER &&
4004 attachmentObject->type() != GL_TEXTURE)
4005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004006 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004007 return false;
4008 }
4009 break;
4010
4011 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4012 if (attachmentObject->type() != GL_TEXTURE)
4013 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004014 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004015 return false;
4016 }
4017 break;
4018
4019 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4020 if (attachmentObject->type() != GL_TEXTURE)
4021 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004022 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004023 return false;
4024 }
4025 break;
4026
4027 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4028 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4029 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004030 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004031 return false;
4032 }
4033 break;
4034
4035 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4036 if (attachmentObject->type() != GL_TEXTURE)
4037 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004038 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004039 return false;
4040 }
4041 break;
4042
4043 default:
4044 break;
4045 }
4046 }
4047 else
4048 {
4049 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4050 // is NONE, then querying any other pname will generate INVALID_ENUM.
4051
4052 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4053 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4054 // INVALID_OPERATION for all other pnames
4055
4056 switch (pname)
4057 {
4058 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4059 break;
4060
4061 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4062 if (clientVersion < 3)
4063 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004064 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004065 return false;
4066 }
4067 break;
4068
4069 default:
4070 if (clientVersion < 3)
4071 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004072 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004073 return false;
4074 }
4075 else
4076 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004077 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004078 return false;
4079 }
4080 }
4081 }
4082
4083 return true;
4084}
4085
4086bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4087 GLenum target,
4088 GLenum attachment,
4089 GLenum pname,
4090 GLsizei bufSize,
4091 GLsizei *numParams)
4092{
4093 if (!ValidateRobustEntryPoint(context, bufSize))
4094 {
4095 return false;
4096 }
4097
Jamie Madillbe849e42017-05-02 15:49:00 -04004098 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4099 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004100 {
4101 return false;
4102 }
4103
4104 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4105 {
4106 return false;
4107 }
4108
4109 return true;
4110}
4111
Geoff Langff5b2d52016-09-07 11:32:23 -04004112bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4113 GLenum target,
4114 GLenum pname,
4115 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004116 GLsizei *length,
4117 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004118{
4119 if (!ValidateRobustEntryPoint(context, bufSize))
4120 {
4121 return false;
4122 }
4123
Geoff Langebebe1c2016-10-14 12:01:31 -04004124 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004125 {
4126 return false;
4127 }
4128
Geoff Langebebe1c2016-10-14 12:01:31 -04004129 if (!ValidateRobustBufferSize(context, bufSize, *length))
4130 {
4131 return false;
4132 }
4133
4134 return true;
4135}
4136
4137bool ValidateGetBufferParameteri64v(ValidationContext *context,
4138 GLenum target,
4139 GLenum pname,
4140 GLint64 *params)
4141{
4142 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4143}
4144
4145bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4146 GLenum target,
4147 GLenum pname,
4148 GLsizei bufSize,
4149 GLsizei *length,
4150 GLint64 *params)
4151{
4152 if (!ValidateRobustEntryPoint(context, bufSize))
4153 {
4154 return false;
4155 }
4156
4157 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4158 {
4159 return false;
4160 }
4161
4162 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004163 {
4164 return false;
4165 }
4166
4167 return true;
4168}
4169
Jamie Madillbe849e42017-05-02 15:49:00 -04004170bool ValidateGetProgramivBase(ValidationContext *context,
4171 GLuint program,
4172 GLenum pname,
4173 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004174{
4175 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004176 if (numParams)
4177 {
4178 *numParams = 1;
4179 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004180
4181 Program *programObject = GetValidProgram(context, program);
4182 if (!programObject)
4183 {
4184 return false;
4185 }
4186
4187 switch (pname)
4188 {
4189 case GL_DELETE_STATUS:
4190 case GL_LINK_STATUS:
4191 case GL_VALIDATE_STATUS:
4192 case GL_INFO_LOG_LENGTH:
4193 case GL_ATTACHED_SHADERS:
4194 case GL_ACTIVE_ATTRIBUTES:
4195 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4196 case GL_ACTIVE_UNIFORMS:
4197 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4198 break;
4199
4200 case GL_PROGRAM_BINARY_LENGTH:
4201 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4202 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004203 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4204 "requires GL_OES_get_program_binary or "
4205 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004206 return false;
4207 }
4208 break;
4209
4210 case GL_ACTIVE_UNIFORM_BLOCKS:
4211 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4212 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4213 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4214 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4215 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4216 if (context->getClientMajorVersion() < 3)
4217 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004218 context->handleError(InvalidEnum() << "Querying requires at least ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004219 return false;
4220 }
4221 break;
4222
Yunchao He61afff12017-03-14 15:34:03 +08004223 case GL_PROGRAM_SEPARABLE:
4224 if (context->getClientVersion() < Version(3, 1))
4225 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004226 context->handleError(InvalidEnum() << "Querying requires at least ES 3.1.");
Yunchao He61afff12017-03-14 15:34:03 +08004227 return false;
4228 }
4229 break;
4230
Geoff Langff5b2d52016-09-07 11:32:23 -04004231 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004232 context->handleError(InvalidEnum() << "Unknown parameter name.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004233 return false;
4234 }
4235
4236 return true;
4237}
4238
4239bool ValidateGetProgramivRobustANGLE(Context *context,
4240 GLuint program,
4241 GLenum pname,
4242 GLsizei bufSize,
4243 GLsizei *numParams)
4244{
4245 if (!ValidateRobustEntryPoint(context, bufSize))
4246 {
4247 return false;
4248 }
4249
Jamie Madillbe849e42017-05-02 15:49:00 -04004250 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004251 {
4252 return false;
4253 }
4254
4255 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4256 {
4257 return false;
4258 }
4259
4260 return true;
4261}
4262
Geoff Lang740d9022016-10-07 11:20:52 -04004263bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4264 GLenum target,
4265 GLenum pname,
4266 GLsizei bufSize,
4267 GLsizei *length,
4268 GLint *params)
4269{
4270 if (!ValidateRobustEntryPoint(context, bufSize))
4271 {
4272 return false;
4273 }
4274
4275 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4276 {
4277 return false;
4278 }
4279
4280 if (!ValidateRobustBufferSize(context, bufSize, *length))
4281 {
4282 return false;
4283 }
4284
4285 return true;
4286}
4287
Geoff Langd7d0ed32016-10-07 11:33:51 -04004288bool ValidateGetShaderivRobustANGLE(Context *context,
4289 GLuint shader,
4290 GLenum pname,
4291 GLsizei bufSize,
4292 GLsizei *length,
4293 GLint *params)
4294{
4295 if (!ValidateRobustEntryPoint(context, bufSize))
4296 {
4297 return false;
4298 }
4299
4300 if (!ValidateGetShaderivBase(context, shader, pname, length))
4301 {
4302 return false;
4303 }
4304
4305 if (!ValidateRobustBufferSize(context, bufSize, *length))
4306 {
4307 return false;
4308 }
4309
4310 return true;
4311}
4312
Geoff Langc1984ed2016-10-07 12:41:00 -04004313bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4314 GLenum target,
4315 GLenum pname,
4316 GLsizei bufSize,
4317 GLsizei *length,
4318 GLfloat *params)
4319{
4320 if (!ValidateRobustEntryPoint(context, bufSize))
4321 {
4322 return false;
4323 }
4324
4325 if (!ValidateGetTexParameterBase(context, target, pname, length))
4326 {
4327 return false;
4328 }
4329
4330 if (!ValidateRobustBufferSize(context, bufSize, *length))
4331 {
4332 return false;
4333 }
4334
4335 return true;
4336}
4337
Geoff Langc1984ed2016-10-07 12:41:00 -04004338bool ValidateGetTexParameterivRobustANGLE(Context *context,
4339 GLenum target,
4340 GLenum pname,
4341 GLsizei bufSize,
4342 GLsizei *length,
4343 GLint *params)
4344{
4345 if (!ValidateRobustEntryPoint(context, bufSize))
4346 {
4347 return false;
4348 }
4349
4350 if (!ValidateGetTexParameterBase(context, target, pname, length))
4351 {
4352 return false;
4353 }
4354
4355 if (!ValidateRobustBufferSize(context, bufSize, *length))
4356 {
4357 return false;
4358 }
4359
4360 return true;
4361}
4362
Geoff Langc1984ed2016-10-07 12:41:00 -04004363bool ValidateTexParameterfvRobustANGLE(Context *context,
4364 GLenum target,
4365 GLenum pname,
4366 GLsizei bufSize,
4367 const GLfloat *params)
4368{
4369 if (!ValidateRobustEntryPoint(context, bufSize))
4370 {
4371 return false;
4372 }
4373
4374 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4375}
4376
Geoff Langc1984ed2016-10-07 12:41:00 -04004377bool ValidateTexParameterivRobustANGLE(Context *context,
4378 GLenum target,
4379 GLenum pname,
4380 GLsizei bufSize,
4381 const GLint *params)
4382{
4383 if (!ValidateRobustEntryPoint(context, bufSize))
4384 {
4385 return false;
4386 }
4387
4388 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4389}
4390
4391bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4392{
4393 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4394}
4395
4396bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4397 GLuint sampler,
4398 GLenum pname,
4399 GLuint bufSize,
4400 GLsizei *length,
4401 GLfloat *params)
4402{
4403 if (!ValidateRobustEntryPoint(context, bufSize))
4404 {
4405 return false;
4406 }
4407
4408 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4409 {
4410 return false;
4411 }
4412
4413 if (!ValidateRobustBufferSize(context, bufSize, *length))
4414 {
4415 return false;
4416 }
4417
4418 return true;
4419}
4420
4421bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4422{
4423 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4424}
4425
4426bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4427 GLuint sampler,
4428 GLenum pname,
4429 GLuint bufSize,
4430 GLsizei *length,
4431 GLint *params)
4432{
4433 if (!ValidateRobustEntryPoint(context, bufSize))
4434 {
4435 return false;
4436 }
4437
4438 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4439 {
4440 return false;
4441 }
4442
4443 if (!ValidateRobustBufferSize(context, bufSize, *length))
4444 {
4445 return false;
4446 }
4447
4448 return true;
4449}
4450
4451bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4452{
4453 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4454}
4455
4456bool ValidateSamplerParameterfv(Context *context,
4457 GLuint sampler,
4458 GLenum pname,
4459 const GLfloat *params)
4460{
4461 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4462}
4463
4464bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4465 GLuint sampler,
4466 GLenum pname,
4467 GLsizei bufSize,
4468 const GLfloat *params)
4469{
4470 if (!ValidateRobustEntryPoint(context, bufSize))
4471 {
4472 return false;
4473 }
4474
4475 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4476}
4477
4478bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4479{
4480 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4481}
4482
4483bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4484{
4485 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4486}
4487
4488bool ValidateSamplerParameterivRobustANGLE(Context *context,
4489 GLuint sampler,
4490 GLenum pname,
4491 GLsizei bufSize,
4492 const GLint *params)
4493{
4494 if (!ValidateRobustEntryPoint(context, bufSize))
4495 {
4496 return false;
4497 }
4498
4499 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4500}
4501
Geoff Lang0b031062016-10-13 14:30:04 -04004502bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4503 GLuint index,
4504 GLenum pname,
4505 GLsizei bufSize,
4506 GLsizei *length,
4507 GLfloat *params)
4508{
4509 if (!ValidateRobustEntryPoint(context, bufSize))
4510 {
4511 return false;
4512 }
4513
4514 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4515 {
4516 return false;
4517 }
4518
4519 if (!ValidateRobustBufferSize(context, bufSize, *length))
4520 {
4521 return false;
4522 }
4523
4524 return true;
4525}
4526
Geoff Lang0b031062016-10-13 14:30:04 -04004527bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4528 GLuint index,
4529 GLenum pname,
4530 GLsizei bufSize,
4531 GLsizei *length,
4532 GLint *params)
4533{
4534 if (!ValidateRobustEntryPoint(context, bufSize))
4535 {
4536 return false;
4537 }
4538
4539 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4540 {
4541 return false;
4542 }
4543
4544 if (!ValidateRobustBufferSize(context, bufSize, *length))
4545 {
4546 return false;
4547 }
4548
4549 return true;
4550}
4551
Geoff Lang0b031062016-10-13 14:30:04 -04004552bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4553 GLuint index,
4554 GLenum pname,
4555 GLsizei bufSize,
4556 GLsizei *length,
4557 void **pointer)
4558{
4559 if (!ValidateRobustEntryPoint(context, bufSize))
4560 {
4561 return false;
4562 }
4563
4564 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4565 {
4566 return false;
4567 }
4568
4569 if (!ValidateRobustBufferSize(context, bufSize, *length))
4570 {
4571 return false;
4572 }
4573
4574 return true;
4575}
4576
4577bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4578{
4579 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4580}
4581
4582bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4583 GLuint index,
4584 GLenum pname,
4585 GLsizei bufSize,
4586 GLsizei *length,
4587 GLint *params)
4588{
4589 if (!ValidateRobustEntryPoint(context, bufSize))
4590 {
4591 return false;
4592 }
4593
4594 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4595 {
4596 return false;
4597 }
4598
4599 if (!ValidateRobustBufferSize(context, bufSize, *length))
4600 {
4601 return false;
4602 }
4603
4604 return true;
4605}
4606
4607bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4608{
4609 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4610}
4611
4612bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4613 GLuint index,
4614 GLenum pname,
4615 GLsizei bufSize,
4616 GLsizei *length,
4617 GLuint *params)
4618{
4619 if (!ValidateRobustEntryPoint(context, bufSize))
4620 {
4621 return false;
4622 }
4623
4624 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4625 {
4626 return false;
4627 }
4628
4629 if (!ValidateRobustBufferSize(context, bufSize, *length))
4630 {
4631 return false;
4632 }
4633
4634 return true;
4635}
4636
Geoff Lang6899b872016-10-14 11:30:13 -04004637bool ValidateGetActiveUniformBlockiv(Context *context,
4638 GLuint program,
4639 GLuint uniformBlockIndex,
4640 GLenum pname,
4641 GLint *params)
4642{
4643 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
4644}
4645
4646bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4647 GLuint program,
4648 GLuint uniformBlockIndex,
4649 GLenum pname,
4650 GLsizei bufSize,
4651 GLsizei *length,
4652 GLint *params)
4653{
4654 if (!ValidateRobustEntryPoint(context, bufSize))
4655 {
4656 return false;
4657 }
4658
4659 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4660 {
4661 return false;
4662 }
4663
4664 if (!ValidateRobustBufferSize(context, bufSize, *length))
4665 {
4666 return false;
4667 }
4668
4669 return true;
4670}
4671
Geoff Lang0a9661f2016-10-20 10:59:20 -07004672bool ValidateGetInternalFormativ(Context *context,
4673 GLenum target,
4674 GLenum internalformat,
4675 GLenum pname,
4676 GLsizei bufSize,
4677 GLint *params)
4678{
4679 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4680 nullptr);
4681}
4682
4683bool ValidateGetInternalFormativRobustANGLE(Context *context,
4684 GLenum target,
4685 GLenum internalformat,
4686 GLenum pname,
4687 GLsizei bufSize,
4688 GLsizei *length,
4689 GLint *params)
4690{
4691 if (!ValidateRobustEntryPoint(context, bufSize))
4692 {
4693 return false;
4694 }
4695
4696 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4697 {
4698 return false;
4699 }
4700
4701 if (!ValidateRobustBufferSize(context, bufSize, *length))
4702 {
4703 return false;
4704 }
4705
4706 return true;
4707}
4708
Shao80957d92017-02-20 21:25:59 +08004709bool ValidateVertexFormatBase(ValidationContext *context,
4710 GLuint attribIndex,
4711 GLint size,
4712 GLenum type,
4713 GLboolean pureInteger)
4714{
4715 const Caps &caps = context->getCaps();
4716 if (attribIndex >= caps.maxVertexAttributes)
4717 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004718 context->handleError(InvalidValue()
4719 << "attribindex must be smaller than MAX_VERTEX_ATTRIBS.");
Shao80957d92017-02-20 21:25:59 +08004720 return false;
4721 }
4722
4723 if (size < 1 || size > 4)
4724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004725 context->handleError(InvalidValue() << "size must be between one and four.");
Shao80957d92017-02-20 21:25:59 +08004726 }
4727
4728 switch (type)
4729 {
4730 case GL_BYTE:
4731 case GL_UNSIGNED_BYTE:
4732 case GL_SHORT:
4733 case GL_UNSIGNED_SHORT:
4734 break;
4735
4736 case GL_INT:
4737 case GL_UNSIGNED_INT:
4738 if (context->getClientMajorVersion() < 3)
4739 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004740 context->handleError(InvalidEnum()
4741 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004742 return false;
4743 }
4744 break;
4745
4746 case GL_FIXED:
4747 case GL_FLOAT:
4748 if (pureInteger)
4749 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004750 context->handleError(InvalidEnum() << "Type is not integer.");
Shao80957d92017-02-20 21:25:59 +08004751 return false;
4752 }
4753 break;
4754
4755 case GL_HALF_FLOAT:
4756 if (context->getClientMajorVersion() < 3)
4757 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004758 context->handleError(InvalidEnum()
4759 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004760 return false;
4761 }
4762 if (pureInteger)
4763 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004764 context->handleError(InvalidEnum() << "Type is not integer.");
Shao80957d92017-02-20 21:25:59 +08004765 return false;
4766 }
4767 break;
4768
4769 case GL_INT_2_10_10_10_REV:
4770 case GL_UNSIGNED_INT_2_10_10_10_REV:
4771 if (context->getClientMajorVersion() < 3)
4772 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004773 context->handleError(InvalidEnum()
4774 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004775 return false;
4776 }
4777 if (pureInteger)
4778 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004779 context->handleError(InvalidEnum() << "Type is not integer.");
Shao80957d92017-02-20 21:25:59 +08004780 return false;
4781 }
4782 if (size != 4)
4783 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004784 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4785 "UNSIGNED_INT_2_10_10_10_REV and "
4786 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004787 return false;
4788 }
4789 break;
4790
4791 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004792 context->handleError(InvalidEnum() << "Invalid vertex type.");
Shao80957d92017-02-20 21:25:59 +08004793 return false;
4794 }
4795
4796 return true;
4797}
4798
Geoff Lang76e65652017-03-27 14:58:02 -04004799// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4800// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4801// specified clear value and the type of a buffer that is being cleared generates an
4802// INVALID_OPERATION error instead of producing undefined results
4803bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4804 GLint drawbuffer,
4805 const GLenum *validComponentTypes,
4806 size_t validComponentTypeCount)
4807{
4808 const FramebufferAttachment *attachment =
4809 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4810 if (attachment)
4811 {
4812 GLenum componentType = attachment->getFormat().info->componentType;
4813 const GLenum *end = validComponentTypes + validComponentTypeCount;
4814 if (std::find(validComponentTypes, end, componentType) == end)
4815 {
4816 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004817 InvalidOperation()
4818 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004819 return false;
4820 }
4821 }
4822
4823 return true;
4824}
4825
Corentin Wallezb2931602017-04-11 15:58:57 -04004826bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4827 GLsizei imageSize,
4828 GLsizei dataSize)
4829{
4830 if (!ValidateRobustEntryPoint(context, dataSize))
4831 {
4832 return false;
4833 }
4834
4835 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
4836 if (pixelUnpackBuffer == nullptr)
4837 {
4838 if (dataSize < imageSize)
4839 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004840 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004841 }
4842 }
4843 return true;
4844}
4845
Jamie Madillbe849e42017-05-02 15:49:00 -04004846bool ValidateGetBufferParameterBase(ValidationContext *context,
4847 GLenum target,
4848 GLenum pname,
4849 bool pointerVersion,
4850 GLsizei *numParams)
4851{
4852 if (numParams)
4853 {
4854 *numParams = 0;
4855 }
4856
4857 if (!ValidBufferTarget(context, target))
4858 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004859 context->handleError(InvalidEnum() << "Invalid buffer target.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004860 return false;
4861 }
4862
4863 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4864 if (!buffer)
4865 {
4866 // A null buffer means that "0" is bound to the requested buffer target
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004867 context->handleError(InvalidOperation() << "No buffer bound.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004868 return false;
4869 }
4870
4871 const Extensions &extensions = context->getExtensions();
4872
4873 switch (pname)
4874 {
4875 case GL_BUFFER_USAGE:
4876 case GL_BUFFER_SIZE:
4877 break;
4878
4879 case GL_BUFFER_ACCESS_OES:
4880 if (!extensions.mapBuffer)
4881 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004882 context->handleError(InvalidEnum()
4883 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004884 return false;
4885 }
4886 break;
4887
4888 case GL_BUFFER_MAPPED:
4889 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4890 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4891 !extensions.mapBufferRange)
4892 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004893 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4894 "GL_OES_mapbuffer or "
4895 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004896 return false;
4897 }
4898 break;
4899
4900 case GL_BUFFER_MAP_POINTER:
4901 if (!pointerVersion)
4902 {
4903 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004904 InvalidEnum()
4905 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004906 return false;
4907 }
4908 break;
4909
4910 case GL_BUFFER_ACCESS_FLAGS:
4911 case GL_BUFFER_MAP_OFFSET:
4912 case GL_BUFFER_MAP_LENGTH:
4913 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4914 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004915 context->handleError(InvalidEnum()
4916 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004917 return false;
4918 }
4919 break;
4920
4921 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004922 context->handleError(InvalidEnum() << "Unknown pname.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004923 return false;
4924 }
4925
4926 // All buffer parameter queries return one value.
4927 if (numParams)
4928 {
4929 *numParams = 1;
4930 }
4931
4932 return true;
4933}
4934
4935bool ValidateGetRenderbufferParameterivBase(Context *context,
4936 GLenum target,
4937 GLenum pname,
4938 GLsizei *length)
4939{
4940 if (length)
4941 {
4942 *length = 0;
4943 }
4944
4945 if (target != GL_RENDERBUFFER)
4946 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004947 context->handleError(InvalidEnum() << "Invalid target.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004948 return false;
4949 }
4950
4951 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4952 if (renderbuffer == nullptr)
4953 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004954 context->handleError(InvalidOperation() << "No renderbuffer bound.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004955 return false;
4956 }
4957
4958 switch (pname)
4959 {
4960 case GL_RENDERBUFFER_WIDTH:
4961 case GL_RENDERBUFFER_HEIGHT:
4962 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4963 case GL_RENDERBUFFER_RED_SIZE:
4964 case GL_RENDERBUFFER_GREEN_SIZE:
4965 case GL_RENDERBUFFER_BLUE_SIZE:
4966 case GL_RENDERBUFFER_ALPHA_SIZE:
4967 case GL_RENDERBUFFER_DEPTH_SIZE:
4968 case GL_RENDERBUFFER_STENCIL_SIZE:
4969 break;
4970
4971 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4972 if (!context->getExtensions().framebufferMultisample)
4973 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004974 context->handleError(InvalidEnum()
4975 << "GL_ANGLE_framebuffer_multisample is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004976 return false;
4977 }
4978 break;
4979
4980 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004981 context->handleError(InvalidEnum() << "Unknown pname.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004982 return false;
4983 }
4984
4985 if (length)
4986 {
4987 *length = 1;
4988 }
4989 return true;
4990}
4991
4992bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4993{
4994 if (length)
4995 {
4996 *length = 0;
4997 }
4998
4999 if (GetValidShader(context, shader) == nullptr)
5000 {
5001 return false;
5002 }
5003
5004 switch (pname)
5005 {
5006 case GL_SHADER_TYPE:
5007 case GL_DELETE_STATUS:
5008 case GL_COMPILE_STATUS:
5009 case GL_INFO_LOG_LENGTH:
5010 case GL_SHADER_SOURCE_LENGTH:
5011 break;
5012
5013 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5014 if (!context->getExtensions().translatedShaderSource)
5015 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005016 context->handleError(InvalidEnum()
5017 << "GL_ANGLE_translated_shader_source is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005018 return false;
5019 }
5020 break;
5021
5022 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005023 context->handleError(InvalidEnum() << "Unknown pname.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005024 return false;
5025 }
5026
5027 if (length)
5028 {
5029 *length = 1;
5030 }
5031 return true;
5032}
5033
5034bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
5035{
5036 if (length)
5037 {
5038 *length = 0;
5039 }
5040
5041 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5042 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005043 context->handleError(InvalidEnum() << "Invalid texture target");
Jamie Madillbe849e42017-05-02 15:49:00 -04005044 return false;
5045 }
5046
5047 if (context->getTargetTexture(target) == nullptr)
5048 {
5049 // Should only be possible for external textures
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005050 context->handleError(InvalidEnum() << "No texture bound.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005051 return false;
5052 }
5053
5054 switch (pname)
5055 {
5056 case GL_TEXTURE_MAG_FILTER:
5057 case GL_TEXTURE_MIN_FILTER:
5058 case GL_TEXTURE_WRAP_S:
5059 case GL_TEXTURE_WRAP_T:
5060 break;
5061
5062 case GL_TEXTURE_USAGE_ANGLE:
5063 if (!context->getExtensions().textureUsage)
5064 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005065 context->handleError(InvalidEnum() << "GL_ANGLE_texture_usage is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005066 return false;
5067 }
5068 break;
5069
5070 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5071 if (!context->getExtensions().textureFilterAnisotropic)
5072 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005073 context->handleError(InvalidEnum()
5074 << "GL_EXT_texture_filter_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005075 return false;
5076 }
5077 break;
5078
5079 case GL_TEXTURE_IMMUTABLE_FORMAT:
5080 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5081 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005082 context->handleError(InvalidEnum() << "GL_EXT_texture_storage is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005083 return false;
5084 }
5085 break;
5086
5087 case GL_TEXTURE_WRAP_R:
5088 case GL_TEXTURE_IMMUTABLE_LEVELS:
5089 case GL_TEXTURE_SWIZZLE_R:
5090 case GL_TEXTURE_SWIZZLE_G:
5091 case GL_TEXTURE_SWIZZLE_B:
5092 case GL_TEXTURE_SWIZZLE_A:
5093 case GL_TEXTURE_BASE_LEVEL:
5094 case GL_TEXTURE_MAX_LEVEL:
5095 case GL_TEXTURE_MIN_LOD:
5096 case GL_TEXTURE_MAX_LOD:
5097 case GL_TEXTURE_COMPARE_MODE:
5098 case GL_TEXTURE_COMPARE_FUNC:
5099 if (context->getClientMajorVersion() < 3)
5100 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005101 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005102 return false;
5103 }
5104 break;
5105
5106 case GL_TEXTURE_SRGB_DECODE_EXT:
5107 if (!context->getExtensions().textureSRGBDecode)
5108 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005109 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005110 return false;
5111 }
5112 break;
5113
5114 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005115 context->handleError(InvalidEnum() << "Unknown pname.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005116 return false;
5117 }
5118
5119 if (length)
5120 {
5121 *length = 1;
5122 }
5123 return true;
5124}
5125
5126bool ValidateGetVertexAttribBase(Context *context,
5127 GLuint index,
5128 GLenum pname,
5129 GLsizei *length,
5130 bool pointer,
5131 bool pureIntegerEntryPoint)
5132{
5133 if (length)
5134 {
5135 *length = 0;
5136 }
5137
5138 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5139 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005140 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005141 return false;
5142 }
5143
5144 if (index >= context->getCaps().maxVertexAttributes)
5145 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005146 context->handleError(InvalidValue()
5147 << "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005148 return false;
5149 }
5150
5151 if (pointer)
5152 {
5153 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5154 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005155 context->handleError(InvalidEnum() << "Unknown pname.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005156 return false;
5157 }
5158 }
5159 else
5160 {
5161 switch (pname)
5162 {
5163 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5164 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5165 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5166 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5167 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5168 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5169 case GL_CURRENT_VERTEX_ATTRIB:
5170 break;
5171
5172 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5173 static_assert(
5174 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5175 "ANGLE extension enums not equal to GL enums.");
5176 if (context->getClientMajorVersion() < 3 &&
5177 !context->getExtensions().instancedArrays)
5178 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005179 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5180 "requires OpenGL ES 3.0 or "
5181 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005182 return false;
5183 }
5184 break;
5185
5186 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5187 if (context->getClientMajorVersion() < 3)
5188 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005189 context->handleError(
5190 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005191 return false;
5192 }
5193 break;
5194
5195 case GL_VERTEX_ATTRIB_BINDING:
5196 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5197 if (context->getClientVersion() < ES_3_1)
5198 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005199 context->handleError(InvalidEnum()
5200 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005201 return false;
5202 }
5203 break;
5204
5205 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005206 context->handleError(InvalidEnum() << "Unknown pname.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005207 return false;
5208 }
5209 }
5210
5211 if (length)
5212 {
5213 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5214 {
5215 *length = 4;
5216 }
5217 else
5218 {
5219 *length = 1;
5220 }
5221 }
5222
5223 return true;
5224}
5225
5226bool ValidateReadPixelsBase(ValidationContext *context,
5227 GLint x,
5228 GLint y,
5229 GLsizei width,
5230 GLsizei height,
5231 GLenum format,
5232 GLenum type,
5233 GLsizei bufSize,
5234 GLsizei *length,
5235 GLsizei *columns,
5236 GLsizei *rows,
5237 void *pixels)
5238{
5239 if (length != nullptr)
5240 {
5241 *length = 0;
5242 }
5243 if (rows != nullptr)
5244 {
5245 *rows = 0;
5246 }
5247 if (columns != nullptr)
5248 {
5249 *columns = 0;
5250 }
5251
5252 if (width < 0 || height < 0)
5253 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005254 context->handleError(InvalidValue() << "width and height must be positive");
Jamie Madillbe849e42017-05-02 15:49:00 -04005255 return false;
5256 }
5257
5258 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5259
5260 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5261 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005262 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005263 return false;
5264 }
5265
5266 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5267 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005268 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005269 return false;
5270 }
5271
5272 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5273 ASSERT(framebuffer);
5274
5275 if (framebuffer->getReadBufferState() == GL_NONE)
5276 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005277 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Jamie Madillbe849e42017-05-02 15:49:00 -04005278 return false;
5279 }
5280
5281 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5282 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5283 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5284 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5285 // situation is an application error that would lead to a crash in ANGLE.
5286 if (readBuffer == nullptr)
5287 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005288 context->handleError(InvalidOperation() << "Missing read attachment");
Jamie Madillbe849e42017-05-02 15:49:00 -04005289 return false;
5290 }
5291
5292 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
5293 GLenum currentType = framebuffer->getImplementationColorReadType();
5294 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5295
5296 bool validFormatTypeCombination =
5297 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5298
5299 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5300 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005301 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005302 return false;
5303 }
5304
5305 // Check for pixel pack buffer related API errors
5306 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5307 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5308 {
5309 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005310 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005311 return false;
5312 }
5313
5314 // .. the data would be packed to the buffer object such that the memory writes required
5315 // would exceed the data store size.
5316 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5317 const gl::Extents size(width, height, 1);
5318 const auto &pack = context->getGLState().getPackState();
5319
5320 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5321 if (endByteOrErr.isError())
5322 {
5323 context->handleError(endByteOrErr.getError());
5324 return false;
5325 }
5326
5327 size_t endByte = endByteOrErr.getResult();
5328 if (bufSize >= 0)
5329 {
5330 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5331 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005332 context->handleError(InvalidOperation()
5333 << "bufSize must be at least " << endByte << " bytes.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005334 return false;
5335 }
5336 }
5337
5338 if (pixelPackBuffer != nullptr)
5339 {
5340 CheckedNumeric<size_t> checkedEndByte(endByte);
5341 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5342 checkedEndByte += checkedOffset;
5343
5344 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5345 {
5346 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005347 context->handleError(InvalidOperation()
5348 << "Writes would overflow the pixel pack buffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005349 return false;
5350 }
5351 }
5352
5353 if (pixelPackBuffer == nullptr && length != nullptr)
5354 {
5355 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5356 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005357 context->handleError(InvalidOperation() << "length would overflow GLsizei.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005358 return false;
5359 }
5360
5361 *length = static_cast<GLsizei>(endByte);
5362 }
5363
5364 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5365 angle::CheckedNumeric<int> clippedExtent(length);
5366 if (start < 0)
5367 {
5368 // "subtract" the area that is less than 0
5369 clippedExtent += start;
5370 }
5371
5372 const int readExtent = start + length;
5373 if (readExtent > bufferSize)
5374 {
5375 // Subtract the region to the right of the read buffer
5376 clippedExtent -= (readExtent - bufferSize);
5377 }
5378
5379 if (!clippedExtent.IsValid())
5380 {
5381 return 0;
5382 }
5383
5384 return std::max(clippedExtent.ValueOrDie(), 0);
5385 };
5386
5387 if (columns != nullptr)
5388 {
5389 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5390 }
5391
5392 if (rows != nullptr)
5393 {
5394 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5395 }
5396
5397 return true;
5398}
5399
5400template <typename ParamType>
5401bool ValidateTexParameterBase(Context *context,
5402 GLenum target,
5403 GLenum pname,
5404 GLsizei bufSize,
5405 const ParamType *params)
5406{
5407 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5408 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005409 context->handleError(InvalidEnum() << "Invalid texture target");
Jamie Madillbe849e42017-05-02 15:49:00 -04005410 return false;
5411 }
5412
5413 if (context->getTargetTexture(target) == nullptr)
5414 {
5415 // Should only be possible for external textures
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005416 context->handleError(InvalidEnum() << "No texture bound.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005417 return false;
5418 }
5419
5420 const GLsizei minBufSize = 1;
5421 if (bufSize >= 0 && bufSize < minBufSize)
5422 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005423 context->handleError(InvalidOperation() << "bufSize must be at least " << minBufSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005424 return false;
5425 }
5426
5427 switch (pname)
5428 {
5429 case GL_TEXTURE_WRAP_R:
5430 case GL_TEXTURE_SWIZZLE_R:
5431 case GL_TEXTURE_SWIZZLE_G:
5432 case GL_TEXTURE_SWIZZLE_B:
5433 case GL_TEXTURE_SWIZZLE_A:
5434 case GL_TEXTURE_BASE_LEVEL:
5435 case GL_TEXTURE_MAX_LEVEL:
5436 case GL_TEXTURE_COMPARE_MODE:
5437 case GL_TEXTURE_COMPARE_FUNC:
5438 case GL_TEXTURE_MIN_LOD:
5439 case GL_TEXTURE_MAX_LOD:
5440 if (context->getClientMajorVersion() < 3)
5441 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005442 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005443 return false;
5444 }
5445 if (target == GL_TEXTURE_EXTERNAL_OES &&
5446 !context->getExtensions().eglImageExternalEssl3)
5447 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005448 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5449 "available without "
5450 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005451 return false;
5452 }
5453 break;
5454
5455 default:
5456 break;
5457 }
5458
5459 switch (pname)
5460 {
5461 case GL_TEXTURE_WRAP_S:
5462 case GL_TEXTURE_WRAP_T:
5463 case GL_TEXTURE_WRAP_R:
5464 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
5465 {
5466 return false;
5467 }
5468 break;
5469
5470 case GL_TEXTURE_MIN_FILTER:
5471 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
5472 {
5473 return false;
5474 }
5475 break;
5476
5477 case GL_TEXTURE_MAG_FILTER:
5478 if (!ValidateTextureMagFilterValue(context, params))
5479 {
5480 return false;
5481 }
5482 break;
5483
5484 case GL_TEXTURE_USAGE_ANGLE:
5485 switch (ConvertToGLenum(params[0]))
5486 {
5487 case GL_NONE:
5488 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5489 break;
5490
5491 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005492 context->handleError(InvalidEnum() << "Unknown param value.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005493 return false;
5494 }
5495 break;
5496
5497 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5498 if (!context->getExtensions().textureFilterAnisotropic)
5499 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005500 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005501 return false;
5502 }
5503
5504 // we assume the parameter passed to this validation method is truncated, not rounded
5505 if (params[0] < 1)
5506 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005507 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005508 return false;
5509 }
5510 break;
5511
5512 case GL_TEXTURE_MIN_LOD:
5513 case GL_TEXTURE_MAX_LOD:
5514 // any value is permissible
5515 break;
5516
5517 case GL_TEXTURE_COMPARE_MODE:
5518 if (!ValidateTextureCompareModeValue(context, params))
5519 {
5520 return false;
5521 }
5522 break;
5523
5524 case GL_TEXTURE_COMPARE_FUNC:
5525 if (!ValidateTextureCompareFuncValue(context, params))
5526 {
5527 return false;
5528 }
5529 break;
5530
5531 case GL_TEXTURE_SWIZZLE_R:
5532 case GL_TEXTURE_SWIZZLE_G:
5533 case GL_TEXTURE_SWIZZLE_B:
5534 case GL_TEXTURE_SWIZZLE_A:
5535 switch (ConvertToGLenum(params[0]))
5536 {
5537 case GL_RED:
5538 case GL_GREEN:
5539 case GL_BLUE:
5540 case GL_ALPHA:
5541 case GL_ZERO:
5542 case GL_ONE:
5543 break;
5544
5545 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005546 context->handleError(InvalidEnum() << "Unknown param value.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005547 return false;
5548 }
5549 break;
5550
5551 case GL_TEXTURE_BASE_LEVEL:
5552 if (params[0] < 0)
5553 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005554 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005555 return false;
5556 }
5557 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005559 context->handleError(InvalidOperation()
5560 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005561 return false;
5562 }
5563 break;
5564
5565 case GL_TEXTURE_MAX_LEVEL:
5566 if (params[0] < 0)
5567 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005568 context->handleError(InvalidValue() << "Max level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005569 return false;
5570 }
5571 break;
5572
5573 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5574 if (context->getClientVersion() < Version(3, 1))
5575 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005576 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005577 return false;
5578 }
5579 switch (ConvertToGLenum(params[0]))
5580 {
5581 case GL_DEPTH_COMPONENT:
5582 case GL_STENCIL_INDEX:
5583 break;
5584
5585 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005586 context->handleError(InvalidEnum() << "Unknown param value.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005587 return false;
5588 }
5589 break;
5590
5591 case GL_TEXTURE_SRGB_DECODE_EXT:
5592 if (!ValidateTextureSRGBDecodeValue(context, params))
5593 {
5594 return false;
5595 }
5596 break;
5597
5598 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005599 context->handleError(InvalidEnum() << "Unknown pname.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005600 return false;
5601 }
5602
5603 return true;
5604}
5605
5606template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5607template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5608
Jamie Madillc29968b2016-01-20 11:17:23 -05005609} // namespace gl