blob: b8bf5a448c8c820ec8fe98e8e76c18387bfcdea8 [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/validationES2.h"
12#include "libANGLE/validationES3.h"
13#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040014#include "libANGLE/Display.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Texture.h"
16#include "libANGLE/Framebuffer.h"
17#include "libANGLE/FramebufferAttachment.h"
18#include "libANGLE/formatutils.h"
Geoff Langa8406172015-07-21 16:53:39 -040019#include "libANGLE/Image.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/Query.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050021#include "libANGLE/Program.h"
22#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050023#include "libANGLE/TransformFeedback.h"
24#include "libANGLE/VertexArray.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
He Yunchaoced53ae2016-11-29 15:00:51 +080047 const VertexArray *vao = state.getVertexArray();
48 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080049 const auto &vertexBindings = vao->getVertexBindings();
He Yunchaoced53ae2016-11-29 15:00:51 +080050 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];
Corentin Wallezfd456442016-12-21 17:57:00 -050060 // If we have no buffer, then we either get an error, or there are no more checks to be done.
Jiawei-Shao2597fb62016-12-09 16:38:02 +080061 gl::Buffer *buffer = binding.buffer.get();
Corentin Wallezfd456442016-12-21 17:57:00 -050062 if (!buffer)
63 {
Geoff Langfeb8c682017-02-13 16:07:35 -050064 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050065 {
66 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050067 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
68 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
69 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
70 // error.
Corentin Wallez327411e2016-12-09 11:09:17 -050071 context->handleError(
72 Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer."));
Corentin Wallezfd456442016-12-21 17:57:00 -050073 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050074 }
Corentin Wallezfd456442016-12-21 17:57:00 -050075 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040076 {
77 // This is an application error that would normally result in a crash,
78 // but we catch it and return an error
Corentin Wallezfd456442016-12-21 17:57:00 -050079 context->handleError(
80 Error(GL_INVALID_OPERATION,
81 "An enabled vertex array has no buffer and no pointer."));
Jamie Madill1ca74672015-07-21 15:14:11 -040082 return false;
83 }
Corentin Wallezfd456442016-12-21 17:57:00 -050084 continue;
85 }
86
87 // If we're drawing zero vertices, we have enough data.
88 if (vertexCount <= 0 || primcount <= 0)
89 {
90 continue;
91 }
92
93 GLint maxVertexElement = 0;
Jiawei-Shao2597fb62016-12-09 16:38:02 +080094 if (binding.divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -050095 {
96 maxVertexElement = maxVertex;
97 }
98 else
99 {
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800100 maxVertexElement = (primcount - 1) / binding.divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500101 }
102
103 // We do manual overflow checks here instead of using safe_math.h because it was
104 // a bottleneck. Thanks to some properties of GL we know inequalities that can
105 // help us make the overflow checks faster.
106
107 // The max possible attribSize is 16 for a vector of 4 32 bit values.
108 constexpr uint64_t kMaxAttribSize = 16;
109 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
110 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
111
112 // We know attribStride is given as a GLsizei which is typedefed to int.
113 // We also know an upper bound for attribSize.
114 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800115 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500116 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
117 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
118
119 // Computing the max offset using uint64_t without attrib.offset is overflow
120 // safe. Note: Last vertex element does not take the full stride!
121 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
122 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
123
124 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800125 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
126 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500127 {
128 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
129 return false;
130 }
131 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
132
133 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
134 // We can return INVALID_OPERATION if our vertex attribute does not have
135 // enough backing data.
136 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
137 {
138 context->handleError(Error(GL_INVALID_OPERATION,
139 "Vertex buffer is not big enough for the draw call"));
140 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400141 }
142 }
143
144 return true;
145}
146
Geoff Langf607c602016-09-21 11:46:48 -0400147bool ValidReadPixelsFormatType(ValidationContext *context,
148 GLenum framebufferComponentType,
149 GLenum format,
150 GLenum type)
151{
152 switch (framebufferComponentType)
153 {
154 case GL_UNSIGNED_NORMALIZED:
155 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
156 // ReadPixels with BGRA even if the extension is not present
157 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
158 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
159 type == GL_UNSIGNED_BYTE);
160
161 case GL_SIGNED_NORMALIZED:
162 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
163
164 case GL_INT:
165 return (format == GL_RGBA_INTEGER && type == GL_INT);
166
167 case GL_UNSIGNED_INT:
168 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
169
170 case GL_FLOAT:
171 return (format == GL_RGBA && type == GL_FLOAT);
172
173 default:
174 UNREACHABLE();
175 return false;
176 }
177}
178
Geoff Langc1984ed2016-10-07 12:41:00 -0400179template <typename ParamType>
180bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
181{
182 switch (ConvertToGLenum(params[0]))
183 {
184 case GL_CLAMP_TO_EDGE:
185 break;
186
187 case GL_REPEAT:
188 case GL_MIRRORED_REPEAT:
189 if (isExternalTextureTarget)
190 {
191 // OES_EGL_image_external specifies this error.
192 context->handleError(Error(
193 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
194 return false;
195 }
196 break;
197
198 default:
199 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
200 return false;
201 }
202
203 return true;
204}
205
206template <typename ParamType>
207bool ValidateTextureMinFilterValue(Context *context,
208 ParamType *params,
209 bool isExternalTextureTarget)
210{
211 switch (ConvertToGLenum(params[0]))
212 {
213 case GL_NEAREST:
214 case GL_LINEAR:
215 break;
216
217 case GL_NEAREST_MIPMAP_NEAREST:
218 case GL_LINEAR_MIPMAP_NEAREST:
219 case GL_NEAREST_MIPMAP_LINEAR:
220 case GL_LINEAR_MIPMAP_LINEAR:
221 if (isExternalTextureTarget)
222 {
223 // OES_EGL_image_external specifies this error.
224 context->handleError(
225 Error(GL_INVALID_ENUM,
226 "external textures only support NEAREST and LINEAR filtering"));
227 return false;
228 }
229 break;
230
231 default:
232 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
233 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:
249 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
250 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:
267 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
268 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:
291 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
292 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 {
303 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
304 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:
314 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
315 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 {
330 context->handleError(
331 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
332 return false;
333 }
334
335 if (!context->isSampler(sampler))
336 {
337 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
338 return false;
339 }
340
341 const GLsizei minBufSize = 1;
342 if (bufSize >= 0 && bufSize < minBufSize)
343 {
344 context->handleError(
345 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
346 return false;
347 }
348
349 switch (pname)
350 {
351 case GL_TEXTURE_WRAP_S:
352 case GL_TEXTURE_WRAP_T:
353 case GL_TEXTURE_WRAP_R:
354 if (!ValidateTextureWrapModeValue(context, params, false))
355 {
356 return false;
357 }
358 break;
359
360 case GL_TEXTURE_MIN_FILTER:
361 if (!ValidateTextureMinFilterValue(context, params, false))
362 {
363 return false;
364 }
365 break;
366
367 case GL_TEXTURE_MAG_FILTER:
368 if (!ValidateTextureMagFilterValue(context, params))
369 {
370 return false;
371 }
372 break;
373
374 case GL_TEXTURE_MIN_LOD:
375 case GL_TEXTURE_MAX_LOD:
376 // any value is permissible
377 break;
378
379 case GL_TEXTURE_COMPARE_MODE:
380 if (!ValidateTextureCompareModeValue(context, params))
381 {
382 return false;
383 }
384 break;
385
386 case GL_TEXTURE_COMPARE_FUNC:
387 if (!ValidateTextureCompareFuncValue(context, params))
388 {
389 return false;
390 }
391 break;
392
Geoff Lang81c6b572016-10-19 14:07:52 -0700393 case GL_TEXTURE_SRGB_DECODE_EXT:
394 if (!ValidateTextureSRGBDecodeValue(context, params))
395 {
396 return false;
397 }
398 break;
399
Geoff Langc1984ed2016-10-07 12:41:00 -0400400 default:
401 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
402 return false;
403 }
404
405 return true;
406}
407
408bool ValidateGetSamplerParameterBase(Context *context,
409 GLuint sampler,
410 GLenum pname,
411 GLsizei *length)
412{
413 if (length)
414 {
415 *length = 0;
416 }
417
418 if (context->getClientMajorVersion() < 3)
419 {
420 context->handleError(
421 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
422 return false;
423 }
424
425 if (!context->isSampler(sampler))
426 {
427 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
428 return false;
429 }
430
431 switch (pname)
432 {
433 case GL_TEXTURE_WRAP_S:
434 case GL_TEXTURE_WRAP_T:
435 case GL_TEXTURE_WRAP_R:
436 case GL_TEXTURE_MIN_FILTER:
437 case GL_TEXTURE_MAG_FILTER:
438 case GL_TEXTURE_MIN_LOD:
439 case GL_TEXTURE_MAX_LOD:
440 case GL_TEXTURE_COMPARE_MODE:
441 case GL_TEXTURE_COMPARE_FUNC:
442 break;
443
Geoff Lang81c6b572016-10-19 14:07:52 -0700444 case GL_TEXTURE_SRGB_DECODE_EXT:
445 if (!context->getExtensions().textureSRGBDecode)
446 {
447 context->handleError(
448 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
449 return false;
450 }
451 break;
452
Geoff Langc1984ed2016-10-07 12:41:00 -0400453 default:
454 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
455 return false;
456 }
457
458 if (length)
459 {
460 *length = 1;
461 }
462 return true;
463}
464
Geoff Lang6899b872016-10-14 11:30:13 -0400465bool ValidateGetActiveUniformBlockivBase(Context *context,
466 GLuint program,
467 GLuint uniformBlockIndex,
468 GLenum pname,
469 GLsizei *length)
470{
471 if (length)
472 {
473 *length = 0;
474 }
475
476 if (context->getClientMajorVersion() < 3)
477 {
478 context->handleError(
479 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
480 return false;
481 }
482
483 Program *programObject = GetValidProgram(context, program);
484 if (!programObject)
485 {
486 return false;
487 }
488
489 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
490 {
491 context->handleError(
492 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
493 return false;
494 }
495
496 switch (pname)
497 {
498 case GL_UNIFORM_BLOCK_BINDING:
499 case GL_UNIFORM_BLOCK_DATA_SIZE:
500 case GL_UNIFORM_BLOCK_NAME_LENGTH:
501 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
502 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
503 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
504 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
505 break;
506
507 default:
508 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
509 return false;
510 }
511
512 if (length)
513 {
514 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
515 {
516 const UniformBlock &uniformBlock =
517 programObject->getUniformBlockByIndex(uniformBlockIndex);
518 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
519 }
520 else
521 {
522 *length = 1;
523 }
524 }
525
526 return true;
527}
528
Geoff Lang0a9661f2016-10-20 10:59:20 -0700529bool ValidateGetInternalFormativBase(Context *context,
530 GLenum target,
531 GLenum internalformat,
532 GLenum pname,
533 GLsizei bufSize,
534 GLsizei *numParams)
535{
536 if (numParams)
537 {
538 *numParams = 0;
539 }
540
541 if (context->getClientMajorVersion() < 3)
542 {
543 context->handleError(
544 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
545 return false;
546 }
547
548 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
549 if (!formatCaps.renderable)
550 {
551 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
552 return false;
553 }
554
555 switch (target)
556 {
557 case GL_RENDERBUFFER:
558 break;
559
JiangYizhoubddc46b2016-12-09 09:50:51 +0800560 case GL_TEXTURE_2D_MULTISAMPLE:
561 if (context->getClientVersion() < ES_3_1)
562 {
563 context->handleError(
564 Error(GL_INVALID_OPERATION, "Texture target requires at least OpenGL ES 3.1."));
565 return false;
566 }
567 break;
568
Geoff Lang0a9661f2016-10-20 10:59:20 -0700569 default:
570 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
571 return false;
572 }
573
574 if (bufSize < 0)
575 {
576 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
577 return false;
578 }
579
580 GLsizei maxWriteParams = 0;
581 switch (pname)
582 {
583 case GL_NUM_SAMPLE_COUNTS:
584 maxWriteParams = 1;
585 break;
586
587 case GL_SAMPLES:
588 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
589 break;
590
591 default:
592 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
593 return false;
594 }
595
596 if (numParams)
597 {
598 // glGetInternalFormativ will not overflow bufSize
599 *numParams = std::min(bufSize, maxWriteParams);
600 }
601
602 return true;
603}
604
Jamie Madillc1d770e2017-04-13 17:31:24 -0400605bool ValidateUniformCommonBase(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500606 gl::Program *program,
607 GLint location,
608 GLsizei count,
609 const LinkedUniform **uniformOut)
610{
611 // TODO(Jiajia): Add image uniform check in future.
612 if (count < 0)
613 {
614 context->handleError(Error(GL_INVALID_VALUE));
615 return false;
616 }
617
618 if (!program || !program->isLinked())
619 {
620 context->handleError(Error(GL_INVALID_OPERATION));
621 return false;
622 }
623
624 if (location == -1)
625 {
626 // Silently ignore the uniform command
627 return false;
628 }
629
630 const auto &uniformLocations = program->getUniformLocations();
Jamie Madillbe849e42017-05-02 15:49:00 -0400631 size_t castedLocation = static_cast<size_t>(location);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500632 if (castedLocation >= uniformLocations.size())
633 {
634 context->handleError(Error(GL_INVALID_OPERATION, "Invalid uniform location"));
635 return false;
636 }
637
638 const auto &uniformLocation = uniformLocations[castedLocation];
639 if (uniformLocation.ignored)
640 {
641 // Silently ignore the uniform command
642 return false;
643 }
644
645 if (!uniformLocation.used)
646 {
647 context->handleError(Error(GL_INVALID_OPERATION));
648 return false;
649 }
650
651 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
652
653 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
654 if (!uniform.isArray() && count > 1)
655 {
656 context->handleError(Error(GL_INVALID_OPERATION));
657 return false;
658 }
659
660 *uniformOut = &uniform;
661 return true;
662}
663
Frank Henigman999b0fd2017-02-02 21:45:55 -0500664bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -0500665 GLenum uniformType,
666 GLsizei count,
667 const GLint *value)
668{
669 // Value type is GL_INT, because we only get here from glUniform1i{v}.
670 // It is compatible with INT or BOOL.
671 // Do these cheap tests first, for a little extra speed.
672 if (GL_INT == uniformType || GL_BOOL == uniformType)
673 {
674 return true;
675 }
676
677 if (IsSamplerType(uniformType))
678 {
Frank Henigman999b0fd2017-02-02 21:45:55 -0500679 // Check that the values are in range.
680 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
681 for (GLsizei i = 0; i < count; ++i)
682 {
683 if (value[i] < 0 || value[i] >= max)
684 {
685 context->handleError(Error(GL_INVALID_VALUE, "sampler uniform value out of range"));
686 return false;
687 }
688 }
Frank Henigmana98a6472017-02-02 21:38:32 -0500689 return true;
690 }
691
692 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
693 return false;
694}
695
Jamie Madillc1d770e2017-04-13 17:31:24 -0400696bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500697{
698 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -0500699 // Do the cheaper test first, for a little extra speed.
700 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500701 {
702 return true;
703 }
704
705 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
706 return false;
707}
708
Jamie Madillc1d770e2017-04-13 17:31:24 -0400709bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500710{
711 // Check that the value type is compatible with uniform type.
712 if (valueType == uniformType)
713 {
714 return true;
715 }
716
717 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
718 return false;
719}
720
Geoff Langf41a7152016-09-19 15:11:17 -0400721} // anonymous namespace
722
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500723bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400724{
Jamie Madilld7460c72014-01-21 16:38:14 -0500725 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400726 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800727 case GL_TEXTURE_2D:
728 case GL_TEXTURE_CUBE_MAP:
729 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400730
He Yunchaoced53ae2016-11-29 15:00:51 +0800731 case GL_TEXTURE_3D:
732 case GL_TEXTURE_2D_ARRAY:
733 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500734
He Yunchaoced53ae2016-11-29 15:00:51 +0800735 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800736 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400737
He Yunchaoced53ae2016-11-29 15:00:51 +0800738 default:
739 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500740 }
Jamie Madill35d15012013-10-07 10:46:37 -0400741}
742
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500743bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
744{
745 switch (target)
746 {
747 case GL_TEXTURE_2D:
748 case GL_TEXTURE_CUBE_MAP:
749 return true;
750
751 default:
752 return false;
753 }
754}
755
756bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
757{
758 switch (target)
759 {
760 case GL_TEXTURE_3D:
761 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300762 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500763
764 default:
765 return false;
766 }
767}
768
Ian Ewellbda75592016-04-18 17:25:54 -0400769// Most texture GL calls are not compatible with external textures, so we have a separate validation
770// function for use in the GL calls that do
771bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
772{
773 return (target == GL_TEXTURE_EXTERNAL_OES) &&
774 (context->getExtensions().eglImageExternal ||
775 context->getExtensions().eglStreamConsumerExternal);
776}
777
Shannon Woods4dfed832014-03-17 20:03:39 -0400778// This function differs from ValidTextureTarget in that the target must be
779// usable as the destination of a 2D operation-- so a cube face is valid, but
780// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400781// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500782bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400783{
784 switch (target)
785 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800786 case GL_TEXTURE_2D:
787 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
788 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
789 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
790 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
791 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
792 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
793 return true;
794 default:
795 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500796 }
797}
798
Jamie Madillbe849e42017-05-02 15:49:00 -0400799bool ValidateDrawElementsInstancedBase(ValidationContext *context,
800 GLenum mode,
801 GLsizei count,
802 GLenum type,
803 const GLvoid *indices,
804 GLsizei primcount)
805{
806 if (primcount < 0)
807 {
808 context->handleError(Error(GL_INVALID_VALUE, "primcount cannot be negative."));
809 return false;
810 }
811
812 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
813 {
814 return false;
815 }
816
817 // No-op zero primitive count
818 return (primcount > 0);
819}
820
821bool ValidateDrawArraysInstancedBase(Context *context,
822 GLenum mode,
823 GLint first,
824 GLsizei count,
825 GLsizei primcount)
826{
827 if (primcount < 0)
828 {
829 context->handleError(Error(GL_INVALID_VALUE, "primcount cannot be negative."));
830 return false;
831 }
832
833 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
834 {
835 return false;
836 }
837
838 // No-op if zero primitive count
839 return (primcount > 0);
840}
841
842bool ValidateDrawInstancedANGLEAndWebGL(ValidationContext *context)
843{
844 // Verify there is at least one active attribute with a divisor of zero
845 const State &state = context->getGLState();
846
847 Program *program = state.getProgram();
848
849 const auto &attribs = state.getVertexArray()->getVertexAttributes();
850 const auto &bindings = state.getVertexArray()->getVertexBindings();
851 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
852 {
853 const VertexAttribute &attrib = attribs[attributeIndex];
854 const VertexBinding &binding = bindings[attrib.bindingIndex];
855 if (program->isAttribLocationActive(attributeIndex) && binding.divisor == 0)
856 {
857 return true;
858 }
859 }
860
861 context->handleError(
862 Error(GL_INVALID_OPERATION, "At least one attribute must have a divisor of zero."));
863 return false;
864}
865
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500866bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
867{
868 switch (target)
869 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800870 case GL_TEXTURE_3D:
871 case GL_TEXTURE_2D_ARRAY:
872 return true;
873 default:
874 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400875 }
876}
877
He Yunchao11b038b2016-11-22 21:24:04 +0800878bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
879{
880 switch (target)
881 {
882 case GL_TEXTURE_2D:
883 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
884 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
885 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
886 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
887 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
888 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
889 case GL_TEXTURE_3D:
890 case GL_TEXTURE_2D_ARRAY:
891 case GL_TEXTURE_2D_MULTISAMPLE:
892 return true;
893 default:
894 return false;
895 }
896}
897
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500898bool ValidFramebufferTarget(GLenum target)
899{
He Yunchaoced53ae2016-11-29 15:00:51 +0800900 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
901 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400902 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500903
904 switch (target)
905 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800906 case GL_FRAMEBUFFER:
907 return true;
908 case GL_READ_FRAMEBUFFER:
909 return true;
910 case GL_DRAW_FRAMEBUFFER:
911 return true;
912 default:
913 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500914 }
915}
916
Jamie Madill29639852016-09-02 15:00:09 -0400917bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -0500918{
919 switch (target)
920 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800921 case GL_ARRAY_BUFFER:
922 case GL_ELEMENT_ARRAY_BUFFER:
923 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -0500924
He Yunchaoced53ae2016-11-29 15:00:51 +0800925 case GL_PIXEL_PACK_BUFFER:
926 case GL_PIXEL_UNPACK_BUFFER:
927 return (context->getExtensions().pixelBufferObject ||
928 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -0400929
He Yunchaoced53ae2016-11-29 15:00:51 +0800930 case GL_COPY_READ_BUFFER:
931 case GL_COPY_WRITE_BUFFER:
932 case GL_TRANSFORM_FEEDBACK_BUFFER:
933 case GL_UNIFORM_BUFFER:
934 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -0500935
He Yunchaoced53ae2016-11-29 15:00:51 +0800936 case GL_ATOMIC_COUNTER_BUFFER:
937 case GL_SHADER_STORAGE_BUFFER:
938 case GL_DRAW_INDIRECT_BUFFER:
939 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800940 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -0400941
He Yunchaoced53ae2016-11-29 15:00:51 +0800942 default:
943 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -0500944 }
945}
946
Jamie Madillc29968b2016-01-20 11:17:23 -0500947bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400948{
Jamie Madillc29968b2016-01-20 11:17:23 -0500949 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400950 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400951 switch (target)
952 {
Jamie Madillc29968b2016-01-20 11:17:23 -0500953 case GL_TEXTURE_2D:
954 maxDimension = caps.max2DTextureSize;
955 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800956 case GL_TEXTURE_CUBE_MAP:
957 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
958 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
959 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
960 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
961 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
962 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
963 maxDimension = caps.maxCubeMapTextureSize;
964 break;
965 case GL_TEXTURE_3D:
966 maxDimension = caps.max3DTextureSize;
967 break;
968 case GL_TEXTURE_2D_ARRAY:
969 maxDimension = caps.max2DTextureSize;
970 break;
He Yunchao11b038b2016-11-22 21:24:04 +0800971 case GL_TEXTURE_2D_MULTISAMPLE:
972 maxDimension = caps.max2DTextureSize;
973 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800974 default:
975 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400976 }
977
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700978 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -0400979}
980
Geoff Langcc507aa2016-12-12 10:09:52 -0500981bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -0700982 GLenum target,
983 GLint level,
984 GLsizei width,
985 GLsizei height,
986 GLsizei depth,
987 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400988{
989 if (level < 0 || width < 0 || height < 0 || depth < 0)
990 {
991 return false;
992 }
993
Austin Kinross08528e12015-10-07 16:24:40 -0700994 // TexSubImage parameters can be NPOT without textureNPOT extension,
995 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500996 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500997 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500998 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400999 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001000 {
1001 return false;
1002 }
1003
1004 if (!ValidMipLevel(context, target, level))
1005 {
1006 return false;
1007 }
1008
1009 return true;
1010}
1011
Geoff Lang0d8b7242015-09-09 14:56:53 -04001012bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1013{
1014 // List of compressed format that require that the texture size is smaller than or a multiple of
1015 // the compressed block size.
1016 switch (internalFormat)
1017 {
1018 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1019 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1020 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1021 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001022 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001023 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1024 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1025 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1026 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1027 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
1028 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001029 return true;
1030
1031 default:
1032 return false;
1033 }
1034}
1035
Geoff Lang966c9402017-04-18 12:38:27 -04001036bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
1037{
1038 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
1039 (size % blockSize == 0);
1040}
1041
Jamie Madillc29968b2016-01-20 11:17:23 -05001042bool ValidCompressedImageSize(const ValidationContext *context,
1043 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -04001044 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -05001045 GLsizei width,
1046 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001047{
Geoff Langca271392017-04-05 12:30:00 -04001048 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -04001049 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001050 {
1051 return false;
1052 }
1053
Geoff Lang966c9402017-04-18 12:38:27 -04001054 if (width < 0 || height < 0)
1055 {
1056 return false;
1057 }
1058
1059 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1060 {
1061 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
1062 // block size for level 0 but WebGL disallows this.
1063 bool smallerThanBlockSizeAllowed =
1064 level > 0 || !context->getExtensions().webglCompatibility;
1065
1066 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
1067 smallerThanBlockSizeAllowed) ||
1068 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
1069 smallerThanBlockSizeAllowed))
1070 {
1071 return false;
1072 }
1073 }
1074
1075 return true;
1076}
1077
1078bool ValidCompressedSubImageSize(const ValidationContext *context,
1079 GLenum internalFormat,
1080 GLint xoffset,
1081 GLint yoffset,
1082 GLsizei width,
1083 GLsizei height,
1084 size_t textureWidth,
1085 size_t textureHeight)
1086{
1087 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
1088 if (!formatInfo.compressed)
1089 {
1090 return false;
1091 }
1092
Geoff Lang44ff5a72017-02-03 15:15:43 -05001093 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001094 {
1095 return false;
1096 }
1097
Geoff Lang0d8b7242015-09-09 14:56:53 -04001098 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1099 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05001100 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -04001101 yoffset % formatInfo.compressedBlockHeight != 0)
1102 {
1103 return false;
1104 }
1105
1106 // Allowed to either have data that is a multiple of block size or is smaller than the block
1107 // size but fills the entire mip
1108 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
1109 static_cast<size_t>(width) == textureWidth &&
1110 static_cast<size_t>(height) == textureHeight;
1111 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
1112 (height % formatInfo.compressedBlockHeight) == 0;
1113 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -04001114 {
1115 return false;
1116 }
1117 }
1118
Geoff Langd4f180b2013-09-24 13:57:44 -04001119 return true;
1120}
1121
Geoff Langff5b2d52016-09-07 11:32:23 -04001122bool ValidImageDataSize(ValidationContext *context,
1123 GLenum textureTarget,
1124 GLsizei width,
1125 GLsizei height,
1126 GLsizei depth,
1127 GLenum internalFormat,
1128 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001129 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001130 GLsizei imageSize)
1131{
1132 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1133 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1134 {
1135 // Checks are not required
1136 return true;
1137 }
1138
1139 // ...the data would be unpacked from the buffer object such that the memory reads required
1140 // would exceed the data store size.
Geoff Langca271392017-04-05 12:30:00 -04001141 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
Geoff Langff5b2d52016-09-07 11:32:23 -04001142 const gl::Extents size(width, height, depth);
1143 const auto &unpack = context->getGLState().getUnpackState();
1144
1145 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1146 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1147 if (endByteOrErr.isError())
1148 {
1149 context->handleError(endByteOrErr.getError());
1150 return false;
1151 }
1152
1153 GLuint endByte = endByteOrErr.getResult();
1154
1155 if (pixelUnpackBuffer)
1156 {
1157 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1158 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1159 checkedEndByte += checkedOffset;
1160
1161 if (!checkedEndByte.IsValid() ||
1162 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1163 {
1164 // Overflow past the end of the buffer
1165 context->handleError(Error(GL_INVALID_OPERATION));
1166 return false;
1167 }
1168 }
1169 else
1170 {
1171 ASSERT(imageSize >= 0);
1172 if (pixels == nullptr && imageSize != 0)
1173 {
1174 context->handleError(
1175 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001176 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001177 }
1178
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001179 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001180 {
1181 context->handleError(
1182 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1183 return false;
1184 }
1185 }
1186
1187 return true;
1188}
1189
Geoff Lang37dde692014-01-31 16:34:54 -05001190bool ValidQueryType(const Context *context, GLenum queryType)
1191{
He Yunchaoced53ae2016-11-29 15:00:51 +08001192 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1193 "GL extension enums not equal.");
1194 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1195 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001196
1197 switch (queryType)
1198 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001199 case GL_ANY_SAMPLES_PASSED:
1200 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1201 return true;
1202 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1203 return (context->getClientMajorVersion() >= 3);
1204 case GL_TIME_ELAPSED_EXT:
1205 return context->getExtensions().disjointTimerQuery;
1206 case GL_COMMANDS_COMPLETED_CHROMIUM:
1207 return context->getExtensions().syncQuery;
1208 default:
1209 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001210 }
1211}
1212
Geoff Lang2d62ab72017-03-23 16:54:40 -04001213bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
1214 GLenum type,
1215 GLboolean normalized,
1216 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001217 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001218 bool pureInteger)
1219{
1220 ASSERT(context->getExtensions().webglCompatibility);
1221
1222 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1223 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1224 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1225 // parameter exceeds 255.
1226 constexpr GLsizei kMaxWebGLStride = 255;
1227 if (stride > kMaxWebGLStride)
1228 {
1229 context->handleError(
1230 Error(GL_INVALID_VALUE, "Stride is over the maximum stride allowed by WebGL."));
1231 return false;
1232 }
1233
1234 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1235 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1236 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1237 // or an INVALID_OPERATION error is generated.
1238 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1239 size_t typeSize = GetVertexFormatTypeSize(internalType);
1240
1241 ASSERT(isPow2(typeSize) && typeSize > 0);
1242 size_t sizeMask = (typeSize - 1);
1243 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1244 {
1245 context->handleError(
1246 Error(GL_INVALID_OPERATION, "Offset is not a multiple of the type size."));
1247 return false;
1248 }
1249
1250 if ((stride & sizeMask) != 0)
1251 {
1252 context->handleError(
1253 Error(GL_INVALID_OPERATION, "Stride is not a multiple of the type size."));
1254 return false;
1255 }
1256
1257 return true;
1258}
1259
Jamie Madillef300b12016-10-07 15:12:09 -04001260Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001261{
He Yunchaoced53ae2016-11-29 15:00:51 +08001262 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1263 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1264 // or program object and INVALID_OPERATION if the provided name identifies an object
1265 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001266
Dian Xiang769769a2015-09-09 15:20:08 -07001267 Program *validProgram = context->getProgram(id);
1268
1269 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001270 {
Dian Xiang769769a2015-09-09 15:20:08 -07001271 if (context->getShader(id))
1272 {
Jamie Madill437fa652016-05-03 15:13:24 -04001273 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001274 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1275 }
1276 else
1277 {
Jamie Madill437fa652016-05-03 15:13:24 -04001278 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001279 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001280 }
Dian Xiang769769a2015-09-09 15:20:08 -07001281
1282 return validProgram;
1283}
1284
Jamie Madillef300b12016-10-07 15:12:09 -04001285Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001286{
1287 // See ValidProgram for spec details.
1288
1289 Shader *validShader = context->getShader(id);
1290
1291 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001292 {
Dian Xiang769769a2015-09-09 15:20:08 -07001293 if (context->getProgram(id))
1294 {
Jamie Madill437fa652016-05-03 15:13:24 -04001295 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001296 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1297 }
1298 else
1299 {
Jamie Madill437fa652016-05-03 15:13:24 -04001300 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001301 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001302 }
Dian Xiang769769a2015-09-09 15:20:08 -07001303
1304 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001305}
1306
Geoff Langb1196682014-07-23 13:47:29 -04001307bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001308{
1309 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1310 {
1311 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1312
Geoff Langaae65a42014-05-26 12:43:44 -04001313 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001314 {
Jamie Madill437fa652016-05-03 15:13:24 -04001315 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001316 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001317 }
1318 }
1319 else
1320 {
1321 switch (attachment)
1322 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001323 case GL_DEPTH_ATTACHMENT:
1324 case GL_STENCIL_ATTACHMENT:
1325 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001326
He Yunchaoced53ae2016-11-29 15:00:51 +08001327 case GL_DEPTH_STENCIL_ATTACHMENT:
1328 if (!context->getExtensions().webglCompatibility &&
1329 context->getClientMajorVersion() < 3)
1330 {
1331 context->handleError(Error(GL_INVALID_ENUM));
1332 return false;
1333 }
1334 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001335
He Yunchaoced53ae2016-11-29 15:00:51 +08001336 default:
1337 context->handleError(Error(GL_INVALID_ENUM));
1338 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001339 }
1340 }
1341
1342 return true;
1343}
1344
Jamie Madille8fb6402017-02-14 17:56:40 -05001345bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001346 GLenum target,
1347 GLsizei samples,
1348 GLenum internalformat,
1349 GLsizei width,
1350 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001351{
1352 switch (target)
1353 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001354 case GL_RENDERBUFFER:
1355 break;
1356 default:
1357 context->handleError(Error(GL_INVALID_ENUM));
1358 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001359 }
1360
1361 if (width < 0 || height < 0 || samples < 0)
1362 {
Jamie Madill437fa652016-05-03 15:13:24 -04001363 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001364 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001365 }
1366
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001367 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1368 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1369
1370 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001371 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001372 {
Jamie Madill437fa652016-05-03 15:13:24 -04001373 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001374 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001375 }
1376
1377 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1378 // 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 -08001379 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001380 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1381 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001382 {
Jamie Madill437fa652016-05-03 15:13:24 -04001383 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001384 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001385 }
1386
Geoff Langaae65a42014-05-26 12:43:44 -04001387 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001388 {
Jamie Madill437fa652016-05-03 15:13:24 -04001389 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001390 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001391 }
1392
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001393 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001394 if (handle == 0)
1395 {
Jamie Madill437fa652016-05-03 15:13:24 -04001396 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001397 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001398 }
1399
1400 return true;
1401}
1402
He Yunchaoced53ae2016-11-29 15:00:51 +08001403bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1404 GLenum target,
1405 GLenum attachment,
1406 GLenum renderbuffertarget,
1407 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001408{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001409 if (!ValidFramebufferTarget(target))
1410 {
Jamie Madill437fa652016-05-03 15:13:24 -04001411 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001412 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001413 }
1414
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001415 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001416
Jamie Madill84115c92015-04-23 15:00:07 -04001417 ASSERT(framebuffer);
1418 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001419 {
Jamie Madill437fa652016-05-03 15:13:24 -04001420 context->handleError(
1421 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001422 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001423 }
1424
Jamie Madillb4472272014-07-03 10:38:55 -04001425 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001426 {
Jamie Madillb4472272014-07-03 10:38:55 -04001427 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001428 }
1429
Jamie Madillab9d82c2014-01-21 16:38:14 -05001430 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1431 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1432 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1433 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1434 if (renderbuffer != 0)
1435 {
1436 if (!context->getRenderbuffer(renderbuffer))
1437 {
Jamie Madill437fa652016-05-03 15:13:24 -04001438 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001439 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001440 }
1441 }
1442
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001443 return true;
1444}
1445
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001446bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001447 GLint srcX0,
1448 GLint srcY0,
1449 GLint srcX1,
1450 GLint srcY1,
1451 GLint dstX0,
1452 GLint dstY0,
1453 GLint dstX1,
1454 GLint dstY1,
1455 GLbitfield mask,
1456 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001457{
1458 switch (filter)
1459 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001460 case GL_NEAREST:
1461 break;
1462 case GL_LINEAR:
1463 break;
1464 default:
1465 context->handleError(Error(GL_INVALID_ENUM));
1466 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001467 }
1468
1469 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1470 {
Jamie Madill437fa652016-05-03 15:13:24 -04001471 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001472 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001473 }
1474
1475 if (mask == 0)
1476 {
1477 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1478 // buffers are copied.
1479 return false;
1480 }
1481
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001482 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1483 // color buffer, leaving only nearest being unfiltered from above
1484 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1485 {
Jamie Madill437fa652016-05-03 15:13:24 -04001486 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001487 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001488 }
1489
Jamie Madill51f40ec2016-06-15 14:06:00 -04001490 const auto &glState = context->getGLState();
1491 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1492 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001493
1494 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001495 {
Jamie Madill437fa652016-05-03 15:13:24 -04001496 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001497 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001498 }
1499
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001500 if (readFramebuffer->id() == drawFramebuffer->id())
1501 {
1502 context->handleError(Error(GL_INVALID_OPERATION));
1503 return false;
1504 }
1505
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001506 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001507 {
Jamie Madill437fa652016-05-03 15:13:24 -04001508 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001509 return false;
1510 }
1511
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001512 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001513 {
Jamie Madill437fa652016-05-03 15:13:24 -04001514 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001515 return false;
1516 }
1517
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001518 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001519 {
Jamie Madill437fa652016-05-03 15:13:24 -04001520 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001521 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001522 }
1523
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001524 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1525
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001526 if (mask & GL_COLOR_BUFFER_BIT)
1527 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001528 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001529 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001530
He Yunchao66a41a22016-12-15 16:45:05 +08001531 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001532 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001533 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001534
Geoff Langa15472a2015-08-11 11:48:03 -04001535 for (size_t drawbufferIdx = 0;
1536 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001537 {
Geoff Langa15472a2015-08-11 11:48:03 -04001538 const FramebufferAttachment *attachment =
1539 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1540 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001541 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001542 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001543
Geoff Langb2f3d052013-08-13 12:49:27 -04001544 // The GL ES 3.0.2 spec (pg 193) states that:
1545 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001546 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1547 // as well
1548 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1549 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001550 // Changes with EXT_color_buffer_float:
1551 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001552 GLenum readComponentType = readFormat.info->componentType;
1553 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001554 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001555 readComponentType == GL_SIGNED_NORMALIZED);
1556 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1557 drawComponentType == GL_SIGNED_NORMALIZED);
1558
1559 if (extensions.colorBufferFloat)
1560 {
1561 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1562 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1563
1564 if (readFixedOrFloat != drawFixedOrFloat)
1565 {
Jamie Madill437fa652016-05-03 15:13:24 -04001566 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001567 "If the read buffer contains fixed-point or "
1568 "floating-point values, the draw buffer "
1569 "must as well."));
1570 return false;
1571 }
1572 }
1573 else if (readFixedPoint != drawFixedPoint)
1574 {
Jamie Madill437fa652016-05-03 15:13:24 -04001575 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001576 "If the read buffer contains fixed-point "
1577 "values, the draw buffer must as well."));
1578 return false;
1579 }
1580
1581 if (readComponentType == GL_UNSIGNED_INT &&
1582 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001583 {
Jamie Madill437fa652016-05-03 15:13:24 -04001584 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001585 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001586 }
1587
Jamie Madill6163c752015-12-07 16:32:59 -05001588 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001589 {
Jamie Madill437fa652016-05-03 15:13:24 -04001590 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001591 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001592 }
1593
Jamie Madilla3944d42016-07-22 22:13:26 -04001594 if (readColorBuffer->getSamples() > 0 &&
1595 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001596 {
Jamie Madill437fa652016-05-03 15:13:24 -04001597 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001598 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001599 }
Geoff Lange4915782017-04-12 15:19:07 -04001600
1601 if (context->getExtensions().webglCompatibility &&
1602 *readColorBuffer == *attachment)
1603 {
1604 context->handleError(
1605 Error(GL_INVALID_OPERATION,
1606 "Read and write color attachments cannot be the same image."));
1607 return false;
1608 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001609 }
1610 }
1611
Jamie Madilla3944d42016-07-22 22:13:26 -04001612 if ((readFormat.info->componentType == GL_INT ||
1613 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1614 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001615 {
Jamie Madill437fa652016-05-03 15:13:24 -04001616 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001617 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001618 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001619 }
He Yunchao66a41a22016-12-15 16:45:05 +08001620 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1621 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1622 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1623 // situation is an application error that would lead to a crash in ANGLE.
1624 else if (drawFramebuffer->hasEnabledDrawBuffer())
1625 {
1626 context->handleError(Error(
1627 GL_INVALID_OPERATION,
1628 "Attempt to read from a missing color attachment of a complete framebuffer."));
1629 return false;
1630 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001631 }
1632
He Yunchaoced53ae2016-11-29 15:00:51 +08001633 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001634 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1635 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001636 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001637 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001638 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001639 const gl::FramebufferAttachment *readBuffer =
1640 readFramebuffer->getAttachment(attachments[i]);
1641 const gl::FramebufferAttachment *drawBuffer =
1642 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001643
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001644 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001645 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001646 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001647 {
Jamie Madill437fa652016-05-03 15:13:24 -04001648 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001649 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001650 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001651
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001652 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001653 {
Jamie Madill437fa652016-05-03 15:13:24 -04001654 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001655 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001656 }
Geoff Lange4915782017-04-12 15:19:07 -04001657
1658 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1659 {
1660 context->handleError(Error(
1661 GL_INVALID_OPERATION,
1662 "Read and write depth stencil attachments cannot be the same image."));
1663 return false;
1664 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001665 }
He Yunchao66a41a22016-12-15 16:45:05 +08001666 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1667 else if (drawBuffer)
1668 {
1669 context->handleError(Error(GL_INVALID_OPERATION,
1670 "Attempt to read from a missing depth/stencil "
1671 "attachment of a complete framebuffer."));
1672 return false;
1673 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001674 }
1675 }
1676
1677 return true;
1678}
1679
Geoff Lang62fce5b2016-09-30 10:46:35 -04001680bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
1681 GLint x,
1682 GLint y,
1683 GLsizei width,
1684 GLsizei height,
1685 GLenum format,
1686 GLenum type,
1687 GLsizei bufSize,
1688 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001689 GLsizei *columns,
1690 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001691 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001692{
1693 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001694 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001695 return false;
1696 }
1697
Geoff Lang62fce5b2016-09-30 10:46:35 -04001698 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001699 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001700 {
Geoff Langb1196682014-07-23 13:47:29 -04001701 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001702 }
1703
Geoff Lang62fce5b2016-09-30 10:46:35 -04001704 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001705 {
Geoff Langb1196682014-07-23 13:47:29 -04001706 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001707 }
1708
Jamie Madillc29968b2016-01-20 11:17:23 -05001709 return true;
1710}
1711
1712bool ValidateReadnPixelsEXT(Context *context,
1713 GLint x,
1714 GLint y,
1715 GLsizei width,
1716 GLsizei height,
1717 GLenum format,
1718 GLenum type,
1719 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001720 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001721{
1722 if (bufSize < 0)
1723 {
Jamie Madill437fa652016-05-03 15:13:24 -04001724 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001725 return false;
1726 }
1727
Geoff Lang62fce5b2016-09-30 10:46:35 -04001728 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001729 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001730}
Jamie Madill26e91952014-03-05 15:01:27 -05001731
Geoff Lang62fce5b2016-09-30 10:46:35 -04001732bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
1733 GLint x,
1734 GLint y,
1735 GLsizei width,
1736 GLsizei height,
1737 GLenum format,
1738 GLenum type,
1739 GLsizei bufSize,
1740 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001741 GLsizei *columns,
1742 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001743 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001744{
1745 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001746 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001747 return false;
1748 }
1749
Geoff Lange93daba2017-03-30 13:54:40 -04001750 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1751 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001752 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001753 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001754 }
1755
Geoff Lang62fce5b2016-09-30 10:46:35 -04001756 if (!ValidateRobustBufferSize(context, bufSize, *length))
1757 {
1758 return false;
1759 }
1760
1761 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001762}
1763
Olli Etuaho41997e72016-03-10 13:38:39 +02001764bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001765{
1766 if (!context->getExtensions().occlusionQueryBoolean &&
1767 !context->getExtensions().disjointTimerQuery)
1768 {
Jamie Madill437fa652016-05-03 15:13:24 -04001769 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001770 return false;
1771 }
1772
Olli Etuaho41997e72016-03-10 13:38:39 +02001773 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001774}
1775
Olli Etuaho41997e72016-03-10 13:38:39 +02001776bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001777{
1778 if (!context->getExtensions().occlusionQueryBoolean &&
1779 !context->getExtensions().disjointTimerQuery)
1780 {
Jamie Madill437fa652016-05-03 15:13:24 -04001781 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001782 return false;
1783 }
1784
Olli Etuaho41997e72016-03-10 13:38:39 +02001785 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001786}
1787
1788bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001789{
1790 if (!ValidQueryType(context, target))
1791 {
Jamie Madill437fa652016-05-03 15:13:24 -04001792 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04001793 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001794 }
1795
1796 if (id == 0)
1797 {
Jamie Madill437fa652016-05-03 15:13:24 -04001798 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04001799 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001800 }
1801
1802 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1803 // of zero, if the active query object name for <target> is non-zero (for the
1804 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1805 // the active query for either target is non-zero), if <id> is the name of an
1806 // existing query object whose type does not match <target>, or if <id> is the
1807 // active query object name for any query type, the error INVALID_OPERATION is
1808 // generated.
1809
1810 // Ensure no other queries are active
1811 // NOTE: If other queries than occlusion are supported, we will need to check
1812 // separately that:
1813 // a) The query ID passed is not the current active query for any target/type
1814 // b) There are no active queries for the requested target (and in the case
1815 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1816 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001817
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001818 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001819 {
Jamie Madill437fa652016-05-03 15:13:24 -04001820 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04001821 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001822 }
1823
1824 Query *queryObject = context->getQuery(id, true, target);
1825
1826 // check that name was obtained with glGenQueries
1827 if (!queryObject)
1828 {
Jamie Madill437fa652016-05-03 15:13:24 -04001829 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04001830 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001831 }
1832
1833 // check for type mismatch
1834 if (queryObject->getType() != target)
1835 {
Jamie Madill437fa652016-05-03 15:13:24 -04001836 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04001837 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001838 }
1839
1840 return true;
1841}
1842
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001843bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1844{
1845 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001846 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001847 {
Jamie Madill437fa652016-05-03 15:13:24 -04001848 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001849 return false;
1850 }
1851
1852 return ValidateBeginQueryBase(context, target, id);
1853}
1854
1855bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001856{
1857 if (!ValidQueryType(context, target))
1858 {
Jamie Madill437fa652016-05-03 15:13:24 -04001859 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04001860 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001861 }
1862
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001863 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001864
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001865 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001866 {
Jamie Madill437fa652016-05-03 15:13:24 -04001867 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04001868 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001869 }
1870
Jamie Madill45c785d2014-05-13 14:09:34 -04001871 return true;
1872}
1873
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001874bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1875{
1876 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001877 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001878 {
Jamie Madill437fa652016-05-03 15:13:24 -04001879 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001880 return false;
1881 }
1882
1883 return ValidateEndQueryBase(context, target);
1884}
1885
1886bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1887{
1888 if (!context->getExtensions().disjointTimerQuery)
1889 {
Jamie Madill437fa652016-05-03 15:13:24 -04001890 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001891 return false;
1892 }
1893
1894 if (target != GL_TIMESTAMP_EXT)
1895 {
Jamie Madill437fa652016-05-03 15:13:24 -04001896 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001897 return false;
1898 }
1899
1900 Query *queryObject = context->getQuery(id, true, target);
1901 if (queryObject == nullptr)
1902 {
Jamie Madill437fa652016-05-03 15:13:24 -04001903 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001904 return false;
1905 }
1906
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001907 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001908 {
Jamie Madill437fa652016-05-03 15:13:24 -04001909 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001910 return false;
1911 }
1912
1913 return true;
1914}
1915
Geoff Lang2186c382016-10-14 10:54:54 -04001916bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001917{
Geoff Lang2186c382016-10-14 10:54:54 -04001918 if (numParams)
1919 {
1920 *numParams = 0;
1921 }
1922
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001923 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1924 {
Jamie Madill437fa652016-05-03 15:13:24 -04001925 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001926 return false;
1927 }
1928
1929 switch (pname)
1930 {
1931 case GL_CURRENT_QUERY_EXT:
1932 if (target == GL_TIMESTAMP_EXT)
1933 {
Jamie Madill437fa652016-05-03 15:13:24 -04001934 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001935 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
1936 return false;
1937 }
1938 break;
1939 case GL_QUERY_COUNTER_BITS_EXT:
1940 if (!context->getExtensions().disjointTimerQuery ||
1941 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1942 {
Jamie Madill437fa652016-05-03 15:13:24 -04001943 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001944 return false;
1945 }
1946 break;
1947 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001948 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001949 return false;
1950 }
1951
Geoff Lang2186c382016-10-14 10:54:54 -04001952 if (numParams)
1953 {
1954 // All queries return only one value
1955 *numParams = 1;
1956 }
1957
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001958 return true;
1959}
1960
1961bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1962{
1963 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001964 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001965 {
Jamie Madill437fa652016-05-03 15:13:24 -04001966 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001967 return false;
1968 }
1969
Geoff Lang2186c382016-10-14 10:54:54 -04001970 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001971}
1972
Geoff Lang2186c382016-10-14 10:54:54 -04001973bool ValidateGetQueryivRobustANGLE(Context *context,
1974 GLenum target,
1975 GLenum pname,
1976 GLsizei bufSize,
1977 GLsizei *length,
1978 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001979{
Geoff Lang2186c382016-10-14 10:54:54 -04001980 if (!ValidateRobustEntryPoint(context, bufSize))
1981 {
1982 return false;
1983 }
1984
1985 if (!ValidateGetQueryivBase(context, target, pname, length))
1986 {
1987 return false;
1988 }
1989
1990 if (!ValidateRobustBufferSize(context, bufSize, *length))
1991 {
1992 return false;
1993 }
1994
1995 return true;
1996}
1997
1998bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1999{
2000 if (numParams)
2001 {
2002 *numParams = 0;
2003 }
2004
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002005 Query *queryObject = context->getQuery(id, false, GL_NONE);
2006
2007 if (!queryObject)
2008 {
Jamie Madill437fa652016-05-03 15:13:24 -04002009 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002010 return false;
2011 }
2012
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002013 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002014 {
Jamie Madill437fa652016-05-03 15:13:24 -04002015 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002016 return false;
2017 }
2018
2019 switch (pname)
2020 {
2021 case GL_QUERY_RESULT_EXT:
2022 case GL_QUERY_RESULT_AVAILABLE_EXT:
2023 break;
2024
2025 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002026 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002027 return false;
2028 }
2029
Geoff Lang2186c382016-10-14 10:54:54 -04002030 if (numParams)
2031 {
2032 *numParams = 1;
2033 }
2034
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002035 return true;
2036}
2037
2038bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2039{
2040 if (!context->getExtensions().disjointTimerQuery)
2041 {
Jamie Madill437fa652016-05-03 15:13:24 -04002042 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002043 return false;
2044 }
Geoff Lang2186c382016-10-14 10:54:54 -04002045 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2046}
2047
2048bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2049 GLuint id,
2050 GLenum pname,
2051 GLsizei bufSize,
2052 GLsizei *length,
2053 GLint *params)
2054{
2055 if (!context->getExtensions().disjointTimerQuery)
2056 {
2057 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2058 return false;
2059 }
2060
2061 if (!ValidateRobustEntryPoint(context, bufSize))
2062 {
2063 return false;
2064 }
2065
2066 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2067 {
2068 return false;
2069 }
2070
2071 if (!ValidateRobustBufferSize(context, bufSize, *length))
2072 {
2073 return false;
2074 }
2075
2076 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002077}
2078
2079bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2080{
2081 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002082 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002083 {
Jamie Madill437fa652016-05-03 15:13:24 -04002084 context->handleError(Error(GL_INVALID_OPERATION, "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 ValidateGetQueryObjectuivRobustANGLE(Context *context,
2091 GLuint id,
2092 GLenum pname,
2093 GLsizei bufSize,
2094 GLsizei *length,
2095 GLuint *params)
2096{
2097 if (!context->getExtensions().disjointTimerQuery &&
2098 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2099 {
2100 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2101 return false;
2102 }
2103
2104 if (!ValidateRobustEntryPoint(context, bufSize))
2105 {
2106 return false;
2107 }
2108
2109 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2110 {
2111 return false;
2112 }
2113
2114 if (!ValidateRobustBufferSize(context, bufSize, *length))
2115 {
2116 return false;
2117 }
2118
2119 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002120}
2121
2122bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2123{
2124 if (!context->getExtensions().disjointTimerQuery)
2125 {
Jamie Madill437fa652016-05-03 15:13:24 -04002126 context->handleError(Error(GL_INVALID_OPERATION, "Timer 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 ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2133 GLuint id,
2134 GLenum pname,
2135 GLsizei bufSize,
2136 GLsizei *length,
2137 GLint64 *params)
2138{
2139 if (!context->getExtensions().disjointTimerQuery)
2140 {
2141 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2142 return false;
2143 }
2144
2145 if (!ValidateRobustEntryPoint(context, bufSize))
2146 {
2147 return false;
2148 }
2149
2150 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2151 {
2152 return false;
2153 }
2154
2155 if (!ValidateRobustBufferSize(context, bufSize, *length))
2156 {
2157 return false;
2158 }
2159
2160 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002161}
2162
2163bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2164{
2165 if (!context->getExtensions().disjointTimerQuery)
2166 {
Jamie Madill437fa652016-05-03 15:13:24 -04002167 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002168 return false;
2169 }
Geoff Lang2186c382016-10-14 10:54:54 -04002170 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2171}
2172
2173bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2174 GLuint id,
2175 GLenum pname,
2176 GLsizei bufSize,
2177 GLsizei *length,
2178 GLuint64 *params)
2179{
2180 if (!context->getExtensions().disjointTimerQuery)
2181 {
2182 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2183 return false;
2184 }
2185
2186 if (!ValidateRobustEntryPoint(context, bufSize))
2187 {
2188 return false;
2189 }
2190
2191 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2192 {
2193 return false;
2194 }
2195
2196 if (!ValidateRobustBufferSize(context, bufSize, *length))
2197 {
2198 return false;
2199 }
2200
2201 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002202}
2203
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002204bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002205 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002206 GLuint program,
2207 GLint location,
2208 GLsizei count)
2209{
2210 // Check for ES31 program uniform entry points
2211 if (context->getClientVersion() < Version(3, 1))
2212 {
2213 context->handleError(Error(GL_INVALID_OPERATION));
2214 return false;
2215 }
2216
2217 const LinkedUniform *uniform = nullptr;
2218 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002219 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2220 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002221}
2222
Frank Henigmana98a6472017-02-02 21:38:32 -05002223bool ValidateProgramUniform1iv(gl::Context *context,
2224 GLuint program,
2225 GLint location,
2226 GLsizei count,
2227 const GLint *value)
2228{
2229 // Check for ES31 program uniform entry points
2230 if (context->getClientVersion() < Version(3, 1))
2231 {
2232 context->handleError(Error(GL_INVALID_OPERATION));
2233 return false;
2234 }
2235
2236 const LinkedUniform *uniform = nullptr;
2237 gl::Program *programObject = GetValidProgram(context, program);
2238 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2239 ValidateUniform1ivValue(context, uniform->type, count, value);
2240}
2241
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002242bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002243 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002244 GLuint program,
2245 GLint location,
2246 GLsizei count,
2247 GLboolean transpose)
2248{
2249 // Check for ES31 program uniform entry points
2250 if (context->getClientVersion() < Version(3, 1))
2251 {
2252 context->handleError(Error(GL_INVALID_OPERATION));
2253 return false;
2254 }
2255
2256 const LinkedUniform *uniform = nullptr;
2257 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002258 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2259 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002260}
2261
Jamie Madillc1d770e2017-04-13 17:31:24 -04002262bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002263{
2264 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002265 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002266 {
Jamie Madill437fa652016-05-03 15:13:24 -04002267 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002268 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002269 }
2270
Jamie Madill62d31cb2015-09-11 13:25:51 -04002271 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002272 gl::Program *programObject = context->getGLState().getProgram();
2273 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2274 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002275}
2276
Jamie Madillbe849e42017-05-02 15:49:00 -04002277bool ValidateUniform1iv(ValidationContext *context,
2278 GLint location,
2279 GLsizei count,
2280 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002281{
2282 const LinkedUniform *uniform = nullptr;
2283 gl::Program *programObject = context->getGLState().getProgram();
2284 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2285 ValidateUniform1ivValue(context, uniform->type, count, value);
2286}
2287
Jamie Madillc1d770e2017-04-13 17:31:24 -04002288bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002289 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002290 GLint location,
2291 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002292 GLboolean transpose)
2293{
2294 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002295 int rows = VariableRowCount(valueType);
2296 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002297 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002298 {
Jamie Madill437fa652016-05-03 15:13:24 -04002299 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002300 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002301 }
2302
Martin Radev1be913c2016-07-11 17:59:16 +03002303 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002304 {
Jamie Madill437fa652016-05-03 15:13:24 -04002305 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002306 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002307 }
2308
Jamie Madill62d31cb2015-09-11 13:25:51 -04002309 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002310 gl::Program *programObject = context->getGLState().getProgram();
2311 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2312 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002313}
2314
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002315bool ValidateStateQuery(ValidationContext *context,
2316 GLenum pname,
2317 GLenum *nativeType,
2318 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002319{
2320 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2321 {
Jamie Madill437fa652016-05-03 15:13:24 -04002322 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002323 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002324 }
2325
Jamie Madill0af26e12015-03-05 19:54:33 -05002326 const Caps &caps = context->getCaps();
2327
Jamie Madill893ab082014-05-16 16:56:10 -04002328 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2329 {
2330 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2331
Jamie Madill0af26e12015-03-05 19:54:33 -05002332 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002333 {
Jamie Madill437fa652016-05-03 15:13:24 -04002334 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002335 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002336 }
2337 }
2338
2339 switch (pname)
2340 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002341 case GL_TEXTURE_BINDING_2D:
2342 case GL_TEXTURE_BINDING_CUBE_MAP:
2343 case GL_TEXTURE_BINDING_3D:
2344 case GL_TEXTURE_BINDING_2D_ARRAY:
2345 break;
2346 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2347 if (!context->getExtensions().eglStreamConsumerExternal &&
2348 !context->getExtensions().eglImageExternal)
2349 {
2350 context->handleError(Error(GL_INVALID_ENUM,
2351 "Neither NV_EGL_stream_consumer_external nor "
2352 "GL_OES_EGL_image_external extensions enabled"));
2353 return false;
2354 }
2355 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002356
He Yunchaoced53ae2016-11-29 15:00:51 +08002357 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2358 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002359 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002360 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2361 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002362 {
Jamie Madill437fa652016-05-03 15:13:24 -04002363 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002364 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002365 }
2366
Jamie Madill51f40ec2016-06-15 14:06:00 -04002367 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2368 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002369
2370 if (framebuffer->getReadBufferState() == GL_NONE)
2371 {
2372 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2373 return false;
2374 }
2375
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002376 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002377 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002378 {
Jamie Madill437fa652016-05-03 15:13:24 -04002379 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002380 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002381 }
2382 }
2383 break;
2384
He Yunchaoced53ae2016-11-29 15:00:51 +08002385 default:
2386 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002387 }
2388
2389 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002390 if (*numParams == 0)
2391 {
2392 return false;
2393 }
2394
2395 return true;
2396}
2397
2398bool ValidateRobustStateQuery(ValidationContext *context,
2399 GLenum pname,
2400 GLsizei bufSize,
2401 GLenum *nativeType,
2402 unsigned int *numParams)
2403{
2404 if (!ValidateRobustEntryPoint(context, bufSize))
2405 {
2406 return false;
2407 }
2408
2409 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2410 {
2411 return false;
2412 }
2413
2414 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002415 {
2416 return false;
2417 }
2418
2419 return true;
2420}
2421
Jamie Madillc29968b2016-01-20 11:17:23 -05002422bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2423 GLenum target,
2424 GLint level,
2425 GLenum internalformat,
2426 bool isSubImage,
2427 GLint xoffset,
2428 GLint yoffset,
2429 GLint zoffset,
2430 GLint x,
2431 GLint y,
2432 GLsizei width,
2433 GLsizei height,
2434 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002435 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002436{
Jamie Madill560a8d82014-05-21 13:06:20 -04002437 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2438 {
Jamie Madill437fa652016-05-03 15:13:24 -04002439 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002440 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002441 }
2442
He Yunchaoced53ae2016-11-29 15:00:51 +08002443 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2444 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002445 {
Jamie Madill437fa652016-05-03 15:13:24 -04002446 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002447 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002448 }
2449
2450 if (border != 0)
2451 {
Jamie Madill437fa652016-05-03 15:13:24 -04002452 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002453 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002454 }
2455
2456 if (!ValidMipLevel(context, target, level))
2457 {
Jamie Madill437fa652016-05-03 15:13:24 -04002458 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002459 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002460 }
2461
Jamie Madill51f40ec2016-06-15 14:06:00 -04002462 const auto &state = context->getGLState();
2463 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002464 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002465 {
Jamie Madill437fa652016-05-03 15:13:24 -04002466 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002467 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002468 }
2469
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002470 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002471 {
Jamie Madill437fa652016-05-03 15:13:24 -04002472 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002473 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002474 }
2475
Martin Radev138064f2016-07-15 12:03:41 +03002476 if (readFramebuffer->getReadBufferState() == GL_NONE)
2477 {
2478 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2479 return false;
2480 }
2481
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002482 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2483 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002484 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002485 // situation is an application error that would lead to a crash in ANGLE.
2486 if (readFramebuffer->getReadColorbuffer() == nullptr)
2487 {
2488 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
2489 return false;
2490 }
2491
Geoff Langaae65a42014-05-26 12:43:44 -04002492 const gl::Caps &caps = context->getCaps();
2493
Geoff Langaae65a42014-05-26 12:43:44 -04002494 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002495 switch (target)
2496 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002497 case GL_TEXTURE_2D:
2498 maxDimension = caps.max2DTextureSize;
2499 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002500
He Yunchaoced53ae2016-11-29 15:00:51 +08002501 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2502 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2503 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2504 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2505 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2506 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2507 maxDimension = caps.maxCubeMapTextureSize;
2508 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002509
He Yunchaoced53ae2016-11-29 15:00:51 +08002510 case GL_TEXTURE_2D_ARRAY:
2511 maxDimension = caps.max2DTextureSize;
2512 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002513
He Yunchaoced53ae2016-11-29 15:00:51 +08002514 case GL_TEXTURE_3D:
2515 maxDimension = caps.max3DTextureSize;
2516 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002517
He Yunchaoced53ae2016-11-29 15:00:51 +08002518 default:
2519 context->handleError(Error(GL_INVALID_ENUM));
2520 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002521 }
2522
Jamie Madillc29968b2016-01-20 11:17:23 -05002523 gl::Texture *texture =
2524 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002525 if (!texture)
2526 {
Jamie Madill437fa652016-05-03 15:13:24 -04002527 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002528 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002529 }
2530
Geoff Lang69cce582015-09-17 13:20:36 -04002531 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002532 {
Jamie Madill437fa652016-05-03 15:13:24 -04002533 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002534 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002535 }
2536
Geoff Langca271392017-04-05 12:30:00 -04002537 const gl::InternalFormat &formatInfo =
2538 gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002539
Geoff Lang966c9402017-04-18 12:38:27 -04002540 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002541 {
Jamie Madill437fa652016-05-03 15:13:24 -04002542 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002543 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002544 }
2545
2546 if (isSubImage)
2547 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002548 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2549 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2550 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002551 {
Jamie Madill437fa652016-05-03 15:13:24 -04002552 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002553 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002554 }
2555 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002556 else
2557 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002558 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002559 {
Jamie Madill437fa652016-05-03 15:13:24 -04002560 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002561 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002562 }
2563
Geoff Langeb66a6e2016-10-31 13:06:12 -04002564 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002565 {
Jamie Madill437fa652016-05-03 15:13:24 -04002566 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002567 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002568 }
2569
2570 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002571 if (static_cast<int>(width) > maxLevelDimension ||
2572 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002573 {
Jamie Madill437fa652016-05-03 15:13:24 -04002574 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002575 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002576 }
2577 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002578
Jamie Madill0c8abca2016-07-22 20:21:26 -04002579 if (textureFormatOut)
2580 {
2581 *textureFormatOut = texture->getFormat(target, level);
2582 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002583
2584 // Detect texture copying feedback loops for WebGL.
2585 if (context->getExtensions().webglCompatibility)
2586 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002587 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002588 {
2589 context->handleError(Error(GL_INVALID_OPERATION,
2590 "Texture copying feedback loop formed between Framebuffer "
2591 "and specified Texture level."));
2592 return false;
2593 }
2594 }
2595
Jamie Madill560a8d82014-05-21 13:06:20 -04002596 return true;
2597}
2598
Jiajia Qind9671222016-11-29 16:30:31 +08002599bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002600{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002601 switch (mode)
2602 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002603 case GL_POINTS:
2604 case GL_LINES:
2605 case GL_LINE_LOOP:
2606 case GL_LINE_STRIP:
2607 case GL_TRIANGLES:
2608 case GL_TRIANGLE_STRIP:
2609 case GL_TRIANGLE_FAN:
2610 break;
2611 default:
2612 context->handleError(Error(GL_INVALID_ENUM));
2613 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002614 }
2615
Jamie Madill250d33f2014-06-06 17:09:03 -04002616 if (count < 0)
2617 {
Jamie Madill437fa652016-05-03 15:13:24 -04002618 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002619 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002620 }
2621
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002622 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002623
Jamie Madill250d33f2014-06-06 17:09:03 -04002624 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002625 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002626 {
Jamie Madill437fa652016-05-03 15:13:24 -04002627 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002628 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002629 }
2630
Jamie Madillcbcde722017-01-06 14:50:00 -05002631 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2632 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002633 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002634 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
2635 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002636 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002637 const FramebufferAttachment *dsAttachment =
2638 framebuffer->getStencilOrDepthStencilAttachment();
2639 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002640 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002641 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002642
2643 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2644 bool differentWritemasks =
2645 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2646 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2647 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2648 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2649
2650 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002651 {
Jamie Madillcbcde722017-01-06 14:50:00 -05002652 if (!context->getExtensions().webglCompatibility)
2653 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002654 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2655 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002656 }
Jamie Madill437fa652016-05-03 15:13:24 -04002657 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04002658 return false;
2659 }
Jamie Madillac528012014-06-20 13:21:23 -04002660 }
2661
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002662 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002663 {
Jamie Madill437fa652016-05-03 15:13:24 -04002664 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002665 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002666 }
2667
Geoff Lang7dd2e102014-11-10 15:19:26 -05002668 gl::Program *program = state.getProgram();
2669 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002670 {
Jamie Madill437fa652016-05-03 15:13:24 -04002671 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002672 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002673 }
2674
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002675 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002676 {
Jamie Madill437fa652016-05-03 15:13:24 -04002677 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002678 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002679 }
2680
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002681 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002682 for (unsigned int uniformBlockIndex = 0;
2683 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002684 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002685 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002686 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002687 const OffsetBindingPointer<Buffer> &uniformBuffer =
2688 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002689
Geoff Lang5d124a62015-09-15 13:03:27 -04002690 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002691 {
2692 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002693 context->handleError(
2694 Error(GL_INVALID_OPERATION,
2695 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002696 return false;
2697 }
2698
Geoff Lang5d124a62015-09-15 13:03:27 -04002699 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002700 if (uniformBufferSize == 0)
2701 {
2702 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002703 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002704 }
2705
Jamie Madill62d31cb2015-09-11 13:25:51 -04002706 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002707 {
2708 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002709 context->handleError(
2710 Error(GL_INVALID_OPERATION,
2711 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002712 return false;
2713 }
2714 }
2715
Jamie Madilla4595b82017-01-11 17:36:34 -05002716 // Detect rendering feedback loops for WebGL.
2717 if (context->getExtensions().webglCompatibility)
2718 {
2719 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2720 {
2721 context->handleError(
2722 Error(GL_INVALID_OPERATION,
2723 "Rendering feedback loop formed between Framebuffer and active Texture."));
2724 return false;
2725 }
2726 }
2727
Jamie Madill250d33f2014-06-06 17:09:03 -04002728 // No-op if zero count
2729 return (count > 0);
2730}
2731
Jamie Madillc1d770e2017-04-13 17:31:24 -04002732bool ValidateDrawArraysCommon(ValidationContext *context,
2733 GLenum mode,
2734 GLint first,
2735 GLsizei count,
2736 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002737{
Jamie Madillfd716582014-06-06 17:09:04 -04002738 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002739 {
Jamie Madill437fa652016-05-03 15:13:24 -04002740 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002741 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002742 }
2743
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002744 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002745 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002746 if (curTransformFeedback && curTransformFeedback->isActive() &&
2747 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002748 {
2749 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002750 // that does not match the current transform feedback object's draw mode (if transform
2751 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002752 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002753 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002754 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002755 }
2756
Jiajia Qind9671222016-11-29 16:30:31 +08002757 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002758 {
2759 return false;
2760 }
2761
Corentin Wallez71168a02016-12-19 15:11:18 -08002762 // Check the computation of maxVertex doesn't overflow.
2763 // - first < 0 or count < 0 have been checked as an error condition
2764 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2765 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2766 ASSERT(count > 0 && first >= 0);
2767 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2768 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002769 {
2770 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
2771 return false;
2772 }
2773
Corentin Wallez71168a02016-12-19 15:11:18 -08002774 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002775 {
2776 return false;
2777 }
2778
2779 return true;
2780}
2781
He Yunchaoced53ae2016-11-29 15:00:51 +08002782bool ValidateDrawArraysInstanced(Context *context,
2783 GLenum mode,
2784 GLint first,
2785 GLsizei count,
2786 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002787{
Geoff Lang407d4e72017-04-12 14:54:11 -04002788 if (context->getExtensions().webglCompatibility && !ValidateDrawInstancedANGLEAndWebGL(context))
Jamie Madillfd716582014-06-06 17:09:04 -04002789 {
2790 return false;
2791 }
2792
Geoff Lang407d4e72017-04-12 14:54:11 -04002793 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
Geoff Lang87a93302014-09-16 13:29:43 -04002794}
2795
He Yunchaoced53ae2016-11-29 15:00:51 +08002796bool ValidateDrawArraysInstancedANGLE(Context *context,
2797 GLenum mode,
2798 GLint first,
2799 GLsizei count,
2800 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002801{
Geoff Lang407d4e72017-04-12 14:54:11 -04002802 if (!ValidateDrawInstancedANGLEAndWebGL(context))
Geoff Lang87a93302014-09-16 13:29:43 -04002803 {
2804 return false;
2805 }
2806
Geoff Lang407d4e72017-04-12 14:54:11 -04002807 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
Geoff Lang87a93302014-09-16 13:29:43 -04002808}
2809
Jiajia Qind9671222016-11-29 16:30:31 +08002810bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002811{
Jamie Madill250d33f2014-06-06 17:09:03 -04002812 switch (type)
2813 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002814 case GL_UNSIGNED_BYTE:
2815 case GL_UNSIGNED_SHORT:
2816 break;
2817 case GL_UNSIGNED_INT:
2818 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2819 {
2820 context->handleError(Error(GL_INVALID_ENUM));
2821 return false;
2822 }
2823 break;
2824 default:
2825 context->handleError(Error(GL_INVALID_ENUM));
2826 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002827 }
2828
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002829 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002830
2831 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002832 if (curTransformFeedback && curTransformFeedback->isActive() &&
2833 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002834 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002835 // It is an invalid operation to call DrawElements, DrawRangeElements or
2836 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002837 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002838 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002839 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002840 }
2841
Jiajia Qind9671222016-11-29 16:30:31 +08002842 return true;
2843}
2844
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002845bool ValidateDrawElementsCommon(ValidationContext *context,
2846 GLenum mode,
2847 GLsizei count,
2848 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002849 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002850 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002851{
2852 if (!ValidateDrawElementsBase(context, type))
2853 return false;
2854
2855 const State &state = context->getGLState();
2856
Jamie Madill250d33f2014-06-06 17:09:03 -04002857 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002858 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002859 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002860 context->handleError(Error(GL_INVALID_OPERATION, "Index buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -04002861 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002862 }
2863
He Yunchaoced53ae2016-11-29 15:00:51 +08002864 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002865 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002866
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002867 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2868
2869 if (context->getExtensions().webglCompatibility)
2870 {
2871 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2872 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2873 {
2874 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2875 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2876 // data type passed to the call, or an INVALID_OPERATION error is generated.
2877 context->handleError(Error(GL_INVALID_OPERATION,
2878 "indices must be a multiple of the element type size."));
2879 return false;
2880 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002881
2882 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2883 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2884 // error is generated.
2885 if (reinterpret_cast<intptr_t>(indices) < 0)
2886 {
2887 context->handleError(Error(GL_INVALID_VALUE, "Offset < 0."));
2888 return false;
2889 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002890 }
2891
2892 if (context->getExtensions().webglCompatibility ||
2893 !context->getGLState().areClientArraysEnabled())
2894 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002895 if (!elementArrayBuffer && count > 0)
2896 {
2897 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2898 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2899 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
2900 context->handleError(Error(GL_INVALID_OPERATION,
2901 "There is no element array buffer bound and count > 0."));
2902 return false;
2903 }
2904 }
2905
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002906 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002907 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002908 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002909 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002910 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2911 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2912 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2913 constexpr uint64_t kMaxTypeSize = 8;
2914 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2915 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2916 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002917
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002918 uint64_t typeSize = typeBytes;
2919 uint64_t elementCount = static_cast<uint64_t>(count);
2920 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2921
2922 // Doing the multiplication here is overflow-safe
2923 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2924
2925 // The offset can be any value, check for overflows
2926 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2927 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002928 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002929 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002930 return false;
2931 }
2932
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002933 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2934 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002935 {
2936 context->handleError(
2937 Error(GL_INVALID_OPERATION, "Index buffer is not big enough for the draw."));
2938 return false;
2939 }
2940 }
2941 else if (!indices)
2942 {
2943 // This is an application error that would normally result in a crash,
2944 // but we catch it and return an error
2945 context->handleError(
2946 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04002947 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002948 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002949 }
2950
Jiajia Qind9671222016-11-29 16:30:31 +08002951 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002952 {
2953 return false;
2954 }
2955
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002956 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill2b976812014-08-25 15:47:49 -04002957 // TODO: offer fast path, with disabled index validation.
2958 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002959 const auto &params = context->getParams<HasIndexRange>();
2960 const auto &indexRangeOpt = params.getIndexRange();
2961 if (!indexRangeOpt.valid())
Jamie Madill2b976812014-08-25 15:47:49 -04002962 {
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002963 // Unexpected error.
2964 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04002965 }
2966
Jamie Madille79b1e12015-11-04 16:36:37 -05002967 // If we use an index greater than our maximum supported index range, return an error.
2968 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2969 // return an error if possible here.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002970 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
Jamie Madille79b1e12015-11-04 16:36:37 -05002971 {
Jamie Madill437fa652016-05-03 15:13:24 -04002972 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05002973 return false;
2974 }
2975
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002976 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2977 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04002978 {
2979 return false;
2980 }
2981
Geoff Lang3edfe032015-09-04 16:38:24 -04002982 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002983 return (indexRangeOpt.value().vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04002984}
2985
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002986bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2987 GLenum mode,
2988 GLsizei count,
2989 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002990 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002991 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002992{
Geoff Lang407d4e72017-04-12 14:54:11 -04002993 if (context->getExtensions().webglCompatibility && !ValidateDrawInstancedANGLEAndWebGL(context))
Jamie Madillfd716582014-06-06 17:09:04 -04002994 {
2995 return false;
2996 }
2997
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002998 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002999}
3000
Geoff Lang3edfe032015-09-04 16:38:24 -04003001bool ValidateDrawElementsInstancedANGLE(Context *context,
3002 GLenum mode,
3003 GLsizei count,
3004 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003005 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003006 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003007{
Geoff Lang407d4e72017-04-12 14:54:11 -04003008 if (!ValidateDrawInstancedANGLEAndWebGL(context))
Geoff Lang87a93302014-09-16 13:29:43 -04003009 {
3010 return false;
3011 }
3012
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003013 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Geoff Lang87a93302014-09-16 13:29:43 -04003014}
3015
He Yunchaoced53ae2016-11-29 15:00:51 +08003016bool ValidateFramebufferTextureBase(Context *context,
3017 GLenum target,
3018 GLenum attachment,
3019 GLuint texture,
3020 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003021{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003022 if (!ValidFramebufferTarget(target))
3023 {
Jamie Madill437fa652016-05-03 15:13:24 -04003024 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003025 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003026 }
3027
3028 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003029 {
3030 return false;
3031 }
3032
Jamie Madill55ec3b12014-07-03 10:38:57 -04003033 if (texture != 0)
3034 {
3035 gl::Texture *tex = context->getTexture(texture);
3036
Jamie Madillbe849e42017-05-02 15:49:00 -04003037 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003038 {
Jamie Madill437fa652016-05-03 15:13:24 -04003039 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003040 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003041 }
3042
3043 if (level < 0)
3044 {
Jamie Madill437fa652016-05-03 15:13:24 -04003045 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003046 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003047 }
3048 }
3049
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003050 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003051 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003052
Jamie Madill84115c92015-04-23 15:00:07 -04003053 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003054 {
Jamie Madill437fa652016-05-03 15:13:24 -04003055 context->handleError(
3056 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003057 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003058 }
3059
3060 return true;
3061}
3062
Geoff Langb1196682014-07-23 13:47:29 -04003063bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003064{
3065 if (program == 0)
3066 {
Jamie Madill437fa652016-05-03 15:13:24 -04003067 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003068 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003069 }
3070
Dian Xiang769769a2015-09-09 15:20:08 -07003071 gl::Program *programObject = GetValidProgram(context, program);
3072 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003073 {
3074 return false;
3075 }
3076
Jamie Madill0063c512014-08-25 15:47:53 -04003077 if (!programObject || !programObject->isLinked())
3078 {
Jamie Madill437fa652016-05-03 15:13:24 -04003079 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003080 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003081 }
3082
Geoff Lang7dd2e102014-11-10 15:19:26 -05003083 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003084 {
Jamie Madill437fa652016-05-03 15:13:24 -04003085 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003086 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003087 }
3088
Jamie Madill0063c512014-08-25 15:47:53 -04003089 return true;
3090}
3091
Geoff Langf41d0ee2016-10-07 13:04:23 -04003092static bool ValidateSizedGetUniform(Context *context,
3093 GLuint program,
3094 GLint location,
3095 GLsizei bufSize,
3096 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003097{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003098 if (length)
3099 {
3100 *length = 0;
3101 }
3102
Jamie Madill78f41802014-08-25 15:47:55 -04003103 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003104 {
Jamie Madill78f41802014-08-25 15:47:55 -04003105 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003106 }
3107
Geoff Langf41d0ee2016-10-07 13:04:23 -04003108 if (bufSize < 0)
3109 {
3110 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3111 return false;
3112 }
3113
Jamie Madilla502c742014-08-28 17:19:13 -04003114 gl::Program *programObject = context->getProgram(program);
3115 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003116
Jamie Madill78f41802014-08-25 15:47:55 -04003117 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003118 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003119 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003120 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003121 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003122 context->handleError(
3123 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003124 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003125 }
3126
Geoff Langf41d0ee2016-10-07 13:04:23 -04003127 if (length)
3128 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003129 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003130 }
3131
Jamie Madill0063c512014-08-25 15:47:53 -04003132 return true;
3133}
3134
He Yunchaoced53ae2016-11-29 15:00:51 +08003135bool ValidateGetnUniformfvEXT(Context *context,
3136 GLuint program,
3137 GLint location,
3138 GLsizei bufSize,
3139 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003140{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003141 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003142}
3143
He Yunchaoced53ae2016-11-29 15:00:51 +08003144bool ValidateGetnUniformivEXT(Context *context,
3145 GLuint program,
3146 GLint location,
3147 GLsizei bufSize,
3148 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003149{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003150 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3151}
3152
3153bool ValidateGetUniformfvRobustANGLE(Context *context,
3154 GLuint program,
3155 GLint location,
3156 GLsizei bufSize,
3157 GLsizei *length,
3158 GLfloat *params)
3159{
3160 if (!ValidateRobustEntryPoint(context, bufSize))
3161 {
3162 return false;
3163 }
3164
3165 // bufSize is validated in ValidateSizedGetUniform
3166 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3167}
3168
3169bool ValidateGetUniformivRobustANGLE(Context *context,
3170 GLuint program,
3171 GLint location,
3172 GLsizei bufSize,
3173 GLsizei *length,
3174 GLint *params)
3175{
3176 if (!ValidateRobustEntryPoint(context, bufSize))
3177 {
3178 return false;
3179 }
3180
3181 // bufSize is validated in ValidateSizedGetUniform
3182 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3183}
3184
3185bool ValidateGetUniformuivRobustANGLE(Context *context,
3186 GLuint program,
3187 GLint location,
3188 GLsizei bufSize,
3189 GLsizei *length,
3190 GLuint *params)
3191{
3192 if (!ValidateRobustEntryPoint(context, bufSize))
3193 {
3194 return false;
3195 }
3196
3197 if (context->getClientMajorVersion() < 3)
3198 {
3199 context->handleError(
3200 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3201 return false;
3202 }
3203
3204 // bufSize is validated in ValidateSizedGetUniform
3205 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003206}
3207
He Yunchaoced53ae2016-11-29 15:00:51 +08003208bool ValidateDiscardFramebufferBase(Context *context,
3209 GLenum target,
3210 GLsizei numAttachments,
3211 const GLenum *attachments,
3212 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003213{
3214 if (numAttachments < 0)
3215 {
Jamie Madill437fa652016-05-03 15:13:24 -04003216 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003217 return false;
3218 }
3219
3220 for (GLsizei i = 0; i < numAttachments; ++i)
3221 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003222 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003223 {
3224 if (defaultFramebuffer)
3225 {
Jamie Madill437fa652016-05-03 15:13:24 -04003226 context->handleError(Error(
3227 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003228 return false;
3229 }
3230
3231 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3232 {
Jamie Madill437fa652016-05-03 15:13:24 -04003233 context->handleError(Error(GL_INVALID_OPERATION,
3234 "Requested color attachment is greater than the maximum "
3235 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003236 return false;
3237 }
3238 }
3239 else
3240 {
3241 switch (attachments[i])
3242 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003243 case GL_DEPTH_ATTACHMENT:
3244 case GL_STENCIL_ATTACHMENT:
3245 case GL_DEPTH_STENCIL_ATTACHMENT:
3246 if (defaultFramebuffer)
3247 {
3248 context->handleError(
3249 Error(GL_INVALID_ENUM,
3250 "Invalid attachment when the default framebuffer is bound"));
3251 return false;
3252 }
3253 break;
3254 case GL_COLOR:
3255 case GL_DEPTH:
3256 case GL_STENCIL:
3257 if (!defaultFramebuffer)
3258 {
3259 context->handleError(
3260 Error(GL_INVALID_ENUM,
3261 "Invalid attachment when the default framebuffer is not bound"));
3262 return false;
3263 }
3264 break;
3265 default:
3266 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003267 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003268 }
3269 }
3270 }
3271
3272 return true;
3273}
3274
Austin Kinross6ee1e782015-05-29 17:05:37 -07003275bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3276{
3277 // Note that debug marker calls must not set error state
3278
3279 if (length < 0)
3280 {
3281 return false;
3282 }
3283
3284 if (marker == nullptr)
3285 {
3286 return false;
3287 }
3288
3289 return true;
3290}
3291
3292bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3293{
3294 // Note that debug marker calls must not set error state
3295
3296 if (length < 0)
3297 {
3298 return false;
3299 }
3300
3301 if (length > 0 && marker == nullptr)
3302 {
3303 return false;
3304 }
3305
3306 return true;
3307}
3308
Geoff Langdcab33b2015-07-21 13:03:16 -04003309bool ValidateEGLImageTargetTexture2DOES(Context *context,
3310 egl::Display *display,
3311 GLenum target,
3312 egl::Image *image)
3313{
Geoff Langa8406172015-07-21 16:53:39 -04003314 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3315 {
Jamie Madill437fa652016-05-03 15:13:24 -04003316 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003317 return false;
3318 }
3319
3320 switch (target)
3321 {
3322 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003323 if (!context->getExtensions().eglImage)
3324 {
3325 context->handleError(Error(
3326 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3327 }
3328 break;
3329
3330 case GL_TEXTURE_EXTERNAL_OES:
3331 if (!context->getExtensions().eglImageExternal)
3332 {
3333 context->handleError(Error(
3334 GL_INVALID_ENUM,
3335 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3336 }
Geoff Langa8406172015-07-21 16:53:39 -04003337 break;
3338
3339 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003340 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003341 return false;
3342 }
3343
3344 if (!display->isValidImage(image))
3345 {
Jamie Madill437fa652016-05-03 15:13:24 -04003346 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003347 return false;
3348 }
3349
3350 if (image->getSamples() > 0)
3351 {
Jamie Madill437fa652016-05-03 15:13:24 -04003352 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003353 "cannot create a 2D texture from a multisampled EGL image."));
3354 return false;
3355 }
3356
Geoff Langca271392017-04-05 12:30:00 -04003357 const TextureCaps &textureCaps =
3358 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003359 if (!textureCaps.texturable)
3360 {
Jamie Madill437fa652016-05-03 15:13:24 -04003361 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003362 "EGL image internal format is not supported as a texture."));
3363 return false;
3364 }
3365
Geoff Langdcab33b2015-07-21 13:03:16 -04003366 return true;
3367}
3368
3369bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3370 egl::Display *display,
3371 GLenum target,
3372 egl::Image *image)
3373{
Geoff Langa8406172015-07-21 16:53:39 -04003374 if (!context->getExtensions().eglImage)
3375 {
Jamie Madill437fa652016-05-03 15:13:24 -04003376 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003377 return false;
3378 }
3379
3380 switch (target)
3381 {
3382 case GL_RENDERBUFFER:
3383 break;
3384
3385 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003386 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003387 return false;
3388 }
3389
3390 if (!display->isValidImage(image))
3391 {
Jamie Madill437fa652016-05-03 15:13:24 -04003392 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003393 return false;
3394 }
3395
Geoff Langca271392017-04-05 12:30:00 -04003396 const TextureCaps &textureCaps =
3397 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003398 if (!textureCaps.renderable)
3399 {
Jamie Madill437fa652016-05-03 15:13:24 -04003400 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003401 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3402 return false;
3403 }
3404
Geoff Langdcab33b2015-07-21 13:03:16 -04003405 return true;
3406}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003407
3408bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3409{
Geoff Lang36167ab2015-12-07 10:27:14 -05003410 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003411 {
3412 // The default VAO should always exist
3413 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003414 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003415 return false;
3416 }
3417
3418 return true;
3419}
3420
Geoff Langc5629752015-12-07 16:29:04 -05003421bool ValidateProgramBinaryBase(Context *context,
3422 GLuint program,
3423 GLenum binaryFormat,
3424 const void *binary,
3425 GLint length)
3426{
3427 Program *programObject = GetValidProgram(context, program);
3428 if (programObject == nullptr)
3429 {
3430 return false;
3431 }
3432
3433 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3434 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3435 programBinaryFormats.end())
3436 {
Jamie Madill437fa652016-05-03 15:13:24 -04003437 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05003438 return false;
3439 }
3440
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003441 if (context->hasActiveTransformFeedback(program))
3442 {
3443 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003444 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003445 "Cannot change program binary while program is associated with "
3446 "an active transform feedback object."));
3447 return false;
3448 }
3449
Geoff Langc5629752015-12-07 16:29:04 -05003450 return true;
3451}
3452
3453bool ValidateGetProgramBinaryBase(Context *context,
3454 GLuint program,
3455 GLsizei bufSize,
3456 GLsizei *length,
3457 GLenum *binaryFormat,
3458 void *binary)
3459{
3460 Program *programObject = GetValidProgram(context, program);
3461 if (programObject == nullptr)
3462 {
3463 return false;
3464 }
3465
3466 if (!programObject->isLinked())
3467 {
Jamie Madill437fa652016-05-03 15:13:24 -04003468 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05003469 return false;
3470 }
3471
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003472 if (context->getCaps().programBinaryFormats.empty())
3473 {
3474 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
3475 return false;
3476 }
3477
Geoff Langc5629752015-12-07 16:29:04 -05003478 return true;
3479}
Jamie Madillc29968b2016-01-20 11:17:23 -05003480
Jamie Madillc29968b2016-01-20 11:17:23 -05003481bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3482{
3483 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3484 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3485 {
Jamie Madill437fa652016-05-03 15:13:24 -04003486 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003487 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
3488 return false;
3489 }
3490
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003491 ASSERT(context->getGLState().getDrawFramebuffer());
3492 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003493 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3494
3495 // This should come first before the check for the default frame buffer
3496 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3497 // rather than INVALID_OPERATION
3498 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3499 {
3500 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3501
3502 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003503 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3504 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003505 {
3506 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003507 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3508 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3509 // 3.1 is still a bit ambiguous about the error, but future specs are
3510 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04003511 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02003512 return false;
3513 }
3514 else if (bufs[colorAttachment] >= maxColorAttachment)
3515 {
Jamie Madill437fa652016-05-03 15:13:24 -04003516 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02003517 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05003518 return false;
3519 }
3520 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3521 frameBufferId != 0)
3522 {
3523 // INVALID_OPERATION-GL is bound to buffer and ith argument
3524 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04003525 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003526 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
3527 return false;
3528 }
3529 }
3530
3531 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3532 // and n is not 1 or bufs is bound to value other than BACK and NONE
3533 if (frameBufferId == 0)
3534 {
3535 if (n != 1)
3536 {
Jamie Madill437fa652016-05-03 15:13:24 -04003537 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05003538 "n must be 1 when GL is bound to the default framebuffer"));
3539 return false;
3540 }
3541
3542 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3543 {
Jamie Madill437fa652016-05-03 15:13:24 -04003544 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05003545 GL_INVALID_OPERATION,
3546 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
3547 return false;
3548 }
3549 }
3550
3551 return true;
3552}
3553
Geoff Lang496c02d2016-10-20 11:38:11 -07003554bool ValidateGetBufferPointervBase(Context *context,
3555 GLenum target,
3556 GLenum pname,
3557 GLsizei *length,
3558 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003559{
Geoff Lang496c02d2016-10-20 11:38:11 -07003560 if (length)
3561 {
3562 *length = 0;
3563 }
3564
3565 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3566 {
3567 context->handleError(
3568 Error(GL_INVALID_OPERATION,
Jamie Madillcc6ac252017-01-25 12:57:21 -08003569 "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
Geoff Lang496c02d2016-10-20 11:38:11 -07003570 return false;
3571 }
3572
Olli Etuaho4f667482016-03-30 15:56:35 +03003573 if (!ValidBufferTarget(context, target))
3574 {
Jamie Madill437fa652016-05-03 15:13:24 -04003575 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03003576 return false;
3577 }
3578
Geoff Lang496c02d2016-10-20 11:38:11 -07003579 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003580 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003581 case GL_BUFFER_MAP_POINTER:
3582 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003583
Geoff Lang496c02d2016-10-20 11:38:11 -07003584 default:
3585 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
3586 return false;
3587 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003588
3589 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3590 // target bound to zero generate an INVALID_OPERATION error."
3591 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003592 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003593 {
Jamie Madill437fa652016-05-03 15:13:24 -04003594 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003595 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
3596 return false;
3597 }
3598
Geoff Lang496c02d2016-10-20 11:38:11 -07003599 if (length)
3600 {
3601 *length = 1;
3602 }
3603
Olli Etuaho4f667482016-03-30 15:56:35 +03003604 return true;
3605}
3606
3607bool ValidateUnmapBufferBase(Context *context, GLenum target)
3608{
3609 if (!ValidBufferTarget(context, target))
3610 {
Jamie Madill437fa652016-05-03 15:13:24 -04003611 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003612 return false;
3613 }
3614
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003615 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003616
3617 if (buffer == nullptr || !buffer->isMapped())
3618 {
Jamie Madill437fa652016-05-03 15:13:24 -04003619 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003620 return false;
3621 }
3622
3623 return true;
3624}
3625
3626bool ValidateMapBufferRangeBase(Context *context,
3627 GLenum target,
3628 GLintptr offset,
3629 GLsizeiptr length,
3630 GLbitfield access)
3631{
3632 if (!ValidBufferTarget(context, target))
3633 {
Jamie Madill437fa652016-05-03 15:13:24 -04003634 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003635 return false;
3636 }
3637
3638 if (offset < 0 || length < 0)
3639 {
Jamie Madill437fa652016-05-03 15:13:24 -04003640 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003641 return false;
3642 }
3643
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003644 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003645
3646 if (!buffer)
3647 {
Jamie Madill437fa652016-05-03 15:13:24 -04003648 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003649 return false;
3650 }
3651
3652 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003653 CheckedNumeric<size_t> checkedOffset(offset);
3654 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003655
Jamie Madille2e406c2016-06-02 13:04:10 -04003656 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003657 {
Jamie Madill437fa652016-05-03 15:13:24 -04003658 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003659 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
3660 return false;
3661 }
3662
3663 // Check for invalid bits in the mask
3664 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3665 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3666 GL_MAP_UNSYNCHRONIZED_BIT;
3667
3668 if (access & ~(allAccessBits))
3669 {
Jamie Madill437fa652016-05-03 15:13:24 -04003670 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03003671 return false;
3672 }
3673
3674 if (length == 0)
3675 {
Jamie Madill437fa652016-05-03 15:13:24 -04003676 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003677 return false;
3678 }
3679
3680 if (buffer->isMapped())
3681 {
Jamie Madill437fa652016-05-03 15:13:24 -04003682 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003683 return false;
3684 }
3685
3686 // Check for invalid bit combinations
3687 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3688 {
Jamie Madill437fa652016-05-03 15:13:24 -04003689 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003690 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
3691 return false;
3692 }
3693
3694 GLbitfield writeOnlyBits =
3695 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3696
3697 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3698 {
Jamie Madill437fa652016-05-03 15:13:24 -04003699 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03003700 "Invalid access bits when mapping buffer for reading: 0x%X.",
3701 access));
3702 return false;
3703 }
3704
3705 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3706 {
Jamie Madill437fa652016-05-03 15:13:24 -04003707 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003708 GL_INVALID_OPERATION,
3709 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
3710 return false;
3711 }
3712 return true;
3713}
3714
3715bool ValidateFlushMappedBufferRangeBase(Context *context,
3716 GLenum target,
3717 GLintptr offset,
3718 GLsizeiptr length)
3719{
3720 if (offset < 0 || length < 0)
3721 {
Jamie Madill437fa652016-05-03 15:13:24 -04003722 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003723 return false;
3724 }
3725
3726 if (!ValidBufferTarget(context, target))
3727 {
Jamie Madill437fa652016-05-03 15:13:24 -04003728 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003729 return false;
3730 }
3731
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003732 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003733
3734 if (buffer == nullptr)
3735 {
Jamie Madill437fa652016-05-03 15:13:24 -04003736 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003737 return false;
3738 }
3739
3740 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3741 {
Jamie Madill437fa652016-05-03 15:13:24 -04003742 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003743 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
3744 return false;
3745 }
3746
3747 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003748 CheckedNumeric<size_t> checkedOffset(offset);
3749 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003750
Jamie Madille2e406c2016-06-02 13:04:10 -04003751 if (!checkedSize.IsValid() ||
3752 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003753 {
Jamie Madill437fa652016-05-03 15:13:24 -04003754 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003755 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
3756 return false;
3757 }
3758
3759 return true;
3760}
3761
Olli Etuaho41997e72016-03-10 13:38:39 +02003762bool ValidateGenOrDelete(Context *context, GLint n)
3763{
3764 if (n < 0)
3765 {
Jamie Madill437fa652016-05-03 15:13:24 -04003766 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02003767 return false;
3768 }
3769 return true;
3770}
3771
Geoff Langff5b2d52016-09-07 11:32:23 -04003772bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3773{
3774 if (!context->getExtensions().robustClientMemory)
3775 {
3776 context->handleError(
3777 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
3778 return false;
3779 }
3780
3781 if (bufSize < 0)
3782 {
3783 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3784 return false;
3785 }
3786
3787 return true;
3788}
3789
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003790bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3791{
3792 if (bufSize < numParams)
3793 {
3794 context->handleError(Error(GL_INVALID_OPERATION,
3795 "%u parameters are required but %i were provided.", numParams,
3796 bufSize));
3797 return false;
3798 }
3799
3800 return true;
3801}
3802
Jamie Madillbe849e42017-05-02 15:49:00 -04003803bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3804 GLenum target,
3805 GLenum attachment,
3806 GLenum pname,
3807 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003808{
3809 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
Yunchao He33151a52017-04-13 09:58:17 +08003810 if (numParams)
3811 {
3812 *numParams = 1;
3813 }
Geoff Langff5b2d52016-09-07 11:32:23 -04003814
3815 if (!ValidFramebufferTarget(target))
3816 {
3817 context->handleError(Error(GL_INVALID_ENUM));
3818 return false;
3819 }
3820
3821 int clientVersion = context->getClientMajorVersion();
3822
3823 switch (pname)
3824 {
3825 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3826 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3827 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3828 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3829 break;
3830
3831 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3832 if (clientVersion < 3 && !context->getExtensions().sRGB)
3833 {
3834 context->handleError(Error(GL_INVALID_ENUM));
3835 return false;
3836 }
3837 break;
3838
3839 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3840 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3841 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3842 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3843 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3844 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3845 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3846 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3847 if (clientVersion < 3)
3848 {
3849 context->handleError(Error(GL_INVALID_ENUM));
3850 return false;
3851 }
3852 break;
3853
3854 default:
3855 context->handleError(Error(GL_INVALID_ENUM));
3856 return false;
3857 }
3858
3859 // Determine if the attachment is a valid enum
3860 switch (attachment)
3861 {
3862 case GL_BACK:
3863 case GL_FRONT:
3864 case GL_DEPTH:
3865 case GL_STENCIL:
3866 case GL_DEPTH_STENCIL_ATTACHMENT:
3867 if (clientVersion < 3)
3868 {
3869 context->handleError(Error(GL_INVALID_ENUM));
3870 return false;
3871 }
3872 break;
3873
3874 case GL_DEPTH_ATTACHMENT:
3875 case GL_STENCIL_ATTACHMENT:
3876 break;
3877
3878 default:
3879 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
3880 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3881 {
3882 context->handleError(Error(GL_INVALID_ENUM));
3883 return false;
3884 }
3885 break;
3886 }
3887
3888 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3889 ASSERT(framebuffer);
3890
3891 if (framebuffer->id() == 0)
3892 {
3893 if (clientVersion < 3)
3894 {
3895 context->handleError(Error(GL_INVALID_OPERATION));
3896 return false;
3897 }
3898
3899 switch (attachment)
3900 {
3901 case GL_BACK:
3902 case GL_DEPTH:
3903 case GL_STENCIL:
3904 break;
3905
3906 default:
3907 context->handleError(Error(GL_INVALID_OPERATION));
3908 return false;
3909 }
3910 }
3911 else
3912 {
3913 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3914 {
3915 // Valid attachment query
3916 }
3917 else
3918 {
3919 switch (attachment)
3920 {
3921 case GL_DEPTH_ATTACHMENT:
3922 case GL_STENCIL_ATTACHMENT:
3923 break;
3924
3925 case GL_DEPTH_STENCIL_ATTACHMENT:
3926 if (!framebuffer->hasValidDepthStencil())
3927 {
3928 context->handleError(Error(GL_INVALID_OPERATION));
3929 return false;
3930 }
3931 break;
3932
3933 default:
3934 context->handleError(Error(GL_INVALID_OPERATION));
3935 return false;
3936 }
3937 }
3938 }
3939
3940 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3941 if (attachmentObject)
3942 {
3943 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3944 attachmentObject->type() == GL_TEXTURE ||
3945 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3946
3947 switch (pname)
3948 {
3949 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3950 if (attachmentObject->type() != GL_RENDERBUFFER &&
3951 attachmentObject->type() != GL_TEXTURE)
3952 {
3953 context->handleError(Error(GL_INVALID_ENUM));
3954 return false;
3955 }
3956 break;
3957
3958 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3959 if (attachmentObject->type() != GL_TEXTURE)
3960 {
3961 context->handleError(Error(GL_INVALID_ENUM));
3962 return false;
3963 }
3964 break;
3965
3966 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3967 if (attachmentObject->type() != GL_TEXTURE)
3968 {
3969 context->handleError(Error(GL_INVALID_ENUM));
3970 return false;
3971 }
3972 break;
3973
3974 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3975 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3976 {
3977 context->handleError(Error(GL_INVALID_OPERATION));
3978 return false;
3979 }
3980 break;
3981
3982 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3983 if (attachmentObject->type() != GL_TEXTURE)
3984 {
3985 context->handleError(Error(GL_INVALID_ENUM));
3986 return false;
3987 }
3988 break;
3989
3990 default:
3991 break;
3992 }
3993 }
3994 else
3995 {
3996 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3997 // is NONE, then querying any other pname will generate INVALID_ENUM.
3998
3999 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4000 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4001 // INVALID_OPERATION for all other pnames
4002
4003 switch (pname)
4004 {
4005 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4006 break;
4007
4008 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4009 if (clientVersion < 3)
4010 {
4011 context->handleError(Error(GL_INVALID_ENUM));
4012 return false;
4013 }
4014 break;
4015
4016 default:
4017 if (clientVersion < 3)
4018 {
4019 context->handleError(Error(GL_INVALID_ENUM));
4020 return false;
4021 }
4022 else
4023 {
4024 context->handleError(Error(GL_INVALID_OPERATION));
4025 return false;
4026 }
4027 }
4028 }
4029
4030 return true;
4031}
4032
4033bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4034 GLenum target,
4035 GLenum attachment,
4036 GLenum pname,
4037 GLsizei bufSize,
4038 GLsizei *numParams)
4039{
4040 if (!ValidateRobustEntryPoint(context, bufSize))
4041 {
4042 return false;
4043 }
4044
Jamie Madillbe849e42017-05-02 15:49:00 -04004045 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4046 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004047 {
4048 return false;
4049 }
4050
4051 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4052 {
4053 return false;
4054 }
4055
4056 return true;
4057}
4058
Geoff Langff5b2d52016-09-07 11:32:23 -04004059bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4060 GLenum target,
4061 GLenum pname,
4062 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004063 GLsizei *length,
4064 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004065{
4066 if (!ValidateRobustEntryPoint(context, bufSize))
4067 {
4068 return false;
4069 }
4070
Geoff Langebebe1c2016-10-14 12:01:31 -04004071 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004072 {
4073 return false;
4074 }
4075
Geoff Langebebe1c2016-10-14 12:01:31 -04004076 if (!ValidateRobustBufferSize(context, bufSize, *length))
4077 {
4078 return false;
4079 }
4080
4081 return true;
4082}
4083
4084bool ValidateGetBufferParameteri64v(ValidationContext *context,
4085 GLenum target,
4086 GLenum pname,
4087 GLint64 *params)
4088{
4089 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4090}
4091
4092bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4093 GLenum target,
4094 GLenum pname,
4095 GLsizei bufSize,
4096 GLsizei *length,
4097 GLint64 *params)
4098{
4099 if (!ValidateRobustEntryPoint(context, bufSize))
4100 {
4101 return false;
4102 }
4103
4104 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4105 {
4106 return false;
4107 }
4108
4109 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004110 {
4111 return false;
4112 }
4113
4114 return true;
4115}
4116
Jamie Madillbe849e42017-05-02 15:49:00 -04004117bool ValidateGetProgramivBase(ValidationContext *context,
4118 GLuint program,
4119 GLenum pname,
4120 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004121{
4122 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004123 if (numParams)
4124 {
4125 *numParams = 1;
4126 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004127
4128 Program *programObject = GetValidProgram(context, program);
4129 if (!programObject)
4130 {
4131 return false;
4132 }
4133
4134 switch (pname)
4135 {
4136 case GL_DELETE_STATUS:
4137 case GL_LINK_STATUS:
4138 case GL_VALIDATE_STATUS:
4139 case GL_INFO_LOG_LENGTH:
4140 case GL_ATTACHED_SHADERS:
4141 case GL_ACTIVE_ATTRIBUTES:
4142 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4143 case GL_ACTIVE_UNIFORMS:
4144 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4145 break;
4146
4147 case GL_PROGRAM_BINARY_LENGTH:
4148 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4149 {
4150 context->handleError(Error(GL_INVALID_ENUM,
4151 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4152 "GL_OES_get_program_binary or ES 3.0."));
4153 return false;
4154 }
4155 break;
4156
4157 case GL_ACTIVE_UNIFORM_BLOCKS:
4158 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4159 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4160 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4161 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4162 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4163 if (context->getClientMajorVersion() < 3)
4164 {
4165 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4166 return false;
4167 }
4168 break;
4169
Yunchao He61afff12017-03-14 15:34:03 +08004170 case GL_PROGRAM_SEPARABLE:
4171 if (context->getClientVersion() < Version(3, 1))
4172 {
4173 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.1."));
4174 return false;
4175 }
4176 break;
4177
Geoff Langff5b2d52016-09-07 11:32:23 -04004178 default:
4179 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4180 return false;
4181 }
4182
4183 return true;
4184}
4185
4186bool ValidateGetProgramivRobustANGLE(Context *context,
4187 GLuint program,
4188 GLenum pname,
4189 GLsizei bufSize,
4190 GLsizei *numParams)
4191{
4192 if (!ValidateRobustEntryPoint(context, bufSize))
4193 {
4194 return false;
4195 }
4196
Jamie Madillbe849e42017-05-02 15:49:00 -04004197 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004198 {
4199 return false;
4200 }
4201
4202 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4203 {
4204 return false;
4205 }
4206
4207 return true;
4208}
4209
Geoff Lang740d9022016-10-07 11:20:52 -04004210bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4211 GLenum target,
4212 GLenum pname,
4213 GLsizei bufSize,
4214 GLsizei *length,
4215 GLint *params)
4216{
4217 if (!ValidateRobustEntryPoint(context, bufSize))
4218 {
4219 return false;
4220 }
4221
4222 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4223 {
4224 return false;
4225 }
4226
4227 if (!ValidateRobustBufferSize(context, bufSize, *length))
4228 {
4229 return false;
4230 }
4231
4232 return true;
4233}
4234
Geoff Langd7d0ed32016-10-07 11:33:51 -04004235bool ValidateGetShaderivRobustANGLE(Context *context,
4236 GLuint shader,
4237 GLenum pname,
4238 GLsizei bufSize,
4239 GLsizei *length,
4240 GLint *params)
4241{
4242 if (!ValidateRobustEntryPoint(context, bufSize))
4243 {
4244 return false;
4245 }
4246
4247 if (!ValidateGetShaderivBase(context, shader, pname, length))
4248 {
4249 return false;
4250 }
4251
4252 if (!ValidateRobustBufferSize(context, bufSize, *length))
4253 {
4254 return false;
4255 }
4256
4257 return true;
4258}
4259
Geoff Langc1984ed2016-10-07 12:41:00 -04004260bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4261 GLenum target,
4262 GLenum pname,
4263 GLsizei bufSize,
4264 GLsizei *length,
4265 GLfloat *params)
4266{
4267 if (!ValidateRobustEntryPoint(context, bufSize))
4268 {
4269 return false;
4270 }
4271
4272 if (!ValidateGetTexParameterBase(context, target, pname, length))
4273 {
4274 return false;
4275 }
4276
4277 if (!ValidateRobustBufferSize(context, bufSize, *length))
4278 {
4279 return false;
4280 }
4281
4282 return true;
4283}
4284
Geoff Langc1984ed2016-10-07 12:41:00 -04004285bool ValidateGetTexParameterivRobustANGLE(Context *context,
4286 GLenum target,
4287 GLenum pname,
4288 GLsizei bufSize,
4289 GLsizei *length,
4290 GLint *params)
4291{
4292 if (!ValidateRobustEntryPoint(context, bufSize))
4293 {
4294 return false;
4295 }
4296
4297 if (!ValidateGetTexParameterBase(context, target, pname, length))
4298 {
4299 return false;
4300 }
4301
4302 if (!ValidateRobustBufferSize(context, bufSize, *length))
4303 {
4304 return false;
4305 }
4306
4307 return true;
4308}
4309
Geoff Langc1984ed2016-10-07 12:41:00 -04004310bool ValidateTexParameterfvRobustANGLE(Context *context,
4311 GLenum target,
4312 GLenum pname,
4313 GLsizei bufSize,
4314 const GLfloat *params)
4315{
4316 if (!ValidateRobustEntryPoint(context, bufSize))
4317 {
4318 return false;
4319 }
4320
4321 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4322}
4323
Geoff Langc1984ed2016-10-07 12:41:00 -04004324bool ValidateTexParameterivRobustANGLE(Context *context,
4325 GLenum target,
4326 GLenum pname,
4327 GLsizei bufSize,
4328 const GLint *params)
4329{
4330 if (!ValidateRobustEntryPoint(context, bufSize))
4331 {
4332 return false;
4333 }
4334
4335 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4336}
4337
4338bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4339{
4340 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4341}
4342
4343bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4344 GLuint sampler,
4345 GLenum pname,
4346 GLuint bufSize,
4347 GLsizei *length,
4348 GLfloat *params)
4349{
4350 if (!ValidateRobustEntryPoint(context, bufSize))
4351 {
4352 return false;
4353 }
4354
4355 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4356 {
4357 return false;
4358 }
4359
4360 if (!ValidateRobustBufferSize(context, bufSize, *length))
4361 {
4362 return false;
4363 }
4364
4365 return true;
4366}
4367
4368bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4369{
4370 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4371}
4372
4373bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4374 GLuint sampler,
4375 GLenum pname,
4376 GLuint bufSize,
4377 GLsizei *length,
4378 GLint *params)
4379{
4380 if (!ValidateRobustEntryPoint(context, bufSize))
4381 {
4382 return false;
4383 }
4384
4385 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4386 {
4387 return false;
4388 }
4389
4390 if (!ValidateRobustBufferSize(context, bufSize, *length))
4391 {
4392 return false;
4393 }
4394
4395 return true;
4396}
4397
4398bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4399{
4400 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4401}
4402
4403bool ValidateSamplerParameterfv(Context *context,
4404 GLuint sampler,
4405 GLenum pname,
4406 const GLfloat *params)
4407{
4408 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4409}
4410
4411bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4412 GLuint sampler,
4413 GLenum pname,
4414 GLsizei bufSize,
4415 const GLfloat *params)
4416{
4417 if (!ValidateRobustEntryPoint(context, bufSize))
4418 {
4419 return false;
4420 }
4421
4422 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4423}
4424
4425bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4426{
4427 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4428}
4429
4430bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4431{
4432 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4433}
4434
4435bool ValidateSamplerParameterivRobustANGLE(Context *context,
4436 GLuint sampler,
4437 GLenum pname,
4438 GLsizei bufSize,
4439 const GLint *params)
4440{
4441 if (!ValidateRobustEntryPoint(context, bufSize))
4442 {
4443 return false;
4444 }
4445
4446 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4447}
4448
Geoff Lang0b031062016-10-13 14:30:04 -04004449bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4450 GLuint index,
4451 GLenum pname,
4452 GLsizei bufSize,
4453 GLsizei *length,
4454 GLfloat *params)
4455{
4456 if (!ValidateRobustEntryPoint(context, bufSize))
4457 {
4458 return false;
4459 }
4460
4461 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4462 {
4463 return false;
4464 }
4465
4466 if (!ValidateRobustBufferSize(context, bufSize, *length))
4467 {
4468 return false;
4469 }
4470
4471 return true;
4472}
4473
Geoff Lang0b031062016-10-13 14:30:04 -04004474bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4475 GLuint index,
4476 GLenum pname,
4477 GLsizei bufSize,
4478 GLsizei *length,
4479 GLint *params)
4480{
4481 if (!ValidateRobustEntryPoint(context, bufSize))
4482 {
4483 return false;
4484 }
4485
4486 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4487 {
4488 return false;
4489 }
4490
4491 if (!ValidateRobustBufferSize(context, bufSize, *length))
4492 {
4493 return false;
4494 }
4495
4496 return true;
4497}
4498
Geoff Lang0b031062016-10-13 14:30:04 -04004499bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4500 GLuint index,
4501 GLenum pname,
4502 GLsizei bufSize,
4503 GLsizei *length,
4504 void **pointer)
4505{
4506 if (!ValidateRobustEntryPoint(context, bufSize))
4507 {
4508 return false;
4509 }
4510
4511 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4512 {
4513 return false;
4514 }
4515
4516 if (!ValidateRobustBufferSize(context, bufSize, *length))
4517 {
4518 return false;
4519 }
4520
4521 return true;
4522}
4523
4524bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4525{
4526 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4527}
4528
4529bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4530 GLuint index,
4531 GLenum pname,
4532 GLsizei bufSize,
4533 GLsizei *length,
4534 GLint *params)
4535{
4536 if (!ValidateRobustEntryPoint(context, bufSize))
4537 {
4538 return false;
4539 }
4540
4541 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4542 {
4543 return false;
4544 }
4545
4546 if (!ValidateRobustBufferSize(context, bufSize, *length))
4547 {
4548 return false;
4549 }
4550
4551 return true;
4552}
4553
4554bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4555{
4556 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4557}
4558
4559bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4560 GLuint index,
4561 GLenum pname,
4562 GLsizei bufSize,
4563 GLsizei *length,
4564 GLuint *params)
4565{
4566 if (!ValidateRobustEntryPoint(context, bufSize))
4567 {
4568 return false;
4569 }
4570
4571 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4572 {
4573 return false;
4574 }
4575
4576 if (!ValidateRobustBufferSize(context, bufSize, *length))
4577 {
4578 return false;
4579 }
4580
4581 return true;
4582}
4583
Geoff Lang6899b872016-10-14 11:30:13 -04004584bool ValidateGetActiveUniformBlockiv(Context *context,
4585 GLuint program,
4586 GLuint uniformBlockIndex,
4587 GLenum pname,
4588 GLint *params)
4589{
4590 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
4591}
4592
4593bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4594 GLuint program,
4595 GLuint uniformBlockIndex,
4596 GLenum pname,
4597 GLsizei bufSize,
4598 GLsizei *length,
4599 GLint *params)
4600{
4601 if (!ValidateRobustEntryPoint(context, bufSize))
4602 {
4603 return false;
4604 }
4605
4606 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4607 {
4608 return false;
4609 }
4610
4611 if (!ValidateRobustBufferSize(context, bufSize, *length))
4612 {
4613 return false;
4614 }
4615
4616 return true;
4617}
4618
Geoff Lang0a9661f2016-10-20 10:59:20 -07004619bool ValidateGetInternalFormativ(Context *context,
4620 GLenum target,
4621 GLenum internalformat,
4622 GLenum pname,
4623 GLsizei bufSize,
4624 GLint *params)
4625{
4626 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4627 nullptr);
4628}
4629
4630bool ValidateGetInternalFormativRobustANGLE(Context *context,
4631 GLenum target,
4632 GLenum internalformat,
4633 GLenum pname,
4634 GLsizei bufSize,
4635 GLsizei *length,
4636 GLint *params)
4637{
4638 if (!ValidateRobustEntryPoint(context, bufSize))
4639 {
4640 return false;
4641 }
4642
4643 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4644 {
4645 return false;
4646 }
4647
4648 if (!ValidateRobustBufferSize(context, bufSize, *length))
4649 {
4650 return false;
4651 }
4652
4653 return true;
4654}
4655
Shao80957d92017-02-20 21:25:59 +08004656bool ValidateVertexFormatBase(ValidationContext *context,
4657 GLuint attribIndex,
4658 GLint size,
4659 GLenum type,
4660 GLboolean pureInteger)
4661{
4662 const Caps &caps = context->getCaps();
4663 if (attribIndex >= caps.maxVertexAttributes)
4664 {
4665 context->handleError(
4666 Error(GL_INVALID_VALUE, "attribindex must be smaller than MAX_VERTEX_ATTRIBS."));
4667 return false;
4668 }
4669
4670 if (size < 1 || size > 4)
4671 {
4672 context->handleError(Error(GL_INVALID_VALUE, "size must be between one and four."));
4673 }
4674
4675 switch (type)
4676 {
4677 case GL_BYTE:
4678 case GL_UNSIGNED_BYTE:
4679 case GL_SHORT:
4680 case GL_UNSIGNED_SHORT:
4681 break;
4682
4683 case GL_INT:
4684 case GL_UNSIGNED_INT:
4685 if (context->getClientMajorVersion() < 3)
4686 {
4687 context->handleError(
4688 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
4689 return false;
4690 }
4691 break;
4692
4693 case GL_FIXED:
4694 case GL_FLOAT:
4695 if (pureInteger)
4696 {
4697 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
4698 return false;
4699 }
4700 break;
4701
4702 case GL_HALF_FLOAT:
4703 if (context->getClientMajorVersion() < 3)
4704 {
4705 context->handleError(
4706 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
4707 return false;
4708 }
4709 if (pureInteger)
4710 {
4711 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
4712 return false;
4713 }
4714 break;
4715
4716 case GL_INT_2_10_10_10_REV:
4717 case GL_UNSIGNED_INT_2_10_10_10_REV:
4718 if (context->getClientMajorVersion() < 3)
4719 {
4720 context->handleError(
4721 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
4722 return false;
4723 }
4724 if (pureInteger)
4725 {
4726 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
4727 return false;
4728 }
4729 if (size != 4)
4730 {
4731 context->handleError(Error(GL_INVALID_OPERATION,
4732 "Type is INT_2_10_10_10_REV or "
4733 "UNSIGNED_INT_2_10_10_10_REV and size is not 4."));
4734 return false;
4735 }
4736 break;
4737
4738 default:
4739 context->handleError(Error(GL_INVALID_ENUM, "Invalid vertex type."));
4740 return false;
4741 }
4742
4743 return true;
4744}
4745
Geoff Lang76e65652017-03-27 14:58:02 -04004746// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4747// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4748// specified clear value and the type of a buffer that is being cleared generates an
4749// INVALID_OPERATION error instead of producing undefined results
4750bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4751 GLint drawbuffer,
4752 const GLenum *validComponentTypes,
4753 size_t validComponentTypeCount)
4754{
4755 const FramebufferAttachment *attachment =
4756 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4757 if (attachment)
4758 {
4759 GLenum componentType = attachment->getFormat().info->componentType;
4760 const GLenum *end = validComponentTypes + validComponentTypeCount;
4761 if (std::find(validComponentTypes, end, componentType) == end)
4762 {
4763 context->handleError(
4764 Error(GL_INVALID_OPERATION,
4765 "No defined conversion between clear value and attachment format."));
4766 return false;
4767 }
4768 }
4769
4770 return true;
4771}
4772
Corentin Wallezb2931602017-04-11 15:58:57 -04004773bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4774 GLsizei imageSize,
4775 GLsizei dataSize)
4776{
4777 if (!ValidateRobustEntryPoint(context, dataSize))
4778 {
4779 return false;
4780 }
4781
4782 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
4783 if (pixelUnpackBuffer == nullptr)
4784 {
4785 if (dataSize < imageSize)
4786 {
4787 context->handleError(
4788 Error(GL_INVALID_OPERATION, "dataSize must be at least %i.", imageSize));
4789 }
4790 }
4791 return true;
4792}
4793
Jamie Madillbe849e42017-05-02 15:49:00 -04004794bool ValidateGetBufferParameterBase(ValidationContext *context,
4795 GLenum target,
4796 GLenum pname,
4797 bool pointerVersion,
4798 GLsizei *numParams)
4799{
4800 if (numParams)
4801 {
4802 *numParams = 0;
4803 }
4804
4805 if (!ValidBufferTarget(context, target))
4806 {
4807 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
4808 return false;
4809 }
4810
4811 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4812 if (!buffer)
4813 {
4814 // A null buffer means that "0" is bound to the requested buffer target
4815 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
4816 return false;
4817 }
4818
4819 const Extensions &extensions = context->getExtensions();
4820
4821 switch (pname)
4822 {
4823 case GL_BUFFER_USAGE:
4824 case GL_BUFFER_SIZE:
4825 break;
4826
4827 case GL_BUFFER_ACCESS_OES:
4828 if (!extensions.mapBuffer)
4829 {
4830 context->handleError(
4831 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer."));
4832 return false;
4833 }
4834 break;
4835
4836 case GL_BUFFER_MAPPED:
4837 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4838 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4839 !extensions.mapBufferRange)
4840 {
4841 context->handleError(Error(
4842 GL_INVALID_ENUM,
4843 "pname requires OpenGL ES 3.0, GL_OES_mapbuffer or GL_EXT_map_buffer_range."));
4844 return false;
4845 }
4846 break;
4847
4848 case GL_BUFFER_MAP_POINTER:
4849 if (!pointerVersion)
4850 {
4851 context->handleError(
4852 Error(GL_INVALID_ENUM,
4853 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
4854 return false;
4855 }
4856 break;
4857
4858 case GL_BUFFER_ACCESS_FLAGS:
4859 case GL_BUFFER_MAP_OFFSET:
4860 case GL_BUFFER_MAP_LENGTH:
4861 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4862 {
4863 context->handleError(Error(
4864 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
4865 return false;
4866 }
4867 break;
4868
4869 default:
4870 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4871 return false;
4872 }
4873
4874 // All buffer parameter queries return one value.
4875 if (numParams)
4876 {
4877 *numParams = 1;
4878 }
4879
4880 return true;
4881}
4882
4883bool ValidateGetRenderbufferParameterivBase(Context *context,
4884 GLenum target,
4885 GLenum pname,
4886 GLsizei *length)
4887{
4888 if (length)
4889 {
4890 *length = 0;
4891 }
4892
4893 if (target != GL_RENDERBUFFER)
4894 {
4895 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
4896 return false;
4897 }
4898
4899 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4900 if (renderbuffer == nullptr)
4901 {
4902 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
4903 return false;
4904 }
4905
4906 switch (pname)
4907 {
4908 case GL_RENDERBUFFER_WIDTH:
4909 case GL_RENDERBUFFER_HEIGHT:
4910 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4911 case GL_RENDERBUFFER_RED_SIZE:
4912 case GL_RENDERBUFFER_GREEN_SIZE:
4913 case GL_RENDERBUFFER_BLUE_SIZE:
4914 case GL_RENDERBUFFER_ALPHA_SIZE:
4915 case GL_RENDERBUFFER_DEPTH_SIZE:
4916 case GL_RENDERBUFFER_STENCIL_SIZE:
4917 break;
4918
4919 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4920 if (!context->getExtensions().framebufferMultisample)
4921 {
4922 context->handleError(
4923 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
4924 return false;
4925 }
4926 break;
4927
4928 default:
4929 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4930 return false;
4931 }
4932
4933 if (length)
4934 {
4935 *length = 1;
4936 }
4937 return true;
4938}
4939
4940bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4941{
4942 if (length)
4943 {
4944 *length = 0;
4945 }
4946
4947 if (GetValidShader(context, shader) == nullptr)
4948 {
4949 return false;
4950 }
4951
4952 switch (pname)
4953 {
4954 case GL_SHADER_TYPE:
4955 case GL_DELETE_STATUS:
4956 case GL_COMPILE_STATUS:
4957 case GL_INFO_LOG_LENGTH:
4958 case GL_SHADER_SOURCE_LENGTH:
4959 break;
4960
4961 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4962 if (!context->getExtensions().translatedShaderSource)
4963 {
4964 context->handleError(
4965 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
4966 return false;
4967 }
4968 break;
4969
4970 default:
4971 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4972 return false;
4973 }
4974
4975 if (length)
4976 {
4977 *length = 1;
4978 }
4979 return true;
4980}
4981
4982bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4983{
4984 if (length)
4985 {
4986 *length = 0;
4987 }
4988
4989 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4990 {
4991 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
4992 return false;
4993 }
4994
4995 if (context->getTargetTexture(target) == nullptr)
4996 {
4997 // Should only be possible for external textures
4998 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
4999 return false;
5000 }
5001
5002 switch (pname)
5003 {
5004 case GL_TEXTURE_MAG_FILTER:
5005 case GL_TEXTURE_MIN_FILTER:
5006 case GL_TEXTURE_WRAP_S:
5007 case GL_TEXTURE_WRAP_T:
5008 break;
5009
5010 case GL_TEXTURE_USAGE_ANGLE:
5011 if (!context->getExtensions().textureUsage)
5012 {
5013 context->handleError(
5014 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
5015 return false;
5016 }
5017 break;
5018
5019 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5020 if (!context->getExtensions().textureFilterAnisotropic)
5021 {
5022 context->handleError(
5023 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
5024 return false;
5025 }
5026 break;
5027
5028 case GL_TEXTURE_IMMUTABLE_FORMAT:
5029 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5030 {
5031 context->handleError(
5032 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
5033 return false;
5034 }
5035 break;
5036
5037 case GL_TEXTURE_WRAP_R:
5038 case GL_TEXTURE_IMMUTABLE_LEVELS:
5039 case GL_TEXTURE_SWIZZLE_R:
5040 case GL_TEXTURE_SWIZZLE_G:
5041 case GL_TEXTURE_SWIZZLE_B:
5042 case GL_TEXTURE_SWIZZLE_A:
5043 case GL_TEXTURE_BASE_LEVEL:
5044 case GL_TEXTURE_MAX_LEVEL:
5045 case GL_TEXTURE_MIN_LOD:
5046 case GL_TEXTURE_MAX_LOD:
5047 case GL_TEXTURE_COMPARE_MODE:
5048 case GL_TEXTURE_COMPARE_FUNC:
5049 if (context->getClientMajorVersion() < 3)
5050 {
5051 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
5052 return false;
5053 }
5054 break;
5055
5056 case GL_TEXTURE_SRGB_DECODE_EXT:
5057 if (!context->getExtensions().textureSRGBDecode)
5058 {
5059 context->handleError(
5060 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
5061 return false;
5062 }
5063 break;
5064
5065 default:
5066 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
5067 return false;
5068 }
5069
5070 if (length)
5071 {
5072 *length = 1;
5073 }
5074 return true;
5075}
5076
5077bool ValidateGetVertexAttribBase(Context *context,
5078 GLuint index,
5079 GLenum pname,
5080 GLsizei *length,
5081 bool pointer,
5082 bool pureIntegerEntryPoint)
5083{
5084 if (length)
5085 {
5086 *length = 0;
5087 }
5088
5089 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5090 {
5091 context->handleError(
5092 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
5093 return false;
5094 }
5095
5096 if (index >= context->getCaps().maxVertexAttributes)
5097 {
5098 context->handleError(Error(
5099 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
5100 return false;
5101 }
5102
5103 if (pointer)
5104 {
5105 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5106 {
5107 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
5108 return false;
5109 }
5110 }
5111 else
5112 {
5113 switch (pname)
5114 {
5115 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5116 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5117 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5118 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5119 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5120 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5121 case GL_CURRENT_VERTEX_ATTRIB:
5122 break;
5123
5124 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5125 static_assert(
5126 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5127 "ANGLE extension enums not equal to GL enums.");
5128 if (context->getClientMajorVersion() < 3 &&
5129 !context->getExtensions().instancedArrays)
5130 {
5131 context->handleError(Error(GL_INVALID_ENUM,
5132 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
5133 "3.0 or GL_ANGLE_instanced_arrays."));
5134 return false;
5135 }
5136 break;
5137
5138 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5139 if (context->getClientMajorVersion() < 3)
5140 {
5141 context->handleError(Error(
5142 GL_INVALID_ENUM, "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0."));
5143 return false;
5144 }
5145 break;
5146
5147 case GL_VERTEX_ATTRIB_BINDING:
5148 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5149 if (context->getClientVersion() < ES_3_1)
5150 {
5151 context->handleError(
5152 Error(GL_INVALID_ENUM, "Vertex Attrib Bindings require OpenGL ES 3.1."));
5153 return false;
5154 }
5155 break;
5156
5157 default:
5158 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
5159 return false;
5160 }
5161 }
5162
5163 if (length)
5164 {
5165 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5166 {
5167 *length = 4;
5168 }
5169 else
5170 {
5171 *length = 1;
5172 }
5173 }
5174
5175 return true;
5176}
5177
5178bool ValidateReadPixelsBase(ValidationContext *context,
5179 GLint x,
5180 GLint y,
5181 GLsizei width,
5182 GLsizei height,
5183 GLenum format,
5184 GLenum type,
5185 GLsizei bufSize,
5186 GLsizei *length,
5187 GLsizei *columns,
5188 GLsizei *rows,
5189 void *pixels)
5190{
5191 if (length != nullptr)
5192 {
5193 *length = 0;
5194 }
5195 if (rows != nullptr)
5196 {
5197 *rows = 0;
5198 }
5199 if (columns != nullptr)
5200 {
5201 *columns = 0;
5202 }
5203
5204 if (width < 0 || height < 0)
5205 {
5206 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
5207 return false;
5208 }
5209
5210 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5211
5212 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5213 {
5214 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
5215 return false;
5216 }
5217
5218 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5219 {
5220 context->handleError(Error(GL_INVALID_OPERATION));
5221 return false;
5222 }
5223
5224 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5225 ASSERT(framebuffer);
5226
5227 if (framebuffer->getReadBufferState() == GL_NONE)
5228 {
5229 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
5230 return false;
5231 }
5232
5233 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5234 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5235 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5236 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5237 // situation is an application error that would lead to a crash in ANGLE.
5238 if (readBuffer == nullptr)
5239 {
5240 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
5241 return false;
5242 }
5243
5244 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
5245 GLenum currentType = framebuffer->getImplementationColorReadType();
5246 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5247
5248 bool validFormatTypeCombination =
5249 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5250
5251 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5252 {
5253 context->handleError(Error(GL_INVALID_OPERATION));
5254 return false;
5255 }
5256
5257 // Check for pixel pack buffer related API errors
5258 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5259 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5260 {
5261 // ...the buffer object's data store is currently mapped.
5262 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
5263 return false;
5264 }
5265
5266 // .. the data would be packed to the buffer object such that the memory writes required
5267 // would exceed the data store size.
5268 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5269 const gl::Extents size(width, height, 1);
5270 const auto &pack = context->getGLState().getPackState();
5271
5272 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5273 if (endByteOrErr.isError())
5274 {
5275 context->handleError(endByteOrErr.getError());
5276 return false;
5277 }
5278
5279 size_t endByte = endByteOrErr.getResult();
5280 if (bufSize >= 0)
5281 {
5282 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5283 {
5284 context->handleError(
5285 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
5286 return false;
5287 }
5288 }
5289
5290 if (pixelPackBuffer != nullptr)
5291 {
5292 CheckedNumeric<size_t> checkedEndByte(endByte);
5293 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5294 checkedEndByte += checkedOffset;
5295
5296 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5297 {
5298 // Overflow past the end of the buffer
5299 context->handleError(
5300 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
5301 return false;
5302 }
5303 }
5304
5305 if (pixelPackBuffer == nullptr && length != nullptr)
5306 {
5307 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5308 {
5309 context->handleError(
5310 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
5311 return false;
5312 }
5313
5314 *length = static_cast<GLsizei>(endByte);
5315 }
5316
5317 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5318 angle::CheckedNumeric<int> clippedExtent(length);
5319 if (start < 0)
5320 {
5321 // "subtract" the area that is less than 0
5322 clippedExtent += start;
5323 }
5324
5325 const int readExtent = start + length;
5326 if (readExtent > bufferSize)
5327 {
5328 // Subtract the region to the right of the read buffer
5329 clippedExtent -= (readExtent - bufferSize);
5330 }
5331
5332 if (!clippedExtent.IsValid())
5333 {
5334 return 0;
5335 }
5336
5337 return std::max(clippedExtent.ValueOrDie(), 0);
5338 };
5339
5340 if (columns != nullptr)
5341 {
5342 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5343 }
5344
5345 if (rows != nullptr)
5346 {
5347 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5348 }
5349
5350 return true;
5351}
5352
5353template <typename ParamType>
5354bool ValidateTexParameterBase(Context *context,
5355 GLenum target,
5356 GLenum pname,
5357 GLsizei bufSize,
5358 const ParamType *params)
5359{
5360 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5361 {
5362 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
5363 return false;
5364 }
5365
5366 if (context->getTargetTexture(target) == nullptr)
5367 {
5368 // Should only be possible for external textures
5369 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
5370 return false;
5371 }
5372
5373 const GLsizei minBufSize = 1;
5374 if (bufSize >= 0 && bufSize < minBufSize)
5375 {
5376 context->handleError(
5377 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
5378 return false;
5379 }
5380
5381 switch (pname)
5382 {
5383 case GL_TEXTURE_WRAP_R:
5384 case GL_TEXTURE_SWIZZLE_R:
5385 case GL_TEXTURE_SWIZZLE_G:
5386 case GL_TEXTURE_SWIZZLE_B:
5387 case GL_TEXTURE_SWIZZLE_A:
5388 case GL_TEXTURE_BASE_LEVEL:
5389 case GL_TEXTURE_MAX_LEVEL:
5390 case GL_TEXTURE_COMPARE_MODE:
5391 case GL_TEXTURE_COMPARE_FUNC:
5392 case GL_TEXTURE_MIN_LOD:
5393 case GL_TEXTURE_MAX_LOD:
5394 if (context->getClientMajorVersion() < 3)
5395 {
5396 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
5397 return false;
5398 }
5399 if (target == GL_TEXTURE_EXTERNAL_OES &&
5400 !context->getExtensions().eglImageExternalEssl3)
5401 {
5402 context->handleError(Error(GL_INVALID_ENUM,
5403 "ES3 texture parameters are not available without "
5404 "GL_OES_EGL_image_external_essl3."));
5405 return false;
5406 }
5407 break;
5408
5409 default:
5410 break;
5411 }
5412
5413 switch (pname)
5414 {
5415 case GL_TEXTURE_WRAP_S:
5416 case GL_TEXTURE_WRAP_T:
5417 case GL_TEXTURE_WRAP_R:
5418 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
5419 {
5420 return false;
5421 }
5422 break;
5423
5424 case GL_TEXTURE_MIN_FILTER:
5425 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
5426 {
5427 return false;
5428 }
5429 break;
5430
5431 case GL_TEXTURE_MAG_FILTER:
5432 if (!ValidateTextureMagFilterValue(context, params))
5433 {
5434 return false;
5435 }
5436 break;
5437
5438 case GL_TEXTURE_USAGE_ANGLE:
5439 switch (ConvertToGLenum(params[0]))
5440 {
5441 case GL_NONE:
5442 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5443 break;
5444
5445 default:
5446 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
5447 return false;
5448 }
5449 break;
5450
5451 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5452 if (!context->getExtensions().textureFilterAnisotropic)
5453 {
5454 context->handleError(
5455 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
5456 return false;
5457 }
5458
5459 // we assume the parameter passed to this validation method is truncated, not rounded
5460 if (params[0] < 1)
5461 {
5462 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
5463 return false;
5464 }
5465 break;
5466
5467 case GL_TEXTURE_MIN_LOD:
5468 case GL_TEXTURE_MAX_LOD:
5469 // any value is permissible
5470 break;
5471
5472 case GL_TEXTURE_COMPARE_MODE:
5473 if (!ValidateTextureCompareModeValue(context, params))
5474 {
5475 return false;
5476 }
5477 break;
5478
5479 case GL_TEXTURE_COMPARE_FUNC:
5480 if (!ValidateTextureCompareFuncValue(context, params))
5481 {
5482 return false;
5483 }
5484 break;
5485
5486 case GL_TEXTURE_SWIZZLE_R:
5487 case GL_TEXTURE_SWIZZLE_G:
5488 case GL_TEXTURE_SWIZZLE_B:
5489 case GL_TEXTURE_SWIZZLE_A:
5490 switch (ConvertToGLenum(params[0]))
5491 {
5492 case GL_RED:
5493 case GL_GREEN:
5494 case GL_BLUE:
5495 case GL_ALPHA:
5496 case GL_ZERO:
5497 case GL_ONE:
5498 break;
5499
5500 default:
5501 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
5502 return false;
5503 }
5504 break;
5505
5506 case GL_TEXTURE_BASE_LEVEL:
5507 if (params[0] < 0)
5508 {
5509 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
5510 return false;
5511 }
5512 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5513 {
5514 context->handleError(
5515 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
5516 return false;
5517 }
5518 break;
5519
5520 case GL_TEXTURE_MAX_LEVEL:
5521 if (params[0] < 0)
5522 {
5523 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
5524 return false;
5525 }
5526 break;
5527
5528 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5529 if (context->getClientVersion() < Version(3, 1))
5530 {
5531 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
5532 return false;
5533 }
5534 switch (ConvertToGLenum(params[0]))
5535 {
5536 case GL_DEPTH_COMPONENT:
5537 case GL_STENCIL_INDEX:
5538 break;
5539
5540 default:
5541 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
5542 return false;
5543 }
5544 break;
5545
5546 case GL_TEXTURE_SRGB_DECODE_EXT:
5547 if (!ValidateTextureSRGBDecodeValue(context, params))
5548 {
5549 return false;
5550 }
5551 break;
5552
5553 default:
5554 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
5555 return false;
5556 }
5557
5558 return true;
5559}
5560
5561template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5562template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5563
Jamie Madillc29968b2016-01-20 11:17:23 -05005564} // namespace gl