blob: 21459cf255e20f9f5b565b60a337995fb156a4f0 [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"
Brandon Jones6cad5662017-06-14 13:25:13 -070013#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040016#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050017#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Query.h"
19#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/TransformFeedback.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040021#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050022#include "libANGLE/VertexArray.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040023#include "libANGLE/formatutils.h"
24#include "libANGLE/validationES2.h"
25#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040026
27#include "common/mathutil.h"
28#include "common/utilities.h"
29
Jamie Madille2e406c2016-06-02 13:04:10 -040030using namespace angle;
31
Geoff Lange8ebe7f2013-08-05 15:03:13 -040032namespace gl
33{
Jamie Madill1ca74672015-07-21 15:14:11 -040034namespace
35{
Corentin Wallez92db6942016-12-09 13:10:36 -050036bool ValidateDrawAttribs(ValidationContext *context,
37 GLint primcount,
38 GLint maxVertex,
39 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040040{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070041 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040042 const gl::Program *program = state.getProgram();
43
Corentin Wallez327411e2016-12-09 11:09:17 -050044 bool webglCompatibility = context->getExtensions().webglCompatibility;
45
Jamie Madill231c7f52017-04-26 13:45:37 -040046 const VertexArray *vao = state.getVertexArray();
47 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080048 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madill231c7f52017-04-26 13:45:37 -040049 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040050 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
51 {
52 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallez672f7f32017-06-15 17:42:17 -040053
54 // No need to range check for disabled attribs.
55 if (!attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040056 {
Corentin Wallezfd456442016-12-21 17:57:00 -050057 continue;
58 }
Jamie Madill1ca74672015-07-21 15:14:11 -040059
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.
Corentin Wallez672f7f32017-06-15 17:42:17 -040062 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
63 gl::Buffer *buffer = binding.getBuffer().get();
Corentin Wallezfd456442016-12-21 17:57:00 -050064 if (!buffer)
65 {
Geoff Langfeb8c682017-02-13 16:07:35 -050066 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050067 {
68 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050069 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
70 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
71 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
72 // error.
Brandon Jonesafa75152017-07-21 13:11:29 -070073 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
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
Brandon Jonesafa75152017-07-21 13:11:29 -070080 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
Jamie Madill1ca74672015-07-21 15:14:11 -040081 return false;
82 }
Corentin Wallezfd456442016-12-21 17:57:00 -050083 continue;
84 }
85
Corentin Wallez672f7f32017-06-15 17:42:17 -040086 // This needs to come after the check for client arrays as even unused attributes cannot use
87 // client-side arrays
88 if (!program->isAttribLocationActive(attributeIndex))
89 {
90 continue;
91 }
92
Corentin Wallezfd456442016-12-21 17:57:00 -050093 // If we're drawing zero vertices, we have enough data.
94 if (vertexCount <= 0 || primcount <= 0)
95 {
96 continue;
97 }
98
99 GLint maxVertexElement = 0;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300100 GLuint divisor = binding.getDivisor();
101 if (divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500102 {
103 maxVertexElement = maxVertex;
104 }
105 else
106 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300107 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500108 }
109
110 // We do manual overflow checks here instead of using safe_math.h because it was
111 // a bottleneck. Thanks to some properties of GL we know inequalities that can
112 // help us make the overflow checks faster.
113
114 // The max possible attribSize is 16 for a vector of 4 32 bit values.
115 constexpr uint64_t kMaxAttribSize = 16;
116 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
117 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
118
119 // We know attribStride is given as a GLsizei which is typedefed to int.
120 // We also know an upper bound for attribSize.
121 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800122 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500123 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
124 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
125
126 // Computing the max offset using uint64_t without attrib.offset is overflow
127 // safe. Note: Last vertex element does not take the full stride!
128 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
129 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
130
131 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800132 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
133 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500134 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700135 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500136 return false;
137 }
138 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
139
140 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
141 // We can return INVALID_OPERATION if our vertex attribute does not have
142 // enough backing data.
143 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
144 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700145 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500146 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400147 }
148 }
149
150 return true;
151}
152
Geoff Lang280ba992017-04-18 16:30:58 -0400153bool ValidReadPixelsTypeEnum(ValidationContext *context, GLenum type)
154{
155 switch (type)
156 {
157 // Types referenced in Table 3.4 of the ES 2.0.25 spec
158 case GL_UNSIGNED_BYTE:
159 case GL_UNSIGNED_SHORT_4_4_4_4:
160 case GL_UNSIGNED_SHORT_5_5_5_1:
161 case GL_UNSIGNED_SHORT_5_6_5:
162 return context->getClientVersion() >= ES_2_0;
163
164 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
165 case GL_BYTE:
166 case GL_INT:
167 case GL_SHORT:
168 case GL_UNSIGNED_INT:
169 case GL_UNSIGNED_INT_10F_11F_11F_REV:
170 case GL_UNSIGNED_INT_24_8:
171 case GL_UNSIGNED_INT_2_10_10_10_REV:
172 case GL_UNSIGNED_INT_5_9_9_9_REV:
173 case GL_UNSIGNED_SHORT:
174 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
175 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
176 return context->getClientVersion() >= ES_3_0;
177
178 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400179 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
180 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400181
182 case GL_HALF_FLOAT:
183 return context->getClientVersion() >= ES_3_0 ||
184 context->getExtensions().textureHalfFloat;
185
186 case GL_HALF_FLOAT_OES:
187 return context->getExtensions().colorBufferHalfFloat;
188
189 default:
190 return false;
191 }
192}
193
194bool ValidReadPixelsFormatEnum(ValidationContext *context, GLenum format)
195{
196 switch (format)
197 {
198 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
199 case GL_RGBA:
200 case GL_RGB:
201 case GL_ALPHA:
202 return context->getClientVersion() >= ES_2_0;
203
204 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
205 case GL_RG:
206 case GL_RED:
207 case GL_RGBA_INTEGER:
208 case GL_RGB_INTEGER:
209 case GL_RG_INTEGER:
210 case GL_RED_INTEGER:
211 return context->getClientVersion() >= ES_3_0;
212
213 case GL_SRGB_ALPHA_EXT:
214 case GL_SRGB_EXT:
215 return context->getExtensions().sRGB;
216
217 case GL_BGRA_EXT:
218 return context->getExtensions().readFormatBGRA;
219
220 default:
221 return false;
222 }
223}
224
Geoff Langf607c602016-09-21 11:46:48 -0400225bool ValidReadPixelsFormatType(ValidationContext *context,
226 GLenum framebufferComponentType,
227 GLenum format,
228 GLenum type)
229{
230 switch (framebufferComponentType)
231 {
232 case GL_UNSIGNED_NORMALIZED:
233 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
234 // ReadPixels with BGRA even if the extension is not present
235 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
236 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
237 type == GL_UNSIGNED_BYTE);
238
239 case GL_SIGNED_NORMALIZED:
240 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
241
242 case GL_INT:
243 return (format == GL_RGBA_INTEGER && type == GL_INT);
244
245 case GL_UNSIGNED_INT:
246 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
247
248 case GL_FLOAT:
249 return (format == GL_RGBA && type == GL_FLOAT);
250
251 default:
252 UNREACHABLE();
253 return false;
254 }
255}
256
Geoff Langc1984ed2016-10-07 12:41:00 -0400257template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400258bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400259{
260 switch (ConvertToGLenum(params[0]))
261 {
262 case GL_CLAMP_TO_EDGE:
263 break;
264
265 case GL_REPEAT:
266 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400267 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400268 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400269 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700270 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400271 return false;
272 }
273 break;
274
275 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700276 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400277 return false;
278 }
279
280 return true;
281}
282
283template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400284bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400285{
286 switch (ConvertToGLenum(params[0]))
287 {
288 case GL_NEAREST:
289 case GL_LINEAR:
290 break;
291
292 case GL_NEAREST_MIPMAP_NEAREST:
293 case GL_LINEAR_MIPMAP_NEAREST:
294 case GL_NEAREST_MIPMAP_LINEAR:
295 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400296 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400297 {
298 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700299 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400300 return false;
301 }
302 break;
303
304 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700305 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400306 return false;
307 }
308
309 return true;
310}
311
312template <typename ParamType>
313bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
314{
315 switch (ConvertToGLenum(params[0]))
316 {
317 case GL_NEAREST:
318 case GL_LINEAR:
319 break;
320
321 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700322 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400323 return false;
324 }
325
326 return true;
327}
328
329template <typename ParamType>
330bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
331{
332 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
333 switch (ConvertToGLenum(params[0]))
334 {
335 case GL_NONE:
336 case GL_COMPARE_REF_TO_TEXTURE:
337 break;
338
339 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700340 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400341 return false;
342 }
343
344 return true;
345}
346
347template <typename ParamType>
348bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
349{
350 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
351 switch (ConvertToGLenum(params[0]))
352 {
353 case GL_LEQUAL:
354 case GL_GEQUAL:
355 case GL_LESS:
356 case GL_GREATER:
357 case GL_EQUAL:
358 case GL_NOTEQUAL:
359 case GL_ALWAYS:
360 case GL_NEVER:
361 break;
362
363 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700364 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400365 return false;
366 }
367
368 return true;
369}
370
371template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700372bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
373{
374 if (!context->getExtensions().textureSRGBDecode)
375 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700376 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700377 return false;
378 }
379
380 switch (ConvertToGLenum(params[0]))
381 {
382 case GL_DECODE_EXT:
383 case GL_SKIP_DECODE_EXT:
384 break;
385
386 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700387 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700388 return false;
389 }
390
391 return true;
392}
393
Jamie Madillc1d770e2017-04-13 17:31:24 -0400394bool ValidateUniformCommonBase(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500395 gl::Program *program,
396 GLint location,
397 GLsizei count,
398 const LinkedUniform **uniformOut)
399{
400 // TODO(Jiajia): Add image uniform check in future.
401 if (count < 0)
402 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700403 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500404 return false;
405 }
406
Brandon Jones6cad5662017-06-14 13:25:13 -0700407 if (!program)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500408 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700409 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
410 return false;
411 }
412
413 if (!program->isLinked())
414 {
415 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500416 return false;
417 }
418
419 if (location == -1)
420 {
421 // Silently ignore the uniform command
422 return false;
423 }
424
425 const auto &uniformLocations = program->getUniformLocations();
Jamie Madillbe849e42017-05-02 15:49:00 -0400426 size_t castedLocation = static_cast<size_t>(location);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500427 if (castedLocation >= uniformLocations.size())
428 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500429 context->handleError(InvalidOperation() << "Invalid uniform location");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500430 return false;
431 }
432
433 const auto &uniformLocation = uniformLocations[castedLocation];
434 if (uniformLocation.ignored)
435 {
436 // Silently ignore the uniform command
437 return false;
438 }
439
Jamie Madillfb997ec2017-09-20 15:44:27 -0400440 if (!uniformLocation.used())
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500441 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500442 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500443 return false;
444 }
445
446 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
447
448 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
449 if (!uniform.isArray() && count > 1)
450 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500451 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500452 return false;
453 }
454
455 *uniformOut = &uniform;
456 return true;
457}
458
Frank Henigman999b0fd2017-02-02 21:45:55 -0500459bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -0500460 GLenum uniformType,
461 GLsizei count,
462 const GLint *value)
463{
464 // Value type is GL_INT, because we only get here from glUniform1i{v}.
465 // It is compatible with INT or BOOL.
466 // Do these cheap tests first, for a little extra speed.
467 if (GL_INT == uniformType || GL_BOOL == uniformType)
468 {
469 return true;
470 }
471
472 if (IsSamplerType(uniformType))
473 {
Frank Henigman999b0fd2017-02-02 21:45:55 -0500474 // Check that the values are in range.
475 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
476 for (GLsizei i = 0; i < count; ++i)
477 {
478 if (value[i] < 0 || value[i] >= max)
479 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500480 context->handleError(InvalidValue() << "sampler uniform value out of range");
Frank Henigman999b0fd2017-02-02 21:45:55 -0500481 return false;
482 }
483 }
Frank Henigmana98a6472017-02-02 21:38:32 -0500484 return true;
485 }
486
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500487 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmana98a6472017-02-02 21:38:32 -0500488 return false;
489}
490
Jamie Madillc1d770e2017-04-13 17:31:24 -0400491bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500492{
493 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -0500494 // Do the cheaper test first, for a little extra speed.
495 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500496 {
497 return true;
498 }
499
Brandon Jonesafa75152017-07-21 13:11:29 -0700500 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500501 return false;
502}
503
Jamie Madillc1d770e2017-04-13 17:31:24 -0400504bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500505{
506 // Check that the value type is compatible with uniform type.
507 if (valueType == uniformType)
508 {
509 return true;
510 }
511
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500512 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500513 return false;
514}
515
Geoff Lange0cff192017-05-30 13:04:56 -0400516bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
517{
518 const Program *program = context->getGLState().getProgram();
519 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
520
521 const auto &programOutputTypes = program->getOutputVariableTypes();
522 for (size_t drawBufferIdx = 0; drawBufferIdx < programOutputTypes.size(); drawBufferIdx++)
523 {
524 GLenum outputType = programOutputTypes[drawBufferIdx];
525 GLenum inputType = framebuffer->getDrawbufferWriteType(drawBufferIdx);
526 if (outputType != GL_NONE && inputType != GL_NONE && inputType != outputType)
527 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500528 context->handleError(InvalidOperation() << "Fragment shader output type does not "
529 "match the bound framebuffer attachment "
530 "type.");
Geoff Lange0cff192017-05-30 13:04:56 -0400531 return false;
532 }
533 }
534
535 return true;
536}
537
Geoff Lang9ab5b822017-05-30 16:19:23 -0400538bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
539{
540 const Program *program = context->getGLState().getProgram();
541 const VertexArray *vao = context->getGLState().getVertexArray();
542
543 for (const auto &shaderAttribute : program->getAttributes())
544 {
Geoff Lang69df2422017-07-05 12:42:31 -0400545 // gl_VertexID and gl_InstanceID are active attributes but don't have a bound attribute.
546 if (shaderAttribute.isBuiltIn())
547 {
548 continue;
549 }
550
Geoff Lang9ab5b822017-05-30 16:19:23 -0400551 GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
552
553 const auto &attrib = vao->getVertexAttribute(shaderAttribute.location);
554 const auto &currentValue =
555 context->getGLState().getVertexAttribCurrentValue(shaderAttribute.location);
556 GLenum vertexType = attrib.enabled ? GetVertexAttributeBaseType(attrib) : currentValue.Type;
557
558 if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
559 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500560 context->handleError(InvalidOperation() << "Vertex shader input type does not "
561 "match the type of the bound vertex "
562 "attribute.");
Geoff Lang9ab5b822017-05-30 16:19:23 -0400563 return false;
564 }
565 }
566
567 return true;
568}
569
Geoff Langf41a7152016-09-19 15:11:17 -0400570} // anonymous namespace
571
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500572bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400573{
Jamie Madilld7460c72014-01-21 16:38:14 -0500574 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400575 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800576 case GL_TEXTURE_2D:
577 case GL_TEXTURE_CUBE_MAP:
578 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400579
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400580 case GL_TEXTURE_RECTANGLE_ANGLE:
581 return context->getExtensions().textureRectangle;
582
He Yunchaoced53ae2016-11-29 15:00:51 +0800583 case GL_TEXTURE_3D:
584 case GL_TEXTURE_2D_ARRAY:
585 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500586
He Yunchaoced53ae2016-11-29 15:00:51 +0800587 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800588 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400589
He Yunchaoced53ae2016-11-29 15:00:51 +0800590 default:
591 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500592 }
Jamie Madill35d15012013-10-07 10:46:37 -0400593}
594
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500595bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
596{
597 switch (target)
598 {
599 case GL_TEXTURE_2D:
600 case GL_TEXTURE_CUBE_MAP:
601 return true;
602
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400603 case GL_TEXTURE_RECTANGLE_ANGLE:
604 return context->getExtensions().textureRectangle;
605
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500606 default:
607 return false;
608 }
609}
610
611bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
612{
613 switch (target)
614 {
615 case GL_TEXTURE_3D:
616 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300617 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500618
619 default:
620 return false;
621 }
622}
623
Ian Ewellbda75592016-04-18 17:25:54 -0400624// Most texture GL calls are not compatible with external textures, so we have a separate validation
625// function for use in the GL calls that do
626bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
627{
628 return (target == GL_TEXTURE_EXTERNAL_OES) &&
629 (context->getExtensions().eglImageExternal ||
630 context->getExtensions().eglStreamConsumerExternal);
631}
632
Shannon Woods4dfed832014-03-17 20:03:39 -0400633// This function differs from ValidTextureTarget in that the target must be
634// usable as the destination of a 2D operation-- so a cube face is valid, but
635// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400636// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500637bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400638{
639 switch (target)
640 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800641 case GL_TEXTURE_2D:
642 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
643 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
644 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
645 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
646 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
647 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
648 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400649 case GL_TEXTURE_RECTANGLE_ANGLE:
650 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800651 default:
652 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500653 }
654}
655
Jamie Madillbe849e42017-05-02 15:49:00 -0400656bool ValidateDrawElementsInstancedBase(ValidationContext *context,
657 GLenum mode,
658 GLsizei count,
659 GLenum type,
660 const GLvoid *indices,
661 GLsizei primcount)
662{
663 if (primcount < 0)
664 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700665 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400666 return false;
667 }
668
669 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
670 {
671 return false;
672 }
673
674 // No-op zero primitive count
675 return (primcount > 0);
676}
677
678bool ValidateDrawArraysInstancedBase(Context *context,
679 GLenum mode,
680 GLint first,
681 GLsizei count,
682 GLsizei primcount)
683{
684 if (primcount < 0)
685 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700686 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400687 return false;
688 }
689
690 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
691 {
692 return false;
693 }
694
695 // No-op if zero primitive count
696 return (primcount > 0);
697}
698
Corentin Wallez0dc97812017-06-22 14:38:44 -0400699bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400700{
701 // Verify there is at least one active attribute with a divisor of zero
702 const State &state = context->getGLState();
703
704 Program *program = state.getProgram();
705
706 const auto &attribs = state.getVertexArray()->getVertexAttributes();
707 const auto &bindings = state.getVertexArray()->getVertexBindings();
708 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
709 {
710 const VertexAttribute &attrib = attribs[attributeIndex];
711 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300712 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400713 {
714 return true;
715 }
716 }
717
Brandon Jonesafa75152017-07-21 13:11:29 -0700718 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400719 return false;
720}
721
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500722bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
723{
724 switch (target)
725 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800726 case GL_TEXTURE_3D:
727 case GL_TEXTURE_2D_ARRAY:
728 return true;
729 default:
730 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400731 }
732}
733
He Yunchao11b038b2016-11-22 21:24:04 +0800734bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
735{
736 switch (target)
737 {
738 case GL_TEXTURE_2D:
739 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
740 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
741 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
742 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
743 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
744 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
745 case GL_TEXTURE_3D:
746 case GL_TEXTURE_2D_ARRAY:
747 case GL_TEXTURE_2D_MULTISAMPLE:
748 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400749 case GL_TEXTURE_RECTANGLE_ANGLE:
750 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800751 default:
752 return false;
753 }
754}
755
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500756bool ValidFramebufferTarget(GLenum target)
757{
He Yunchaoced53ae2016-11-29 15:00:51 +0800758 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
759 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400760 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500761
762 switch (target)
763 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800764 case GL_FRAMEBUFFER:
765 return true;
766 case GL_READ_FRAMEBUFFER:
767 return true;
768 case GL_DRAW_FRAMEBUFFER:
769 return true;
770 default:
771 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500772 }
773}
774
Jamie Madill29639852016-09-02 15:00:09 -0400775bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -0500776{
777 switch (target)
778 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800779 case GL_ARRAY_BUFFER:
780 case GL_ELEMENT_ARRAY_BUFFER:
781 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -0500782
He Yunchaoced53ae2016-11-29 15:00:51 +0800783 case GL_PIXEL_PACK_BUFFER:
784 case GL_PIXEL_UNPACK_BUFFER:
785 return (context->getExtensions().pixelBufferObject ||
786 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -0400787
He Yunchaoced53ae2016-11-29 15:00:51 +0800788 case GL_COPY_READ_BUFFER:
789 case GL_COPY_WRITE_BUFFER:
790 case GL_TRANSFORM_FEEDBACK_BUFFER:
791 case GL_UNIFORM_BUFFER:
792 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -0500793
He Yunchaoced53ae2016-11-29 15:00:51 +0800794 case GL_ATOMIC_COUNTER_BUFFER:
795 case GL_SHADER_STORAGE_BUFFER:
796 case GL_DRAW_INDIRECT_BUFFER:
797 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800798 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -0400799
He Yunchaoced53ae2016-11-29 15:00:51 +0800800 default:
801 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -0500802 }
803}
804
Jamie Madillc29968b2016-01-20 11:17:23 -0500805bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400806{
Jamie Madillc29968b2016-01-20 11:17:23 -0500807 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400808 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400809 switch (target)
810 {
Jamie Madillc29968b2016-01-20 11:17:23 -0500811 case GL_TEXTURE_2D:
812 maxDimension = caps.max2DTextureSize;
813 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800814 case GL_TEXTURE_CUBE_MAP:
815 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
816 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
817 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
818 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
819 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
820 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
821 maxDimension = caps.maxCubeMapTextureSize;
822 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400823 case GL_TEXTURE_RECTANGLE_ANGLE:
824 return level == 0;
He Yunchaoced53ae2016-11-29 15:00:51 +0800825 case GL_TEXTURE_3D:
826 maxDimension = caps.max3DTextureSize;
827 break;
828 case GL_TEXTURE_2D_ARRAY:
829 maxDimension = caps.max2DTextureSize;
830 break;
He Yunchao11b038b2016-11-22 21:24:04 +0800831 case GL_TEXTURE_2D_MULTISAMPLE:
832 maxDimension = caps.max2DTextureSize;
833 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800834 default:
835 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400836 }
837
Brandon Jones6cad5662017-06-14 13:25:13 -0700838 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400839}
840
Brandon Jones6cad5662017-06-14 13:25:13 -0700841bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -0700842 GLenum target,
843 GLint level,
844 GLsizei width,
845 GLsizei height,
846 GLsizei depth,
847 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400848{
Brandon Jones6cad5662017-06-14 13:25:13 -0700849 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400850 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700851 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400852 return false;
853 }
Austin Kinross08528e12015-10-07 16:24:40 -0700854 // TexSubImage parameters can be NPOT without textureNPOT extension,
855 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500856 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500857 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500858 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400859 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400860 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700861 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400862 return false;
863 }
864
865 if (!ValidMipLevel(context, target, level))
866 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700867 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400868 return false;
869 }
870
871 return true;
872}
873
Geoff Lang0d8b7242015-09-09 14:56:53 -0400874bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
875{
876 // List of compressed format that require that the texture size is smaller than or a multiple of
877 // the compressed block size.
878 switch (internalFormat)
879 {
880 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
881 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
882 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
883 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -0400884 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
885 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
886 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
887 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -0800888 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800889 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
890 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
891 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
892 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
893 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
894 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -0400895 return true;
896
897 default:
898 return false;
899 }
900}
901
Geoff Lang966c9402017-04-18 12:38:27 -0400902bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
903{
904 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
905 (size % blockSize == 0);
906}
907
Jamie Madillc29968b2016-01-20 11:17:23 -0500908bool ValidCompressedImageSize(const ValidationContext *context,
909 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400910 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500911 GLsizei width,
912 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400913{
Geoff Langca271392017-04-05 12:30:00 -0400914 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400915 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400916 {
917 return false;
918 }
919
Geoff Lang966c9402017-04-18 12:38:27 -0400920 if (width < 0 || height < 0)
921 {
922 return false;
923 }
924
925 if (CompressedTextureFormatRequiresExactSize(internalFormat))
926 {
927 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
928 // block size for level 0 but WebGL disallows this.
929 bool smallerThanBlockSizeAllowed =
930 level > 0 || !context->getExtensions().webglCompatibility;
931
932 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
933 smallerThanBlockSizeAllowed) ||
934 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
935 smallerThanBlockSizeAllowed))
936 {
937 return false;
938 }
939 }
940
941 return true;
942}
943
944bool ValidCompressedSubImageSize(const ValidationContext *context,
945 GLenum internalFormat,
946 GLint xoffset,
947 GLint yoffset,
948 GLsizei width,
949 GLsizei height,
950 size_t textureWidth,
951 size_t textureHeight)
952{
953 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
954 if (!formatInfo.compressed)
955 {
956 return false;
957 }
958
Geoff Lang44ff5a72017-02-03 15:15:43 -0500959 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400960 {
961 return false;
962 }
963
Geoff Lang0d8b7242015-09-09 14:56:53 -0400964 if (CompressedTextureFormatRequiresExactSize(internalFormat))
965 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500966 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400967 yoffset % formatInfo.compressedBlockHeight != 0)
968 {
969 return false;
970 }
971
972 // Allowed to either have data that is a multiple of block size or is smaller than the block
973 // size but fills the entire mip
974 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
975 static_cast<size_t>(width) == textureWidth &&
976 static_cast<size_t>(height) == textureHeight;
977 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
978 (height % formatInfo.compressedBlockHeight) == 0;
979 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400980 {
981 return false;
982 }
983 }
984
Geoff Langd4f180b2013-09-24 13:57:44 -0400985 return true;
986}
987
Geoff Langff5b2d52016-09-07 11:32:23 -0400988bool ValidImageDataSize(ValidationContext *context,
989 GLenum textureTarget,
990 GLsizei width,
991 GLsizei height,
992 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400993 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400994 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400995 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400996 GLsizei imageSize)
997{
998 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
999 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1000 {
1001 // Checks are not required
1002 return true;
1003 }
1004
1005 // ...the data would be unpacked from the buffer object such that the memory reads required
1006 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -04001007 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
1008 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -04001009 const gl::Extents size(width, height, depth);
1010 const auto &unpack = context->getGLState().getUnpackState();
1011
1012 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1013 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1014 if (endByteOrErr.isError())
1015 {
1016 context->handleError(endByteOrErr.getError());
1017 return false;
1018 }
1019
1020 GLuint endByte = endByteOrErr.getResult();
1021
1022 if (pixelUnpackBuffer)
1023 {
1024 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1025 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1026 checkedEndByte += checkedOffset;
1027
1028 if (!checkedEndByte.IsValid() ||
1029 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1030 {
1031 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001032 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04001033 return false;
1034 }
1035 }
1036 else
1037 {
1038 ASSERT(imageSize >= 0);
1039 if (pixels == nullptr && imageSize != 0)
1040 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001041 context->handleError(InvalidOperation()
1042 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001043 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001044 }
1045
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001046 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001047 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001048 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001049 return false;
1050 }
1051 }
1052
1053 return true;
1054}
1055
Geoff Lang37dde692014-01-31 16:34:54 -05001056bool ValidQueryType(const Context *context, GLenum queryType)
1057{
He Yunchaoced53ae2016-11-29 15:00:51 +08001058 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1059 "GL extension enums not equal.");
1060 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1061 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001062
1063 switch (queryType)
1064 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001065 case GL_ANY_SAMPLES_PASSED:
1066 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001067 return context->getClientMajorVersion() >= 3 ||
1068 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +08001069 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1070 return (context->getClientMajorVersion() >= 3);
1071 case GL_TIME_ELAPSED_EXT:
1072 return context->getExtensions().disjointTimerQuery;
1073 case GL_COMMANDS_COMPLETED_CHROMIUM:
1074 return context->getExtensions().syncQuery;
1075 default:
1076 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001077 }
1078}
1079
Geoff Lang2d62ab72017-03-23 16:54:40 -04001080bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
1081 GLenum type,
1082 GLboolean normalized,
1083 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001084 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001085 bool pureInteger)
1086{
1087 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001088 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1089 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1090 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1091 // parameter exceeds 255.
1092 constexpr GLsizei kMaxWebGLStride = 255;
1093 if (stride > kMaxWebGLStride)
1094 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001095 context->handleError(InvalidValue()
1096 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001097 return false;
1098 }
1099
1100 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1101 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1102 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1103 // or an INVALID_OPERATION error is generated.
1104 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1105 size_t typeSize = GetVertexFormatTypeSize(internalType);
1106
1107 ASSERT(isPow2(typeSize) && typeSize > 0);
1108 size_t sizeMask = (typeSize - 1);
1109 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1110 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001111 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001112 return false;
1113 }
1114
1115 if ((stride & sizeMask) != 0)
1116 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001117 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001118 return false;
1119 }
1120
1121 return true;
1122}
1123
Jamie Madillef300b12016-10-07 15:12:09 -04001124Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001125{
He Yunchaoced53ae2016-11-29 15:00:51 +08001126 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1127 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1128 // or program object and INVALID_OPERATION if the provided name identifies an object
1129 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001130
Dian Xiang769769a2015-09-09 15:20:08 -07001131 Program *validProgram = context->getProgram(id);
1132
1133 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001134 {
Dian Xiang769769a2015-09-09 15:20:08 -07001135 if (context->getShader(id))
1136 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001137 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001138 }
1139 else
1140 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001141 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001142 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001143 }
Dian Xiang769769a2015-09-09 15:20:08 -07001144
1145 return validProgram;
1146}
1147
Jamie Madillef300b12016-10-07 15:12:09 -04001148Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001149{
1150 // See ValidProgram for spec details.
1151
1152 Shader *validShader = context->getShader(id);
1153
1154 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001155 {
Dian Xiang769769a2015-09-09 15:20:08 -07001156 if (context->getProgram(id))
1157 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001158 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001159 }
1160 else
1161 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001162 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001163 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001164 }
Dian Xiang769769a2015-09-09 15:20:08 -07001165
1166 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001167}
1168
Geoff Langb1196682014-07-23 13:47:29 -04001169bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001170{
1171 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1172 {
1173 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1174
Geoff Langaae65a42014-05-26 12:43:44 -04001175 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001176 {
Martin Radevd178aa42017-07-13 14:03:22 +03001177 context->handleError(
1178 InvalidOperation()
1179 << "attachment index cannot be greater or equal to MAX_COLOR_ATTACHMENTS.");
Geoff Langb1196682014-07-23 13:47:29 -04001180 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001181 }
1182 }
1183 else
1184 {
1185 switch (attachment)
1186 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001187 case GL_DEPTH_ATTACHMENT:
1188 case GL_STENCIL_ATTACHMENT:
1189 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001190
He Yunchaoced53ae2016-11-29 15:00:51 +08001191 case GL_DEPTH_STENCIL_ATTACHMENT:
1192 if (!context->getExtensions().webglCompatibility &&
1193 context->getClientMajorVersion() < 3)
1194 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001195 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001196 return false;
1197 }
1198 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001199
He Yunchaoced53ae2016-11-29 15:00:51 +08001200 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001201 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001202 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001203 }
1204 }
1205
1206 return true;
1207}
1208
Jamie Madille8fb6402017-02-14 17:56:40 -05001209bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001210 GLenum target,
1211 GLsizei samples,
1212 GLenum internalformat,
1213 GLsizei width,
1214 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001215{
1216 switch (target)
1217 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001218 case GL_RENDERBUFFER:
1219 break;
1220 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001221 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001222 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001223 }
1224
1225 if (width < 0 || height < 0 || samples < 0)
1226 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001227 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001228 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001229 }
1230
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001231 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1232 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1233
1234 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001235 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001236 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001237 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001238 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001239 }
1240
1241 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1242 // 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 -08001243 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001244 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1245 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001246 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001247 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001248 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001249 }
1250
Geoff Langaae65a42014-05-26 12:43:44 -04001251 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001252 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001253 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001254 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001255 }
1256
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001257 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001258 if (handle == 0)
1259 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001260 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001261 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001262 }
1263
1264 return true;
1265}
1266
He Yunchaoced53ae2016-11-29 15:00:51 +08001267bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1268 GLenum target,
1269 GLenum attachment,
1270 GLenum renderbuffertarget,
1271 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001272{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001273 if (!ValidFramebufferTarget(target))
1274 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001275 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001276 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001277 }
1278
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001279 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001280
Jamie Madill84115c92015-04-23 15:00:07 -04001281 ASSERT(framebuffer);
1282 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001283 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001284 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001285 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001286 }
1287
Jamie Madillb4472272014-07-03 10:38:55 -04001288 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001289 {
Jamie Madillb4472272014-07-03 10:38:55 -04001290 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001291 }
1292
Jamie Madillab9d82c2014-01-21 16:38:14 -05001293 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1294 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1295 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1296 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1297 if (renderbuffer != 0)
1298 {
1299 if (!context->getRenderbuffer(renderbuffer))
1300 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001301 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001302 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001303 }
1304 }
1305
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001306 return true;
1307}
1308
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001309bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001310 GLint srcX0,
1311 GLint srcY0,
1312 GLint srcX1,
1313 GLint srcY1,
1314 GLint dstX0,
1315 GLint dstY0,
1316 GLint dstX1,
1317 GLint dstY1,
1318 GLbitfield mask,
1319 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001320{
1321 switch (filter)
1322 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001323 case GL_NEAREST:
1324 break;
1325 case GL_LINEAR:
1326 break;
1327 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001328 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001329 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001330 }
1331
1332 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1333 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001334 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001335 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001336 }
1337
1338 if (mask == 0)
1339 {
1340 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1341 // buffers are copied.
1342 return false;
1343 }
1344
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001345 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1346 // color buffer, leaving only nearest being unfiltered from above
1347 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1348 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001349 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001350 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001351 }
1352
Jamie Madill51f40ec2016-06-15 14:06:00 -04001353 const auto &glState = context->getGLState();
1354 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1355 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001356
1357 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001358 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001359 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001360 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001361 }
1362
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001363 if (readFramebuffer->id() == drawFramebuffer->id())
1364 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001365 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001366 return false;
1367 }
1368
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001369 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001371 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001372 return false;
1373 }
1374
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001375 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001376 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001377 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001378 return false;
1379 }
1380
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001381 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001382 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001383 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001384 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001385 }
1386
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001387 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1388
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001389 if (mask & GL_COLOR_BUFFER_BIT)
1390 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001391 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001392 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001393
He Yunchao66a41a22016-12-15 16:45:05 +08001394 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001395 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001396 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001397
Geoff Langa15472a2015-08-11 11:48:03 -04001398 for (size_t drawbufferIdx = 0;
1399 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001400 {
Geoff Langa15472a2015-08-11 11:48:03 -04001401 const FramebufferAttachment *attachment =
1402 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1403 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001404 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001405 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001406
Geoff Langb2f3d052013-08-13 12:49:27 -04001407 // The GL ES 3.0.2 spec (pg 193) states that:
1408 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001409 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1410 // as well
1411 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1412 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001413 // Changes with EXT_color_buffer_float:
1414 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001415 GLenum readComponentType = readFormat.info->componentType;
1416 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001417 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001418 readComponentType == GL_SIGNED_NORMALIZED);
1419 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1420 drawComponentType == GL_SIGNED_NORMALIZED);
1421
1422 if (extensions.colorBufferFloat)
1423 {
1424 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1425 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1426
1427 if (readFixedOrFloat != drawFixedOrFloat)
1428 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001429 context->handleError(InvalidOperation()
1430 << "If the read buffer contains fixed-point or "
1431 "floating-point values, the draw buffer must "
1432 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001433 return false;
1434 }
1435 }
1436 else if (readFixedPoint != drawFixedPoint)
1437 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001438 context->handleError(InvalidOperation()
1439 << "If the read buffer contains fixed-point values, "
1440 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001441 return false;
1442 }
1443
1444 if (readComponentType == GL_UNSIGNED_INT &&
1445 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001446 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001447 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001448 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001449 }
1450
Jamie Madill6163c752015-12-07 16:32:59 -05001451 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001452 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001453 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001454 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001455 }
1456
Jamie Madilla3944d42016-07-22 22:13:26 -04001457 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001458 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001459 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001460 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001461 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001462 }
Geoff Lange4915782017-04-12 15:19:07 -04001463
1464 if (context->getExtensions().webglCompatibility &&
1465 *readColorBuffer == *attachment)
1466 {
1467 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001468 InvalidOperation()
1469 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001470 return false;
1471 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001472 }
1473 }
1474
Jamie Madilla3944d42016-07-22 22:13:26 -04001475 if ((readFormat.info->componentType == GL_INT ||
1476 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1477 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001478 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001479 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001480 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001481 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001482 }
He Yunchao66a41a22016-12-15 16:45:05 +08001483 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1484 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1485 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1486 // situation is an application error that would lead to a crash in ANGLE.
1487 else if (drawFramebuffer->hasEnabledDrawBuffer())
1488 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001489 context->handleError(
1490 InvalidOperation()
1491 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001492 return false;
1493 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001494 }
1495
He Yunchaoced53ae2016-11-29 15:00:51 +08001496 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001497 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1498 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001499 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001500 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001501 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001502 const gl::FramebufferAttachment *readBuffer =
1503 readFramebuffer->getAttachment(attachments[i]);
1504 const gl::FramebufferAttachment *drawBuffer =
1505 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001506
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001507 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001508 {
Kenneth Russell69382852017-07-21 16:38:44 -04001509 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001510 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001511 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001512 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001513 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001514
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001515 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001516 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001517 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001518 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001519 }
Geoff Lange4915782017-04-12 15:19:07 -04001520
1521 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1522 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001523 context->handleError(
1524 InvalidOperation()
1525 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001526 return false;
1527 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001528 }
He Yunchao66a41a22016-12-15 16:45:05 +08001529 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1530 else if (drawBuffer)
1531 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001532 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1533 "depth/stencil attachment of a "
1534 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001535 return false;
1536 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001537 }
1538 }
1539
Martin Radeva3ed4572017-07-27 18:29:37 +03001540 // ANGLE_multiview, Revision 1:
1541 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1542 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1543 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1544 {
1545 context->handleError(InvalidFramebufferOperation()
1546 << "Attempt to read from a multi-view framebuffer.");
1547 return false;
1548 }
1549 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1550 {
1551 context->handleError(InvalidFramebufferOperation()
1552 << "Attempt to write to a multi-view framebuffer.");
1553 return false;
1554 }
1555
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001556 return true;
1557}
1558
Jamie Madill4928b7c2017-06-20 12:57:39 -04001559bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001560 GLint x,
1561 GLint y,
1562 GLsizei width,
1563 GLsizei height,
1564 GLenum format,
1565 GLenum type,
1566 GLsizei bufSize,
1567 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001568 GLsizei *columns,
1569 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001570 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001571{
1572 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001573 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001574 return false;
1575 }
1576
Geoff Lang62fce5b2016-09-30 10:46:35 -04001577 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001578 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001579 {
Geoff Langb1196682014-07-23 13:47:29 -04001580 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001581 }
1582
Geoff Lang62fce5b2016-09-30 10:46:35 -04001583 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001584 {
Geoff Langb1196682014-07-23 13:47:29 -04001585 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001586 }
1587
Jamie Madillc29968b2016-01-20 11:17:23 -05001588 return true;
1589}
1590
1591bool ValidateReadnPixelsEXT(Context *context,
1592 GLint x,
1593 GLint y,
1594 GLsizei width,
1595 GLsizei height,
1596 GLenum format,
1597 GLenum type,
1598 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001599 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001600{
1601 if (bufSize < 0)
1602 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001603 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001604 return false;
1605 }
1606
Geoff Lang62fce5b2016-09-30 10:46:35 -04001607 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001608 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001609}
Jamie Madill26e91952014-03-05 15:01:27 -05001610
Jamie Madill4928b7c2017-06-20 12:57:39 -04001611bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001612 GLint x,
1613 GLint y,
1614 GLsizei width,
1615 GLsizei height,
1616 GLenum format,
1617 GLenum type,
1618 GLsizei bufSize,
1619 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001620 GLsizei *columns,
1621 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001622 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001623{
1624 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001625 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001626 return false;
1627 }
1628
Geoff Lange93daba2017-03-30 13:54:40 -04001629 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1630 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001631 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001632 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001633 }
1634
Geoff Lang62fce5b2016-09-30 10:46:35 -04001635 if (!ValidateRobustBufferSize(context, bufSize, *length))
1636 {
1637 return false;
1638 }
1639
1640 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001641}
1642
Jamie Madillf0e04492017-08-26 15:28:42 -04001643bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001644{
1645 if (!context->getExtensions().occlusionQueryBoolean &&
1646 !context->getExtensions().disjointTimerQuery)
1647 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001648 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001649 return false;
1650 }
1651
Olli Etuaho41997e72016-03-10 13:38:39 +02001652 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001653}
1654
Jamie Madillf0e04492017-08-26 15:28:42 -04001655bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001656{
1657 if (!context->getExtensions().occlusionQueryBoolean &&
1658 !context->getExtensions().disjointTimerQuery)
1659 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001660 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001661 return false;
1662 }
1663
Olli Etuaho41997e72016-03-10 13:38:39 +02001664 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001665}
1666
Jamie Madillf0e04492017-08-26 15:28:42 -04001667bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1668{
1669 if (!context->getExtensions().occlusionQueryBoolean &&
1670 !context->getExtensions().disjointTimerQuery)
1671 {
1672 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1673 return false;
1674 }
1675
1676 return true;
1677}
1678
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001679bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001680{
1681 if (!ValidQueryType(context, target))
1682 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001683 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001684 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001685 }
1686
1687 if (id == 0)
1688 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001689 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001690 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001691 }
1692
1693 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1694 // of zero, if the active query object name for <target> is non-zero (for the
1695 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1696 // the active query for either target is non-zero), if <id> is the name of an
1697 // existing query object whose type does not match <target>, or if <id> is the
1698 // active query object name for any query type, the error INVALID_OPERATION is
1699 // generated.
1700
1701 // Ensure no other queries are active
1702 // NOTE: If other queries than occlusion are supported, we will need to check
1703 // separately that:
1704 // a) The query ID passed is not the current active query for any target/type
1705 // b) There are no active queries for the requested target (and in the case
1706 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1707 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001708
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001709 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001710 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001711 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001712 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001713 }
1714
1715 Query *queryObject = context->getQuery(id, true, target);
1716
1717 // check that name was obtained with glGenQueries
1718 if (!queryObject)
1719 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001720 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001721 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001722 }
1723
1724 // check for type mismatch
1725 if (queryObject->getType() != target)
1726 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001727 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001728 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001729 }
1730
1731 return true;
1732}
1733
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001734bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1735{
1736 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001737 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001738 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001739 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001740 return false;
1741 }
1742
1743 return ValidateBeginQueryBase(context, target, id);
1744}
1745
1746bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001747{
1748 if (!ValidQueryType(context, target))
1749 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001750 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001751 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001752 }
1753
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001754 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001755
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001756 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001757 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001758 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001759 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001760 }
1761
Jamie Madill45c785d2014-05-13 14:09:34 -04001762 return true;
1763}
1764
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001765bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1766{
1767 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001768 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001769 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001770 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001771 return false;
1772 }
1773
1774 return ValidateEndQueryBase(context, target);
1775}
1776
1777bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1778{
1779 if (!context->getExtensions().disjointTimerQuery)
1780 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001781 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001782 return false;
1783 }
1784
1785 if (target != GL_TIMESTAMP_EXT)
1786 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001787 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001788 return false;
1789 }
1790
1791 Query *queryObject = context->getQuery(id, true, target);
1792 if (queryObject == nullptr)
1793 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001794 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001795 return false;
1796 }
1797
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001798 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001799 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001800 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001801 return false;
1802 }
1803
1804 return true;
1805}
1806
Geoff Lang2186c382016-10-14 10:54:54 -04001807bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001808{
Geoff Lang2186c382016-10-14 10:54:54 -04001809 if (numParams)
1810 {
1811 *numParams = 0;
1812 }
1813
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001814 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1815 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001816 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001817 return false;
1818 }
1819
1820 switch (pname)
1821 {
1822 case GL_CURRENT_QUERY_EXT:
1823 if (target == GL_TIMESTAMP_EXT)
1824 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001825 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001826 return false;
1827 }
1828 break;
1829 case GL_QUERY_COUNTER_BITS_EXT:
1830 if (!context->getExtensions().disjointTimerQuery ||
1831 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1832 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001833 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001834 return false;
1835 }
1836 break;
1837 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001838 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001839 return false;
1840 }
1841
Geoff Lang2186c382016-10-14 10:54:54 -04001842 if (numParams)
1843 {
1844 // All queries return only one value
1845 *numParams = 1;
1846 }
1847
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001848 return true;
1849}
1850
1851bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1852{
1853 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001854 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001855 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001856 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001857 return false;
1858 }
1859
Geoff Lang2186c382016-10-14 10:54:54 -04001860 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001861}
1862
Geoff Lang2186c382016-10-14 10:54:54 -04001863bool ValidateGetQueryivRobustANGLE(Context *context,
1864 GLenum target,
1865 GLenum pname,
1866 GLsizei bufSize,
1867 GLsizei *length,
1868 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001869{
Geoff Lang2186c382016-10-14 10:54:54 -04001870 if (!ValidateRobustEntryPoint(context, bufSize))
1871 {
1872 return false;
1873 }
1874
1875 if (!ValidateGetQueryivBase(context, target, pname, length))
1876 {
1877 return false;
1878 }
1879
1880 if (!ValidateRobustBufferSize(context, bufSize, *length))
1881 {
1882 return false;
1883 }
1884
1885 return true;
1886}
1887
1888bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1889{
1890 if (numParams)
1891 {
1892 *numParams = 0;
1893 }
1894
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001895 Query *queryObject = context->getQuery(id, false, GL_NONE);
1896
1897 if (!queryObject)
1898 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001899 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001900 return false;
1901 }
1902
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001903 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001904 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001905 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001906 return false;
1907 }
1908
1909 switch (pname)
1910 {
1911 case GL_QUERY_RESULT_EXT:
1912 case GL_QUERY_RESULT_AVAILABLE_EXT:
1913 break;
1914
1915 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001916 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001917 return false;
1918 }
1919
Geoff Lang2186c382016-10-14 10:54:54 -04001920 if (numParams)
1921 {
1922 *numParams = 1;
1923 }
1924
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001925 return true;
1926}
1927
1928bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1929{
1930 if (!context->getExtensions().disjointTimerQuery)
1931 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001932 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001933 return false;
1934 }
Geoff Lang2186c382016-10-14 10:54:54 -04001935 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1936}
1937
1938bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1939 GLuint id,
1940 GLenum pname,
1941 GLsizei bufSize,
1942 GLsizei *length,
1943 GLint *params)
1944{
1945 if (!context->getExtensions().disjointTimerQuery)
1946 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001947 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001948 return false;
1949 }
1950
1951 if (!ValidateRobustEntryPoint(context, bufSize))
1952 {
1953 return false;
1954 }
1955
1956 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1957 {
1958 return false;
1959 }
1960
1961 if (!ValidateRobustBufferSize(context, bufSize, *length))
1962 {
1963 return false;
1964 }
1965
1966 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001967}
1968
1969bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1970{
1971 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001972 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001973 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001974 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001975 return false;
1976 }
Geoff Lang2186c382016-10-14 10:54:54 -04001977 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1978}
1979
1980bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1981 GLuint id,
1982 GLenum pname,
1983 GLsizei bufSize,
1984 GLsizei *length,
1985 GLuint *params)
1986{
1987 if (!context->getExtensions().disjointTimerQuery &&
1988 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1989 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001990 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001991 return false;
1992 }
1993
1994 if (!ValidateRobustEntryPoint(context, bufSize))
1995 {
1996 return false;
1997 }
1998
1999 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2000 {
2001 return false;
2002 }
2003
2004 if (!ValidateRobustBufferSize(context, bufSize, *length))
2005 {
2006 return false;
2007 }
2008
2009 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002010}
2011
2012bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2013{
2014 if (!context->getExtensions().disjointTimerQuery)
2015 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002016 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002017 return false;
2018 }
Geoff Lang2186c382016-10-14 10:54:54 -04002019 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2020}
2021
2022bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2023 GLuint id,
2024 GLenum pname,
2025 GLsizei bufSize,
2026 GLsizei *length,
2027 GLint64 *params)
2028{
2029 if (!context->getExtensions().disjointTimerQuery)
2030 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002031 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002032 return false;
2033 }
2034
2035 if (!ValidateRobustEntryPoint(context, bufSize))
2036 {
2037 return false;
2038 }
2039
2040 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2041 {
2042 return false;
2043 }
2044
2045 if (!ValidateRobustBufferSize(context, bufSize, *length))
2046 {
2047 return false;
2048 }
2049
2050 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002051}
2052
2053bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2054{
2055 if (!context->getExtensions().disjointTimerQuery)
2056 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002057 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002058 return false;
2059 }
Geoff Lang2186c382016-10-14 10:54:54 -04002060 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2061}
2062
2063bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2064 GLuint id,
2065 GLenum pname,
2066 GLsizei bufSize,
2067 GLsizei *length,
2068 GLuint64 *params)
2069{
2070 if (!context->getExtensions().disjointTimerQuery)
2071 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002072 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002073 return false;
2074 }
2075
2076 if (!ValidateRobustEntryPoint(context, bufSize))
2077 {
2078 return false;
2079 }
2080
2081 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2082 {
2083 return false;
2084 }
2085
2086 if (!ValidateRobustBufferSize(context, bufSize, *length))
2087 {
2088 return false;
2089 }
2090
2091 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002092}
2093
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002094bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002095 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002096 GLuint program,
2097 GLint location,
2098 GLsizei count)
2099{
2100 // Check for ES31 program uniform entry points
2101 if (context->getClientVersion() < Version(3, 1))
2102 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002103 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002104 return false;
2105 }
2106
2107 const LinkedUniform *uniform = nullptr;
2108 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002109 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2110 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002111}
2112
Frank Henigmana98a6472017-02-02 21:38:32 -05002113bool ValidateProgramUniform1iv(gl::Context *context,
2114 GLuint program,
2115 GLint location,
2116 GLsizei count,
2117 const GLint *value)
2118{
2119 // Check for ES31 program uniform entry points
2120 if (context->getClientVersion() < Version(3, 1))
2121 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002122 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Frank Henigmana98a6472017-02-02 21:38:32 -05002123 return false;
2124 }
2125
2126 const LinkedUniform *uniform = nullptr;
2127 gl::Program *programObject = GetValidProgram(context, program);
2128 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2129 ValidateUniform1ivValue(context, uniform->type, count, value);
2130}
2131
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002132bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002133 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002134 GLuint program,
2135 GLint location,
2136 GLsizei count,
2137 GLboolean transpose)
2138{
2139 // Check for ES31 program uniform entry points
2140 if (context->getClientVersion() < Version(3, 1))
2141 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002142 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002143 return false;
2144 }
2145
2146 const LinkedUniform *uniform = nullptr;
2147 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002148 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2149 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002150}
2151
Jamie Madillc1d770e2017-04-13 17:31:24 -04002152bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002153{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002154 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002155 gl::Program *programObject = context->getGLState().getProgram();
2156 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2157 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002158}
2159
Jamie Madillbe849e42017-05-02 15:49:00 -04002160bool ValidateUniform1iv(ValidationContext *context,
2161 GLint location,
2162 GLsizei count,
2163 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002164{
2165 const LinkedUniform *uniform = nullptr;
2166 gl::Program *programObject = context->getGLState().getProgram();
2167 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2168 ValidateUniform1ivValue(context, uniform->type, count, value);
2169}
2170
Jamie Madillc1d770e2017-04-13 17:31:24 -04002171bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002172 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002173 GLint location,
2174 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002175 GLboolean transpose)
2176{
Martin Radev1be913c2016-07-11 17:59:16 +03002177 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002178 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002179 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002180 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002181 }
2182
Jamie Madill62d31cb2015-09-11 13:25:51 -04002183 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002184 gl::Program *programObject = context->getGLState().getProgram();
2185 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2186 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002187}
2188
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002189bool ValidateStateQuery(ValidationContext *context,
2190 GLenum pname,
2191 GLenum *nativeType,
2192 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002193{
2194 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2195 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002196 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002197 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002198 }
2199
Jamie Madill0af26e12015-03-05 19:54:33 -05002200 const Caps &caps = context->getCaps();
2201
Jamie Madill893ab082014-05-16 16:56:10 -04002202 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2203 {
2204 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2205
Jamie Madill0af26e12015-03-05 19:54:33 -05002206 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002207 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002208 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002209 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002210 }
2211 }
2212
2213 switch (pname)
2214 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002215 case GL_TEXTURE_BINDING_2D:
2216 case GL_TEXTURE_BINDING_CUBE_MAP:
2217 case GL_TEXTURE_BINDING_3D:
2218 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002219 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002220 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002221 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2222 if (!context->getExtensions().textureRectangle)
2223 {
2224 context->handleError(InvalidEnum()
2225 << "ANGLE_texture_rectangle extension not present");
2226 return false;
2227 }
2228 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002229 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2230 if (!context->getExtensions().eglStreamConsumerExternal &&
2231 !context->getExtensions().eglImageExternal)
2232 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002233 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2234 "nor GL_OES_EGL_image_external "
2235 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002236 return false;
2237 }
2238 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002239
He Yunchaoced53ae2016-11-29 15:00:51 +08002240 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2241 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002242 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002243 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2244 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002245 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002246 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002247 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002248 }
2249
Jamie Madill51f40ec2016-06-15 14:06:00 -04002250 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2251 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002252
2253 if (framebuffer->getReadBufferState() == GL_NONE)
2254 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002255 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002256 return false;
2257 }
2258
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002259 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002260 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002261 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002262 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002263 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002264 }
2265 }
2266 break;
2267
He Yunchaoced53ae2016-11-29 15:00:51 +08002268 default:
2269 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002270 }
2271
2272 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002273 if (*numParams == 0)
2274 {
2275 return false;
2276 }
2277
2278 return true;
2279}
2280
2281bool ValidateRobustStateQuery(ValidationContext *context,
2282 GLenum pname,
2283 GLsizei bufSize,
2284 GLenum *nativeType,
2285 unsigned int *numParams)
2286{
2287 if (!ValidateRobustEntryPoint(context, bufSize))
2288 {
2289 return false;
2290 }
2291
2292 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2293 {
2294 return false;
2295 }
2296
2297 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002298 {
2299 return false;
2300 }
2301
2302 return true;
2303}
2304
Jamie Madillc29968b2016-01-20 11:17:23 -05002305bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2306 GLenum target,
2307 GLint level,
2308 GLenum internalformat,
2309 bool isSubImage,
2310 GLint xoffset,
2311 GLint yoffset,
2312 GLint zoffset,
2313 GLint x,
2314 GLint y,
2315 GLsizei width,
2316 GLsizei height,
2317 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002318 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002319{
Brandon Jones6cad5662017-06-14 13:25:13 -07002320 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002321 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002322 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2323 return false;
2324 }
2325
2326 if (width < 0 || height < 0)
2327 {
2328 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002329 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002330 }
2331
He Yunchaoced53ae2016-11-29 15:00:51 +08002332 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2333 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002334 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002335 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002336 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002337 }
2338
2339 if (border != 0)
2340 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002341 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002342 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002343 }
2344
2345 if (!ValidMipLevel(context, target, level))
2346 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002347 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002348 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002349 }
2350
Jamie Madill51f40ec2016-06-15 14:06:00 -04002351 const auto &state = context->getGLState();
2352 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002353 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002354 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002355 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002356 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002357 }
2358
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002359 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002360 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002361 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002362 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002363 }
2364
Martin Radev138064f2016-07-15 12:03:41 +03002365 if (readFramebuffer->getReadBufferState() == GL_NONE)
2366 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002367 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002368 return false;
2369 }
2370
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002371 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2372 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002373 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002374 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002375 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2376 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002377 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002378 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002379 return false;
2380 }
2381
Martin Radev04e2c3b2017-07-27 16:54:35 +03002382 // ANGLE_multiview spec, Revision 1:
2383 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2384 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2385 // is not NONE.
2386 if (source->getMultiviewLayout() != GL_NONE)
2387 {
2388 context->handleError(InvalidFramebufferOperation()
2389 << "The active read framebuffer object has multiview attachments.");
2390 return false;
2391 }
2392
Geoff Langaae65a42014-05-26 12:43:44 -04002393 const gl::Caps &caps = context->getCaps();
2394
Geoff Langaae65a42014-05-26 12:43:44 -04002395 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002396 switch (target)
2397 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002398 case GL_TEXTURE_2D:
2399 maxDimension = caps.max2DTextureSize;
2400 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002401
He Yunchaoced53ae2016-11-29 15:00:51 +08002402 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2403 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2404 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2405 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2406 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2407 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2408 maxDimension = caps.maxCubeMapTextureSize;
2409 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002410
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002411 case GL_TEXTURE_RECTANGLE_ANGLE:
2412 maxDimension = caps.maxRectangleTextureSize;
2413 break;
2414
He Yunchaoced53ae2016-11-29 15:00:51 +08002415 case GL_TEXTURE_2D_ARRAY:
2416 maxDimension = caps.max2DTextureSize;
2417 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002418
He Yunchaoced53ae2016-11-29 15:00:51 +08002419 case GL_TEXTURE_3D:
2420 maxDimension = caps.max3DTextureSize;
2421 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002422
He Yunchaoced53ae2016-11-29 15:00:51 +08002423 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002424 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002425 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002426 }
2427
Jamie Madillc29968b2016-01-20 11:17:23 -05002428 gl::Texture *texture =
2429 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002430 if (!texture)
2431 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002432 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002433 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002434 }
2435
Geoff Lang69cce582015-09-17 13:20:36 -04002436 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002437 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002438 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002439 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002440 }
2441
Geoff Langca271392017-04-05 12:30:00 -04002442 const gl::InternalFormat &formatInfo =
2443 gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002444
Geoff Lang966c9402017-04-18 12:38:27 -04002445 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002446 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002447 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002448 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002449 }
2450
2451 if (isSubImage)
2452 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002453 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2454 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2455 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002456 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002457 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002458 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002459 }
2460 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002461 else
2462 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002463 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002464 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002465 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002466 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002467 }
2468
Geoff Langeb66a6e2016-10-31 13:06:12 -04002469 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002470 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002471 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002472 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002473 }
2474
2475 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002476 if (static_cast<int>(width) > maxLevelDimension ||
2477 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002478 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002479 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002480 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002481 }
2482 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002483
Jamie Madill0c8abca2016-07-22 20:21:26 -04002484 if (textureFormatOut)
2485 {
2486 *textureFormatOut = texture->getFormat(target, level);
2487 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002488
2489 // Detect texture copying feedback loops for WebGL.
2490 if (context->getExtensions().webglCompatibility)
2491 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002492 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002493 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002494 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002495 return false;
2496 }
2497 }
2498
Jamie Madill560a8d82014-05-21 13:06:20 -04002499 return true;
2500}
2501
Jiajia Qind9671222016-11-29 16:30:31 +08002502bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002503{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002504 switch (mode)
2505 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002506 case GL_POINTS:
2507 case GL_LINES:
2508 case GL_LINE_LOOP:
2509 case GL_LINE_STRIP:
2510 case GL_TRIANGLES:
2511 case GL_TRIANGLE_STRIP:
2512 case GL_TRIANGLE_FAN:
2513 break;
2514 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002515 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002516 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002517 }
2518
Jamie Madill250d33f2014-06-06 17:09:03 -04002519 if (count < 0)
2520 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002521 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002522 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002523 }
2524
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002525 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002526
Jamie Madill250d33f2014-06-06 17:09:03 -04002527 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002528 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002529 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002530 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002531 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002532 }
2533
Jamie Madillcbcde722017-01-06 14:50:00 -05002534 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2535 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002536 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002537 const Extensions &extensions = context->getExtensions();
2538 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002539 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002540 const FramebufferAttachment *dsAttachment =
2541 framebuffer->getStencilOrDepthStencilAttachment();
2542 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002543 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002544 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002545
2546 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2547 bool differentWritemasks =
2548 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2549 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2550 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2551 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2552
2553 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002554 {
Martin Radevffe754b2017-07-31 10:38:07 +03002555 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002556 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002557 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2558 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002559 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002560 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002561 return false;
2562 }
Jamie Madillac528012014-06-20 13:21:23 -04002563 }
2564
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002565 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002566 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002567 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002568 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002569 }
2570
Geoff Lang7dd2e102014-11-10 15:19:26 -05002571 gl::Program *program = state.getProgram();
2572 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002573 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002574 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002575 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002576 }
2577
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002578 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002579 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002580 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002581 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002582 }
2583
Martin Radevffe754b2017-07-31 10:38:07 +03002584 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002585 {
Martin Radevda8e2572017-09-12 17:21:16 +03002586 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002587 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002588 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002589 {
2590 context->handleError(InvalidOperation() << "The number of views in the active program "
2591 "and draw framebuffer does not match.");
2592 return false;
2593 }
Martin Radev7e69f762017-07-27 14:54:13 +03002594
2595 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2596 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2597 framebufferNumViews > 1)
2598 {
2599 context->handleError(InvalidOperation()
2600 << "There is an active transform feedback object "
2601 "when the number of views in the active draw "
2602 "framebuffer is greater than 1.");
2603 return false;
2604 }
Martin Radevffe754b2017-07-31 10:38:07 +03002605
2606 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2607 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2608 {
2609 context->handleError(InvalidOperation() << "There is an active query for target "
2610 "GL_TIME_ELAPSED_EXT when the number of "
2611 "views in the active draw framebuffer is "
2612 "greater than 1.");
2613 return false;
2614 }
Martin Radev7cf61662017-07-26 17:10:53 +03002615 }
2616
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002617 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002618 for (unsigned int uniformBlockIndex = 0;
2619 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002620 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002621 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002622 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002623 const OffsetBindingPointer<Buffer> &uniformBuffer =
2624 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002625
Geoff Lang5d124a62015-09-15 13:03:27 -04002626 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002627 {
2628 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002629 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002630 InvalidOperation()
2631 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002632 return false;
2633 }
2634
Geoff Lang5d124a62015-09-15 13:03:27 -04002635 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002636 if (uniformBufferSize == 0)
2637 {
2638 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002639 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002640 }
2641
Jamie Madill62d31cb2015-09-11 13:25:51 -04002642 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002643 {
2644 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002645 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002646 InvalidOperation()
2647 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002648 return false;
2649 }
2650 }
2651
Geoff Lange0cff192017-05-30 13:04:56 -04002652 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002653 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002654 {
Geoff Lange0cff192017-05-30 13:04:56 -04002655 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002656 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2657 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002658 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002659 return false;
2660 }
Geoff Lange0cff192017-05-30 13:04:56 -04002661
Geoff Lang9ab5b822017-05-30 16:19:23 -04002662 // Detect that the vertex shader input types match the attribute types
2663 if (!ValidateVertexShaderAttributeTypeMatch(context))
2664 {
2665 return false;
2666 }
2667
Geoff Lange0cff192017-05-30 13:04:56 -04002668 // Detect that the color buffer types match the fragment shader output types
2669 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2670 {
2671 return false;
2672 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002673 }
2674
Jamie Madill250d33f2014-06-06 17:09:03 -04002675 // No-op if zero count
2676 return (count > 0);
2677}
2678
Jamie Madillc1d770e2017-04-13 17:31:24 -04002679bool ValidateDrawArraysCommon(ValidationContext *context,
2680 GLenum mode,
2681 GLint first,
2682 GLsizei count,
2683 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002684{
Jamie Madillfd716582014-06-06 17:09:04 -04002685 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002686 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002687 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002688 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002689 }
2690
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002691 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002692 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002693 if (curTransformFeedback && curTransformFeedback->isActive() &&
2694 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002695 {
2696 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002697 // that does not match the current transform feedback object's draw mode (if transform
2698 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002699 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002700 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002701 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002702 }
2703
Jiajia Qind9671222016-11-29 16:30:31 +08002704 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002705 {
2706 return false;
2707 }
2708
Corentin Wallez71168a02016-12-19 15:11:18 -08002709 // Check the computation of maxVertex doesn't overflow.
2710 // - first < 0 or count < 0 have been checked as an error condition
2711 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2712 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2713 ASSERT(count > 0 && first >= 0);
2714 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2715 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002716 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002717 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002718 return false;
2719 }
2720
Corentin Wallez71168a02016-12-19 15:11:18 -08002721 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002722 {
2723 return false;
2724 }
2725
2726 return true;
2727}
2728
He Yunchaoced53ae2016-11-29 15:00:51 +08002729bool ValidateDrawArraysInstancedANGLE(Context *context,
2730 GLenum mode,
2731 GLint first,
2732 GLsizei count,
2733 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002734{
Corentin Wallez170efbf2017-05-02 13:45:01 -04002735 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002736 {
2737 return false;
2738 }
2739
Corentin Wallez0dc97812017-06-22 14:38:44 -04002740 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002741}
2742
Jiajia Qind9671222016-11-29 16:30:31 +08002743bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002744{
Jamie Madill250d33f2014-06-06 17:09:03 -04002745 switch (type)
2746 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002747 case GL_UNSIGNED_BYTE:
2748 case GL_UNSIGNED_SHORT:
2749 break;
2750 case GL_UNSIGNED_INT:
2751 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2752 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002753 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002754 return false;
2755 }
2756 break;
2757 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002758 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002759 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002760 }
2761
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002762 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002763
2764 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002765 if (curTransformFeedback && curTransformFeedback->isActive() &&
2766 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002767 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002768 // It is an invalid operation to call DrawElements, DrawRangeElements or
2769 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002770 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002771 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002772 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002773 }
2774
Jiajia Qind9671222016-11-29 16:30:31 +08002775 return true;
2776}
2777
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002778bool ValidateDrawElementsCommon(ValidationContext *context,
2779 GLenum mode,
2780 GLsizei count,
2781 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002782 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002783 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002784{
2785 if (!ValidateDrawElementsBase(context, type))
2786 return false;
2787
2788 const State &state = context->getGLState();
2789
Corentin Wallez170efbf2017-05-02 13:45:01 -04002790 if (!ValidateDrawBase(context, mode, count))
2791 {
2792 return false;
2793 }
2794
Jamie Madill250d33f2014-06-06 17:09:03 -04002795 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002796 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002797 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002798 context->handleError(InvalidOperation() << "Index buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -04002799 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002800 }
2801
He Yunchaoced53ae2016-11-29 15:00:51 +08002802 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002803 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002804
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002805 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2806
2807 if (context->getExtensions().webglCompatibility)
2808 {
2809 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2810 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2811 {
2812 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2813 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2814 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002815 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002816 return false;
2817 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002818
2819 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2820 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2821 // error is generated.
2822 if (reinterpret_cast<intptr_t>(indices) < 0)
2823 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002824 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002825 return false;
2826 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002827 }
2828
2829 if (context->getExtensions().webglCompatibility ||
2830 !context->getGLState().areClientArraysEnabled())
2831 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002832 if (!elementArrayBuffer && count > 0)
2833 {
2834 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2835 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2836 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002837 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002838 return false;
2839 }
2840 }
2841
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002842 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002843 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002844 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002845 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002846 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2847 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2848 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2849 constexpr uint64_t kMaxTypeSize = 8;
2850 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2851 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2852 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002853
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002854 uint64_t typeSize = typeBytes;
2855 uint64_t elementCount = static_cast<uint64_t>(count);
2856 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2857
2858 // Doing the multiplication here is overflow-safe
2859 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2860
2861 // The offset can be any value, check for overflows
2862 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2863 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002864 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002865 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002866 return false;
2867 }
2868
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002869 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2870 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002871 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002872 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002873 return false;
2874 }
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002875
Corentin Wallez487653b2017-09-01 17:17:55 -04002876 ASSERT(isPow2(typeSize) && typeSize > 0);
2877 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002878 {
2879 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
2880 return false;
2881 }
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002882 }
2883 else if (!indices)
2884 {
2885 // This is an application error that would normally result in a crash,
2886 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002887 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04002888 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002889 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002890 }
2891
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002892 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002893 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002894 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2895 // access is enabled.
2896 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2897 {
2898 return false;
2899 }
2900 }
2901 else
2902 {
2903 // Use the parameter buffer to retrieve and cache the index range.
2904 const auto &params = context->getParams<HasIndexRange>();
2905 const auto &indexRangeOpt = params.getIndexRange();
2906 if (!indexRangeOpt.valid())
2907 {
2908 // Unexpected error.
2909 return false;
2910 }
2911
2912 // If we use an index greater than our maximum supported index range, return an error.
2913 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2914 // return an error if possible here.
2915 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2916 {
2917 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2918 return false;
2919 }
2920
2921 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2922 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2923 {
2924 return false;
2925 }
2926
2927 // No op if there are no real indices in the index data (all are primitive restart).
2928 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002929 }
2930
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002931 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002932}
2933
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002934bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2935 GLenum mode,
2936 GLsizei count,
2937 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002938 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002939 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002940{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002941 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002942}
2943
Geoff Lang3edfe032015-09-04 16:38:24 -04002944bool ValidateDrawElementsInstancedANGLE(Context *context,
2945 GLenum mode,
2946 GLsizei count,
2947 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002948 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002949 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002950{
Corentin Wallez170efbf2017-05-02 13:45:01 -04002951 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002952 {
2953 return false;
2954 }
2955
Corentin Wallez0dc97812017-06-22 14:38:44 -04002956 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002957}
2958
He Yunchaoced53ae2016-11-29 15:00:51 +08002959bool ValidateFramebufferTextureBase(Context *context,
2960 GLenum target,
2961 GLenum attachment,
2962 GLuint texture,
2963 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002964{
Jamie Madill55ec3b12014-07-03 10:38:57 -04002965 if (!ValidFramebufferTarget(target))
2966 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002967 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002968 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002969 }
2970
2971 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002972 {
2973 return false;
2974 }
2975
Jamie Madill55ec3b12014-07-03 10:38:57 -04002976 if (texture != 0)
2977 {
2978 gl::Texture *tex = context->getTexture(texture);
2979
Jamie Madillbe849e42017-05-02 15:49:00 -04002980 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002981 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002982 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002983 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002984 }
2985
2986 if (level < 0)
2987 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002988 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002989 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002990 }
2991 }
2992
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002993 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002994 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002995
Jamie Madill84115c92015-04-23 15:00:07 -04002996 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002997 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002998 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002999 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003000 }
3001
3002 return true;
3003}
3004
Geoff Langb1196682014-07-23 13:47:29 -04003005bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003006{
3007 if (program == 0)
3008 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003009 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003010 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003011 }
3012
Dian Xiang769769a2015-09-09 15:20:08 -07003013 gl::Program *programObject = GetValidProgram(context, program);
3014 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003015 {
3016 return false;
3017 }
3018
Jamie Madill0063c512014-08-25 15:47:53 -04003019 if (!programObject || !programObject->isLinked())
3020 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003021 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003022 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003023 }
3024
Geoff Lang7dd2e102014-11-10 15:19:26 -05003025 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003026 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003027 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003028 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003029 }
3030
Jamie Madill0063c512014-08-25 15:47:53 -04003031 return true;
3032}
3033
Geoff Langf41d0ee2016-10-07 13:04:23 -04003034static bool ValidateSizedGetUniform(Context *context,
3035 GLuint program,
3036 GLint location,
3037 GLsizei bufSize,
3038 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003039{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003040 if (length)
3041 {
3042 *length = 0;
3043 }
3044
Jamie Madill78f41802014-08-25 15:47:55 -04003045 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003046 {
Jamie Madill78f41802014-08-25 15:47:55 -04003047 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003048 }
3049
Geoff Langf41d0ee2016-10-07 13:04:23 -04003050 if (bufSize < 0)
3051 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003052 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003053 return false;
3054 }
3055
Jamie Madilla502c742014-08-28 17:19:13 -04003056 gl::Program *programObject = context->getProgram(program);
3057 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003058
Jamie Madill78f41802014-08-25 15:47:55 -04003059 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003060 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003061 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003062 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003063 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003064 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003065 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003066 }
3067
Geoff Langf41d0ee2016-10-07 13:04:23 -04003068 if (length)
3069 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003070 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003071 }
3072
Jamie Madill0063c512014-08-25 15:47:53 -04003073 return true;
3074}
3075
He Yunchaoced53ae2016-11-29 15:00:51 +08003076bool ValidateGetnUniformfvEXT(Context *context,
3077 GLuint program,
3078 GLint location,
3079 GLsizei bufSize,
3080 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003081{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003082 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003083}
3084
He Yunchaoced53ae2016-11-29 15:00:51 +08003085bool ValidateGetnUniformivEXT(Context *context,
3086 GLuint program,
3087 GLint location,
3088 GLsizei bufSize,
3089 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003090{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003091 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3092}
3093
3094bool ValidateGetUniformfvRobustANGLE(Context *context,
3095 GLuint program,
3096 GLint location,
3097 GLsizei bufSize,
3098 GLsizei *length,
3099 GLfloat *params)
3100{
3101 if (!ValidateRobustEntryPoint(context, bufSize))
3102 {
3103 return false;
3104 }
3105
3106 // bufSize is validated in ValidateSizedGetUniform
3107 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3108}
3109
3110bool ValidateGetUniformivRobustANGLE(Context *context,
3111 GLuint program,
3112 GLint location,
3113 GLsizei bufSize,
3114 GLsizei *length,
3115 GLint *params)
3116{
3117 if (!ValidateRobustEntryPoint(context, bufSize))
3118 {
3119 return false;
3120 }
3121
3122 // bufSize is validated in ValidateSizedGetUniform
3123 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3124}
3125
3126bool ValidateGetUniformuivRobustANGLE(Context *context,
3127 GLuint program,
3128 GLint location,
3129 GLsizei bufSize,
3130 GLsizei *length,
3131 GLuint *params)
3132{
3133 if (!ValidateRobustEntryPoint(context, bufSize))
3134 {
3135 return false;
3136 }
3137
3138 if (context->getClientMajorVersion() < 3)
3139 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003140 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003141 return false;
3142 }
3143
3144 // bufSize is validated in ValidateSizedGetUniform
3145 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003146}
3147
He Yunchaoced53ae2016-11-29 15:00:51 +08003148bool ValidateDiscardFramebufferBase(Context *context,
3149 GLenum target,
3150 GLsizei numAttachments,
3151 const GLenum *attachments,
3152 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003153{
3154 if (numAttachments < 0)
3155 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003156 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003157 return false;
3158 }
3159
3160 for (GLsizei i = 0; i < numAttachments; ++i)
3161 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003162 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003163 {
3164 if (defaultFramebuffer)
3165 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003166 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003167 return false;
3168 }
3169
3170 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3171 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003172 context->handleError(InvalidOperation() << "Requested color attachment is "
3173 "greater than the maximum supported "
3174 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003175 return false;
3176 }
3177 }
3178 else
3179 {
3180 switch (attachments[i])
3181 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003182 case GL_DEPTH_ATTACHMENT:
3183 case GL_STENCIL_ATTACHMENT:
3184 case GL_DEPTH_STENCIL_ATTACHMENT:
3185 if (defaultFramebuffer)
3186 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003187 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3188 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003189 return false;
3190 }
3191 break;
3192 case GL_COLOR:
3193 case GL_DEPTH:
3194 case GL_STENCIL:
3195 if (!defaultFramebuffer)
3196 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003197 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3198 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003199 return false;
3200 }
3201 break;
3202 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003203 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003204 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003205 }
3206 }
3207 }
3208
3209 return true;
3210}
3211
Austin Kinross6ee1e782015-05-29 17:05:37 -07003212bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3213{
3214 // Note that debug marker calls must not set error state
3215
3216 if (length < 0)
3217 {
3218 return false;
3219 }
3220
3221 if (marker == nullptr)
3222 {
3223 return false;
3224 }
3225
3226 return true;
3227}
3228
3229bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3230{
3231 // Note that debug marker calls must not set error state
3232
3233 if (length < 0)
3234 {
3235 return false;
3236 }
3237
3238 if (length > 0 && marker == nullptr)
3239 {
3240 return false;
3241 }
3242
3243 return true;
3244}
3245
Geoff Langdcab33b2015-07-21 13:03:16 -04003246bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003247 GLenum target,
3248 egl::Image *image)
3249{
Geoff Langa8406172015-07-21 16:53:39 -04003250 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3251 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003252 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003253 return false;
3254 }
3255
3256 switch (target)
3257 {
3258 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003259 if (!context->getExtensions().eglImage)
3260 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003261 context->handleError(InvalidEnum()
3262 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003263 }
3264 break;
3265
3266 case GL_TEXTURE_EXTERNAL_OES:
3267 if (!context->getExtensions().eglImageExternal)
3268 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003269 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3270 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003271 }
Geoff Langa8406172015-07-21 16:53:39 -04003272 break;
3273
3274 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003275 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003276 return false;
3277 }
3278
Jamie Madill61e16b42017-06-19 11:13:23 -04003279 ASSERT(context->getCurrentDisplay());
3280 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003281 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003282 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003283 return false;
3284 }
3285
3286 if (image->getSamples() > 0)
3287 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003288 context->handleError(InvalidOperation()
3289 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003290 return false;
3291 }
3292
Geoff Langca271392017-04-05 12:30:00 -04003293 const TextureCaps &textureCaps =
3294 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003295 if (!textureCaps.texturable)
3296 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003297 context->handleError(InvalidOperation()
3298 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003299 return false;
3300 }
3301
Geoff Langdcab33b2015-07-21 13:03:16 -04003302 return true;
3303}
3304
3305bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003306 GLenum target,
3307 egl::Image *image)
3308{
Geoff Langa8406172015-07-21 16:53:39 -04003309 if (!context->getExtensions().eglImage)
3310 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003311 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003312 return false;
3313 }
3314
3315 switch (target)
3316 {
3317 case GL_RENDERBUFFER:
3318 break;
3319
3320 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003321 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003322 return false;
3323 }
3324
Jamie Madill61e16b42017-06-19 11:13:23 -04003325 ASSERT(context->getCurrentDisplay());
3326 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003327 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003328 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003329 return false;
3330 }
3331
Geoff Langca271392017-04-05 12:30:00 -04003332 const TextureCaps &textureCaps =
3333 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003334 if (!textureCaps.renderable)
3335 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003336 context->handleError(InvalidOperation()
3337 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003338 return false;
3339 }
3340
Geoff Langdcab33b2015-07-21 13:03:16 -04003341 return true;
3342}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003343
3344bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3345{
Geoff Lang36167ab2015-12-07 10:27:14 -05003346 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003347 {
3348 // The default VAO should always exist
3349 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003350 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003351 return false;
3352 }
3353
3354 return true;
3355}
3356
Geoff Langc5629752015-12-07 16:29:04 -05003357bool ValidateProgramBinaryBase(Context *context,
3358 GLuint program,
3359 GLenum binaryFormat,
3360 const void *binary,
3361 GLint length)
3362{
3363 Program *programObject = GetValidProgram(context, program);
3364 if (programObject == nullptr)
3365 {
3366 return false;
3367 }
3368
3369 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3370 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3371 programBinaryFormats.end())
3372 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003373 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003374 return false;
3375 }
3376
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003377 if (context->hasActiveTransformFeedback(program))
3378 {
3379 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003380 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3381 "is associated with an active transform "
3382 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003383 return false;
3384 }
3385
Geoff Langc5629752015-12-07 16:29:04 -05003386 return true;
3387}
3388
3389bool ValidateGetProgramBinaryBase(Context *context,
3390 GLuint program,
3391 GLsizei bufSize,
3392 GLsizei *length,
3393 GLenum *binaryFormat,
3394 void *binary)
3395{
3396 Program *programObject = GetValidProgram(context, program);
3397 if (programObject == nullptr)
3398 {
3399 return false;
3400 }
3401
3402 if (!programObject->isLinked())
3403 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003404 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003405 return false;
3406 }
3407
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003408 if (context->getCaps().programBinaryFormats.empty())
3409 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003410 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003411 return false;
3412 }
3413
Geoff Langc5629752015-12-07 16:29:04 -05003414 return true;
3415}
Jamie Madillc29968b2016-01-20 11:17:23 -05003416
Jamie Madillc29968b2016-01-20 11:17:23 -05003417bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3418{
3419 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003420 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003421 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003422 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3423 return false;
3424 }
3425 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3426 {
3427 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003428 return false;
3429 }
3430
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003431 ASSERT(context->getGLState().getDrawFramebuffer());
3432 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003433 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3434
3435 // This should come first before the check for the default frame buffer
3436 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3437 // rather than INVALID_OPERATION
3438 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3439 {
3440 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3441
3442 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003443 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3444 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003445 {
3446 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003447 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3448 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3449 // 3.1 is still a bit ambiguous about the error, but future specs are
3450 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003451 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003452 return false;
3453 }
3454 else if (bufs[colorAttachment] >= maxColorAttachment)
3455 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003456 context->handleError(InvalidOperation()
3457 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003458 return false;
3459 }
3460 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3461 frameBufferId != 0)
3462 {
3463 // INVALID_OPERATION-GL is bound to buffer and ith argument
3464 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003465 context->handleError(InvalidOperation()
3466 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003467 return false;
3468 }
3469 }
3470
3471 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3472 // and n is not 1 or bufs is bound to value other than BACK and NONE
3473 if (frameBufferId == 0)
3474 {
3475 if (n != 1)
3476 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003477 context->handleError(InvalidOperation()
3478 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003479 return false;
3480 }
3481
3482 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3483 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003484 context->handleError(
3485 InvalidOperation()
3486 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003487 return false;
3488 }
3489 }
3490
3491 return true;
3492}
3493
Geoff Lang496c02d2016-10-20 11:38:11 -07003494bool ValidateGetBufferPointervBase(Context *context,
3495 GLenum target,
3496 GLenum pname,
3497 GLsizei *length,
3498 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003499{
Geoff Lang496c02d2016-10-20 11:38:11 -07003500 if (length)
3501 {
3502 *length = 0;
3503 }
3504
3505 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3506 {
3507 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003508 InvalidOperation()
3509 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003510 return false;
3511 }
3512
Olli Etuaho4f667482016-03-30 15:56:35 +03003513 if (!ValidBufferTarget(context, target))
3514 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003515 context->handleError(InvalidEnum() << "Buffer target not valid: 0x" << std::hex
3516 << std::uppercase << target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003517 return false;
3518 }
3519
Geoff Lang496c02d2016-10-20 11:38:11 -07003520 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003521 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003522 case GL_BUFFER_MAP_POINTER:
3523 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003524
Geoff Lang496c02d2016-10-20 11:38:11 -07003525 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003526 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003527 return false;
3528 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003529
3530 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3531 // target bound to zero generate an INVALID_OPERATION error."
3532 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003533 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003534 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003535 context->handleError(InvalidOperation()
3536 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003537 return false;
3538 }
3539
Geoff Lang496c02d2016-10-20 11:38:11 -07003540 if (length)
3541 {
3542 *length = 1;
3543 }
3544
Olli Etuaho4f667482016-03-30 15:56:35 +03003545 return true;
3546}
3547
3548bool ValidateUnmapBufferBase(Context *context, GLenum target)
3549{
3550 if (!ValidBufferTarget(context, target))
3551 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003552 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003553 return false;
3554 }
3555
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003556 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003557
3558 if (buffer == nullptr || !buffer->isMapped())
3559 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003560 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003561 return false;
3562 }
3563
3564 return true;
3565}
3566
3567bool ValidateMapBufferRangeBase(Context *context,
3568 GLenum target,
3569 GLintptr offset,
3570 GLsizeiptr length,
3571 GLbitfield access)
3572{
3573 if (!ValidBufferTarget(context, target))
3574 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003575 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003576 return false;
3577 }
3578
Brandon Jones6cad5662017-06-14 13:25:13 -07003579 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003580 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003581 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3582 return false;
3583 }
3584
3585 if (length < 0)
3586 {
3587 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003588 return false;
3589 }
3590
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003591 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003592
3593 if (!buffer)
3594 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003595 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003596 return false;
3597 }
3598
3599 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003600 CheckedNumeric<size_t> checkedOffset(offset);
3601 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003602
Jamie Madille2e406c2016-06-02 13:04:10 -04003603 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003604 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003605 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003606 return false;
3607 }
3608
3609 // Check for invalid bits in the mask
3610 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3611 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3612 GL_MAP_UNSYNCHRONIZED_BIT;
3613
3614 if (access & ~(allAccessBits))
3615 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003616 context->handleError(InvalidValue()
3617 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003618 return false;
3619 }
3620
3621 if (length == 0)
3622 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003623 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003624 return false;
3625 }
3626
3627 if (buffer->isMapped())
3628 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003629 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003630 return false;
3631 }
3632
3633 // Check for invalid bit combinations
3634 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3635 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003636 context->handleError(InvalidOperation()
3637 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003638 return false;
3639 }
3640
3641 GLbitfield writeOnlyBits =
3642 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3643
3644 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003646 context->handleError(InvalidOperation()
3647 << "Invalid access bits when mapping buffer for reading: 0x"
3648 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003649 return false;
3650 }
3651
3652 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3653 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003654 context->handleError(
3655 InvalidOperation()
3656 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003657 return false;
3658 }
Geoff Lang79f71042017-08-14 16:43:43 -04003659
3660 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003661}
3662
3663bool ValidateFlushMappedBufferRangeBase(Context *context,
3664 GLenum target,
3665 GLintptr offset,
3666 GLsizeiptr length)
3667{
Brandon Jones6cad5662017-06-14 13:25:13 -07003668 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003669 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003670 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3671 return false;
3672 }
3673
3674 if (length < 0)
3675 {
3676 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003677 return false;
3678 }
3679
3680 if (!ValidBufferTarget(context, target))
3681 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003682 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003683 return false;
3684 }
3685
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003686 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003687
3688 if (buffer == nullptr)
3689 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003690 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003691 return false;
3692 }
3693
3694 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3695 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003696 context->handleError(InvalidOperation()
3697 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003698 return false;
3699 }
3700
3701 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003702 CheckedNumeric<size_t> checkedOffset(offset);
3703 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003704
Jamie Madille2e406c2016-06-02 13:04:10 -04003705 if (!checkedSize.IsValid() ||
3706 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003707 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003708 context->handleError(InvalidValue()
3709 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003710 return false;
3711 }
3712
3713 return true;
3714}
3715
Olli Etuaho41997e72016-03-10 13:38:39 +02003716bool ValidateGenOrDelete(Context *context, GLint n)
3717{
3718 if (n < 0)
3719 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003720 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003721 return false;
3722 }
3723 return true;
3724}
3725
Geoff Langff5b2d52016-09-07 11:32:23 -04003726bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3727{
3728 if (!context->getExtensions().robustClientMemory)
3729 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003730 context->handleError(InvalidOperation()
3731 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003732 return false;
3733 }
3734
3735 if (bufSize < 0)
3736 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003737 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003738 return false;
3739 }
3740
3741 return true;
3742}
3743
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003744bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3745{
3746 if (bufSize < numParams)
3747 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003748 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3749 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003750 return false;
3751 }
3752
3753 return true;
3754}
3755
Jamie Madillbe849e42017-05-02 15:49:00 -04003756bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3757 GLenum target,
3758 GLenum attachment,
3759 GLenum pname,
3760 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003761{
Geoff Langff5b2d52016-09-07 11:32:23 -04003762 if (!ValidFramebufferTarget(target))
3763 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003764 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003765 return false;
3766 }
3767
3768 int clientVersion = context->getClientMajorVersion();
3769
3770 switch (pname)
3771 {
3772 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3773 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3774 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3775 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3776 break;
3777
Martin Radeve5285d22017-07-14 16:23:53 +03003778 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3779 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3780 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3781 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3782 if (clientVersion < 3 || !context->getExtensions().multiview)
3783 {
3784 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3785 return false;
3786 }
3787 break;
3788
Geoff Langff5b2d52016-09-07 11:32:23 -04003789 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3790 if (clientVersion < 3 && !context->getExtensions().sRGB)
3791 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003792 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003793 return false;
3794 }
3795 break;
3796
3797 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3798 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3799 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3800 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3801 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3802 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3803 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3804 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3805 if (clientVersion < 3)
3806 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003807 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003808 return false;
3809 }
3810 break;
3811
3812 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003813 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003814 return false;
3815 }
3816
3817 // Determine if the attachment is a valid enum
3818 switch (attachment)
3819 {
3820 case GL_BACK:
3821 case GL_FRONT:
3822 case GL_DEPTH:
3823 case GL_STENCIL:
3824 case GL_DEPTH_STENCIL_ATTACHMENT:
3825 if (clientVersion < 3)
3826 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003827 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003828 return false;
3829 }
3830 break;
3831
3832 case GL_DEPTH_ATTACHMENT:
3833 case GL_STENCIL_ATTACHMENT:
3834 break;
3835
3836 default:
3837 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
3838 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3839 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003840 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003841 return false;
3842 }
3843 break;
3844 }
3845
3846 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3847 ASSERT(framebuffer);
3848
3849 if (framebuffer->id() == 0)
3850 {
3851 if (clientVersion < 3)
3852 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003853 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003854 return false;
3855 }
3856
3857 switch (attachment)
3858 {
3859 case GL_BACK:
3860 case GL_DEPTH:
3861 case GL_STENCIL:
3862 break;
3863
3864 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003865 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003866 return false;
3867 }
3868 }
3869 else
3870 {
3871 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3872 {
3873 // Valid attachment query
3874 }
3875 else
3876 {
3877 switch (attachment)
3878 {
3879 case GL_DEPTH_ATTACHMENT:
3880 case GL_STENCIL_ATTACHMENT:
3881 break;
3882
3883 case GL_DEPTH_STENCIL_ATTACHMENT:
3884 if (!framebuffer->hasValidDepthStencil())
3885 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003886 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003887 return false;
3888 }
3889 break;
3890
3891 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003892 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003893 return false;
3894 }
3895 }
3896 }
3897
3898 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3899 if (attachmentObject)
3900 {
3901 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3902 attachmentObject->type() == GL_TEXTURE ||
3903 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3904
3905 switch (pname)
3906 {
3907 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3908 if (attachmentObject->type() != GL_RENDERBUFFER &&
3909 attachmentObject->type() != GL_TEXTURE)
3910 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003911 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003912 return false;
3913 }
3914 break;
3915
3916 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3917 if (attachmentObject->type() != GL_TEXTURE)
3918 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003919 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003920 return false;
3921 }
3922 break;
3923
3924 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3925 if (attachmentObject->type() != GL_TEXTURE)
3926 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003927 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003928 return false;
3929 }
3930 break;
3931
3932 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3933 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3934 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003935 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003936 return false;
3937 }
3938 break;
3939
3940 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3941 if (attachmentObject->type() != GL_TEXTURE)
3942 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003943 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003944 return false;
3945 }
3946 break;
3947
3948 default:
3949 break;
3950 }
3951 }
3952 else
3953 {
3954 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3955 // is NONE, then querying any other pname will generate INVALID_ENUM.
3956
3957 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3958 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3959 // INVALID_OPERATION for all other pnames
3960
3961 switch (pname)
3962 {
3963 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3964 break;
3965
3966 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3967 if (clientVersion < 3)
3968 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003969 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07003970 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003971 return false;
3972 }
3973 break;
3974
3975 default:
3976 if (clientVersion < 3)
3977 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003978 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07003979 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003980 return false;
3981 }
3982 else
3983 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003984 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Brandon Jonesafa75152017-07-21 13:11:29 -07003985 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003986 return false;
3987 }
3988 }
3989 }
3990
Martin Radeve5285d22017-07-14 16:23:53 +03003991 if (numParams)
3992 {
3993 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
3994 {
3995 // Only when the viewport offsets are queried we can have a varying number of output
3996 // parameters.
3997 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
3998 *numParams = numViews * 2;
3999 }
4000 else
4001 {
4002 // For all other queries we can have only one output parameter.
4003 *numParams = 1;
4004 }
4005 }
4006
Geoff Langff5b2d52016-09-07 11:32:23 -04004007 return true;
4008}
4009
4010bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4011 GLenum target,
4012 GLenum attachment,
4013 GLenum pname,
4014 GLsizei bufSize,
4015 GLsizei *numParams)
4016{
4017 if (!ValidateRobustEntryPoint(context, bufSize))
4018 {
4019 return false;
4020 }
4021
Jamie Madillbe849e42017-05-02 15:49:00 -04004022 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4023 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004024 {
4025 return false;
4026 }
4027
4028 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4029 {
4030 return false;
4031 }
4032
4033 return true;
4034}
4035
Geoff Langff5b2d52016-09-07 11:32:23 -04004036bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4037 GLenum target,
4038 GLenum pname,
4039 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004040 GLsizei *length,
4041 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004042{
4043 if (!ValidateRobustEntryPoint(context, bufSize))
4044 {
4045 return false;
4046 }
4047
Geoff Langebebe1c2016-10-14 12:01:31 -04004048 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004049 {
4050 return false;
4051 }
4052
Geoff Langebebe1c2016-10-14 12:01:31 -04004053 if (!ValidateRobustBufferSize(context, bufSize, *length))
4054 {
4055 return false;
4056 }
4057
4058 return true;
4059}
4060
Geoff Langebebe1c2016-10-14 12:01:31 -04004061bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4062 GLenum target,
4063 GLenum pname,
4064 GLsizei bufSize,
4065 GLsizei *length,
4066 GLint64 *params)
4067{
4068 if (!ValidateRobustEntryPoint(context, bufSize))
4069 {
4070 return false;
4071 }
4072
4073 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4074 {
4075 return false;
4076 }
4077
4078 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004079 {
4080 return false;
4081 }
4082
4083 return true;
4084}
4085
Jamie Madillbe849e42017-05-02 15:49:00 -04004086bool ValidateGetProgramivBase(ValidationContext *context,
4087 GLuint program,
4088 GLenum pname,
4089 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004090{
4091 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004092 if (numParams)
4093 {
4094 *numParams = 1;
4095 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004096
4097 Program *programObject = GetValidProgram(context, program);
4098 if (!programObject)
4099 {
4100 return false;
4101 }
4102
4103 switch (pname)
4104 {
4105 case GL_DELETE_STATUS:
4106 case GL_LINK_STATUS:
4107 case GL_VALIDATE_STATUS:
4108 case GL_INFO_LOG_LENGTH:
4109 case GL_ATTACHED_SHADERS:
4110 case GL_ACTIVE_ATTRIBUTES:
4111 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4112 case GL_ACTIVE_UNIFORMS:
4113 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4114 break;
4115
4116 case GL_PROGRAM_BINARY_LENGTH:
4117 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4118 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004119 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4120 "requires GL_OES_get_program_binary or "
4121 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004122 return false;
4123 }
4124 break;
4125
4126 case GL_ACTIVE_UNIFORM_BLOCKS:
4127 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4128 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4129 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4130 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4131 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4132 if (context->getClientMajorVersion() < 3)
4133 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004134 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004135 return false;
4136 }
4137 break;
4138
Yunchao He61afff12017-03-14 15:34:03 +08004139 case GL_PROGRAM_SEPARABLE:
4140 if (context->getClientVersion() < Version(3, 1))
4141 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004142 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004143 return false;
4144 }
4145 break;
4146
Geoff Langff5b2d52016-09-07 11:32:23 -04004147 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004148 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004149 return false;
4150 }
4151
4152 return true;
4153}
4154
4155bool ValidateGetProgramivRobustANGLE(Context *context,
4156 GLuint program,
4157 GLenum pname,
4158 GLsizei bufSize,
4159 GLsizei *numParams)
4160{
4161 if (!ValidateRobustEntryPoint(context, bufSize))
4162 {
4163 return false;
4164 }
4165
Jamie Madillbe849e42017-05-02 15:49:00 -04004166 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004167 {
4168 return false;
4169 }
4170
4171 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4172 {
4173 return false;
4174 }
4175
4176 return true;
4177}
4178
Geoff Lang740d9022016-10-07 11:20:52 -04004179bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4180 GLenum target,
4181 GLenum pname,
4182 GLsizei bufSize,
4183 GLsizei *length,
4184 GLint *params)
4185{
4186 if (!ValidateRobustEntryPoint(context, bufSize))
4187 {
4188 return false;
4189 }
4190
4191 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4192 {
4193 return false;
4194 }
4195
4196 if (!ValidateRobustBufferSize(context, bufSize, *length))
4197 {
4198 return false;
4199 }
4200
4201 return true;
4202}
4203
Geoff Langd7d0ed32016-10-07 11:33:51 -04004204bool ValidateGetShaderivRobustANGLE(Context *context,
4205 GLuint shader,
4206 GLenum pname,
4207 GLsizei bufSize,
4208 GLsizei *length,
4209 GLint *params)
4210{
4211 if (!ValidateRobustEntryPoint(context, bufSize))
4212 {
4213 return false;
4214 }
4215
4216 if (!ValidateGetShaderivBase(context, shader, pname, length))
4217 {
4218 return false;
4219 }
4220
4221 if (!ValidateRobustBufferSize(context, bufSize, *length))
4222 {
4223 return false;
4224 }
4225
4226 return true;
4227}
4228
Geoff Langc1984ed2016-10-07 12:41:00 -04004229bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4230 GLenum target,
4231 GLenum pname,
4232 GLsizei bufSize,
4233 GLsizei *length,
4234 GLfloat *params)
4235{
4236 if (!ValidateRobustEntryPoint(context, bufSize))
4237 {
4238 return false;
4239 }
4240
4241 if (!ValidateGetTexParameterBase(context, target, pname, length))
4242 {
4243 return false;
4244 }
4245
4246 if (!ValidateRobustBufferSize(context, bufSize, *length))
4247 {
4248 return false;
4249 }
4250
4251 return true;
4252}
4253
Geoff Langc1984ed2016-10-07 12:41:00 -04004254bool ValidateGetTexParameterivRobustANGLE(Context *context,
4255 GLenum target,
4256 GLenum pname,
4257 GLsizei bufSize,
4258 GLsizei *length,
4259 GLint *params)
4260{
4261 if (!ValidateRobustEntryPoint(context, bufSize))
4262 {
4263 return false;
4264 }
4265
4266 if (!ValidateGetTexParameterBase(context, target, pname, length))
4267 {
4268 return false;
4269 }
4270
4271 if (!ValidateRobustBufferSize(context, bufSize, *length))
4272 {
4273 return false;
4274 }
4275
4276 return true;
4277}
4278
Geoff Langc1984ed2016-10-07 12:41:00 -04004279bool ValidateTexParameterfvRobustANGLE(Context *context,
4280 GLenum target,
4281 GLenum pname,
4282 GLsizei bufSize,
4283 const GLfloat *params)
4284{
4285 if (!ValidateRobustEntryPoint(context, bufSize))
4286 {
4287 return false;
4288 }
4289
4290 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4291}
4292
Geoff Langc1984ed2016-10-07 12:41:00 -04004293bool ValidateTexParameterivRobustANGLE(Context *context,
4294 GLenum target,
4295 GLenum pname,
4296 GLsizei bufSize,
4297 const GLint *params)
4298{
4299 if (!ValidateRobustEntryPoint(context, bufSize))
4300 {
4301 return false;
4302 }
4303
4304 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4305}
4306
Geoff Langc1984ed2016-10-07 12:41:00 -04004307bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4308 GLuint sampler,
4309 GLenum pname,
4310 GLuint bufSize,
4311 GLsizei *length,
4312 GLfloat *params)
4313{
4314 if (!ValidateRobustEntryPoint(context, bufSize))
4315 {
4316 return false;
4317 }
4318
4319 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4320 {
4321 return false;
4322 }
4323
4324 if (!ValidateRobustBufferSize(context, bufSize, *length))
4325 {
4326 return false;
4327 }
4328
4329 return true;
4330}
4331
Geoff Langc1984ed2016-10-07 12:41:00 -04004332bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4333 GLuint sampler,
4334 GLenum pname,
4335 GLuint bufSize,
4336 GLsizei *length,
4337 GLint *params)
4338{
4339 if (!ValidateRobustEntryPoint(context, bufSize))
4340 {
4341 return false;
4342 }
4343
4344 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4345 {
4346 return false;
4347 }
4348
4349 if (!ValidateRobustBufferSize(context, bufSize, *length))
4350 {
4351 return false;
4352 }
4353
4354 return true;
4355}
4356
Geoff Langc1984ed2016-10-07 12:41:00 -04004357bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4358 GLuint sampler,
4359 GLenum pname,
4360 GLsizei bufSize,
4361 const GLfloat *params)
4362{
4363 if (!ValidateRobustEntryPoint(context, bufSize))
4364 {
4365 return false;
4366 }
4367
4368 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4369}
4370
Geoff Langc1984ed2016-10-07 12:41:00 -04004371bool ValidateSamplerParameterivRobustANGLE(Context *context,
4372 GLuint sampler,
4373 GLenum pname,
4374 GLsizei bufSize,
4375 const GLint *params)
4376{
4377 if (!ValidateRobustEntryPoint(context, bufSize))
4378 {
4379 return false;
4380 }
4381
4382 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4383}
4384
Geoff Lang0b031062016-10-13 14:30:04 -04004385bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4386 GLuint index,
4387 GLenum pname,
4388 GLsizei bufSize,
4389 GLsizei *length,
4390 GLfloat *params)
4391{
4392 if (!ValidateRobustEntryPoint(context, bufSize))
4393 {
4394 return false;
4395 }
4396
4397 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4398 {
4399 return false;
4400 }
4401
4402 if (!ValidateRobustBufferSize(context, bufSize, *length))
4403 {
4404 return false;
4405 }
4406
4407 return true;
4408}
4409
Geoff Lang0b031062016-10-13 14:30:04 -04004410bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4411 GLuint index,
4412 GLenum pname,
4413 GLsizei bufSize,
4414 GLsizei *length,
4415 GLint *params)
4416{
4417 if (!ValidateRobustEntryPoint(context, bufSize))
4418 {
4419 return false;
4420 }
4421
4422 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4423 {
4424 return false;
4425 }
4426
4427 if (!ValidateRobustBufferSize(context, bufSize, *length))
4428 {
4429 return false;
4430 }
4431
4432 return true;
4433}
4434
Geoff Lang0b031062016-10-13 14:30:04 -04004435bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4436 GLuint index,
4437 GLenum pname,
4438 GLsizei bufSize,
4439 GLsizei *length,
4440 void **pointer)
4441{
4442 if (!ValidateRobustEntryPoint(context, bufSize))
4443 {
4444 return false;
4445 }
4446
4447 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4448 {
4449 return false;
4450 }
4451
4452 if (!ValidateRobustBufferSize(context, bufSize, *length))
4453 {
4454 return false;
4455 }
4456
4457 return true;
4458}
4459
Geoff Lang0b031062016-10-13 14:30:04 -04004460bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4461 GLuint index,
4462 GLenum pname,
4463 GLsizei bufSize,
4464 GLsizei *length,
4465 GLint *params)
4466{
4467 if (!ValidateRobustEntryPoint(context, bufSize))
4468 {
4469 return false;
4470 }
4471
4472 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4473 {
4474 return false;
4475 }
4476
4477 if (!ValidateRobustBufferSize(context, bufSize, *length))
4478 {
4479 return false;
4480 }
4481
4482 return true;
4483}
4484
Geoff Lang0b031062016-10-13 14:30:04 -04004485bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4486 GLuint index,
4487 GLenum pname,
4488 GLsizei bufSize,
4489 GLsizei *length,
4490 GLuint *params)
4491{
4492 if (!ValidateRobustEntryPoint(context, bufSize))
4493 {
4494 return false;
4495 }
4496
4497 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4498 {
4499 return false;
4500 }
4501
4502 if (!ValidateRobustBufferSize(context, bufSize, *length))
4503 {
4504 return false;
4505 }
4506
4507 return true;
4508}
4509
Geoff Lang6899b872016-10-14 11:30:13 -04004510bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4511 GLuint program,
4512 GLuint uniformBlockIndex,
4513 GLenum pname,
4514 GLsizei bufSize,
4515 GLsizei *length,
4516 GLint *params)
4517{
4518 if (!ValidateRobustEntryPoint(context, bufSize))
4519 {
4520 return false;
4521 }
4522
4523 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4524 {
4525 return false;
4526 }
4527
4528 if (!ValidateRobustBufferSize(context, bufSize, *length))
4529 {
4530 return false;
4531 }
4532
4533 return true;
4534}
4535
Geoff Lang0a9661f2016-10-20 10:59:20 -07004536bool ValidateGetInternalFormativRobustANGLE(Context *context,
4537 GLenum target,
4538 GLenum internalformat,
4539 GLenum pname,
4540 GLsizei bufSize,
4541 GLsizei *length,
4542 GLint *params)
4543{
4544 if (!ValidateRobustEntryPoint(context, bufSize))
4545 {
4546 return false;
4547 }
4548
4549 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4550 {
4551 return false;
4552 }
4553
4554 if (!ValidateRobustBufferSize(context, bufSize, *length))
4555 {
4556 return false;
4557 }
4558
4559 return true;
4560}
4561
Shao80957d92017-02-20 21:25:59 +08004562bool ValidateVertexFormatBase(ValidationContext *context,
4563 GLuint attribIndex,
4564 GLint size,
4565 GLenum type,
4566 GLboolean pureInteger)
4567{
4568 const Caps &caps = context->getCaps();
4569 if (attribIndex >= caps.maxVertexAttributes)
4570 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004571 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004572 return false;
4573 }
4574
4575 if (size < 1 || size > 4)
4576 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004577 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004578 return false;
Shao80957d92017-02-20 21:25:59 +08004579 }
4580
4581 switch (type)
4582 {
4583 case GL_BYTE:
4584 case GL_UNSIGNED_BYTE:
4585 case GL_SHORT:
4586 case GL_UNSIGNED_SHORT:
4587 break;
4588
4589 case GL_INT:
4590 case GL_UNSIGNED_INT:
4591 if (context->getClientMajorVersion() < 3)
4592 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004593 context->handleError(InvalidEnum()
4594 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004595 return false;
4596 }
4597 break;
4598
4599 case GL_FIXED:
4600 case GL_FLOAT:
4601 if (pureInteger)
4602 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004603 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004604 return false;
4605 }
4606 break;
4607
4608 case GL_HALF_FLOAT:
4609 if (context->getClientMajorVersion() < 3)
4610 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004611 context->handleError(InvalidEnum()
4612 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004613 return false;
4614 }
4615 if (pureInteger)
4616 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004617 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004618 return false;
4619 }
4620 break;
4621
4622 case GL_INT_2_10_10_10_REV:
4623 case GL_UNSIGNED_INT_2_10_10_10_REV:
4624 if (context->getClientMajorVersion() < 3)
4625 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004626 context->handleError(InvalidEnum()
4627 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004628 return false;
4629 }
4630 if (pureInteger)
4631 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004632 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004633 return false;
4634 }
4635 if (size != 4)
4636 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004637 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4638 "UNSIGNED_INT_2_10_10_10_REV and "
4639 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004640 return false;
4641 }
4642 break;
4643
4644 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004645 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004646 return false;
4647 }
4648
4649 return true;
4650}
4651
Geoff Lang76e65652017-03-27 14:58:02 -04004652// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4653// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4654// specified clear value and the type of a buffer that is being cleared generates an
4655// INVALID_OPERATION error instead of producing undefined results
4656bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4657 GLint drawbuffer,
4658 const GLenum *validComponentTypes,
4659 size_t validComponentTypeCount)
4660{
4661 const FramebufferAttachment *attachment =
4662 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4663 if (attachment)
4664 {
4665 GLenum componentType = attachment->getFormat().info->componentType;
4666 const GLenum *end = validComponentTypes + validComponentTypeCount;
4667 if (std::find(validComponentTypes, end, componentType) == end)
4668 {
4669 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004670 InvalidOperation()
4671 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004672 return false;
4673 }
4674 }
4675
4676 return true;
4677}
4678
Corentin Wallezb2931602017-04-11 15:58:57 -04004679bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4680 GLsizei imageSize,
4681 GLsizei dataSize)
4682{
4683 if (!ValidateRobustEntryPoint(context, dataSize))
4684 {
4685 return false;
4686 }
4687
4688 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
4689 if (pixelUnpackBuffer == nullptr)
4690 {
4691 if (dataSize < imageSize)
4692 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004693 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004694 }
4695 }
4696 return true;
4697}
4698
Jamie Madillbe849e42017-05-02 15:49:00 -04004699bool ValidateGetBufferParameterBase(ValidationContext *context,
4700 GLenum target,
4701 GLenum pname,
4702 bool pointerVersion,
4703 GLsizei *numParams)
4704{
4705 if (numParams)
4706 {
4707 *numParams = 0;
4708 }
4709
4710 if (!ValidBufferTarget(context, target))
4711 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004712 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004713 return false;
4714 }
4715
4716 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4717 if (!buffer)
4718 {
4719 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004720 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004721 return false;
4722 }
4723
4724 const Extensions &extensions = context->getExtensions();
4725
4726 switch (pname)
4727 {
4728 case GL_BUFFER_USAGE:
4729 case GL_BUFFER_SIZE:
4730 break;
4731
4732 case GL_BUFFER_ACCESS_OES:
4733 if (!extensions.mapBuffer)
4734 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004735 context->handleError(InvalidEnum()
4736 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004737 return false;
4738 }
4739 break;
4740
4741 case GL_BUFFER_MAPPED:
4742 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4743 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4744 !extensions.mapBufferRange)
4745 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004746 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4747 "GL_OES_mapbuffer or "
4748 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004749 return false;
4750 }
4751 break;
4752
4753 case GL_BUFFER_MAP_POINTER:
4754 if (!pointerVersion)
4755 {
4756 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004757 InvalidEnum()
4758 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004759 return false;
4760 }
4761 break;
4762
4763 case GL_BUFFER_ACCESS_FLAGS:
4764 case GL_BUFFER_MAP_OFFSET:
4765 case GL_BUFFER_MAP_LENGTH:
4766 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4767 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004768 context->handleError(InvalidEnum()
4769 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004770 return false;
4771 }
4772 break;
4773
4774 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004775 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004776 return false;
4777 }
4778
4779 // All buffer parameter queries return one value.
4780 if (numParams)
4781 {
4782 *numParams = 1;
4783 }
4784
4785 return true;
4786}
4787
4788bool ValidateGetRenderbufferParameterivBase(Context *context,
4789 GLenum target,
4790 GLenum pname,
4791 GLsizei *length)
4792{
4793 if (length)
4794 {
4795 *length = 0;
4796 }
4797
4798 if (target != GL_RENDERBUFFER)
4799 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004800 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004801 return false;
4802 }
4803
4804 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4805 if (renderbuffer == nullptr)
4806 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004807 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004808 return false;
4809 }
4810
4811 switch (pname)
4812 {
4813 case GL_RENDERBUFFER_WIDTH:
4814 case GL_RENDERBUFFER_HEIGHT:
4815 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4816 case GL_RENDERBUFFER_RED_SIZE:
4817 case GL_RENDERBUFFER_GREEN_SIZE:
4818 case GL_RENDERBUFFER_BLUE_SIZE:
4819 case GL_RENDERBUFFER_ALPHA_SIZE:
4820 case GL_RENDERBUFFER_DEPTH_SIZE:
4821 case GL_RENDERBUFFER_STENCIL_SIZE:
4822 break;
4823
4824 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4825 if (!context->getExtensions().framebufferMultisample)
4826 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004827 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004828 return false;
4829 }
4830 break;
4831
4832 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004833 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004834 return false;
4835 }
4836
4837 if (length)
4838 {
4839 *length = 1;
4840 }
4841 return true;
4842}
4843
4844bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4845{
4846 if (length)
4847 {
4848 *length = 0;
4849 }
4850
4851 if (GetValidShader(context, shader) == nullptr)
4852 {
4853 return false;
4854 }
4855
4856 switch (pname)
4857 {
4858 case GL_SHADER_TYPE:
4859 case GL_DELETE_STATUS:
4860 case GL_COMPILE_STATUS:
4861 case GL_INFO_LOG_LENGTH:
4862 case GL_SHADER_SOURCE_LENGTH:
4863 break;
4864
4865 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4866 if (!context->getExtensions().translatedShaderSource)
4867 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004868 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004869 return false;
4870 }
4871 break;
4872
4873 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004874 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004875 return false;
4876 }
4877
4878 if (length)
4879 {
4880 *length = 1;
4881 }
4882 return true;
4883}
4884
4885bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4886{
4887 if (length)
4888 {
4889 *length = 0;
4890 }
4891
4892 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4893 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004894 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004895 return false;
4896 }
4897
4898 if (context->getTargetTexture(target) == nullptr)
4899 {
4900 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004901 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004902 return false;
4903 }
4904
4905 switch (pname)
4906 {
4907 case GL_TEXTURE_MAG_FILTER:
4908 case GL_TEXTURE_MIN_FILTER:
4909 case GL_TEXTURE_WRAP_S:
4910 case GL_TEXTURE_WRAP_T:
4911 break;
4912
4913 case GL_TEXTURE_USAGE_ANGLE:
4914 if (!context->getExtensions().textureUsage)
4915 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004916 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004917 return false;
4918 }
4919 break;
4920
4921 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4922 if (!context->getExtensions().textureFilterAnisotropic)
4923 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004924 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004925 return false;
4926 }
4927 break;
4928
4929 case GL_TEXTURE_IMMUTABLE_FORMAT:
4930 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4931 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004932 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004933 return false;
4934 }
4935 break;
4936
4937 case GL_TEXTURE_WRAP_R:
4938 case GL_TEXTURE_IMMUTABLE_LEVELS:
4939 case GL_TEXTURE_SWIZZLE_R:
4940 case GL_TEXTURE_SWIZZLE_G:
4941 case GL_TEXTURE_SWIZZLE_B:
4942 case GL_TEXTURE_SWIZZLE_A:
4943 case GL_TEXTURE_BASE_LEVEL:
4944 case GL_TEXTURE_MAX_LEVEL:
4945 case GL_TEXTURE_MIN_LOD:
4946 case GL_TEXTURE_MAX_LOD:
4947 case GL_TEXTURE_COMPARE_MODE:
4948 case GL_TEXTURE_COMPARE_FUNC:
4949 if (context->getClientMajorVersion() < 3)
4950 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004951 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004952 return false;
4953 }
4954 break;
4955
4956 case GL_TEXTURE_SRGB_DECODE_EXT:
4957 if (!context->getExtensions().textureSRGBDecode)
4958 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004959 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004960 return false;
4961 }
4962 break;
4963
4964 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004965 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004966 return false;
4967 }
4968
4969 if (length)
4970 {
4971 *length = 1;
4972 }
4973 return true;
4974}
4975
4976bool ValidateGetVertexAttribBase(Context *context,
4977 GLuint index,
4978 GLenum pname,
4979 GLsizei *length,
4980 bool pointer,
4981 bool pureIntegerEntryPoint)
4982{
4983 if (length)
4984 {
4985 *length = 0;
4986 }
4987
4988 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
4989 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004990 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004991 return false;
4992 }
4993
4994 if (index >= context->getCaps().maxVertexAttributes)
4995 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004996 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04004997 return false;
4998 }
4999
5000 if (pointer)
5001 {
5002 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5003 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005004 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005005 return false;
5006 }
5007 }
5008 else
5009 {
5010 switch (pname)
5011 {
5012 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5013 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5014 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5015 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5016 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5017 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5018 case GL_CURRENT_VERTEX_ATTRIB:
5019 break;
5020
5021 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5022 static_assert(
5023 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5024 "ANGLE extension enums not equal to GL enums.");
5025 if (context->getClientMajorVersion() < 3 &&
5026 !context->getExtensions().instancedArrays)
5027 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005028 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5029 "requires OpenGL ES 3.0 or "
5030 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005031 return false;
5032 }
5033 break;
5034
5035 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5036 if (context->getClientMajorVersion() < 3)
5037 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005038 context->handleError(
5039 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005040 return false;
5041 }
5042 break;
5043
5044 case GL_VERTEX_ATTRIB_BINDING:
5045 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5046 if (context->getClientVersion() < ES_3_1)
5047 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005048 context->handleError(InvalidEnum()
5049 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005050 return false;
5051 }
5052 break;
5053
5054 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005055 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005056 return false;
5057 }
5058 }
5059
5060 if (length)
5061 {
5062 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5063 {
5064 *length = 4;
5065 }
5066 else
5067 {
5068 *length = 1;
5069 }
5070 }
5071
5072 return true;
5073}
5074
Jamie Madill4928b7c2017-06-20 12:57:39 -04005075bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005076 GLint x,
5077 GLint y,
5078 GLsizei width,
5079 GLsizei height,
5080 GLenum format,
5081 GLenum type,
5082 GLsizei bufSize,
5083 GLsizei *length,
5084 GLsizei *columns,
5085 GLsizei *rows,
5086 void *pixels)
5087{
5088 if (length != nullptr)
5089 {
5090 *length = 0;
5091 }
5092 if (rows != nullptr)
5093 {
5094 *rows = 0;
5095 }
5096 if (columns != nullptr)
5097 {
5098 *columns = 0;
5099 }
5100
5101 if (width < 0 || height < 0)
5102 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005103 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005104 return false;
5105 }
5106
5107 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5108
5109 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5110 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005111 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005112 return false;
5113 }
5114
5115 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5116 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005117 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005118 return false;
5119 }
5120
5121 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5122 ASSERT(framebuffer);
5123
5124 if (framebuffer->getReadBufferState() == GL_NONE)
5125 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005126 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005127 return false;
5128 }
5129
5130 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5131 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5132 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5133 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5134 // situation is an application error that would lead to a crash in ANGLE.
5135 if (readBuffer == nullptr)
5136 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005137 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005138 return false;
5139 }
5140
Martin Radev28031682017-07-28 14:47:56 +03005141 // ANGLE_multiview, Revision 1:
5142 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5143 // current read framebuffer is not NONE.
5144 if (readBuffer->getMultiviewLayout() != GL_NONE)
5145 {
5146 context->handleError(InvalidFramebufferOperation()
5147 << "Attempting to read from a multi-view framebuffer.");
5148 return false;
5149 }
5150
Geoff Lang280ba992017-04-18 16:30:58 -04005151 if (context->getExtensions().webglCompatibility)
5152 {
5153 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5154 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5155 // and type before validating the combination of format and type. However, the
5156 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5157 // verifies that GL_INVALID_OPERATION is generated.
5158 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5159 // dEQP/WebGL.
5160 if (!ValidReadPixelsFormatEnum(context, format))
5161 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005162 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005163 return false;
5164 }
5165
5166 if (!ValidReadPixelsTypeEnum(context, type))
5167 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005168 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005169 return false;
5170 }
5171 }
5172
Jamie Madill4928b7c2017-06-20 12:57:39 -04005173 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5174 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005175 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5176
5177 bool validFormatTypeCombination =
5178 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5179
5180 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5181 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005182 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005183 return false;
5184 }
5185
5186 // Check for pixel pack buffer related API errors
5187 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5188 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5189 {
5190 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005191 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005192 return false;
5193 }
5194
5195 // .. the data would be packed to the buffer object such that the memory writes required
5196 // would exceed the data store size.
5197 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5198 const gl::Extents size(width, height, 1);
5199 const auto &pack = context->getGLState().getPackState();
5200
5201 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5202 if (endByteOrErr.isError())
5203 {
5204 context->handleError(endByteOrErr.getError());
5205 return false;
5206 }
5207
5208 size_t endByte = endByteOrErr.getResult();
5209 if (bufSize >= 0)
5210 {
5211 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5212 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005213 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005214 return false;
5215 }
5216 }
5217
5218 if (pixelPackBuffer != nullptr)
5219 {
5220 CheckedNumeric<size_t> checkedEndByte(endByte);
5221 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5222 checkedEndByte += checkedOffset;
5223
5224 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5225 {
5226 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005227 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005228 return false;
5229 }
5230 }
5231
5232 if (pixelPackBuffer == nullptr && length != nullptr)
5233 {
5234 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5235 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005236 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005237 return false;
5238 }
5239
5240 *length = static_cast<GLsizei>(endByte);
5241 }
5242
5243 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5244 angle::CheckedNumeric<int> clippedExtent(length);
5245 if (start < 0)
5246 {
5247 // "subtract" the area that is less than 0
5248 clippedExtent += start;
5249 }
5250
5251 const int readExtent = start + length;
5252 if (readExtent > bufferSize)
5253 {
5254 // Subtract the region to the right of the read buffer
5255 clippedExtent -= (readExtent - bufferSize);
5256 }
5257
5258 if (!clippedExtent.IsValid())
5259 {
5260 return 0;
5261 }
5262
5263 return std::max(clippedExtent.ValueOrDie(), 0);
5264 };
5265
5266 if (columns != nullptr)
5267 {
5268 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5269 }
5270
5271 if (rows != nullptr)
5272 {
5273 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5274 }
5275
5276 return true;
5277}
5278
5279template <typename ParamType>
5280bool ValidateTexParameterBase(Context *context,
5281 GLenum target,
5282 GLenum pname,
5283 GLsizei bufSize,
5284 const ParamType *params)
5285{
5286 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5287 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005288 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005289 return false;
5290 }
5291
5292 if (context->getTargetTexture(target) == nullptr)
5293 {
5294 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005295 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005296 return false;
5297 }
5298
5299 const GLsizei minBufSize = 1;
5300 if (bufSize >= 0 && bufSize < minBufSize)
5301 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005302 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005303 return false;
5304 }
5305
5306 switch (pname)
5307 {
5308 case GL_TEXTURE_WRAP_R:
5309 case GL_TEXTURE_SWIZZLE_R:
5310 case GL_TEXTURE_SWIZZLE_G:
5311 case GL_TEXTURE_SWIZZLE_B:
5312 case GL_TEXTURE_SWIZZLE_A:
5313 case GL_TEXTURE_BASE_LEVEL:
5314 case GL_TEXTURE_MAX_LEVEL:
5315 case GL_TEXTURE_COMPARE_MODE:
5316 case GL_TEXTURE_COMPARE_FUNC:
5317 case GL_TEXTURE_MIN_LOD:
5318 case GL_TEXTURE_MAX_LOD:
5319 if (context->getClientMajorVersion() < 3)
5320 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005321 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005322 return false;
5323 }
5324 if (target == GL_TEXTURE_EXTERNAL_OES &&
5325 !context->getExtensions().eglImageExternalEssl3)
5326 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005327 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5328 "available without "
5329 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005330 return false;
5331 }
5332 break;
5333
5334 default:
5335 break;
5336 }
5337
JiangYizhou4cff8d62017-07-06 14:54:09 +08005338 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5339 {
5340 switch (pname)
5341 {
5342 case GL_TEXTURE_MIN_FILTER:
5343 case GL_TEXTURE_MAG_FILTER:
5344 case GL_TEXTURE_WRAP_S:
5345 case GL_TEXTURE_WRAP_T:
5346 case GL_TEXTURE_WRAP_R:
5347 case GL_TEXTURE_MIN_LOD:
5348 case GL_TEXTURE_MAX_LOD:
5349 case GL_TEXTURE_COMPARE_MODE:
5350 case GL_TEXTURE_COMPARE_FUNC:
5351 context->handleError(InvalidEnum()
5352 << "Invalid parameter for 2D multisampled textures.");
5353 return false;
5354 }
5355 }
5356
Jamie Madillbe849e42017-05-02 15:49:00 -04005357 switch (pname)
5358 {
5359 case GL_TEXTURE_WRAP_S:
5360 case GL_TEXTURE_WRAP_T:
5361 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005362 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005363 bool restrictedWrapModes =
5364 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5365 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5366 {
5367 return false;
5368 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005369 }
5370 break;
5371
5372 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005373 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005374 bool restrictedMinFilter =
5375 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5376 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5377 {
5378 return false;
5379 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005380 }
5381 break;
5382
5383 case GL_TEXTURE_MAG_FILTER:
5384 if (!ValidateTextureMagFilterValue(context, params))
5385 {
5386 return false;
5387 }
5388 break;
5389
5390 case GL_TEXTURE_USAGE_ANGLE:
5391 switch (ConvertToGLenum(params[0]))
5392 {
5393 case GL_NONE:
5394 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5395 break;
5396
5397 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005398 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005399 return false;
5400 }
5401 break;
5402
5403 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5404 if (!context->getExtensions().textureFilterAnisotropic)
5405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005406 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005407 return false;
5408 }
5409
5410 // we assume the parameter passed to this validation method is truncated, not rounded
5411 if (params[0] < 1)
5412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005413 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005414 return false;
5415 }
5416 break;
5417
5418 case GL_TEXTURE_MIN_LOD:
5419 case GL_TEXTURE_MAX_LOD:
5420 // any value is permissible
5421 break;
5422
5423 case GL_TEXTURE_COMPARE_MODE:
5424 if (!ValidateTextureCompareModeValue(context, params))
5425 {
5426 return false;
5427 }
5428 break;
5429
5430 case GL_TEXTURE_COMPARE_FUNC:
5431 if (!ValidateTextureCompareFuncValue(context, params))
5432 {
5433 return false;
5434 }
5435 break;
5436
5437 case GL_TEXTURE_SWIZZLE_R:
5438 case GL_TEXTURE_SWIZZLE_G:
5439 case GL_TEXTURE_SWIZZLE_B:
5440 case GL_TEXTURE_SWIZZLE_A:
5441 switch (ConvertToGLenum(params[0]))
5442 {
5443 case GL_RED:
5444 case GL_GREEN:
5445 case GL_BLUE:
5446 case GL_ALPHA:
5447 case GL_ZERO:
5448 case GL_ONE:
5449 break;
5450
5451 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005452 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005453 return false;
5454 }
5455 break;
5456
5457 case GL_TEXTURE_BASE_LEVEL:
5458 if (params[0] < 0)
5459 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005460 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005461 return false;
5462 }
5463 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5464 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005465 context->handleError(InvalidOperation()
5466 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005467 return false;
5468 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005469 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5470 {
5471 context->handleError(InvalidOperation()
5472 << "Base level must be 0 for multisampled textures.");
5473 return false;
5474 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005475 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5476 {
5477 context->handleError(InvalidOperation()
5478 << "Base level must be 0 for rectangle textures.");
5479 return false;
5480 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005481 break;
5482
5483 case GL_TEXTURE_MAX_LEVEL:
5484 if (params[0] < 0)
5485 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005486 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005487 return false;
5488 }
5489 break;
5490
5491 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5492 if (context->getClientVersion() < Version(3, 1))
5493 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005494 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005495 return false;
5496 }
5497 switch (ConvertToGLenum(params[0]))
5498 {
5499 case GL_DEPTH_COMPONENT:
5500 case GL_STENCIL_INDEX:
5501 break;
5502
5503 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005504 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005505 return false;
5506 }
5507 break;
5508
5509 case GL_TEXTURE_SRGB_DECODE_EXT:
5510 if (!ValidateTextureSRGBDecodeValue(context, params))
5511 {
5512 return false;
5513 }
5514 break;
5515
5516 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005517 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005518 return false;
5519 }
5520
5521 return true;
5522}
5523
5524template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5525template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5526
Jamie Madill12e957f2017-08-26 21:42:26 -04005527bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5528{
5529 if (index >= MAX_VERTEX_ATTRIBS)
5530 {
5531 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5532 return false;
5533 }
5534
5535 return true;
5536}
5537
5538bool ValidateGetActiveUniformBlockivBase(Context *context,
5539 GLuint program,
5540 GLuint uniformBlockIndex,
5541 GLenum pname,
5542 GLsizei *length)
5543{
5544 if (length)
5545 {
5546 *length = 0;
5547 }
5548
5549 if (context->getClientMajorVersion() < 3)
5550 {
5551 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5552 return false;
5553 }
5554
5555 Program *programObject = GetValidProgram(context, program);
5556 if (!programObject)
5557 {
5558 return false;
5559 }
5560
5561 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5562 {
5563 context->handleError(InvalidValue()
5564 << "uniformBlockIndex exceeds active uniform block count.");
5565 return false;
5566 }
5567
5568 switch (pname)
5569 {
5570 case GL_UNIFORM_BLOCK_BINDING:
5571 case GL_UNIFORM_BLOCK_DATA_SIZE:
5572 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5573 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5574 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5575 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5576 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5577 break;
5578
5579 default:
5580 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5581 return false;
5582 }
5583
5584 if (length)
5585 {
5586 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5587 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005588 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005589 programObject->getUniformBlockByIndex(uniformBlockIndex);
5590 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5591 }
5592 else
5593 {
5594 *length = 1;
5595 }
5596 }
5597
5598 return true;
5599}
5600
Jamie Madill9696d072017-08-26 23:19:57 -04005601template <typename ParamType>
5602bool ValidateSamplerParameterBase(Context *context,
5603 GLuint sampler,
5604 GLenum pname,
5605 GLsizei bufSize,
5606 ParamType *params)
5607{
5608 if (context->getClientMajorVersion() < 3)
5609 {
5610 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5611 return false;
5612 }
5613
5614 if (!context->isSampler(sampler))
5615 {
5616 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5617 return false;
5618 }
5619
5620 const GLsizei minBufSize = 1;
5621 if (bufSize >= 0 && bufSize < minBufSize)
5622 {
5623 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5624 return false;
5625 }
5626
5627 switch (pname)
5628 {
5629 case GL_TEXTURE_WRAP_S:
5630 case GL_TEXTURE_WRAP_T:
5631 case GL_TEXTURE_WRAP_R:
5632 if (!ValidateTextureWrapModeValue(context, params, false))
5633 {
5634 return false;
5635 }
5636 break;
5637
5638 case GL_TEXTURE_MIN_FILTER:
5639 if (!ValidateTextureMinFilterValue(context, params, false))
5640 {
5641 return false;
5642 }
5643 break;
5644
5645 case GL_TEXTURE_MAG_FILTER:
5646 if (!ValidateTextureMagFilterValue(context, params))
5647 {
5648 return false;
5649 }
5650 break;
5651
5652 case GL_TEXTURE_MIN_LOD:
5653 case GL_TEXTURE_MAX_LOD:
5654 // any value is permissible
5655 break;
5656
5657 case GL_TEXTURE_COMPARE_MODE:
5658 if (!ValidateTextureCompareModeValue(context, params))
5659 {
5660 return false;
5661 }
5662 break;
5663
5664 case GL_TEXTURE_COMPARE_FUNC:
5665 if (!ValidateTextureCompareFuncValue(context, params))
5666 {
5667 return false;
5668 }
5669 break;
5670
5671 case GL_TEXTURE_SRGB_DECODE_EXT:
5672 if (!ValidateTextureSRGBDecodeValue(context, params))
5673 {
5674 return false;
5675 }
5676 break;
5677
5678 default:
5679 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5680 return false;
5681 }
5682
5683 return true;
5684}
5685
5686template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5687template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5688
5689bool ValidateGetSamplerParameterBase(Context *context,
5690 GLuint sampler,
5691 GLenum pname,
5692 GLsizei *length)
5693{
5694 if (length)
5695 {
5696 *length = 0;
5697 }
5698
5699 if (context->getClientMajorVersion() < 3)
5700 {
5701 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5702 return false;
5703 }
5704
5705 if (!context->isSampler(sampler))
5706 {
5707 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5708 return false;
5709 }
5710
5711 switch (pname)
5712 {
5713 case GL_TEXTURE_WRAP_S:
5714 case GL_TEXTURE_WRAP_T:
5715 case GL_TEXTURE_WRAP_R:
5716 case GL_TEXTURE_MIN_FILTER:
5717 case GL_TEXTURE_MAG_FILTER:
5718 case GL_TEXTURE_MIN_LOD:
5719 case GL_TEXTURE_MAX_LOD:
5720 case GL_TEXTURE_COMPARE_MODE:
5721 case GL_TEXTURE_COMPARE_FUNC:
5722 break;
5723
5724 case GL_TEXTURE_SRGB_DECODE_EXT:
5725 if (!context->getExtensions().textureSRGBDecode)
5726 {
5727 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5728 return false;
5729 }
5730 break;
5731
5732 default:
5733 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5734 return false;
5735 }
5736
5737 if (length)
5738 {
5739 *length = 1;
5740 }
5741 return true;
5742}
5743
5744bool ValidateGetInternalFormativBase(Context *context,
5745 GLenum target,
5746 GLenum internalformat,
5747 GLenum pname,
5748 GLsizei bufSize,
5749 GLsizei *numParams)
5750{
5751 if (numParams)
5752 {
5753 *numParams = 0;
5754 }
5755
5756 if (context->getClientMajorVersion() < 3)
5757 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005758 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005759 return false;
5760 }
5761
5762 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5763 if (!formatCaps.renderable)
5764 {
5765 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5766 return false;
5767 }
5768
5769 switch (target)
5770 {
5771 case GL_RENDERBUFFER:
5772 break;
5773
5774 case GL_TEXTURE_2D_MULTISAMPLE:
5775 if (context->getClientVersion() < ES_3_1)
5776 {
5777 context->handleError(InvalidOperation()
5778 << "Texture target requires at least OpenGL ES 3.1.");
5779 return false;
5780 }
5781 break;
5782
5783 default:
5784 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5785 return false;
5786 }
5787
5788 if (bufSize < 0)
5789 {
5790 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5791 return false;
5792 }
5793
5794 GLsizei maxWriteParams = 0;
5795 switch (pname)
5796 {
5797 case GL_NUM_SAMPLE_COUNTS:
5798 maxWriteParams = 1;
5799 break;
5800
5801 case GL_SAMPLES:
5802 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5803 break;
5804
5805 default:
5806 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5807 return false;
5808 }
5809
5810 if (numParams)
5811 {
5812 // glGetInternalFormativ will not overflow bufSize
5813 *numParams = std::min(bufSize, maxWriteParams);
5814 }
5815
5816 return true;
5817}
5818
Jamie Madillc29968b2016-01-20 11:17:23 -05005819} // namespace gl