blob: 0bfdc24cc7c9ee67149aa4adb287e95f5fc2ebbb [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040012#include "libANGLE/Display.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050013#include "libANGLE/Framebuffer.h"
14#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040015#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050016#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040017#include "libANGLE/Query.h"
18#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050019#include "libANGLE/TransformFeedback.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040020#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050021#include "libANGLE/VertexArray.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040022#include "libANGLE/formatutils.h"
23#include "libANGLE/validationES2.h"
24#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025
26#include "common/mathutil.h"
27#include "common/utilities.h"
28
Jamie Madille2e406c2016-06-02 13:04:10 -040029using namespace angle;
30
Geoff Lange8ebe7f2013-08-05 15:03:13 -040031namespace gl
32{
Jamie Madille79b1e12015-11-04 16:36:37 -050033const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum element index.";
34
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
Corentin Wallez92db6942016-12-09 13:10:36 -050037bool ValidateDrawAttribs(ValidationContext *context,
38 GLint primcount,
39 GLint maxVertex,
40 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040041{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070042 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040043 const gl::Program *program = state.getProgram();
44
Corentin Wallez327411e2016-12-09 11:09:17 -050045 bool webglCompatibility = context->getExtensions().webglCompatibility;
46
Jamie Madill231c7f52017-04-26 13:45:37 -040047 const VertexArray *vao = state.getVertexArray();
48 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080049 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madill231c7f52017-04-26 13:45:37 -040050 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040051 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
52 {
53 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallezfd456442016-12-21 17:57:00 -050054 if (!program->isAttribLocationActive(attributeIndex) || !attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040055 {
Corentin Wallezfd456442016-12-21 17:57:00 -050056 continue;
57 }
Jamie Madill1ca74672015-07-21 15:14:11 -040058
Jiawei-Shao2597fb62016-12-09 16:38:02 +080059 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
Jamie Madill231c7f52017-04-26 13:45:37 -040060 // If we have no buffer, then we either get an error, or there are no more checks to be
61 // done.
Jiawei-Shao2597fb62016-12-09 16:38:02 +080062 gl::Buffer *buffer = binding.buffer.get();
Corentin Wallezfd456442016-12-21 17:57:00 -050063 if (!buffer)
64 {
Geoff Langfeb8c682017-02-13 16:07:35 -050065 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050066 {
67 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050068 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
69 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
70 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
71 // error.
Corentin Wallez327411e2016-12-09 11:09:17 -050072 context->handleError(
73 Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer."));
Corentin Wallezfd456442016-12-21 17:57:00 -050074 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050075 }
Corentin Wallezfd456442016-12-21 17:57:00 -050076 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040077 {
78 // This is an application error that would normally result in a crash,
79 // but we catch it and return an error
Jamie Madill231c7f52017-04-26 13:45:37 -040080 context->handleError(Error(
81 GL_INVALID_OPERATION, "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 {
Jamie Madill231c7f52017-04-26 13:45:37 -0400138 context->handleError(
139 Error(GL_INVALID_OPERATION, "Vertex buffer is not big enough for the draw call"));
Corentin Wallezfd456442016-12-21 17:57:00 -0500140 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400141 }
142 }
143
144 return true;
145}
146
Geoff Langf607c602016-09-21 11:46:48 -0400147bool ValidReadPixelsFormatType(ValidationContext *context,
148 GLenum framebufferComponentType,
149 GLenum format,
150 GLenum type)
151{
152 switch (framebufferComponentType)
153 {
154 case GL_UNSIGNED_NORMALIZED:
155 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
156 // ReadPixels with BGRA even if the extension is not present
157 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
158 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
159 type == GL_UNSIGNED_BYTE);
160
161 case GL_SIGNED_NORMALIZED:
162 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
163
164 case GL_INT:
165 return (format == GL_RGBA_INTEGER && type == GL_INT);
166
167 case GL_UNSIGNED_INT:
168 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
169
170 case GL_FLOAT:
171 return (format == GL_RGBA && type == GL_FLOAT);
172
173 default:
174 UNREACHABLE();
175 return false;
176 }
177}
178
Geoff Langc1984ed2016-10-07 12:41:00 -0400179template <typename ParamType>
180bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
181{
182 switch (ConvertToGLenum(params[0]))
183 {
184 case GL_CLAMP_TO_EDGE:
185 break;
186
187 case GL_REPEAT:
188 case GL_MIRRORED_REPEAT:
189 if (isExternalTextureTarget)
190 {
191 // OES_EGL_image_external specifies this error.
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{
Corentin Wallez170efbf2017-05-02 13:45:01 -04002788 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04002789 {
2790 return false;
2791 }
2792
Corentin Wallez170efbf2017-05-02 13:45:01 -04002793 return !context->getExtensions().webglCompatibility ||
2794 ValidateDrawInstancedANGLEAndWebGL(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002795}
2796
He Yunchaoced53ae2016-11-29 15:00:51 +08002797bool ValidateDrawArraysInstancedANGLE(Context *context,
2798 GLenum mode,
2799 GLint first,
2800 GLsizei count,
2801 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002802{
Corentin Wallez170efbf2017-05-02 13:45:01 -04002803 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002804 {
2805 return false;
2806 }
2807
Corentin Wallez170efbf2017-05-02 13:45:01 -04002808 return ValidateDrawInstancedANGLEAndWebGL(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002809}
2810
Jiajia Qind9671222016-11-29 16:30:31 +08002811bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002812{
Jamie Madill250d33f2014-06-06 17:09:03 -04002813 switch (type)
2814 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002815 case GL_UNSIGNED_BYTE:
2816 case GL_UNSIGNED_SHORT:
2817 break;
2818 case GL_UNSIGNED_INT:
2819 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2820 {
2821 context->handleError(Error(GL_INVALID_ENUM));
2822 return false;
2823 }
2824 break;
2825 default:
2826 context->handleError(Error(GL_INVALID_ENUM));
2827 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002828 }
2829
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002830 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002831
2832 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002833 if (curTransformFeedback && curTransformFeedback->isActive() &&
2834 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002835 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002836 // It is an invalid operation to call DrawElements, DrawRangeElements or
2837 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002838 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002839 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002840 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002841 }
2842
Jiajia Qind9671222016-11-29 16:30:31 +08002843 return true;
2844}
2845
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002846bool ValidateDrawElementsCommon(ValidationContext *context,
2847 GLenum mode,
2848 GLsizei count,
2849 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002850 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002851 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002852{
2853 if (!ValidateDrawElementsBase(context, type))
2854 return false;
2855
2856 const State &state = context->getGLState();
2857
Corentin Wallez170efbf2017-05-02 13:45:01 -04002858 if (!ValidateDrawBase(context, mode, count))
2859 {
2860 return false;
2861 }
2862
Jamie Madill250d33f2014-06-06 17:09:03 -04002863 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002864 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002865 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002866 context->handleError(Error(GL_INVALID_OPERATION, "Index buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -04002867 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002868 }
2869
He Yunchaoced53ae2016-11-29 15:00:51 +08002870 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002871 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002872
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002873 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2874
2875 if (context->getExtensions().webglCompatibility)
2876 {
2877 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2878 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2879 {
2880 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2881 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2882 // data type passed to the call, or an INVALID_OPERATION error is generated.
2883 context->handleError(Error(GL_INVALID_OPERATION,
2884 "indices must be a multiple of the element type size."));
2885 return false;
2886 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002887
2888 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2889 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2890 // error is generated.
2891 if (reinterpret_cast<intptr_t>(indices) < 0)
2892 {
2893 context->handleError(Error(GL_INVALID_VALUE, "Offset < 0."));
2894 return false;
2895 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002896 }
2897
2898 if (context->getExtensions().webglCompatibility ||
2899 !context->getGLState().areClientArraysEnabled())
2900 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002901 if (!elementArrayBuffer && count > 0)
2902 {
2903 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2904 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2905 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
2906 context->handleError(Error(GL_INVALID_OPERATION,
2907 "There is no element array buffer bound and count > 0."));
2908 return false;
2909 }
2910 }
2911
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002912 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002913 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002914 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002915 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002916 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2917 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2918 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2919 constexpr uint64_t kMaxTypeSize = 8;
2920 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2921 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2922 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002923
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002924 uint64_t typeSize = typeBytes;
2925 uint64_t elementCount = static_cast<uint64_t>(count);
2926 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2927
2928 // Doing the multiplication here is overflow-safe
2929 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2930
2931 // The offset can be any value, check for overflows
2932 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2933 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002934 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002935 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002936 return false;
2937 }
2938
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002939 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2940 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002941 {
2942 context->handleError(
2943 Error(GL_INVALID_OPERATION, "Index buffer is not big enough for the draw."));
2944 return false;
2945 }
2946 }
2947 else if (!indices)
2948 {
2949 // This is an application error that would normally result in a crash,
2950 // but we catch it and return an error
2951 context->handleError(
2952 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04002953 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002954 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002955 }
2956
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002957 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill2b976812014-08-25 15:47:49 -04002958 // TODO: offer fast path, with disabled index validation.
2959 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002960 const auto &params = context->getParams<HasIndexRange>();
2961 const auto &indexRangeOpt = params.getIndexRange();
2962 if (!indexRangeOpt.valid())
Jamie Madill2b976812014-08-25 15:47:49 -04002963 {
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002964 // Unexpected error.
2965 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04002966 }
2967
Jamie Madille79b1e12015-11-04 16:36:37 -05002968 // If we use an index greater than our maximum supported index range, return an error.
2969 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2970 // return an error if possible here.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002971 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
Jamie Madille79b1e12015-11-04 16:36:37 -05002972 {
Jamie Madill437fa652016-05-03 15:13:24 -04002973 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05002974 return false;
2975 }
2976
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002977 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2978 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04002979 {
2980 return false;
2981 }
2982
Geoff Lang3edfe032015-09-04 16:38:24 -04002983 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002984 return (indexRangeOpt.value().vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04002985}
2986
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002987bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2988 GLenum mode,
2989 GLsizei count,
2990 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002991 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002992 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002993{
Corentin Wallez170efbf2017-05-02 13:45:01 -04002994 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04002995 {
2996 return false;
2997 }
2998
Corentin Wallez170efbf2017-05-02 13:45:01 -04002999 return !context->getExtensions().webglCompatibility ||
3000 ValidateDrawInstancedANGLEAndWebGL(context);
Jamie Madill250d33f2014-06-06 17:09:03 -04003001}
3002
Geoff Lang3edfe032015-09-04 16:38:24 -04003003bool ValidateDrawElementsInstancedANGLE(Context *context,
3004 GLenum mode,
3005 GLsizei count,
3006 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003007 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003008 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003009{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003010 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003011 {
3012 return false;
3013 }
3014
Corentin Wallez170efbf2017-05-02 13:45:01 -04003015 return ValidateDrawInstancedANGLEAndWebGL(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003016}
3017
He Yunchaoced53ae2016-11-29 15:00:51 +08003018bool ValidateFramebufferTextureBase(Context *context,
3019 GLenum target,
3020 GLenum attachment,
3021 GLuint texture,
3022 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003023{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003024 if (!ValidFramebufferTarget(target))
3025 {
Jamie Madill437fa652016-05-03 15:13:24 -04003026 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003027 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003028 }
3029
3030 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003031 {
3032 return false;
3033 }
3034
Jamie Madill55ec3b12014-07-03 10:38:57 -04003035 if (texture != 0)
3036 {
3037 gl::Texture *tex = context->getTexture(texture);
3038
Jamie Madillbe849e42017-05-02 15:49:00 -04003039 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003040 {
Jamie Madill437fa652016-05-03 15:13:24 -04003041 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003042 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003043 }
3044
3045 if (level < 0)
3046 {
Jamie Madill437fa652016-05-03 15:13:24 -04003047 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003048 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003049 }
3050 }
3051
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003052 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003053 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003054
Jamie Madill84115c92015-04-23 15:00:07 -04003055 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003056 {
Jamie Madill437fa652016-05-03 15:13:24 -04003057 context->handleError(
3058 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003059 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003060 }
3061
3062 return true;
3063}
3064
Geoff Langb1196682014-07-23 13:47:29 -04003065bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003066{
3067 if (program == 0)
3068 {
Jamie Madill437fa652016-05-03 15:13:24 -04003069 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003070 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003071 }
3072
Dian Xiang769769a2015-09-09 15:20:08 -07003073 gl::Program *programObject = GetValidProgram(context, program);
3074 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003075 {
3076 return false;
3077 }
3078
Jamie Madill0063c512014-08-25 15:47:53 -04003079 if (!programObject || !programObject->isLinked())
3080 {
Jamie Madill437fa652016-05-03 15:13:24 -04003081 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003082 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003083 }
3084
Geoff Lang7dd2e102014-11-10 15:19:26 -05003085 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003086 {
Jamie Madill437fa652016-05-03 15:13:24 -04003087 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003088 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003089 }
3090
Jamie Madill0063c512014-08-25 15:47:53 -04003091 return true;
3092}
3093
Geoff Langf41d0ee2016-10-07 13:04:23 -04003094static bool ValidateSizedGetUniform(Context *context,
3095 GLuint program,
3096 GLint location,
3097 GLsizei bufSize,
3098 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003099{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003100 if (length)
3101 {
3102 *length = 0;
3103 }
3104
Jamie Madill78f41802014-08-25 15:47:55 -04003105 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003106 {
Jamie Madill78f41802014-08-25 15:47:55 -04003107 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003108 }
3109
Geoff Langf41d0ee2016-10-07 13:04:23 -04003110 if (bufSize < 0)
3111 {
3112 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3113 return false;
3114 }
3115
Jamie Madilla502c742014-08-28 17:19:13 -04003116 gl::Program *programObject = context->getProgram(program);
3117 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003118
Jamie Madill78f41802014-08-25 15:47:55 -04003119 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003120 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003121 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003122 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003123 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003124 context->handleError(
3125 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003126 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003127 }
3128
Geoff Langf41d0ee2016-10-07 13:04:23 -04003129 if (length)
3130 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003131 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003132 }
3133
Jamie Madill0063c512014-08-25 15:47:53 -04003134 return true;
3135}
3136
He Yunchaoced53ae2016-11-29 15:00:51 +08003137bool ValidateGetnUniformfvEXT(Context *context,
3138 GLuint program,
3139 GLint location,
3140 GLsizei bufSize,
3141 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003142{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003143 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003144}
3145
He Yunchaoced53ae2016-11-29 15:00:51 +08003146bool ValidateGetnUniformivEXT(Context *context,
3147 GLuint program,
3148 GLint location,
3149 GLsizei bufSize,
3150 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003151{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003152 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3153}
3154
3155bool ValidateGetUniformfvRobustANGLE(Context *context,
3156 GLuint program,
3157 GLint location,
3158 GLsizei bufSize,
3159 GLsizei *length,
3160 GLfloat *params)
3161{
3162 if (!ValidateRobustEntryPoint(context, bufSize))
3163 {
3164 return false;
3165 }
3166
3167 // bufSize is validated in ValidateSizedGetUniform
3168 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3169}
3170
3171bool ValidateGetUniformivRobustANGLE(Context *context,
3172 GLuint program,
3173 GLint location,
3174 GLsizei bufSize,
3175 GLsizei *length,
3176 GLint *params)
3177{
3178 if (!ValidateRobustEntryPoint(context, bufSize))
3179 {
3180 return false;
3181 }
3182
3183 // bufSize is validated in ValidateSizedGetUniform
3184 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3185}
3186
3187bool ValidateGetUniformuivRobustANGLE(Context *context,
3188 GLuint program,
3189 GLint location,
3190 GLsizei bufSize,
3191 GLsizei *length,
3192 GLuint *params)
3193{
3194 if (!ValidateRobustEntryPoint(context, bufSize))
3195 {
3196 return false;
3197 }
3198
3199 if (context->getClientMajorVersion() < 3)
3200 {
3201 context->handleError(
3202 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3203 return false;
3204 }
3205
3206 // bufSize is validated in ValidateSizedGetUniform
3207 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003208}
3209
He Yunchaoced53ae2016-11-29 15:00:51 +08003210bool ValidateDiscardFramebufferBase(Context *context,
3211 GLenum target,
3212 GLsizei numAttachments,
3213 const GLenum *attachments,
3214 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003215{
3216 if (numAttachments < 0)
3217 {
Jamie Madill437fa652016-05-03 15:13:24 -04003218 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003219 return false;
3220 }
3221
3222 for (GLsizei i = 0; i < numAttachments; ++i)
3223 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003224 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003225 {
3226 if (defaultFramebuffer)
3227 {
Jamie Madill437fa652016-05-03 15:13:24 -04003228 context->handleError(Error(
3229 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003230 return false;
3231 }
3232
3233 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3234 {
Jamie Madill437fa652016-05-03 15:13:24 -04003235 context->handleError(Error(GL_INVALID_OPERATION,
3236 "Requested color attachment is greater than the maximum "
3237 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003238 return false;
3239 }
3240 }
3241 else
3242 {
3243 switch (attachments[i])
3244 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003245 case GL_DEPTH_ATTACHMENT:
3246 case GL_STENCIL_ATTACHMENT:
3247 case GL_DEPTH_STENCIL_ATTACHMENT:
3248 if (defaultFramebuffer)
3249 {
3250 context->handleError(
3251 Error(GL_INVALID_ENUM,
3252 "Invalid attachment when the default framebuffer is bound"));
3253 return false;
3254 }
3255 break;
3256 case GL_COLOR:
3257 case GL_DEPTH:
3258 case GL_STENCIL:
3259 if (!defaultFramebuffer)
3260 {
3261 context->handleError(
3262 Error(GL_INVALID_ENUM,
3263 "Invalid attachment when the default framebuffer is not bound"));
3264 return false;
3265 }
3266 break;
3267 default:
3268 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003269 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003270 }
3271 }
3272 }
3273
3274 return true;
3275}
3276
Austin Kinross6ee1e782015-05-29 17:05:37 -07003277bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3278{
3279 // Note that debug marker calls must not set error state
3280
3281 if (length < 0)
3282 {
3283 return false;
3284 }
3285
3286 if (marker == nullptr)
3287 {
3288 return false;
3289 }
3290
3291 return true;
3292}
3293
3294bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3295{
3296 // Note that debug marker calls must not set error state
3297
3298 if (length < 0)
3299 {
3300 return false;
3301 }
3302
3303 if (length > 0 && marker == nullptr)
3304 {
3305 return false;
3306 }
3307
3308 return true;
3309}
3310
Geoff Langdcab33b2015-07-21 13:03:16 -04003311bool ValidateEGLImageTargetTexture2DOES(Context *context,
3312 egl::Display *display,
3313 GLenum target,
3314 egl::Image *image)
3315{
Geoff Langa8406172015-07-21 16:53:39 -04003316 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3317 {
Jamie Madill437fa652016-05-03 15:13:24 -04003318 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003319 return false;
3320 }
3321
3322 switch (target)
3323 {
3324 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003325 if (!context->getExtensions().eglImage)
3326 {
3327 context->handleError(Error(
3328 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3329 }
3330 break;
3331
3332 case GL_TEXTURE_EXTERNAL_OES:
3333 if (!context->getExtensions().eglImageExternal)
3334 {
3335 context->handleError(Error(
3336 GL_INVALID_ENUM,
3337 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3338 }
Geoff Langa8406172015-07-21 16:53:39 -04003339 break;
3340
3341 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003342 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003343 return false;
3344 }
3345
3346 if (!display->isValidImage(image))
3347 {
Jamie Madill437fa652016-05-03 15:13:24 -04003348 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003349 return false;
3350 }
3351
3352 if (image->getSamples() > 0)
3353 {
Jamie Madill437fa652016-05-03 15:13:24 -04003354 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003355 "cannot create a 2D texture from a multisampled EGL image."));
3356 return false;
3357 }
3358
Geoff Langca271392017-04-05 12:30:00 -04003359 const TextureCaps &textureCaps =
3360 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003361 if (!textureCaps.texturable)
3362 {
Jamie Madill437fa652016-05-03 15:13:24 -04003363 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003364 "EGL image internal format is not supported as a texture."));
3365 return false;
3366 }
3367
Geoff Langdcab33b2015-07-21 13:03:16 -04003368 return true;
3369}
3370
3371bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3372 egl::Display *display,
3373 GLenum target,
3374 egl::Image *image)
3375{
Geoff Langa8406172015-07-21 16:53:39 -04003376 if (!context->getExtensions().eglImage)
3377 {
Jamie Madill437fa652016-05-03 15:13:24 -04003378 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003379 return false;
3380 }
3381
3382 switch (target)
3383 {
3384 case GL_RENDERBUFFER:
3385 break;
3386
3387 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003388 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003389 return false;
3390 }
3391
3392 if (!display->isValidImage(image))
3393 {
Jamie Madill437fa652016-05-03 15:13:24 -04003394 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003395 return false;
3396 }
3397
Geoff Langca271392017-04-05 12:30:00 -04003398 const TextureCaps &textureCaps =
3399 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003400 if (!textureCaps.renderable)
3401 {
Jamie Madill437fa652016-05-03 15:13:24 -04003402 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003403 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3404 return false;
3405 }
3406
Geoff Langdcab33b2015-07-21 13:03:16 -04003407 return true;
3408}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003409
3410bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3411{
Geoff Lang36167ab2015-12-07 10:27:14 -05003412 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003413 {
3414 // The default VAO should always exist
3415 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003416 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003417 return false;
3418 }
3419
3420 return true;
3421}
3422
Geoff Langc5629752015-12-07 16:29:04 -05003423bool ValidateProgramBinaryBase(Context *context,
3424 GLuint program,
3425 GLenum binaryFormat,
3426 const void *binary,
3427 GLint length)
3428{
3429 Program *programObject = GetValidProgram(context, program);
3430 if (programObject == nullptr)
3431 {
3432 return false;
3433 }
3434
3435 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3436 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3437 programBinaryFormats.end())
3438 {
Jamie Madill437fa652016-05-03 15:13:24 -04003439 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05003440 return false;
3441 }
3442
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003443 if (context->hasActiveTransformFeedback(program))
3444 {
3445 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003446 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003447 "Cannot change program binary while program is associated with "
3448 "an active transform feedback object."));
3449 return false;
3450 }
3451
Geoff Langc5629752015-12-07 16:29:04 -05003452 return true;
3453}
3454
3455bool ValidateGetProgramBinaryBase(Context *context,
3456 GLuint program,
3457 GLsizei bufSize,
3458 GLsizei *length,
3459 GLenum *binaryFormat,
3460 void *binary)
3461{
3462 Program *programObject = GetValidProgram(context, program);
3463 if (programObject == nullptr)
3464 {
3465 return false;
3466 }
3467
3468 if (!programObject->isLinked())
3469 {
Jamie Madill437fa652016-05-03 15:13:24 -04003470 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05003471 return false;
3472 }
3473
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003474 if (context->getCaps().programBinaryFormats.empty())
3475 {
3476 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
3477 return false;
3478 }
3479
Geoff Langc5629752015-12-07 16:29:04 -05003480 return true;
3481}
Jamie Madillc29968b2016-01-20 11:17:23 -05003482
Jamie Madillc29968b2016-01-20 11:17:23 -05003483bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3484{
3485 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3486 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3487 {
Jamie Madill437fa652016-05-03 15:13:24 -04003488 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003489 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
3490 return false;
3491 }
3492
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003493 ASSERT(context->getGLState().getDrawFramebuffer());
3494 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003495 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3496
3497 // This should come first before the check for the default frame buffer
3498 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3499 // rather than INVALID_OPERATION
3500 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3501 {
3502 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3503
3504 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003505 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3506 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003507 {
3508 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003509 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3510 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3511 // 3.1 is still a bit ambiguous about the error, but future specs are
3512 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04003513 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02003514 return false;
3515 }
3516 else if (bufs[colorAttachment] >= maxColorAttachment)
3517 {
Jamie Madill437fa652016-05-03 15:13:24 -04003518 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02003519 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05003520 return false;
3521 }
3522 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3523 frameBufferId != 0)
3524 {
3525 // INVALID_OPERATION-GL is bound to buffer and ith argument
3526 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04003527 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003528 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
3529 return false;
3530 }
3531 }
3532
3533 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3534 // and n is not 1 or bufs is bound to value other than BACK and NONE
3535 if (frameBufferId == 0)
3536 {
3537 if (n != 1)
3538 {
Jamie Madill437fa652016-05-03 15:13:24 -04003539 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05003540 "n must be 1 when GL is bound to the default framebuffer"));
3541 return false;
3542 }
3543
3544 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3545 {
Jamie Madill437fa652016-05-03 15:13:24 -04003546 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05003547 GL_INVALID_OPERATION,
3548 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
3549 return false;
3550 }
3551 }
3552
3553 return true;
3554}
3555
Geoff Lang496c02d2016-10-20 11:38:11 -07003556bool ValidateGetBufferPointervBase(Context *context,
3557 GLenum target,
3558 GLenum pname,
3559 GLsizei *length,
3560 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003561{
Geoff Lang496c02d2016-10-20 11:38:11 -07003562 if (length)
3563 {
3564 *length = 0;
3565 }
3566
3567 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3568 {
3569 context->handleError(
3570 Error(GL_INVALID_OPERATION,
Jamie Madillcc6ac252017-01-25 12:57:21 -08003571 "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
Geoff Lang496c02d2016-10-20 11:38:11 -07003572 return false;
3573 }
3574
Olli Etuaho4f667482016-03-30 15:56:35 +03003575 if (!ValidBufferTarget(context, target))
3576 {
Jamie Madill437fa652016-05-03 15:13:24 -04003577 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03003578 return false;
3579 }
3580
Geoff Lang496c02d2016-10-20 11:38:11 -07003581 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003582 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003583 case GL_BUFFER_MAP_POINTER:
3584 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003585
Geoff Lang496c02d2016-10-20 11:38:11 -07003586 default:
3587 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
3588 return false;
3589 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003590
3591 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3592 // target bound to zero generate an INVALID_OPERATION error."
3593 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003594 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003595 {
Jamie Madill437fa652016-05-03 15:13:24 -04003596 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003597 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
3598 return false;
3599 }
3600
Geoff Lang496c02d2016-10-20 11:38:11 -07003601 if (length)
3602 {
3603 *length = 1;
3604 }
3605
Olli Etuaho4f667482016-03-30 15:56:35 +03003606 return true;
3607}
3608
3609bool ValidateUnmapBufferBase(Context *context, GLenum target)
3610{
3611 if (!ValidBufferTarget(context, target))
3612 {
Jamie Madill437fa652016-05-03 15:13:24 -04003613 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003614 return false;
3615 }
3616
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003617 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003618
3619 if (buffer == nullptr || !buffer->isMapped())
3620 {
Jamie Madill437fa652016-05-03 15:13:24 -04003621 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003622 return false;
3623 }
3624
3625 return true;
3626}
3627
3628bool ValidateMapBufferRangeBase(Context *context,
3629 GLenum target,
3630 GLintptr offset,
3631 GLsizeiptr length,
3632 GLbitfield access)
3633{
3634 if (!ValidBufferTarget(context, target))
3635 {
Jamie Madill437fa652016-05-03 15:13:24 -04003636 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003637 return false;
3638 }
3639
3640 if (offset < 0 || length < 0)
3641 {
Jamie Madill437fa652016-05-03 15:13:24 -04003642 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003643 return false;
3644 }
3645
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003646 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003647
3648 if (!buffer)
3649 {
Jamie Madill437fa652016-05-03 15:13:24 -04003650 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003651 return false;
3652 }
3653
3654 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003655 CheckedNumeric<size_t> checkedOffset(offset);
3656 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003657
Jamie Madille2e406c2016-06-02 13:04:10 -04003658 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003659 {
Jamie Madill437fa652016-05-03 15:13:24 -04003660 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003661 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
3662 return false;
3663 }
3664
3665 // Check for invalid bits in the mask
3666 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3667 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3668 GL_MAP_UNSYNCHRONIZED_BIT;
3669
3670 if (access & ~(allAccessBits))
3671 {
Jamie Madill437fa652016-05-03 15:13:24 -04003672 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03003673 return false;
3674 }
3675
3676 if (length == 0)
3677 {
Jamie Madill437fa652016-05-03 15:13:24 -04003678 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003679 return false;
3680 }
3681
3682 if (buffer->isMapped())
3683 {
Jamie Madill437fa652016-05-03 15:13:24 -04003684 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003685 return false;
3686 }
3687
3688 // Check for invalid bit combinations
3689 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3690 {
Jamie Madill437fa652016-05-03 15:13:24 -04003691 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003692 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
3693 return false;
3694 }
3695
3696 GLbitfield writeOnlyBits =
3697 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3698
3699 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3700 {
Jamie Madill437fa652016-05-03 15:13:24 -04003701 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03003702 "Invalid access bits when mapping buffer for reading: 0x%X.",
3703 access));
3704 return false;
3705 }
3706
3707 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3708 {
Jamie Madill437fa652016-05-03 15:13:24 -04003709 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003710 GL_INVALID_OPERATION,
3711 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
3712 return false;
3713 }
3714 return true;
3715}
3716
3717bool ValidateFlushMappedBufferRangeBase(Context *context,
3718 GLenum target,
3719 GLintptr offset,
3720 GLsizeiptr length)
3721{
3722 if (offset < 0 || length < 0)
3723 {
Jamie Madill437fa652016-05-03 15:13:24 -04003724 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003725 return false;
3726 }
3727
3728 if (!ValidBufferTarget(context, target))
3729 {
Jamie Madill437fa652016-05-03 15:13:24 -04003730 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003731 return false;
3732 }
3733
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003734 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003735
3736 if (buffer == nullptr)
3737 {
Jamie Madill437fa652016-05-03 15:13:24 -04003738 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003739 return false;
3740 }
3741
3742 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3743 {
Jamie Madill437fa652016-05-03 15:13:24 -04003744 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003745 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
3746 return false;
3747 }
3748
3749 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003750 CheckedNumeric<size_t> checkedOffset(offset);
3751 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003752
Jamie Madille2e406c2016-06-02 13:04:10 -04003753 if (!checkedSize.IsValid() ||
3754 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003755 {
Jamie Madill437fa652016-05-03 15:13:24 -04003756 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003757 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
3758 return false;
3759 }
3760
3761 return true;
3762}
3763
Olli Etuaho41997e72016-03-10 13:38:39 +02003764bool ValidateGenOrDelete(Context *context, GLint n)
3765{
3766 if (n < 0)
3767 {
Jamie Madill437fa652016-05-03 15:13:24 -04003768 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02003769 return false;
3770 }
3771 return true;
3772}
3773
Geoff Langff5b2d52016-09-07 11:32:23 -04003774bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3775{
3776 if (!context->getExtensions().robustClientMemory)
3777 {
3778 context->handleError(
3779 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
3780 return false;
3781 }
3782
3783 if (bufSize < 0)
3784 {
3785 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3786 return false;
3787 }
3788
3789 return true;
3790}
3791
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003792bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3793{
3794 if (bufSize < numParams)
3795 {
3796 context->handleError(Error(GL_INVALID_OPERATION,
3797 "%u parameters are required but %i were provided.", numParams,
3798 bufSize));
3799 return false;
3800 }
3801
3802 return true;
3803}
3804
Jamie Madillbe849e42017-05-02 15:49:00 -04003805bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3806 GLenum target,
3807 GLenum attachment,
3808 GLenum pname,
3809 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003810{
3811 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
Yunchao He33151a52017-04-13 09:58:17 +08003812 if (numParams)
3813 {
3814 *numParams = 1;
3815 }
Geoff Langff5b2d52016-09-07 11:32:23 -04003816
3817 if (!ValidFramebufferTarget(target))
3818 {
3819 context->handleError(Error(GL_INVALID_ENUM));
3820 return false;
3821 }
3822
3823 int clientVersion = context->getClientMajorVersion();
3824
3825 switch (pname)
3826 {
3827 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3828 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3829 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3830 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3831 break;
3832
3833 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3834 if (clientVersion < 3 && !context->getExtensions().sRGB)
3835 {
3836 context->handleError(Error(GL_INVALID_ENUM));
3837 return false;
3838 }
3839 break;
3840
3841 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3842 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3843 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3844 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3845 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3846 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3847 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3848 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3849 if (clientVersion < 3)
3850 {
3851 context->handleError(Error(GL_INVALID_ENUM));
3852 return false;
3853 }
3854 break;
3855
3856 default:
3857 context->handleError(Error(GL_INVALID_ENUM));
3858 return false;
3859 }
3860
3861 // Determine if the attachment is a valid enum
3862 switch (attachment)
3863 {
3864 case GL_BACK:
3865 case GL_FRONT:
3866 case GL_DEPTH:
3867 case GL_STENCIL:
3868 case GL_DEPTH_STENCIL_ATTACHMENT:
3869 if (clientVersion < 3)
3870 {
3871 context->handleError(Error(GL_INVALID_ENUM));
3872 return false;
3873 }
3874 break;
3875
3876 case GL_DEPTH_ATTACHMENT:
3877 case GL_STENCIL_ATTACHMENT:
3878 break;
3879
3880 default:
3881 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
3882 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3883 {
3884 context->handleError(Error(GL_INVALID_ENUM));
3885 return false;
3886 }
3887 break;
3888 }
3889
3890 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3891 ASSERT(framebuffer);
3892
3893 if (framebuffer->id() == 0)
3894 {
3895 if (clientVersion < 3)
3896 {
3897 context->handleError(Error(GL_INVALID_OPERATION));
3898 return false;
3899 }
3900
3901 switch (attachment)
3902 {
3903 case GL_BACK:
3904 case GL_DEPTH:
3905 case GL_STENCIL:
3906 break;
3907
3908 default:
3909 context->handleError(Error(GL_INVALID_OPERATION));
3910 return false;
3911 }
3912 }
3913 else
3914 {
3915 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3916 {
3917 // Valid attachment query
3918 }
3919 else
3920 {
3921 switch (attachment)
3922 {
3923 case GL_DEPTH_ATTACHMENT:
3924 case GL_STENCIL_ATTACHMENT:
3925 break;
3926
3927 case GL_DEPTH_STENCIL_ATTACHMENT:
3928 if (!framebuffer->hasValidDepthStencil())
3929 {
3930 context->handleError(Error(GL_INVALID_OPERATION));
3931 return false;
3932 }
3933 break;
3934
3935 default:
3936 context->handleError(Error(GL_INVALID_OPERATION));
3937 return false;
3938 }
3939 }
3940 }
3941
3942 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3943 if (attachmentObject)
3944 {
3945 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3946 attachmentObject->type() == GL_TEXTURE ||
3947 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3948
3949 switch (pname)
3950 {
3951 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3952 if (attachmentObject->type() != GL_RENDERBUFFER &&
3953 attachmentObject->type() != GL_TEXTURE)
3954 {
3955 context->handleError(Error(GL_INVALID_ENUM));
3956 return false;
3957 }
3958 break;
3959
3960 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3961 if (attachmentObject->type() != GL_TEXTURE)
3962 {
3963 context->handleError(Error(GL_INVALID_ENUM));
3964 return false;
3965 }
3966 break;
3967
3968 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3969 if (attachmentObject->type() != GL_TEXTURE)
3970 {
3971 context->handleError(Error(GL_INVALID_ENUM));
3972 return false;
3973 }
3974 break;
3975
3976 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3977 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3978 {
3979 context->handleError(Error(GL_INVALID_OPERATION));
3980 return false;
3981 }
3982 break;
3983
3984 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3985 if (attachmentObject->type() != GL_TEXTURE)
3986 {
3987 context->handleError(Error(GL_INVALID_ENUM));
3988 return false;
3989 }
3990 break;
3991
3992 default:
3993 break;
3994 }
3995 }
3996 else
3997 {
3998 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3999 // is NONE, then querying any other pname will generate INVALID_ENUM.
4000
4001 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4002 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4003 // INVALID_OPERATION for all other pnames
4004
4005 switch (pname)
4006 {
4007 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4008 break;
4009
4010 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4011 if (clientVersion < 3)
4012 {
4013 context->handleError(Error(GL_INVALID_ENUM));
4014 return false;
4015 }
4016 break;
4017
4018 default:
4019 if (clientVersion < 3)
4020 {
4021 context->handleError(Error(GL_INVALID_ENUM));
4022 return false;
4023 }
4024 else
4025 {
4026 context->handleError(Error(GL_INVALID_OPERATION));
4027 return false;
4028 }
4029 }
4030 }
4031
4032 return true;
4033}
4034
4035bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4036 GLenum target,
4037 GLenum attachment,
4038 GLenum pname,
4039 GLsizei bufSize,
4040 GLsizei *numParams)
4041{
4042 if (!ValidateRobustEntryPoint(context, bufSize))
4043 {
4044 return false;
4045 }
4046
Jamie Madillbe849e42017-05-02 15:49:00 -04004047 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4048 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004049 {
4050 return false;
4051 }
4052
4053 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4054 {
4055 return false;
4056 }
4057
4058 return true;
4059}
4060
Geoff Langff5b2d52016-09-07 11:32:23 -04004061bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4062 GLenum target,
4063 GLenum pname,
4064 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004065 GLsizei *length,
4066 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004067{
4068 if (!ValidateRobustEntryPoint(context, bufSize))
4069 {
4070 return false;
4071 }
4072
Geoff Langebebe1c2016-10-14 12:01:31 -04004073 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004074 {
4075 return false;
4076 }
4077
Geoff Langebebe1c2016-10-14 12:01:31 -04004078 if (!ValidateRobustBufferSize(context, bufSize, *length))
4079 {
4080 return false;
4081 }
4082
4083 return true;
4084}
4085
4086bool ValidateGetBufferParameteri64v(ValidationContext *context,
4087 GLenum target,
4088 GLenum pname,
4089 GLint64 *params)
4090{
4091 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4092}
4093
4094bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4095 GLenum target,
4096 GLenum pname,
4097 GLsizei bufSize,
4098 GLsizei *length,
4099 GLint64 *params)
4100{
4101 if (!ValidateRobustEntryPoint(context, bufSize))
4102 {
4103 return false;
4104 }
4105
4106 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4107 {
4108 return false;
4109 }
4110
4111 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004112 {
4113 return false;
4114 }
4115
4116 return true;
4117}
4118
Jamie Madillbe849e42017-05-02 15:49:00 -04004119bool ValidateGetProgramivBase(ValidationContext *context,
4120 GLuint program,
4121 GLenum pname,
4122 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004123{
4124 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004125 if (numParams)
4126 {
4127 *numParams = 1;
4128 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004129
4130 Program *programObject = GetValidProgram(context, program);
4131 if (!programObject)
4132 {
4133 return false;
4134 }
4135
4136 switch (pname)
4137 {
4138 case GL_DELETE_STATUS:
4139 case GL_LINK_STATUS:
4140 case GL_VALIDATE_STATUS:
4141 case GL_INFO_LOG_LENGTH:
4142 case GL_ATTACHED_SHADERS:
4143 case GL_ACTIVE_ATTRIBUTES:
4144 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4145 case GL_ACTIVE_UNIFORMS:
4146 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4147 break;
4148
4149 case GL_PROGRAM_BINARY_LENGTH:
4150 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4151 {
4152 context->handleError(Error(GL_INVALID_ENUM,
4153 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4154 "GL_OES_get_program_binary or ES 3.0."));
4155 return false;
4156 }
4157 break;
4158
4159 case GL_ACTIVE_UNIFORM_BLOCKS:
4160 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4161 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4162 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4163 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4164 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4165 if (context->getClientMajorVersion() < 3)
4166 {
4167 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4168 return false;
4169 }
4170 break;
4171
Yunchao He61afff12017-03-14 15:34:03 +08004172 case GL_PROGRAM_SEPARABLE:
4173 if (context->getClientVersion() < Version(3, 1))
4174 {
4175 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.1."));
4176 return false;
4177 }
4178 break;
4179
Geoff Langff5b2d52016-09-07 11:32:23 -04004180 default:
4181 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4182 return false;
4183 }
4184
4185 return true;
4186}
4187
4188bool ValidateGetProgramivRobustANGLE(Context *context,
4189 GLuint program,
4190 GLenum pname,
4191 GLsizei bufSize,
4192 GLsizei *numParams)
4193{
4194 if (!ValidateRobustEntryPoint(context, bufSize))
4195 {
4196 return false;
4197 }
4198
Jamie Madillbe849e42017-05-02 15:49:00 -04004199 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004200 {
4201 return false;
4202 }
4203
4204 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4205 {
4206 return false;
4207 }
4208
4209 return true;
4210}
4211
Geoff Lang740d9022016-10-07 11:20:52 -04004212bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4213 GLenum target,
4214 GLenum pname,
4215 GLsizei bufSize,
4216 GLsizei *length,
4217 GLint *params)
4218{
4219 if (!ValidateRobustEntryPoint(context, bufSize))
4220 {
4221 return false;
4222 }
4223
4224 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4225 {
4226 return false;
4227 }
4228
4229 if (!ValidateRobustBufferSize(context, bufSize, *length))
4230 {
4231 return false;
4232 }
4233
4234 return true;
4235}
4236
Geoff Langd7d0ed32016-10-07 11:33:51 -04004237bool ValidateGetShaderivRobustANGLE(Context *context,
4238 GLuint shader,
4239 GLenum pname,
4240 GLsizei bufSize,
4241 GLsizei *length,
4242 GLint *params)
4243{
4244 if (!ValidateRobustEntryPoint(context, bufSize))
4245 {
4246 return false;
4247 }
4248
4249 if (!ValidateGetShaderivBase(context, shader, pname, length))
4250 {
4251 return false;
4252 }
4253
4254 if (!ValidateRobustBufferSize(context, bufSize, *length))
4255 {
4256 return false;
4257 }
4258
4259 return true;
4260}
4261
Geoff Langc1984ed2016-10-07 12:41:00 -04004262bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4263 GLenum target,
4264 GLenum pname,
4265 GLsizei bufSize,
4266 GLsizei *length,
4267 GLfloat *params)
4268{
4269 if (!ValidateRobustEntryPoint(context, bufSize))
4270 {
4271 return false;
4272 }
4273
4274 if (!ValidateGetTexParameterBase(context, target, pname, length))
4275 {
4276 return false;
4277 }
4278
4279 if (!ValidateRobustBufferSize(context, bufSize, *length))
4280 {
4281 return false;
4282 }
4283
4284 return true;
4285}
4286
Geoff Langc1984ed2016-10-07 12:41:00 -04004287bool ValidateGetTexParameterivRobustANGLE(Context *context,
4288 GLenum target,
4289 GLenum pname,
4290 GLsizei bufSize,
4291 GLsizei *length,
4292 GLint *params)
4293{
4294 if (!ValidateRobustEntryPoint(context, bufSize))
4295 {
4296 return false;
4297 }
4298
4299 if (!ValidateGetTexParameterBase(context, target, pname, length))
4300 {
4301 return false;
4302 }
4303
4304 if (!ValidateRobustBufferSize(context, bufSize, *length))
4305 {
4306 return false;
4307 }
4308
4309 return true;
4310}
4311
Geoff Langc1984ed2016-10-07 12:41:00 -04004312bool ValidateTexParameterfvRobustANGLE(Context *context,
4313 GLenum target,
4314 GLenum pname,
4315 GLsizei bufSize,
4316 const GLfloat *params)
4317{
4318 if (!ValidateRobustEntryPoint(context, bufSize))
4319 {
4320 return false;
4321 }
4322
4323 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4324}
4325
Geoff Langc1984ed2016-10-07 12:41:00 -04004326bool ValidateTexParameterivRobustANGLE(Context *context,
4327 GLenum target,
4328 GLenum pname,
4329 GLsizei bufSize,
4330 const GLint *params)
4331{
4332 if (!ValidateRobustEntryPoint(context, bufSize))
4333 {
4334 return false;
4335 }
4336
4337 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4338}
4339
4340bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4341{
4342 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4343}
4344
4345bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4346 GLuint sampler,
4347 GLenum pname,
4348 GLuint bufSize,
4349 GLsizei *length,
4350 GLfloat *params)
4351{
4352 if (!ValidateRobustEntryPoint(context, bufSize))
4353 {
4354 return false;
4355 }
4356
4357 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4358 {
4359 return false;
4360 }
4361
4362 if (!ValidateRobustBufferSize(context, bufSize, *length))
4363 {
4364 return false;
4365 }
4366
4367 return true;
4368}
4369
4370bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4371{
4372 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4373}
4374
4375bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4376 GLuint sampler,
4377 GLenum pname,
4378 GLuint bufSize,
4379 GLsizei *length,
4380 GLint *params)
4381{
4382 if (!ValidateRobustEntryPoint(context, bufSize))
4383 {
4384 return false;
4385 }
4386
4387 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4388 {
4389 return false;
4390 }
4391
4392 if (!ValidateRobustBufferSize(context, bufSize, *length))
4393 {
4394 return false;
4395 }
4396
4397 return true;
4398}
4399
4400bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4401{
4402 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4403}
4404
4405bool ValidateSamplerParameterfv(Context *context,
4406 GLuint sampler,
4407 GLenum pname,
4408 const GLfloat *params)
4409{
4410 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4411}
4412
4413bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4414 GLuint sampler,
4415 GLenum pname,
4416 GLsizei bufSize,
4417 const GLfloat *params)
4418{
4419 if (!ValidateRobustEntryPoint(context, bufSize))
4420 {
4421 return false;
4422 }
4423
4424 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4425}
4426
4427bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4428{
4429 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4430}
4431
4432bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4433{
4434 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4435}
4436
4437bool ValidateSamplerParameterivRobustANGLE(Context *context,
4438 GLuint sampler,
4439 GLenum pname,
4440 GLsizei bufSize,
4441 const GLint *params)
4442{
4443 if (!ValidateRobustEntryPoint(context, bufSize))
4444 {
4445 return false;
4446 }
4447
4448 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4449}
4450
Geoff Lang0b031062016-10-13 14:30:04 -04004451bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4452 GLuint index,
4453 GLenum pname,
4454 GLsizei bufSize,
4455 GLsizei *length,
4456 GLfloat *params)
4457{
4458 if (!ValidateRobustEntryPoint(context, bufSize))
4459 {
4460 return false;
4461 }
4462
4463 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4464 {
4465 return false;
4466 }
4467
4468 if (!ValidateRobustBufferSize(context, bufSize, *length))
4469 {
4470 return false;
4471 }
4472
4473 return true;
4474}
4475
Geoff Lang0b031062016-10-13 14:30:04 -04004476bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4477 GLuint index,
4478 GLenum pname,
4479 GLsizei bufSize,
4480 GLsizei *length,
4481 GLint *params)
4482{
4483 if (!ValidateRobustEntryPoint(context, bufSize))
4484 {
4485 return false;
4486 }
4487
4488 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4489 {
4490 return false;
4491 }
4492
4493 if (!ValidateRobustBufferSize(context, bufSize, *length))
4494 {
4495 return false;
4496 }
4497
4498 return true;
4499}
4500
Geoff Lang0b031062016-10-13 14:30:04 -04004501bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4502 GLuint index,
4503 GLenum pname,
4504 GLsizei bufSize,
4505 GLsizei *length,
4506 void **pointer)
4507{
4508 if (!ValidateRobustEntryPoint(context, bufSize))
4509 {
4510 return false;
4511 }
4512
4513 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4514 {
4515 return false;
4516 }
4517
4518 if (!ValidateRobustBufferSize(context, bufSize, *length))
4519 {
4520 return false;
4521 }
4522
4523 return true;
4524}
4525
4526bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4527{
4528 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4529}
4530
4531bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4532 GLuint index,
4533 GLenum pname,
4534 GLsizei bufSize,
4535 GLsizei *length,
4536 GLint *params)
4537{
4538 if (!ValidateRobustEntryPoint(context, bufSize))
4539 {
4540 return false;
4541 }
4542
4543 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4544 {
4545 return false;
4546 }
4547
4548 if (!ValidateRobustBufferSize(context, bufSize, *length))
4549 {
4550 return false;
4551 }
4552
4553 return true;
4554}
4555
4556bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4557{
4558 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4559}
4560
4561bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4562 GLuint index,
4563 GLenum pname,
4564 GLsizei bufSize,
4565 GLsizei *length,
4566 GLuint *params)
4567{
4568 if (!ValidateRobustEntryPoint(context, bufSize))
4569 {
4570 return false;
4571 }
4572
4573 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4574 {
4575 return false;
4576 }
4577
4578 if (!ValidateRobustBufferSize(context, bufSize, *length))
4579 {
4580 return false;
4581 }
4582
4583 return true;
4584}
4585
Geoff Lang6899b872016-10-14 11:30:13 -04004586bool ValidateGetActiveUniformBlockiv(Context *context,
4587 GLuint program,
4588 GLuint uniformBlockIndex,
4589 GLenum pname,
4590 GLint *params)
4591{
4592 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
4593}
4594
4595bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4596 GLuint program,
4597 GLuint uniformBlockIndex,
4598 GLenum pname,
4599 GLsizei bufSize,
4600 GLsizei *length,
4601 GLint *params)
4602{
4603 if (!ValidateRobustEntryPoint(context, bufSize))
4604 {
4605 return false;
4606 }
4607
4608 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4609 {
4610 return false;
4611 }
4612
4613 if (!ValidateRobustBufferSize(context, bufSize, *length))
4614 {
4615 return false;
4616 }
4617
4618 return true;
4619}
4620
Geoff Lang0a9661f2016-10-20 10:59:20 -07004621bool ValidateGetInternalFormativ(Context *context,
4622 GLenum target,
4623 GLenum internalformat,
4624 GLenum pname,
4625 GLsizei bufSize,
4626 GLint *params)
4627{
4628 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4629 nullptr);
4630}
4631
4632bool ValidateGetInternalFormativRobustANGLE(Context *context,
4633 GLenum target,
4634 GLenum internalformat,
4635 GLenum pname,
4636 GLsizei bufSize,
4637 GLsizei *length,
4638 GLint *params)
4639{
4640 if (!ValidateRobustEntryPoint(context, bufSize))
4641 {
4642 return false;
4643 }
4644
4645 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4646 {
4647 return false;
4648 }
4649
4650 if (!ValidateRobustBufferSize(context, bufSize, *length))
4651 {
4652 return false;
4653 }
4654
4655 return true;
4656}
4657
Shao80957d92017-02-20 21:25:59 +08004658bool ValidateVertexFormatBase(ValidationContext *context,
4659 GLuint attribIndex,
4660 GLint size,
4661 GLenum type,
4662 GLboolean pureInteger)
4663{
4664 const Caps &caps = context->getCaps();
4665 if (attribIndex >= caps.maxVertexAttributes)
4666 {
4667 context->handleError(
4668 Error(GL_INVALID_VALUE, "attribindex must be smaller than MAX_VERTEX_ATTRIBS."));
4669 return false;
4670 }
4671
4672 if (size < 1 || size > 4)
4673 {
4674 context->handleError(Error(GL_INVALID_VALUE, "size must be between one and four."));
4675 }
4676
4677 switch (type)
4678 {
4679 case GL_BYTE:
4680 case GL_UNSIGNED_BYTE:
4681 case GL_SHORT:
4682 case GL_UNSIGNED_SHORT:
4683 break;
4684
4685 case GL_INT:
4686 case GL_UNSIGNED_INT:
4687 if (context->getClientMajorVersion() < 3)
4688 {
4689 context->handleError(
4690 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
4691 return false;
4692 }
4693 break;
4694
4695 case GL_FIXED:
4696 case GL_FLOAT:
4697 if (pureInteger)
4698 {
4699 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
4700 return false;
4701 }
4702 break;
4703
4704 case GL_HALF_FLOAT:
4705 if (context->getClientMajorVersion() < 3)
4706 {
4707 context->handleError(
4708 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
4709 return false;
4710 }
4711 if (pureInteger)
4712 {
4713 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
4714 return false;
4715 }
4716 break;
4717
4718 case GL_INT_2_10_10_10_REV:
4719 case GL_UNSIGNED_INT_2_10_10_10_REV:
4720 if (context->getClientMajorVersion() < 3)
4721 {
4722 context->handleError(
4723 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
4724 return false;
4725 }
4726 if (pureInteger)
4727 {
4728 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
4729 return false;
4730 }
4731 if (size != 4)
4732 {
4733 context->handleError(Error(GL_INVALID_OPERATION,
4734 "Type is INT_2_10_10_10_REV or "
4735 "UNSIGNED_INT_2_10_10_10_REV and size is not 4."));
4736 return false;
4737 }
4738 break;
4739
4740 default:
4741 context->handleError(Error(GL_INVALID_ENUM, "Invalid vertex type."));
4742 return false;
4743 }
4744
4745 return true;
4746}
4747
Geoff Lang76e65652017-03-27 14:58:02 -04004748// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4749// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4750// specified clear value and the type of a buffer that is being cleared generates an
4751// INVALID_OPERATION error instead of producing undefined results
4752bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4753 GLint drawbuffer,
4754 const GLenum *validComponentTypes,
4755 size_t validComponentTypeCount)
4756{
4757 const FramebufferAttachment *attachment =
4758 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4759 if (attachment)
4760 {
4761 GLenum componentType = attachment->getFormat().info->componentType;
4762 const GLenum *end = validComponentTypes + validComponentTypeCount;
4763 if (std::find(validComponentTypes, end, componentType) == end)
4764 {
4765 context->handleError(
4766 Error(GL_INVALID_OPERATION,
4767 "No defined conversion between clear value and attachment format."));
4768 return false;
4769 }
4770 }
4771
4772 return true;
4773}
4774
Corentin Wallezb2931602017-04-11 15:58:57 -04004775bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4776 GLsizei imageSize,
4777 GLsizei dataSize)
4778{
4779 if (!ValidateRobustEntryPoint(context, dataSize))
4780 {
4781 return false;
4782 }
4783
4784 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
4785 if (pixelUnpackBuffer == nullptr)
4786 {
4787 if (dataSize < imageSize)
4788 {
4789 context->handleError(
4790 Error(GL_INVALID_OPERATION, "dataSize must be at least %i.", imageSize));
4791 }
4792 }
4793 return true;
4794}
4795
Jamie Madillbe849e42017-05-02 15:49:00 -04004796bool ValidateGetBufferParameterBase(ValidationContext *context,
4797 GLenum target,
4798 GLenum pname,
4799 bool pointerVersion,
4800 GLsizei *numParams)
4801{
4802 if (numParams)
4803 {
4804 *numParams = 0;
4805 }
4806
4807 if (!ValidBufferTarget(context, target))
4808 {
4809 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
4810 return false;
4811 }
4812
4813 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4814 if (!buffer)
4815 {
4816 // A null buffer means that "0" is bound to the requested buffer target
4817 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
4818 return false;
4819 }
4820
4821 const Extensions &extensions = context->getExtensions();
4822
4823 switch (pname)
4824 {
4825 case GL_BUFFER_USAGE:
4826 case GL_BUFFER_SIZE:
4827 break;
4828
4829 case GL_BUFFER_ACCESS_OES:
4830 if (!extensions.mapBuffer)
4831 {
4832 context->handleError(
4833 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer."));
4834 return false;
4835 }
4836 break;
4837
4838 case GL_BUFFER_MAPPED:
4839 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4840 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4841 !extensions.mapBufferRange)
4842 {
4843 context->handleError(Error(
4844 GL_INVALID_ENUM,
4845 "pname requires OpenGL ES 3.0, GL_OES_mapbuffer or GL_EXT_map_buffer_range."));
4846 return false;
4847 }
4848 break;
4849
4850 case GL_BUFFER_MAP_POINTER:
4851 if (!pointerVersion)
4852 {
4853 context->handleError(
4854 Error(GL_INVALID_ENUM,
4855 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
4856 return false;
4857 }
4858 break;
4859
4860 case GL_BUFFER_ACCESS_FLAGS:
4861 case GL_BUFFER_MAP_OFFSET:
4862 case GL_BUFFER_MAP_LENGTH:
4863 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4864 {
4865 context->handleError(Error(
4866 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
4867 return false;
4868 }
4869 break;
4870
4871 default:
4872 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4873 return false;
4874 }
4875
4876 // All buffer parameter queries return one value.
4877 if (numParams)
4878 {
4879 *numParams = 1;
4880 }
4881
4882 return true;
4883}
4884
4885bool ValidateGetRenderbufferParameterivBase(Context *context,
4886 GLenum target,
4887 GLenum pname,
4888 GLsizei *length)
4889{
4890 if (length)
4891 {
4892 *length = 0;
4893 }
4894
4895 if (target != GL_RENDERBUFFER)
4896 {
4897 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
4898 return false;
4899 }
4900
4901 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4902 if (renderbuffer == nullptr)
4903 {
4904 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
4905 return false;
4906 }
4907
4908 switch (pname)
4909 {
4910 case GL_RENDERBUFFER_WIDTH:
4911 case GL_RENDERBUFFER_HEIGHT:
4912 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4913 case GL_RENDERBUFFER_RED_SIZE:
4914 case GL_RENDERBUFFER_GREEN_SIZE:
4915 case GL_RENDERBUFFER_BLUE_SIZE:
4916 case GL_RENDERBUFFER_ALPHA_SIZE:
4917 case GL_RENDERBUFFER_DEPTH_SIZE:
4918 case GL_RENDERBUFFER_STENCIL_SIZE:
4919 break;
4920
4921 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4922 if (!context->getExtensions().framebufferMultisample)
4923 {
4924 context->handleError(
4925 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
4926 return false;
4927 }
4928 break;
4929
4930 default:
4931 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4932 return false;
4933 }
4934
4935 if (length)
4936 {
4937 *length = 1;
4938 }
4939 return true;
4940}
4941
4942bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4943{
4944 if (length)
4945 {
4946 *length = 0;
4947 }
4948
4949 if (GetValidShader(context, shader) == nullptr)
4950 {
4951 return false;
4952 }
4953
4954 switch (pname)
4955 {
4956 case GL_SHADER_TYPE:
4957 case GL_DELETE_STATUS:
4958 case GL_COMPILE_STATUS:
4959 case GL_INFO_LOG_LENGTH:
4960 case GL_SHADER_SOURCE_LENGTH:
4961 break;
4962
4963 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4964 if (!context->getExtensions().translatedShaderSource)
4965 {
4966 context->handleError(
4967 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
4968 return false;
4969 }
4970 break;
4971
4972 default:
4973 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4974 return false;
4975 }
4976
4977 if (length)
4978 {
4979 *length = 1;
4980 }
4981 return true;
4982}
4983
4984bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4985{
4986 if (length)
4987 {
4988 *length = 0;
4989 }
4990
4991 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4992 {
4993 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
4994 return false;
4995 }
4996
4997 if (context->getTargetTexture(target) == nullptr)
4998 {
4999 // Should only be possible for external textures
5000 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
5001 return false;
5002 }
5003
5004 switch (pname)
5005 {
5006 case GL_TEXTURE_MAG_FILTER:
5007 case GL_TEXTURE_MIN_FILTER:
5008 case GL_TEXTURE_WRAP_S:
5009 case GL_TEXTURE_WRAP_T:
5010 break;
5011
5012 case GL_TEXTURE_USAGE_ANGLE:
5013 if (!context->getExtensions().textureUsage)
5014 {
5015 context->handleError(
5016 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
5017 return false;
5018 }
5019 break;
5020
5021 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5022 if (!context->getExtensions().textureFilterAnisotropic)
5023 {
5024 context->handleError(
5025 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
5026 return false;
5027 }
5028 break;
5029
5030 case GL_TEXTURE_IMMUTABLE_FORMAT:
5031 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5032 {
5033 context->handleError(
5034 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
5035 return false;
5036 }
5037 break;
5038
5039 case GL_TEXTURE_WRAP_R:
5040 case GL_TEXTURE_IMMUTABLE_LEVELS:
5041 case GL_TEXTURE_SWIZZLE_R:
5042 case GL_TEXTURE_SWIZZLE_G:
5043 case GL_TEXTURE_SWIZZLE_B:
5044 case GL_TEXTURE_SWIZZLE_A:
5045 case GL_TEXTURE_BASE_LEVEL:
5046 case GL_TEXTURE_MAX_LEVEL:
5047 case GL_TEXTURE_MIN_LOD:
5048 case GL_TEXTURE_MAX_LOD:
5049 case GL_TEXTURE_COMPARE_MODE:
5050 case GL_TEXTURE_COMPARE_FUNC:
5051 if (context->getClientMajorVersion() < 3)
5052 {
5053 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
5054 return false;
5055 }
5056 break;
5057
5058 case GL_TEXTURE_SRGB_DECODE_EXT:
5059 if (!context->getExtensions().textureSRGBDecode)
5060 {
5061 context->handleError(
5062 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
5063 return false;
5064 }
5065 break;
5066
5067 default:
5068 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
5069 return false;
5070 }
5071
5072 if (length)
5073 {
5074 *length = 1;
5075 }
5076 return true;
5077}
5078
5079bool ValidateGetVertexAttribBase(Context *context,
5080 GLuint index,
5081 GLenum pname,
5082 GLsizei *length,
5083 bool pointer,
5084 bool pureIntegerEntryPoint)
5085{
5086 if (length)
5087 {
5088 *length = 0;
5089 }
5090
5091 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5092 {
5093 context->handleError(
5094 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
5095 return false;
5096 }
5097
5098 if (index >= context->getCaps().maxVertexAttributes)
5099 {
5100 context->handleError(Error(
5101 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
5102 return false;
5103 }
5104
5105 if (pointer)
5106 {
5107 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5108 {
5109 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
5110 return false;
5111 }
5112 }
5113 else
5114 {
5115 switch (pname)
5116 {
5117 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5118 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5119 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5120 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5121 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5122 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5123 case GL_CURRENT_VERTEX_ATTRIB:
5124 break;
5125
5126 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5127 static_assert(
5128 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5129 "ANGLE extension enums not equal to GL enums.");
5130 if (context->getClientMajorVersion() < 3 &&
5131 !context->getExtensions().instancedArrays)
5132 {
5133 context->handleError(Error(GL_INVALID_ENUM,
5134 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
5135 "3.0 or GL_ANGLE_instanced_arrays."));
5136 return false;
5137 }
5138 break;
5139
5140 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5141 if (context->getClientMajorVersion() < 3)
5142 {
5143 context->handleError(Error(
5144 GL_INVALID_ENUM, "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0."));
5145 return false;
5146 }
5147 break;
5148
5149 case GL_VERTEX_ATTRIB_BINDING:
5150 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5151 if (context->getClientVersion() < ES_3_1)
5152 {
5153 context->handleError(
5154 Error(GL_INVALID_ENUM, "Vertex Attrib Bindings require OpenGL ES 3.1."));
5155 return false;
5156 }
5157 break;
5158
5159 default:
5160 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
5161 return false;
5162 }
5163 }
5164
5165 if (length)
5166 {
5167 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5168 {
5169 *length = 4;
5170 }
5171 else
5172 {
5173 *length = 1;
5174 }
5175 }
5176
5177 return true;
5178}
5179
5180bool ValidateReadPixelsBase(ValidationContext *context,
5181 GLint x,
5182 GLint y,
5183 GLsizei width,
5184 GLsizei height,
5185 GLenum format,
5186 GLenum type,
5187 GLsizei bufSize,
5188 GLsizei *length,
5189 GLsizei *columns,
5190 GLsizei *rows,
5191 void *pixels)
5192{
5193 if (length != nullptr)
5194 {
5195 *length = 0;
5196 }
5197 if (rows != nullptr)
5198 {
5199 *rows = 0;
5200 }
5201 if (columns != nullptr)
5202 {
5203 *columns = 0;
5204 }
5205
5206 if (width < 0 || height < 0)
5207 {
5208 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
5209 return false;
5210 }
5211
5212 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5213
5214 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5215 {
5216 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
5217 return false;
5218 }
5219
5220 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5221 {
5222 context->handleError(Error(GL_INVALID_OPERATION));
5223 return false;
5224 }
5225
5226 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5227 ASSERT(framebuffer);
5228
5229 if (framebuffer->getReadBufferState() == GL_NONE)
5230 {
5231 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
5232 return false;
5233 }
5234
5235 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5236 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5237 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5238 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5239 // situation is an application error that would lead to a crash in ANGLE.
5240 if (readBuffer == nullptr)
5241 {
5242 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
5243 return false;
5244 }
5245
5246 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
5247 GLenum currentType = framebuffer->getImplementationColorReadType();
5248 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5249
5250 bool validFormatTypeCombination =
5251 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5252
5253 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5254 {
5255 context->handleError(Error(GL_INVALID_OPERATION));
5256 return false;
5257 }
5258
5259 // Check for pixel pack buffer related API errors
5260 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5261 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5262 {
5263 // ...the buffer object's data store is currently mapped.
5264 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
5265 return false;
5266 }
5267
5268 // .. the data would be packed to the buffer object such that the memory writes required
5269 // would exceed the data store size.
5270 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5271 const gl::Extents size(width, height, 1);
5272 const auto &pack = context->getGLState().getPackState();
5273
5274 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5275 if (endByteOrErr.isError())
5276 {
5277 context->handleError(endByteOrErr.getError());
5278 return false;
5279 }
5280
5281 size_t endByte = endByteOrErr.getResult();
5282 if (bufSize >= 0)
5283 {
5284 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5285 {
5286 context->handleError(
5287 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
5288 return false;
5289 }
5290 }
5291
5292 if (pixelPackBuffer != nullptr)
5293 {
5294 CheckedNumeric<size_t> checkedEndByte(endByte);
5295 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5296 checkedEndByte += checkedOffset;
5297
5298 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5299 {
5300 // Overflow past the end of the buffer
5301 context->handleError(
5302 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
5303 return false;
5304 }
5305 }
5306
5307 if (pixelPackBuffer == nullptr && length != nullptr)
5308 {
5309 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5310 {
5311 context->handleError(
5312 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
5313 return false;
5314 }
5315
5316 *length = static_cast<GLsizei>(endByte);
5317 }
5318
5319 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5320 angle::CheckedNumeric<int> clippedExtent(length);
5321 if (start < 0)
5322 {
5323 // "subtract" the area that is less than 0
5324 clippedExtent += start;
5325 }
5326
5327 const int readExtent = start + length;
5328 if (readExtent > bufferSize)
5329 {
5330 // Subtract the region to the right of the read buffer
5331 clippedExtent -= (readExtent - bufferSize);
5332 }
5333
5334 if (!clippedExtent.IsValid())
5335 {
5336 return 0;
5337 }
5338
5339 return std::max(clippedExtent.ValueOrDie(), 0);
5340 };
5341
5342 if (columns != nullptr)
5343 {
5344 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5345 }
5346
5347 if (rows != nullptr)
5348 {
5349 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5350 }
5351
5352 return true;
5353}
5354
5355template <typename ParamType>
5356bool ValidateTexParameterBase(Context *context,
5357 GLenum target,
5358 GLenum pname,
5359 GLsizei bufSize,
5360 const ParamType *params)
5361{
5362 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5363 {
5364 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
5365 return false;
5366 }
5367
5368 if (context->getTargetTexture(target) == nullptr)
5369 {
5370 // Should only be possible for external textures
5371 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
5372 return false;
5373 }
5374
5375 const GLsizei minBufSize = 1;
5376 if (bufSize >= 0 && bufSize < minBufSize)
5377 {
5378 context->handleError(
5379 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
5380 return false;
5381 }
5382
5383 switch (pname)
5384 {
5385 case GL_TEXTURE_WRAP_R:
5386 case GL_TEXTURE_SWIZZLE_R:
5387 case GL_TEXTURE_SWIZZLE_G:
5388 case GL_TEXTURE_SWIZZLE_B:
5389 case GL_TEXTURE_SWIZZLE_A:
5390 case GL_TEXTURE_BASE_LEVEL:
5391 case GL_TEXTURE_MAX_LEVEL:
5392 case GL_TEXTURE_COMPARE_MODE:
5393 case GL_TEXTURE_COMPARE_FUNC:
5394 case GL_TEXTURE_MIN_LOD:
5395 case GL_TEXTURE_MAX_LOD:
5396 if (context->getClientMajorVersion() < 3)
5397 {
5398 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
5399 return false;
5400 }
5401 if (target == GL_TEXTURE_EXTERNAL_OES &&
5402 !context->getExtensions().eglImageExternalEssl3)
5403 {
5404 context->handleError(Error(GL_INVALID_ENUM,
5405 "ES3 texture parameters are not available without "
5406 "GL_OES_EGL_image_external_essl3."));
5407 return false;
5408 }
5409 break;
5410
5411 default:
5412 break;
5413 }
5414
5415 switch (pname)
5416 {
5417 case GL_TEXTURE_WRAP_S:
5418 case GL_TEXTURE_WRAP_T:
5419 case GL_TEXTURE_WRAP_R:
5420 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
5421 {
5422 return false;
5423 }
5424 break;
5425
5426 case GL_TEXTURE_MIN_FILTER:
5427 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
5428 {
5429 return false;
5430 }
5431 break;
5432
5433 case GL_TEXTURE_MAG_FILTER:
5434 if (!ValidateTextureMagFilterValue(context, params))
5435 {
5436 return false;
5437 }
5438 break;
5439
5440 case GL_TEXTURE_USAGE_ANGLE:
5441 switch (ConvertToGLenum(params[0]))
5442 {
5443 case GL_NONE:
5444 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5445 break;
5446
5447 default:
5448 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
5449 return false;
5450 }
5451 break;
5452
5453 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5454 if (!context->getExtensions().textureFilterAnisotropic)
5455 {
5456 context->handleError(
5457 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
5458 return false;
5459 }
5460
5461 // we assume the parameter passed to this validation method is truncated, not rounded
5462 if (params[0] < 1)
5463 {
5464 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
5465 return false;
5466 }
5467 break;
5468
5469 case GL_TEXTURE_MIN_LOD:
5470 case GL_TEXTURE_MAX_LOD:
5471 // any value is permissible
5472 break;
5473
5474 case GL_TEXTURE_COMPARE_MODE:
5475 if (!ValidateTextureCompareModeValue(context, params))
5476 {
5477 return false;
5478 }
5479 break;
5480
5481 case GL_TEXTURE_COMPARE_FUNC:
5482 if (!ValidateTextureCompareFuncValue(context, params))
5483 {
5484 return false;
5485 }
5486 break;
5487
5488 case GL_TEXTURE_SWIZZLE_R:
5489 case GL_TEXTURE_SWIZZLE_G:
5490 case GL_TEXTURE_SWIZZLE_B:
5491 case GL_TEXTURE_SWIZZLE_A:
5492 switch (ConvertToGLenum(params[0]))
5493 {
5494 case GL_RED:
5495 case GL_GREEN:
5496 case GL_BLUE:
5497 case GL_ALPHA:
5498 case GL_ZERO:
5499 case GL_ONE:
5500 break;
5501
5502 default:
5503 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
5504 return false;
5505 }
5506 break;
5507
5508 case GL_TEXTURE_BASE_LEVEL:
5509 if (params[0] < 0)
5510 {
5511 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
5512 return false;
5513 }
5514 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5515 {
5516 context->handleError(
5517 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
5518 return false;
5519 }
5520 break;
5521
5522 case GL_TEXTURE_MAX_LEVEL:
5523 if (params[0] < 0)
5524 {
5525 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
5526 return false;
5527 }
5528 break;
5529
5530 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5531 if (context->getClientVersion() < Version(3, 1))
5532 {
5533 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
5534 return false;
5535 }
5536 switch (ConvertToGLenum(params[0]))
5537 {
5538 case GL_DEPTH_COMPONENT:
5539 case GL_STENCIL_INDEX:
5540 break;
5541
5542 default:
5543 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
5544 return false;
5545 }
5546 break;
5547
5548 case GL_TEXTURE_SRGB_DECODE_EXT:
5549 if (!ValidateTextureSRGBDecodeValue(context, params))
5550 {
5551 return false;
5552 }
5553 break;
5554
5555 default:
5556 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
5557 return false;
5558 }
5559
5560 return true;
5561}
5562
5563template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5564template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5565
Jamie Madillc29968b2016-01-20 11:17:23 -05005566} // namespace gl