blob: a4e1a3ae7c9058e986a64e95f54424c7b042b66c [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"
jchen10a99ed552017-09-22 08:10:32 +080024#include "libANGLE/queryconversions.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040025#include "libANGLE/validationES2.h"
26#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040027
28#include "common/mathutil.h"
29#include "common/utilities.h"
30
Jamie Madille2e406c2016-06-02 13:04:10 -040031using namespace angle;
32
Geoff Lange8ebe7f2013-08-05 15:03:13 -040033namespace gl
34{
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
jchen10a99ed552017-09-22 08:10:32 +080037
Corentin Wallez92db6942016-12-09 13:10:36 -050038bool ValidateDrawAttribs(ValidationContext *context,
39 GLint primcount,
40 GLint maxVertex,
41 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040042{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070043 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040044 const gl::Program *program = state.getProgram();
45
Corentin Wallez327411e2016-12-09 11:09:17 -050046 bool webglCompatibility = context->getExtensions().webglCompatibility;
47
Jamie Madill231c7f52017-04-26 13:45:37 -040048 const VertexArray *vao = state.getVertexArray();
49 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080050 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madill231c7f52017-04-26 13:45:37 -040051 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040052 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
53 {
54 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallez672f7f32017-06-15 17:42:17 -040055
56 // No need to range check for disabled attribs.
57 if (!attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040058 {
Corentin Wallezfd456442016-12-21 17:57:00 -050059 continue;
60 }
Jamie Madill1ca74672015-07-21 15:14:11 -040061
Jamie Madill231c7f52017-04-26 13:45:37 -040062 // If we have no buffer, then we either get an error, or there are no more checks to be
63 // done.
Corentin Wallez672f7f32017-06-15 17:42:17 -040064 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
65 gl::Buffer *buffer = binding.getBuffer().get();
Corentin Wallezfd456442016-12-21 17:57:00 -050066 if (!buffer)
67 {
Geoff Langfeb8c682017-02-13 16:07:35 -050068 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050069 {
70 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050071 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
72 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
73 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
74 // error.
Brandon Jonesafa75152017-07-21 13:11:29 -070075 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
Corentin Wallezfd456442016-12-21 17:57:00 -050076 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050077 }
Corentin Wallezfd456442016-12-21 17:57:00 -050078 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040079 {
80 // This is an application error that would normally result in a crash,
81 // but we catch it and return an error
Brandon Jonesafa75152017-07-21 13:11:29 -070082 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
Jamie Madill1ca74672015-07-21 15:14:11 -040083 return false;
84 }
Corentin Wallezfd456442016-12-21 17:57:00 -050085 continue;
86 }
87
Corentin Wallez672f7f32017-06-15 17:42:17 -040088 // This needs to come after the check for client arrays as even unused attributes cannot use
89 // client-side arrays
90 if (!program->isAttribLocationActive(attributeIndex))
91 {
92 continue;
93 }
94
Corentin Wallezfd456442016-12-21 17:57:00 -050095 // If we're drawing zero vertices, we have enough data.
96 if (vertexCount <= 0 || primcount <= 0)
97 {
98 continue;
99 }
100
101 GLint maxVertexElement = 0;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300102 GLuint divisor = binding.getDivisor();
103 if (divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500104 {
105 maxVertexElement = maxVertex;
106 }
107 else
108 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300109 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500110 }
111
112 // We do manual overflow checks here instead of using safe_math.h because it was
113 // a bottleneck. Thanks to some properties of GL we know inequalities that can
114 // help us make the overflow checks faster.
115
116 // The max possible attribSize is 16 for a vector of 4 32 bit values.
117 constexpr uint64_t kMaxAttribSize = 16;
118 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
119 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
120
121 // We know attribStride is given as a GLsizei which is typedefed to int.
122 // We also know an upper bound for attribSize.
123 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800124 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500125 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
126 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
127
128 // Computing the max offset using uint64_t without attrib.offset is overflow
129 // safe. Note: Last vertex element does not take the full stride!
130 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
131 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
132
133 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800134 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
135 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500136 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700137 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500138 return false;
139 }
140 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
141
142 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
143 // We can return INVALID_OPERATION if our vertex attribute does not have
144 // enough backing data.
145 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
146 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700147 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500148 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400149 }
150 }
151
152 return true;
153}
154
Geoff Lang280ba992017-04-18 16:30:58 -0400155bool ValidReadPixelsTypeEnum(ValidationContext *context, GLenum type)
156{
157 switch (type)
158 {
159 // Types referenced in Table 3.4 of the ES 2.0.25 spec
160 case GL_UNSIGNED_BYTE:
161 case GL_UNSIGNED_SHORT_4_4_4_4:
162 case GL_UNSIGNED_SHORT_5_5_5_1:
163 case GL_UNSIGNED_SHORT_5_6_5:
164 return context->getClientVersion() >= ES_2_0;
165
166 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
167 case GL_BYTE:
168 case GL_INT:
169 case GL_SHORT:
170 case GL_UNSIGNED_INT:
171 case GL_UNSIGNED_INT_10F_11F_11F_REV:
172 case GL_UNSIGNED_INT_24_8:
173 case GL_UNSIGNED_INT_2_10_10_10_REV:
174 case GL_UNSIGNED_INT_5_9_9_9_REV:
175 case GL_UNSIGNED_SHORT:
176 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
177 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
178 return context->getClientVersion() >= ES_3_0;
179
180 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400181 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
182 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400183
184 case GL_HALF_FLOAT:
185 return context->getClientVersion() >= ES_3_0 ||
186 context->getExtensions().textureHalfFloat;
187
188 case GL_HALF_FLOAT_OES:
189 return context->getExtensions().colorBufferHalfFloat;
190
191 default:
192 return false;
193 }
194}
195
196bool ValidReadPixelsFormatEnum(ValidationContext *context, GLenum format)
197{
198 switch (format)
199 {
200 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
201 case GL_RGBA:
202 case GL_RGB:
203 case GL_ALPHA:
204 return context->getClientVersion() >= ES_2_0;
205
206 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
207 case GL_RG:
208 case GL_RED:
209 case GL_RGBA_INTEGER:
210 case GL_RGB_INTEGER:
211 case GL_RG_INTEGER:
212 case GL_RED_INTEGER:
213 return context->getClientVersion() >= ES_3_0;
214
215 case GL_SRGB_ALPHA_EXT:
216 case GL_SRGB_EXT:
217 return context->getExtensions().sRGB;
218
219 case GL_BGRA_EXT:
220 return context->getExtensions().readFormatBGRA;
221
222 default:
223 return false;
224 }
225}
226
Geoff Langf607c602016-09-21 11:46:48 -0400227bool ValidReadPixelsFormatType(ValidationContext *context,
228 GLenum framebufferComponentType,
229 GLenum format,
230 GLenum type)
231{
232 switch (framebufferComponentType)
233 {
234 case GL_UNSIGNED_NORMALIZED:
235 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
236 // ReadPixels with BGRA even if the extension is not present
237 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
238 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
239 type == GL_UNSIGNED_BYTE);
240
241 case GL_SIGNED_NORMALIZED:
242 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
243
244 case GL_INT:
245 return (format == GL_RGBA_INTEGER && type == GL_INT);
246
247 case GL_UNSIGNED_INT:
248 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
249
250 case GL_FLOAT:
251 return (format == GL_RGBA && type == GL_FLOAT);
252
253 default:
254 UNREACHABLE();
255 return false;
256 }
257}
258
Geoff Langc1984ed2016-10-07 12:41:00 -0400259template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400260bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400261{
262 switch (ConvertToGLenum(params[0]))
263 {
264 case GL_CLAMP_TO_EDGE:
265 break;
266
267 case GL_REPEAT:
268 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400269 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400270 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400271 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700272 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400273 return false;
274 }
275 break;
276
277 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700278 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400279 return false;
280 }
281
282 return true;
283}
284
285template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400286bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400287{
288 switch (ConvertToGLenum(params[0]))
289 {
290 case GL_NEAREST:
291 case GL_LINEAR:
292 break;
293
294 case GL_NEAREST_MIPMAP_NEAREST:
295 case GL_LINEAR_MIPMAP_NEAREST:
296 case GL_NEAREST_MIPMAP_LINEAR:
297 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400298 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400299 {
300 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700301 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400302 return false;
303 }
304 break;
305
306 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700307 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400308 return false;
309 }
310
311 return true;
312}
313
314template <typename ParamType>
315bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
316{
317 switch (ConvertToGLenum(params[0]))
318 {
319 case GL_NEAREST:
320 case GL_LINEAR:
321 break;
322
323 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700324 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400325 return false;
326 }
327
328 return true;
329}
330
331template <typename ParamType>
332bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
333{
334 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
335 switch (ConvertToGLenum(params[0]))
336 {
337 case GL_NONE:
338 case GL_COMPARE_REF_TO_TEXTURE:
339 break;
340
341 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700342 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400343 return false;
344 }
345
346 return true;
347}
348
349template <typename ParamType>
350bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
351{
352 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
353 switch (ConvertToGLenum(params[0]))
354 {
355 case GL_LEQUAL:
356 case GL_GEQUAL:
357 case GL_LESS:
358 case GL_GREATER:
359 case GL_EQUAL:
360 case GL_NOTEQUAL:
361 case GL_ALWAYS:
362 case GL_NEVER:
363 break;
364
365 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700366 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400367 return false;
368 }
369
370 return true;
371}
372
373template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700374bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
375{
376 if (!context->getExtensions().textureSRGBDecode)
377 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700378 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700379 return false;
380 }
381
382 switch (ConvertToGLenum(params[0]))
383 {
384 case GL_DECODE_EXT:
385 case GL_SKIP_DECODE_EXT:
386 break;
387
388 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700389 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700390 return false;
391 }
392
393 return true;
394}
395
Jamie Madillc1d770e2017-04-13 17:31:24 -0400396bool ValidateUniformCommonBase(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500397 gl::Program *program,
398 GLint location,
399 GLsizei count,
400 const LinkedUniform **uniformOut)
401{
402 // TODO(Jiajia): Add image uniform check in future.
403 if (count < 0)
404 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700405 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500406 return false;
407 }
408
Brandon Jones6cad5662017-06-14 13:25:13 -0700409 if (!program)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500410 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700411 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
412 return false;
413 }
414
415 if (!program->isLinked())
416 {
417 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500418 return false;
419 }
420
421 if (location == -1)
422 {
423 // Silently ignore the uniform command
424 return false;
425 }
426
427 const auto &uniformLocations = program->getUniformLocations();
Jamie Madillbe849e42017-05-02 15:49:00 -0400428 size_t castedLocation = static_cast<size_t>(location);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500429 if (castedLocation >= uniformLocations.size())
430 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500431 context->handleError(InvalidOperation() << "Invalid uniform location");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500432 return false;
433 }
434
435 const auto &uniformLocation = uniformLocations[castedLocation];
436 if (uniformLocation.ignored)
437 {
438 // Silently ignore the uniform command
439 return false;
440 }
441
Jamie Madillfb997ec2017-09-20 15:44:27 -0400442 if (!uniformLocation.used())
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500443 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500444 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500445 return false;
446 }
447
448 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
449
450 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
451 if (!uniform.isArray() && count > 1)
452 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500453 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500454 return false;
455 }
456
457 *uniformOut = &uniform;
458 return true;
459}
460
Frank Henigman999b0fd2017-02-02 21:45:55 -0500461bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -0500462 GLenum uniformType,
463 GLsizei count,
464 const GLint *value)
465{
466 // Value type is GL_INT, because we only get here from glUniform1i{v}.
467 // It is compatible with INT or BOOL.
468 // Do these cheap tests first, for a little extra speed.
469 if (GL_INT == uniformType || GL_BOOL == uniformType)
470 {
471 return true;
472 }
473
474 if (IsSamplerType(uniformType))
475 {
Frank Henigman999b0fd2017-02-02 21:45:55 -0500476 // Check that the values are in range.
477 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
478 for (GLsizei i = 0; i < count; ++i)
479 {
480 if (value[i] < 0 || value[i] >= max)
481 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500482 context->handleError(InvalidValue() << "sampler uniform value out of range");
Frank Henigman999b0fd2017-02-02 21:45:55 -0500483 return false;
484 }
485 }
Frank Henigmana98a6472017-02-02 21:38:32 -0500486 return true;
487 }
488
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500489 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmana98a6472017-02-02 21:38:32 -0500490 return false;
491}
492
Jamie Madillc1d770e2017-04-13 17:31:24 -0400493bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500494{
495 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -0500496 // Do the cheaper test first, for a little extra speed.
497 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500498 {
499 return true;
500 }
501
Brandon Jonesafa75152017-07-21 13:11:29 -0700502 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500503 return false;
504}
505
Jamie Madillc1d770e2017-04-13 17:31:24 -0400506bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500507{
508 // Check that the value type is compatible with uniform type.
509 if (valueType == uniformType)
510 {
511 return true;
512 }
513
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500514 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500515 return false;
516}
517
Geoff Lange0cff192017-05-30 13:04:56 -0400518bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
519{
520 const Program *program = context->getGLState().getProgram();
521 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
522
523 const auto &programOutputTypes = program->getOutputVariableTypes();
524 for (size_t drawBufferIdx = 0; drawBufferIdx < programOutputTypes.size(); drawBufferIdx++)
525 {
526 GLenum outputType = programOutputTypes[drawBufferIdx];
527 GLenum inputType = framebuffer->getDrawbufferWriteType(drawBufferIdx);
528 if (outputType != GL_NONE && inputType != GL_NONE && inputType != outputType)
529 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500530 context->handleError(InvalidOperation() << "Fragment shader output type does not "
531 "match the bound framebuffer attachment "
532 "type.");
Geoff Lange0cff192017-05-30 13:04:56 -0400533 return false;
534 }
535 }
536
537 return true;
538}
539
Geoff Lang9ab5b822017-05-30 16:19:23 -0400540bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
541{
542 const Program *program = context->getGLState().getProgram();
543 const VertexArray *vao = context->getGLState().getVertexArray();
544
545 for (const auto &shaderAttribute : program->getAttributes())
546 {
Geoff Lang69df2422017-07-05 12:42:31 -0400547 // gl_VertexID and gl_InstanceID are active attributes but don't have a bound attribute.
548 if (shaderAttribute.isBuiltIn())
549 {
550 continue;
551 }
552
Geoff Lang9ab5b822017-05-30 16:19:23 -0400553 GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
554
555 const auto &attrib = vao->getVertexAttribute(shaderAttribute.location);
556 const auto &currentValue =
557 context->getGLState().getVertexAttribCurrentValue(shaderAttribute.location);
558 GLenum vertexType = attrib.enabled ? GetVertexAttributeBaseType(attrib) : currentValue.Type;
559
560 if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
561 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500562 context->handleError(InvalidOperation() << "Vertex shader input type does not "
563 "match the type of the bound vertex "
564 "attribute.");
Geoff Lang9ab5b822017-05-30 16:19:23 -0400565 return false;
566 }
567 }
568
569 return true;
570}
571
Geoff Langf41a7152016-09-19 15:11:17 -0400572} // anonymous namespace
573
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500574bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400575{
Jamie Madilld7460c72014-01-21 16:38:14 -0500576 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400577 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800578 case GL_TEXTURE_2D:
579 case GL_TEXTURE_CUBE_MAP:
580 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400581
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400582 case GL_TEXTURE_RECTANGLE_ANGLE:
583 return context->getExtensions().textureRectangle;
584
He Yunchaoced53ae2016-11-29 15:00:51 +0800585 case GL_TEXTURE_3D:
586 case GL_TEXTURE_2D_ARRAY:
587 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500588
He Yunchaoced53ae2016-11-29 15:00:51 +0800589 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800590 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400591
He Yunchaoced53ae2016-11-29 15:00:51 +0800592 default:
593 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500594 }
Jamie Madill35d15012013-10-07 10:46:37 -0400595}
596
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500597bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
598{
599 switch (target)
600 {
601 case GL_TEXTURE_2D:
602 case GL_TEXTURE_CUBE_MAP:
603 return true;
604
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400605 case GL_TEXTURE_RECTANGLE_ANGLE:
606 return context->getExtensions().textureRectangle;
607
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500608 default:
609 return false;
610 }
611}
612
613bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
614{
615 switch (target)
616 {
617 case GL_TEXTURE_3D:
618 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300619 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500620
621 default:
622 return false;
623 }
624}
625
Ian Ewellbda75592016-04-18 17:25:54 -0400626// Most texture GL calls are not compatible with external textures, so we have a separate validation
627// function for use in the GL calls that do
628bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
629{
630 return (target == GL_TEXTURE_EXTERNAL_OES) &&
631 (context->getExtensions().eglImageExternal ||
632 context->getExtensions().eglStreamConsumerExternal);
633}
634
Shannon Woods4dfed832014-03-17 20:03:39 -0400635// This function differs from ValidTextureTarget in that the target must be
636// usable as the destination of a 2D operation-- so a cube face is valid, but
637// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400638// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500639bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400640{
641 switch (target)
642 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800643 case GL_TEXTURE_2D:
644 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
645 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
646 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
647 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
648 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
649 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
650 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400651 case GL_TEXTURE_RECTANGLE_ANGLE:
652 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800653 default:
654 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500655 }
656}
657
Jamie Madillbe849e42017-05-02 15:49:00 -0400658bool ValidateDrawElementsInstancedBase(ValidationContext *context,
659 GLenum mode,
660 GLsizei count,
661 GLenum type,
662 const GLvoid *indices,
663 GLsizei primcount)
664{
665 if (primcount < 0)
666 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700667 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400668 return false;
669 }
670
671 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
672 {
673 return false;
674 }
675
676 // No-op zero primitive count
677 return (primcount > 0);
678}
679
680bool ValidateDrawArraysInstancedBase(Context *context,
681 GLenum mode,
682 GLint first,
683 GLsizei count,
684 GLsizei primcount)
685{
686 if (primcount < 0)
687 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700688 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400689 return false;
690 }
691
692 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
693 {
694 return false;
695 }
696
697 // No-op if zero primitive count
698 return (primcount > 0);
699}
700
Corentin Wallez0dc97812017-06-22 14:38:44 -0400701bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400702{
703 // Verify there is at least one active attribute with a divisor of zero
704 const State &state = context->getGLState();
705
706 Program *program = state.getProgram();
707
708 const auto &attribs = state.getVertexArray()->getVertexAttributes();
709 const auto &bindings = state.getVertexArray()->getVertexBindings();
710 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
711 {
712 const VertexAttribute &attrib = attribs[attributeIndex];
713 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300714 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400715 {
716 return true;
717 }
718 }
719
Brandon Jonesafa75152017-07-21 13:11:29 -0700720 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400721 return false;
722}
723
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500724bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
725{
726 switch (target)
727 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800728 case GL_TEXTURE_3D:
729 case GL_TEXTURE_2D_ARRAY:
730 return true;
731 default:
732 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400733 }
734}
735
He Yunchao11b038b2016-11-22 21:24:04 +0800736bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
737{
738 switch (target)
739 {
740 case GL_TEXTURE_2D:
741 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
742 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
743 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
744 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
745 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
746 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
747 case GL_TEXTURE_3D:
748 case GL_TEXTURE_2D_ARRAY:
749 case GL_TEXTURE_2D_MULTISAMPLE:
750 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400751 case GL_TEXTURE_RECTANGLE_ANGLE:
752 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800753 default:
754 return false;
755 }
756}
757
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500758bool ValidFramebufferTarget(GLenum target)
759{
He Yunchaoced53ae2016-11-29 15:00:51 +0800760 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
761 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400762 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500763
764 switch (target)
765 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800766 case GL_FRAMEBUFFER:
767 return true;
768 case GL_READ_FRAMEBUFFER:
769 return true;
770 case GL_DRAW_FRAMEBUFFER:
771 return true;
772 default:
773 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500774 }
775}
776
Corentin Wallez336129f2017-10-17 15:55:40 -0400777bool ValidBufferType(const ValidationContext *context, BufferBinding target)
Jamie Madill8c96d582014-03-05 15:01:23 -0500778{
779 switch (target)
780 {
Corentin Wallez336129f2017-10-17 15:55:40 -0400781 case BufferBinding::ElementArray:
782 case BufferBinding::Array:
He Yunchaoced53ae2016-11-29 15:00:51 +0800783 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -0500784
Corentin Wallez336129f2017-10-17 15:55:40 -0400785 case BufferBinding::PixelPack:
786 case BufferBinding::PixelUnpack:
He Yunchaoced53ae2016-11-29 15:00:51 +0800787 return (context->getExtensions().pixelBufferObject ||
788 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -0400789
Corentin Wallez336129f2017-10-17 15:55:40 -0400790 case BufferBinding::CopyRead:
791 case BufferBinding::CopyWrite:
792 case BufferBinding::TransformFeedback:
793 case BufferBinding::Uniform:
He Yunchaoced53ae2016-11-29 15:00:51 +0800794 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -0500795
Corentin Wallez336129f2017-10-17 15:55:40 -0400796 case BufferBinding::AtomicCounter:
797 case BufferBinding::ShaderStorage:
798 case BufferBinding::DrawIndirect:
799 case BufferBinding::DispatchIndirect:
He Yunchaoced53ae2016-11-29 15:00:51 +0800800 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -0400801
He Yunchaoced53ae2016-11-29 15:00:51 +0800802 default:
803 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -0500804 }
805}
806
Jamie Madillc29968b2016-01-20 11:17:23 -0500807bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400808{
Jamie Madillc29968b2016-01-20 11:17:23 -0500809 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400810 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400811 switch (target)
812 {
Jamie Madillc29968b2016-01-20 11:17:23 -0500813 case GL_TEXTURE_2D:
814 maxDimension = caps.max2DTextureSize;
815 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800816 case GL_TEXTURE_CUBE_MAP:
817 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
818 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
819 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
820 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
821 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
822 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
823 maxDimension = caps.maxCubeMapTextureSize;
824 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400825 case GL_TEXTURE_RECTANGLE_ANGLE:
826 return level == 0;
He Yunchaoced53ae2016-11-29 15:00:51 +0800827 case GL_TEXTURE_3D:
828 maxDimension = caps.max3DTextureSize;
829 break;
830 case GL_TEXTURE_2D_ARRAY:
831 maxDimension = caps.max2DTextureSize;
832 break;
He Yunchao11b038b2016-11-22 21:24:04 +0800833 case GL_TEXTURE_2D_MULTISAMPLE:
834 maxDimension = caps.max2DTextureSize;
835 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800836 default:
837 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400838 }
839
Brandon Jones6cad5662017-06-14 13:25:13 -0700840 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400841}
842
Brandon Jones6cad5662017-06-14 13:25:13 -0700843bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -0700844 GLenum target,
845 GLint level,
846 GLsizei width,
847 GLsizei height,
848 GLsizei depth,
849 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400850{
Brandon Jones6cad5662017-06-14 13:25:13 -0700851 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400852 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700853 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400854 return false;
855 }
Austin Kinross08528e12015-10-07 16:24:40 -0700856 // TexSubImage parameters can be NPOT without textureNPOT extension,
857 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500858 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500859 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500860 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400861 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400862 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700863 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400864 return false;
865 }
866
867 if (!ValidMipLevel(context, target, level))
868 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700869 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400870 return false;
871 }
872
873 return true;
874}
875
Geoff Lang0d8b7242015-09-09 14:56:53 -0400876bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
877{
878 // List of compressed format that require that the texture size is smaller than or a multiple of
879 // the compressed block size.
880 switch (internalFormat)
881 {
882 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
883 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
884 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
885 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -0400886 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
887 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
888 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
889 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -0800890 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800891 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
892 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
893 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
894 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
895 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
896 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -0400897 return true;
898
899 default:
900 return false;
901 }
902}
903
Geoff Lang966c9402017-04-18 12:38:27 -0400904bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
905{
906 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
907 (size % blockSize == 0);
908}
909
Jamie Madillc29968b2016-01-20 11:17:23 -0500910bool ValidCompressedImageSize(const ValidationContext *context,
911 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400912 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500913 GLsizei width,
914 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400915{
Geoff Langca271392017-04-05 12:30:00 -0400916 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400917 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400918 {
919 return false;
920 }
921
Geoff Lang966c9402017-04-18 12:38:27 -0400922 if (width < 0 || height < 0)
923 {
924 return false;
925 }
926
927 if (CompressedTextureFormatRequiresExactSize(internalFormat))
928 {
929 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
930 // block size for level 0 but WebGL disallows this.
931 bool smallerThanBlockSizeAllowed =
932 level > 0 || !context->getExtensions().webglCompatibility;
933
934 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
935 smallerThanBlockSizeAllowed) ||
936 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
937 smallerThanBlockSizeAllowed))
938 {
939 return false;
940 }
941 }
942
943 return true;
944}
945
946bool ValidCompressedSubImageSize(const ValidationContext *context,
947 GLenum internalFormat,
948 GLint xoffset,
949 GLint yoffset,
950 GLsizei width,
951 GLsizei height,
952 size_t textureWidth,
953 size_t textureHeight)
954{
955 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
956 if (!formatInfo.compressed)
957 {
958 return false;
959 }
960
Geoff Lang44ff5a72017-02-03 15:15:43 -0500961 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400962 {
963 return false;
964 }
965
Geoff Lang0d8b7242015-09-09 14:56:53 -0400966 if (CompressedTextureFormatRequiresExactSize(internalFormat))
967 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500968 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400969 yoffset % formatInfo.compressedBlockHeight != 0)
970 {
971 return false;
972 }
973
974 // Allowed to either have data that is a multiple of block size or is smaller than the block
975 // size but fills the entire mip
976 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
977 static_cast<size_t>(width) == textureWidth &&
978 static_cast<size_t>(height) == textureHeight;
979 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
980 (height % formatInfo.compressedBlockHeight) == 0;
981 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400982 {
983 return false;
984 }
985 }
986
Geoff Langd4f180b2013-09-24 13:57:44 -0400987 return true;
988}
989
Geoff Langff5b2d52016-09-07 11:32:23 -0400990bool ValidImageDataSize(ValidationContext *context,
991 GLenum textureTarget,
992 GLsizei width,
993 GLsizei height,
994 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400995 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400996 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400997 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400998 GLsizei imageSize)
999{
Corentin Wallez336129f2017-10-17 15:55:40 -04001000 gl::Buffer *pixelUnpackBuffer =
1001 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -04001002 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1003 {
1004 // Checks are not required
1005 return true;
1006 }
1007
1008 // ...the data would be unpacked from the buffer object such that the memory reads required
1009 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -04001010 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
1011 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -04001012 const gl::Extents size(width, height, depth);
1013 const auto &unpack = context->getGLState().getUnpackState();
1014
1015 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1016 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1017 if (endByteOrErr.isError())
1018 {
1019 context->handleError(endByteOrErr.getError());
1020 return false;
1021 }
1022
1023 GLuint endByte = endByteOrErr.getResult();
1024
1025 if (pixelUnpackBuffer)
1026 {
1027 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1028 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1029 checkedEndByte += checkedOffset;
1030
1031 if (!checkedEndByte.IsValid() ||
1032 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1033 {
1034 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001035 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04001036 return false;
1037 }
1038 }
1039 else
1040 {
1041 ASSERT(imageSize >= 0);
1042 if (pixels == nullptr && imageSize != 0)
1043 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001044 context->handleError(InvalidOperation()
1045 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001046 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001047 }
1048
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001049 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001050 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001051 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001052 return false;
1053 }
1054 }
1055
1056 return true;
1057}
1058
Geoff Lang37dde692014-01-31 16:34:54 -05001059bool ValidQueryType(const Context *context, GLenum queryType)
1060{
He Yunchaoced53ae2016-11-29 15:00:51 +08001061 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1062 "GL extension enums not equal.");
1063 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1064 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001065
1066 switch (queryType)
1067 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001068 case GL_ANY_SAMPLES_PASSED:
1069 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001070 return context->getClientMajorVersion() >= 3 ||
1071 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +08001072 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1073 return (context->getClientMajorVersion() >= 3);
1074 case GL_TIME_ELAPSED_EXT:
1075 return context->getExtensions().disjointTimerQuery;
1076 case GL_COMMANDS_COMPLETED_CHROMIUM:
1077 return context->getExtensions().syncQuery;
1078 default:
1079 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001080 }
1081}
1082
Geoff Lang2d62ab72017-03-23 16:54:40 -04001083bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
1084 GLenum type,
1085 GLboolean normalized,
1086 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001087 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001088 bool pureInteger)
1089{
1090 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001091 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1092 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1093 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1094 // parameter exceeds 255.
1095 constexpr GLsizei kMaxWebGLStride = 255;
1096 if (stride > kMaxWebGLStride)
1097 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001098 context->handleError(InvalidValue()
1099 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001100 return false;
1101 }
1102
1103 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1104 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1105 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1106 // or an INVALID_OPERATION error is generated.
1107 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1108 size_t typeSize = GetVertexFormatTypeSize(internalType);
1109
1110 ASSERT(isPow2(typeSize) && typeSize > 0);
1111 size_t sizeMask = (typeSize - 1);
1112 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1113 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001114 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001115 return false;
1116 }
1117
1118 if ((stride & sizeMask) != 0)
1119 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001120 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001121 return false;
1122 }
1123
1124 return true;
1125}
1126
Jamie Madillef300b12016-10-07 15:12:09 -04001127Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001128{
He Yunchaoced53ae2016-11-29 15:00:51 +08001129 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1130 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1131 // or program object and INVALID_OPERATION if the provided name identifies an object
1132 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001133
Dian Xiang769769a2015-09-09 15:20:08 -07001134 Program *validProgram = context->getProgram(id);
1135
1136 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001137 {
Dian Xiang769769a2015-09-09 15:20:08 -07001138 if (context->getShader(id))
1139 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001140 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001141 }
1142 else
1143 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001144 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001145 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001146 }
Dian Xiang769769a2015-09-09 15:20:08 -07001147
1148 return validProgram;
1149}
1150
Jamie Madillef300b12016-10-07 15:12:09 -04001151Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001152{
1153 // See ValidProgram for spec details.
1154
1155 Shader *validShader = context->getShader(id);
1156
1157 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001158 {
Dian Xiang769769a2015-09-09 15:20:08 -07001159 if (context->getProgram(id))
1160 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001161 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001162 }
1163 else
1164 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001165 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001166 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001167 }
Dian Xiang769769a2015-09-09 15:20:08 -07001168
1169 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001170}
1171
Geoff Langb1196682014-07-23 13:47:29 -04001172bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001173{
Geoff Langfa125c92017-10-24 13:01:46 -04001174 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001175 {
Geoff Langfa125c92017-10-24 13:01:46 -04001176 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1177 {
1178 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1179 return false;
1180 }
Jamie Madillb4472272014-07-03 10:38:55 -04001181
Geoff Langfa125c92017-10-24 13:01:46 -04001182 // Color attachment 0 is validated below because it is always valid
1183 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001184 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001185 {
Geoff Langfa125c92017-10-24 13:01:46 -04001186 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001187 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001188 }
1189 }
1190 else
1191 {
1192 switch (attachment)
1193 {
Geoff Langfa125c92017-10-24 13:01:46 -04001194 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001195 case GL_DEPTH_ATTACHMENT:
1196 case GL_STENCIL_ATTACHMENT:
1197 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001198
He Yunchaoced53ae2016-11-29 15:00:51 +08001199 case GL_DEPTH_STENCIL_ATTACHMENT:
1200 if (!context->getExtensions().webglCompatibility &&
1201 context->getClientMajorVersion() < 3)
1202 {
Geoff Langfa125c92017-10-24 13:01:46 -04001203 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001204 return false;
1205 }
1206 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001207
He Yunchaoced53ae2016-11-29 15:00:51 +08001208 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001209 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001210 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001211 }
1212 }
1213
1214 return true;
1215}
1216
Jamie Madille8fb6402017-02-14 17:56:40 -05001217bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001218 GLenum target,
1219 GLsizei samples,
1220 GLenum internalformat,
1221 GLsizei width,
1222 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001223{
1224 switch (target)
1225 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001226 case GL_RENDERBUFFER:
1227 break;
1228 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001229 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001230 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001231 }
1232
1233 if (width < 0 || height < 0 || samples < 0)
1234 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001235 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001236 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001237 }
1238
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001239 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1240 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1241
1242 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001243 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001244 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001245 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001246 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001247 }
1248
1249 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1250 // 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 -08001251 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001252 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1253 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001254 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001255 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001256 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001257 }
1258
Geoff Langaae65a42014-05-26 12:43:44 -04001259 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001260 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001261 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001262 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001263 }
1264
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001265 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001266 if (handle == 0)
1267 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001268 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001269 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001270 }
1271
1272 return true;
1273}
1274
He Yunchaoced53ae2016-11-29 15:00:51 +08001275bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1276 GLenum target,
1277 GLenum attachment,
1278 GLenum renderbuffertarget,
1279 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001280{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001281 if (!ValidFramebufferTarget(target))
1282 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001283 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001284 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001285 }
1286
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001287 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001288
Jamie Madill84115c92015-04-23 15:00:07 -04001289 ASSERT(framebuffer);
1290 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001291 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001292 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001293 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001294 }
1295
Jamie Madillb4472272014-07-03 10:38:55 -04001296 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001297 {
Jamie Madillb4472272014-07-03 10:38:55 -04001298 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001299 }
1300
Jamie Madillab9d82c2014-01-21 16:38:14 -05001301 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1302 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1303 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1304 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1305 if (renderbuffer != 0)
1306 {
1307 if (!context->getRenderbuffer(renderbuffer))
1308 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001309 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001310 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001311 }
1312 }
1313
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001314 return true;
1315}
1316
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001317bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001318 GLint srcX0,
1319 GLint srcY0,
1320 GLint srcX1,
1321 GLint srcY1,
1322 GLint dstX0,
1323 GLint dstY0,
1324 GLint dstX1,
1325 GLint dstY1,
1326 GLbitfield mask,
1327 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001328{
1329 switch (filter)
1330 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001331 case GL_NEAREST:
1332 break;
1333 case GL_LINEAR:
1334 break;
1335 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001336 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001337 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001338 }
1339
1340 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1341 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001342 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001343 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001344 }
1345
1346 if (mask == 0)
1347 {
1348 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1349 // buffers are copied.
1350 return false;
1351 }
1352
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001353 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1354 // color buffer, leaving only nearest being unfiltered from above
1355 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1356 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001357 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001358 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001359 }
1360
Jamie Madill51f40ec2016-06-15 14:06:00 -04001361 const auto &glState = context->getGLState();
1362 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1363 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001364
1365 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001366 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001367 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001368 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001369 }
1370
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001371 if (readFramebuffer->id() == drawFramebuffer->id())
1372 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001373 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001374 return false;
1375 }
1376
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001377 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001378 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001379 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001380 return false;
1381 }
1382
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001383 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001385 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001386 return false;
1387 }
1388
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001389 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001390 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001391 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001392 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001393 }
1394
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001395 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1396
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001397 if (mask & GL_COLOR_BUFFER_BIT)
1398 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001399 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001400 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001401
He Yunchao66a41a22016-12-15 16:45:05 +08001402 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001403 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001404 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001405
Geoff Langa15472a2015-08-11 11:48:03 -04001406 for (size_t drawbufferIdx = 0;
1407 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001408 {
Geoff Langa15472a2015-08-11 11:48:03 -04001409 const FramebufferAttachment *attachment =
1410 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1411 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001412 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001413 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001414
Geoff Langb2f3d052013-08-13 12:49:27 -04001415 // The GL ES 3.0.2 spec (pg 193) states that:
1416 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001417 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1418 // as well
1419 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1420 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001421 // Changes with EXT_color_buffer_float:
1422 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001423 GLenum readComponentType = readFormat.info->componentType;
1424 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001425 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001426 readComponentType == GL_SIGNED_NORMALIZED);
1427 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1428 drawComponentType == GL_SIGNED_NORMALIZED);
1429
1430 if (extensions.colorBufferFloat)
1431 {
1432 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1433 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1434
1435 if (readFixedOrFloat != drawFixedOrFloat)
1436 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001437 context->handleError(InvalidOperation()
1438 << "If the read buffer contains fixed-point or "
1439 "floating-point values, the draw buffer must "
1440 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001441 return false;
1442 }
1443 }
1444 else if (readFixedPoint != drawFixedPoint)
1445 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001446 context->handleError(InvalidOperation()
1447 << "If the read buffer contains fixed-point values, "
1448 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001449 return false;
1450 }
1451
1452 if (readComponentType == GL_UNSIGNED_INT &&
1453 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001454 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001455 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001456 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001457 }
1458
Jamie Madill6163c752015-12-07 16:32:59 -05001459 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001460 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001461 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001462 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001463 }
1464
Jamie Madilla3944d42016-07-22 22:13:26 -04001465 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001466 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001467 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001468 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001469 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001470 }
Geoff Lange4915782017-04-12 15:19:07 -04001471
1472 if (context->getExtensions().webglCompatibility &&
1473 *readColorBuffer == *attachment)
1474 {
1475 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001476 InvalidOperation()
1477 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001478 return false;
1479 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001480 }
1481 }
1482
Jamie Madilla3944d42016-07-22 22:13:26 -04001483 if ((readFormat.info->componentType == GL_INT ||
1484 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1485 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001486 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001487 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001488 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001489 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001490 }
He Yunchao66a41a22016-12-15 16:45:05 +08001491 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1492 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1493 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1494 // situation is an application error that would lead to a crash in ANGLE.
1495 else if (drawFramebuffer->hasEnabledDrawBuffer())
1496 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001497 context->handleError(
1498 InvalidOperation()
1499 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001500 return false;
1501 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001502 }
1503
He Yunchaoced53ae2016-11-29 15:00:51 +08001504 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001505 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1506 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001507 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001508 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001509 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001510 const gl::FramebufferAttachment *readBuffer =
1511 readFramebuffer->getAttachment(attachments[i]);
1512 const gl::FramebufferAttachment *drawBuffer =
1513 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001514
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001515 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001516 {
Kenneth Russell69382852017-07-21 16:38:44 -04001517 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001518 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001519 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001520 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001521 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001522
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001523 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001524 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001525 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001526 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001527 }
Geoff Lange4915782017-04-12 15:19:07 -04001528
1529 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1530 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001531 context->handleError(
1532 InvalidOperation()
1533 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001534 return false;
1535 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001536 }
He Yunchao66a41a22016-12-15 16:45:05 +08001537 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1538 else if (drawBuffer)
1539 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001540 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1541 "depth/stencil attachment of a "
1542 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001543 return false;
1544 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001545 }
1546 }
1547
Martin Radeva3ed4572017-07-27 18:29:37 +03001548 // ANGLE_multiview, Revision 1:
1549 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1550 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1551 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1552 {
1553 context->handleError(InvalidFramebufferOperation()
1554 << "Attempt to read from a multi-view framebuffer.");
1555 return false;
1556 }
1557 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1558 {
1559 context->handleError(InvalidFramebufferOperation()
1560 << "Attempt to write to a multi-view framebuffer.");
1561 return false;
1562 }
1563
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001564 return true;
1565}
1566
Jamie Madill4928b7c2017-06-20 12:57:39 -04001567bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001568 GLint x,
1569 GLint y,
1570 GLsizei width,
1571 GLsizei height,
1572 GLenum format,
1573 GLenum type,
1574 GLsizei bufSize,
1575 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001576 GLsizei *columns,
1577 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001578 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001579{
1580 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001581 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001582 return false;
1583 }
1584
Geoff Lang62fce5b2016-09-30 10:46:35 -04001585 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001586 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001587 {
Geoff Langb1196682014-07-23 13:47:29 -04001588 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001589 }
1590
Geoff Lang62fce5b2016-09-30 10:46:35 -04001591 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001592 {
Geoff Langb1196682014-07-23 13:47:29 -04001593 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001594 }
1595
Jamie Madillc29968b2016-01-20 11:17:23 -05001596 return true;
1597}
1598
1599bool ValidateReadnPixelsEXT(Context *context,
1600 GLint x,
1601 GLint y,
1602 GLsizei width,
1603 GLsizei height,
1604 GLenum format,
1605 GLenum type,
1606 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001607 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001608{
1609 if (bufSize < 0)
1610 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001611 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001612 return false;
1613 }
1614
Geoff Lang62fce5b2016-09-30 10:46:35 -04001615 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001616 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001617}
Jamie Madill26e91952014-03-05 15:01:27 -05001618
Jamie Madill4928b7c2017-06-20 12:57:39 -04001619bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001620 GLint x,
1621 GLint y,
1622 GLsizei width,
1623 GLsizei height,
1624 GLenum format,
1625 GLenum type,
1626 GLsizei bufSize,
1627 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001628 GLsizei *columns,
1629 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001630 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001631{
1632 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001633 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001634 return false;
1635 }
1636
Geoff Lange93daba2017-03-30 13:54:40 -04001637 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1638 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001639 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001640 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001641 }
1642
Geoff Lang62fce5b2016-09-30 10:46:35 -04001643 if (!ValidateRobustBufferSize(context, bufSize, *length))
1644 {
1645 return false;
1646 }
1647
1648 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001649}
1650
Jamie Madillf0e04492017-08-26 15:28:42 -04001651bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001652{
1653 if (!context->getExtensions().occlusionQueryBoolean &&
1654 !context->getExtensions().disjointTimerQuery)
1655 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001656 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001657 return false;
1658 }
1659
Olli Etuaho41997e72016-03-10 13:38:39 +02001660 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001661}
1662
Jamie Madillf0e04492017-08-26 15:28:42 -04001663bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001664{
1665 if (!context->getExtensions().occlusionQueryBoolean &&
1666 !context->getExtensions().disjointTimerQuery)
1667 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001668 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001669 return false;
1670 }
1671
Olli Etuaho41997e72016-03-10 13:38:39 +02001672 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001673}
1674
Jamie Madillf0e04492017-08-26 15:28:42 -04001675bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1676{
1677 if (!context->getExtensions().occlusionQueryBoolean &&
1678 !context->getExtensions().disjointTimerQuery)
1679 {
1680 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1681 return false;
1682 }
1683
1684 return true;
1685}
1686
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001687bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001688{
1689 if (!ValidQueryType(context, target))
1690 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001691 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001692 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001693 }
1694
1695 if (id == 0)
1696 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001697 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001698 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001699 }
1700
1701 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1702 // of zero, if the active query object name for <target> is non-zero (for the
1703 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1704 // the active query for either target is non-zero), if <id> is the name of an
1705 // existing query object whose type does not match <target>, or if <id> is the
1706 // active query object name for any query type, the error INVALID_OPERATION is
1707 // generated.
1708
1709 // Ensure no other queries are active
1710 // NOTE: If other queries than occlusion are supported, we will need to check
1711 // separately that:
1712 // a) The query ID passed is not the current active query for any target/type
1713 // b) There are no active queries for the requested target (and in the case
1714 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1715 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001716
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001717 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001719 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001720 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001721 }
1722
1723 Query *queryObject = context->getQuery(id, true, target);
1724
1725 // check that name was obtained with glGenQueries
1726 if (!queryObject)
1727 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001728 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001729 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001730 }
1731
1732 // check for type mismatch
1733 if (queryObject->getType() != target)
1734 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001735 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001736 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001737 }
1738
1739 return true;
1740}
1741
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001742bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1743{
1744 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001745 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001746 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001747 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001748 return false;
1749 }
1750
1751 return ValidateBeginQueryBase(context, target, id);
1752}
1753
1754bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001755{
1756 if (!ValidQueryType(context, target))
1757 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001758 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001759 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001760 }
1761
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001762 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001763
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001764 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001765 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001766 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001767 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001768 }
1769
Jamie Madill45c785d2014-05-13 14:09:34 -04001770 return true;
1771}
1772
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001773bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1774{
1775 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001776 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001777 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001778 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001779 return false;
1780 }
1781
1782 return ValidateEndQueryBase(context, target);
1783}
1784
1785bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1786{
1787 if (!context->getExtensions().disjointTimerQuery)
1788 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001789 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001790 return false;
1791 }
1792
1793 if (target != GL_TIMESTAMP_EXT)
1794 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001795 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001796 return false;
1797 }
1798
1799 Query *queryObject = context->getQuery(id, true, target);
1800 if (queryObject == nullptr)
1801 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001802 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001803 return false;
1804 }
1805
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001806 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001807 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001808 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001809 return false;
1810 }
1811
1812 return true;
1813}
1814
Geoff Lang2186c382016-10-14 10:54:54 -04001815bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001816{
Geoff Lang2186c382016-10-14 10:54:54 -04001817 if (numParams)
1818 {
1819 *numParams = 0;
1820 }
1821
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001822 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1823 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001824 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001825 return false;
1826 }
1827
1828 switch (pname)
1829 {
1830 case GL_CURRENT_QUERY_EXT:
1831 if (target == GL_TIMESTAMP_EXT)
1832 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001833 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001834 return false;
1835 }
1836 break;
1837 case GL_QUERY_COUNTER_BITS_EXT:
1838 if (!context->getExtensions().disjointTimerQuery ||
1839 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1840 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001841 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001842 return false;
1843 }
1844 break;
1845 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001846 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001847 return false;
1848 }
1849
Geoff Lang2186c382016-10-14 10:54:54 -04001850 if (numParams)
1851 {
1852 // All queries return only one value
1853 *numParams = 1;
1854 }
1855
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001856 return true;
1857}
1858
1859bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1860{
1861 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001862 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001863 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001864 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001865 return false;
1866 }
1867
Geoff Lang2186c382016-10-14 10:54:54 -04001868 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001869}
1870
Geoff Lang2186c382016-10-14 10:54:54 -04001871bool ValidateGetQueryivRobustANGLE(Context *context,
1872 GLenum target,
1873 GLenum pname,
1874 GLsizei bufSize,
1875 GLsizei *length,
1876 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001877{
Geoff Lang2186c382016-10-14 10:54:54 -04001878 if (!ValidateRobustEntryPoint(context, bufSize))
1879 {
1880 return false;
1881 }
1882
1883 if (!ValidateGetQueryivBase(context, target, pname, length))
1884 {
1885 return false;
1886 }
1887
1888 if (!ValidateRobustBufferSize(context, bufSize, *length))
1889 {
1890 return false;
1891 }
1892
1893 return true;
1894}
1895
1896bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1897{
1898 if (numParams)
1899 {
1900 *numParams = 0;
1901 }
1902
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001903 Query *queryObject = context->getQuery(id, false, GL_NONE);
1904
1905 if (!queryObject)
1906 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001907 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001908 return false;
1909 }
1910
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001911 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001912 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001913 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001914 return false;
1915 }
1916
1917 switch (pname)
1918 {
1919 case GL_QUERY_RESULT_EXT:
1920 case GL_QUERY_RESULT_AVAILABLE_EXT:
1921 break;
1922
1923 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001924 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001925 return false;
1926 }
1927
Geoff Lang2186c382016-10-14 10:54:54 -04001928 if (numParams)
1929 {
1930 *numParams = 1;
1931 }
1932
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001933 return true;
1934}
1935
1936bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1937{
1938 if (!context->getExtensions().disjointTimerQuery)
1939 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001940 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001941 return false;
1942 }
Geoff Lang2186c382016-10-14 10:54:54 -04001943 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1944}
1945
1946bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1947 GLuint id,
1948 GLenum pname,
1949 GLsizei bufSize,
1950 GLsizei *length,
1951 GLint *params)
1952{
1953 if (!context->getExtensions().disjointTimerQuery)
1954 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001955 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001956 return false;
1957 }
1958
1959 if (!ValidateRobustEntryPoint(context, bufSize))
1960 {
1961 return false;
1962 }
1963
1964 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1965 {
1966 return false;
1967 }
1968
1969 if (!ValidateRobustBufferSize(context, bufSize, *length))
1970 {
1971 return false;
1972 }
1973
1974 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001975}
1976
1977bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1978{
1979 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001980 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001981 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001982 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001983 return false;
1984 }
Geoff Lang2186c382016-10-14 10:54:54 -04001985 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1986}
1987
1988bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1989 GLuint id,
1990 GLenum pname,
1991 GLsizei bufSize,
1992 GLsizei *length,
1993 GLuint *params)
1994{
1995 if (!context->getExtensions().disjointTimerQuery &&
1996 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1997 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001998 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001999 return false;
2000 }
2001
2002 if (!ValidateRobustEntryPoint(context, bufSize))
2003 {
2004 return false;
2005 }
2006
2007 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2008 {
2009 return false;
2010 }
2011
2012 if (!ValidateRobustBufferSize(context, bufSize, *length))
2013 {
2014 return false;
2015 }
2016
2017 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002018}
2019
2020bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2021{
2022 if (!context->getExtensions().disjointTimerQuery)
2023 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002024 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002025 return false;
2026 }
Geoff Lang2186c382016-10-14 10:54:54 -04002027 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2028}
2029
2030bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2031 GLuint id,
2032 GLenum pname,
2033 GLsizei bufSize,
2034 GLsizei *length,
2035 GLint64 *params)
2036{
2037 if (!context->getExtensions().disjointTimerQuery)
2038 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002039 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002040 return false;
2041 }
2042
2043 if (!ValidateRobustEntryPoint(context, bufSize))
2044 {
2045 return false;
2046 }
2047
2048 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2049 {
2050 return false;
2051 }
2052
2053 if (!ValidateRobustBufferSize(context, bufSize, *length))
2054 {
2055 return false;
2056 }
2057
2058 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002059}
2060
2061bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2062{
2063 if (!context->getExtensions().disjointTimerQuery)
2064 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002065 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002066 return false;
2067 }
Geoff Lang2186c382016-10-14 10:54:54 -04002068 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2069}
2070
2071bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2072 GLuint id,
2073 GLenum pname,
2074 GLsizei bufSize,
2075 GLsizei *length,
2076 GLuint64 *params)
2077{
2078 if (!context->getExtensions().disjointTimerQuery)
2079 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002080 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002081 return false;
2082 }
2083
2084 if (!ValidateRobustEntryPoint(context, bufSize))
2085 {
2086 return false;
2087 }
2088
2089 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2090 {
2091 return false;
2092 }
2093
2094 if (!ValidateRobustBufferSize(context, bufSize, *length))
2095 {
2096 return false;
2097 }
2098
2099 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002100}
2101
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002102bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002103 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002104 GLuint program,
2105 GLint location,
2106 GLsizei count)
2107{
2108 // Check for ES31 program uniform entry points
2109 if (context->getClientVersion() < Version(3, 1))
2110 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002111 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002112 return false;
2113 }
2114
2115 const LinkedUniform *uniform = nullptr;
2116 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002117 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2118 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002119}
2120
Frank Henigmana98a6472017-02-02 21:38:32 -05002121bool ValidateProgramUniform1iv(gl::Context *context,
2122 GLuint program,
2123 GLint location,
2124 GLsizei count,
2125 const GLint *value)
2126{
2127 // Check for ES31 program uniform entry points
2128 if (context->getClientVersion() < Version(3, 1))
2129 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002130 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Frank Henigmana98a6472017-02-02 21:38:32 -05002131 return false;
2132 }
2133
2134 const LinkedUniform *uniform = nullptr;
2135 gl::Program *programObject = GetValidProgram(context, program);
2136 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2137 ValidateUniform1ivValue(context, uniform->type, count, value);
2138}
2139
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002140bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002141 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002142 GLuint program,
2143 GLint location,
2144 GLsizei count,
2145 GLboolean transpose)
2146{
2147 // Check for ES31 program uniform entry points
2148 if (context->getClientVersion() < Version(3, 1))
2149 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002150 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002151 return false;
2152 }
2153
2154 const LinkedUniform *uniform = nullptr;
2155 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002156 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2157 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002158}
2159
Jamie Madillc1d770e2017-04-13 17:31:24 -04002160bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002161{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002162 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002163 gl::Program *programObject = context->getGLState().getProgram();
2164 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2165 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002166}
2167
Jamie Madillbe849e42017-05-02 15:49:00 -04002168bool ValidateUniform1iv(ValidationContext *context,
2169 GLint location,
2170 GLsizei count,
2171 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002172{
2173 const LinkedUniform *uniform = nullptr;
2174 gl::Program *programObject = context->getGLState().getProgram();
2175 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2176 ValidateUniform1ivValue(context, uniform->type, count, value);
2177}
2178
Jamie Madillc1d770e2017-04-13 17:31:24 -04002179bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002180 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002181 GLint location,
2182 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002183 GLboolean transpose)
2184{
Martin Radev1be913c2016-07-11 17:59:16 +03002185 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002186 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002187 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002188 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002189 }
2190
Jamie Madill62d31cb2015-09-11 13:25:51 -04002191 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002192 gl::Program *programObject = context->getGLState().getProgram();
2193 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2194 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002195}
2196
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002197bool ValidateStateQuery(ValidationContext *context,
2198 GLenum pname,
2199 GLenum *nativeType,
2200 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002201{
2202 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2203 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002204 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002205 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002206 }
2207
Jamie Madill0af26e12015-03-05 19:54:33 -05002208 const Caps &caps = context->getCaps();
2209
Jamie Madill893ab082014-05-16 16:56:10 -04002210 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2211 {
2212 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2213
Jamie Madill0af26e12015-03-05 19:54:33 -05002214 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002215 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002216 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002217 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002218 }
2219 }
2220
2221 switch (pname)
2222 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002223 case GL_TEXTURE_BINDING_2D:
2224 case GL_TEXTURE_BINDING_CUBE_MAP:
2225 case GL_TEXTURE_BINDING_3D:
2226 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002227 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002228 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002229 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2230 if (!context->getExtensions().textureRectangle)
2231 {
2232 context->handleError(InvalidEnum()
2233 << "ANGLE_texture_rectangle extension not present");
2234 return false;
2235 }
2236 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002237 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2238 if (!context->getExtensions().eglStreamConsumerExternal &&
2239 !context->getExtensions().eglImageExternal)
2240 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002241 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2242 "nor GL_OES_EGL_image_external "
2243 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002244 return false;
2245 }
2246 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002247
He Yunchaoced53ae2016-11-29 15:00:51 +08002248 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2249 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002250 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002251 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2252 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002253 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002254 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002255 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002256 }
2257
Jamie Madill51f40ec2016-06-15 14:06:00 -04002258 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2259 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002260
2261 if (framebuffer->getReadBufferState() == GL_NONE)
2262 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002263 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002264 return false;
2265 }
2266
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002267 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002268 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002269 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002270 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002271 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002272 }
2273 }
2274 break;
2275
He Yunchaoced53ae2016-11-29 15:00:51 +08002276 default:
2277 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002278 }
2279
2280 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002281 if (*numParams == 0)
2282 {
2283 return false;
2284 }
2285
2286 return true;
2287}
2288
2289bool ValidateRobustStateQuery(ValidationContext *context,
2290 GLenum pname,
2291 GLsizei bufSize,
2292 GLenum *nativeType,
2293 unsigned int *numParams)
2294{
2295 if (!ValidateRobustEntryPoint(context, bufSize))
2296 {
2297 return false;
2298 }
2299
2300 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2301 {
2302 return false;
2303 }
2304
2305 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002306 {
2307 return false;
2308 }
2309
2310 return true;
2311}
2312
Jamie Madillc29968b2016-01-20 11:17:23 -05002313bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2314 GLenum target,
2315 GLint level,
2316 GLenum internalformat,
2317 bool isSubImage,
2318 GLint xoffset,
2319 GLint yoffset,
2320 GLint zoffset,
2321 GLint x,
2322 GLint y,
2323 GLsizei width,
2324 GLsizei height,
2325 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002326 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002327{
Brandon Jones6cad5662017-06-14 13:25:13 -07002328 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002329 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002330 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2331 return false;
2332 }
2333
2334 if (width < 0 || height < 0)
2335 {
2336 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002337 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002338 }
2339
He Yunchaoced53ae2016-11-29 15:00:51 +08002340 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2341 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002342 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002343 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002344 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002345 }
2346
2347 if (border != 0)
2348 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002349 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002350 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002351 }
2352
2353 if (!ValidMipLevel(context, target, level))
2354 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002355 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002356 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002357 }
2358
Jamie Madill51f40ec2016-06-15 14:06:00 -04002359 const auto &state = context->getGLState();
2360 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002361 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002363 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002364 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002365 }
2366
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002367 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002368 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002369 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002370 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002371 }
2372
Martin Radev138064f2016-07-15 12:03:41 +03002373 if (readFramebuffer->getReadBufferState() == GL_NONE)
2374 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002375 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002376 return false;
2377 }
2378
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002379 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2380 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002381 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002382 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002383 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2384 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002385 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002386 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002387 return false;
2388 }
2389
Martin Radev04e2c3b2017-07-27 16:54:35 +03002390 // ANGLE_multiview spec, Revision 1:
2391 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2392 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2393 // is not NONE.
2394 if (source->getMultiviewLayout() != GL_NONE)
2395 {
2396 context->handleError(InvalidFramebufferOperation()
2397 << "The active read framebuffer object has multiview attachments.");
2398 return false;
2399 }
2400
Geoff Langaae65a42014-05-26 12:43:44 -04002401 const gl::Caps &caps = context->getCaps();
2402
Geoff Langaae65a42014-05-26 12:43:44 -04002403 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002404 switch (target)
2405 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002406 case GL_TEXTURE_2D:
2407 maxDimension = caps.max2DTextureSize;
2408 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002409
He Yunchaoced53ae2016-11-29 15:00:51 +08002410 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2411 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2412 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2413 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2414 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2415 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2416 maxDimension = caps.maxCubeMapTextureSize;
2417 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002418
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002419 case GL_TEXTURE_RECTANGLE_ANGLE:
2420 maxDimension = caps.maxRectangleTextureSize;
2421 break;
2422
He Yunchaoced53ae2016-11-29 15:00:51 +08002423 case GL_TEXTURE_2D_ARRAY:
2424 maxDimension = caps.max2DTextureSize;
2425 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002426
He Yunchaoced53ae2016-11-29 15:00:51 +08002427 case GL_TEXTURE_3D:
2428 maxDimension = caps.max3DTextureSize;
2429 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002430
He Yunchaoced53ae2016-11-29 15:00:51 +08002431 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002432 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002433 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002434 }
2435
Jamie Madillc29968b2016-01-20 11:17:23 -05002436 gl::Texture *texture =
2437 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002438 if (!texture)
2439 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002440 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002441 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002442 }
2443
Geoff Lang69cce582015-09-17 13:20:36 -04002444 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002445 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002446 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002447 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002448 }
2449
Geoff Langca271392017-04-05 12:30:00 -04002450 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002451 isSubImage ? *texture->getFormat(target, level).info
2452 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002453
Geoff Lang966c9402017-04-18 12:38:27 -04002454 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002455 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002456 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002457 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002458 }
2459
2460 if (isSubImage)
2461 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002462 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2463 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2464 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002465 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002466 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002467 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002468 }
2469 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002470 else
2471 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002472 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002473 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002474 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002475 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002476 }
2477
Geoff Langeb66a6e2016-10-31 13:06:12 -04002478 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002479 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002480 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002481 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002482 }
2483
2484 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002485 if (static_cast<int>(width) > maxLevelDimension ||
2486 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002487 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002488 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002489 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002490 }
2491 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002492
Jamie Madill0c8abca2016-07-22 20:21:26 -04002493 if (textureFormatOut)
2494 {
2495 *textureFormatOut = texture->getFormat(target, level);
2496 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002497
2498 // Detect texture copying feedback loops for WebGL.
2499 if (context->getExtensions().webglCompatibility)
2500 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002501 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002502 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002503 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002504 return false;
2505 }
2506 }
2507
Jamie Madill560a8d82014-05-21 13:06:20 -04002508 return true;
2509}
2510
Jiajia Qind9671222016-11-29 16:30:31 +08002511bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002512{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002513 switch (mode)
2514 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002515 case GL_POINTS:
2516 case GL_LINES:
2517 case GL_LINE_LOOP:
2518 case GL_LINE_STRIP:
2519 case GL_TRIANGLES:
2520 case GL_TRIANGLE_STRIP:
2521 case GL_TRIANGLE_FAN:
2522 break;
2523 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002524 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002525 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002526 }
2527
Jamie Madill250d33f2014-06-06 17:09:03 -04002528 if (count < 0)
2529 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002530 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002531 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002532 }
2533
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002534 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002535
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002536 const Extensions &extensions = context->getExtensions();
2537
2538 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2539 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2540 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2541 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002542 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002543 // Check for mapped buffers
2544 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002545 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002546 {
2547 context->handleError(InvalidOperation());
2548 return false;
2549 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002550 }
2551
Jamie Madillcbcde722017-01-06 14:50:00 -05002552 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2553 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002554 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002555 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002556 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002557 const FramebufferAttachment *dsAttachment =
2558 framebuffer->getStencilOrDepthStencilAttachment();
2559 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002560 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002561 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002562
2563 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2564 bool differentWritemasks =
2565 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2566 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2567 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2568 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2569
2570 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002571 {
Martin Radevffe754b2017-07-31 10:38:07 +03002572 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002573 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002574 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2575 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002576 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002577 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002578 return false;
2579 }
Jamie Madillac528012014-06-20 13:21:23 -04002580 }
2581
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002582 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002583 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002584 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002585 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002586 }
2587
Geoff Lang7dd2e102014-11-10 15:19:26 -05002588 gl::Program *program = state.getProgram();
2589 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002590 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002591 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002592 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002593 }
2594
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002595 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002596 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002597 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002598 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002599 }
2600
Martin Radevffe754b2017-07-31 10:38:07 +03002601 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002602 {
Martin Radevda8e2572017-09-12 17:21:16 +03002603 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002604 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002605 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002606 {
2607 context->handleError(InvalidOperation() << "The number of views in the active program "
2608 "and draw framebuffer does not match.");
2609 return false;
2610 }
Martin Radev7e69f762017-07-27 14:54:13 +03002611
2612 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2613 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2614 framebufferNumViews > 1)
2615 {
2616 context->handleError(InvalidOperation()
2617 << "There is an active transform feedback object "
2618 "when the number of views in the active draw "
2619 "framebuffer is greater than 1.");
2620 return false;
2621 }
Martin Radevffe754b2017-07-31 10:38:07 +03002622
2623 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2624 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2625 {
2626 context->handleError(InvalidOperation() << "There is an active query for target "
2627 "GL_TIME_ELAPSED_EXT when the number of "
2628 "views in the active draw framebuffer is "
2629 "greater than 1.");
2630 return false;
2631 }
Martin Radev7cf61662017-07-26 17:10:53 +03002632 }
2633
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002634 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002635 for (unsigned int uniformBlockIndex = 0;
2636 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002637 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002638 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002639 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002640 const OffsetBindingPointer<Buffer> &uniformBuffer =
2641 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002642
Geoff Lang5d124a62015-09-15 13:03:27 -04002643 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002644 {
2645 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002646 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002647 InvalidOperation()
2648 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002649 return false;
2650 }
2651
Geoff Lang5d124a62015-09-15 13:03:27 -04002652 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002653 if (uniformBufferSize == 0)
2654 {
2655 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002656 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002657 }
2658
Jamie Madill62d31cb2015-09-11 13:25:51 -04002659 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002660 {
2661 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002662 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002663 InvalidOperation()
2664 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002665 return false;
2666 }
2667 }
2668
Geoff Lange0cff192017-05-30 13:04:56 -04002669 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002670 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002671 {
Geoff Lange0cff192017-05-30 13:04:56 -04002672 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002673 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2674 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002675 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002676 return false;
2677 }
Geoff Lange0cff192017-05-30 13:04:56 -04002678
Geoff Lang9ab5b822017-05-30 16:19:23 -04002679 // Detect that the vertex shader input types match the attribute types
2680 if (!ValidateVertexShaderAttributeTypeMatch(context))
2681 {
2682 return false;
2683 }
2684
Geoff Lange0cff192017-05-30 13:04:56 -04002685 // Detect that the color buffer types match the fragment shader output types
2686 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2687 {
2688 return false;
2689 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002690 }
2691
Jamie Madill250d33f2014-06-06 17:09:03 -04002692 // No-op if zero count
2693 return (count > 0);
2694}
2695
Jamie Madillc1d770e2017-04-13 17:31:24 -04002696bool ValidateDrawArraysCommon(ValidationContext *context,
2697 GLenum mode,
2698 GLint first,
2699 GLsizei count,
2700 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002701{
Jamie Madillfd716582014-06-06 17:09:04 -04002702 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002703 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002704 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002705 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002706 }
2707
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002708 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002709 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002710 if (curTransformFeedback && curTransformFeedback->isActive() &&
2711 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002712 {
2713 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002714 // that does not match the current transform feedback object's draw mode (if transform
2715 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002716 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002717 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002718 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002719 }
2720
Jiajia Qind9671222016-11-29 16:30:31 +08002721 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002722 {
2723 return false;
2724 }
2725
Corentin Wallez71168a02016-12-19 15:11:18 -08002726 // Check the computation of maxVertex doesn't overflow.
2727 // - first < 0 or count < 0 have been checked as an error condition
2728 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2729 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2730 ASSERT(count > 0 && first >= 0);
2731 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2732 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002733 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002734 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002735 return false;
2736 }
2737
Corentin Wallez71168a02016-12-19 15:11:18 -08002738 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002739 {
2740 return false;
2741 }
2742
2743 return true;
2744}
2745
He Yunchaoced53ae2016-11-29 15:00:51 +08002746bool ValidateDrawArraysInstancedANGLE(Context *context,
2747 GLenum mode,
2748 GLint first,
2749 GLsizei count,
2750 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002751{
Geoff Lang63c5a592017-09-27 14:08:16 -04002752 if (!context->getExtensions().instancedArrays)
2753 {
2754 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2755 return false;
2756 }
2757
Corentin Wallez170efbf2017-05-02 13:45:01 -04002758 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002759 {
2760 return false;
2761 }
2762
Corentin Wallez0dc97812017-06-22 14:38:44 -04002763 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002764}
2765
Jiajia Qind9671222016-11-29 16:30:31 +08002766bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002767{
Jamie Madill250d33f2014-06-06 17:09:03 -04002768 switch (type)
2769 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002770 case GL_UNSIGNED_BYTE:
2771 case GL_UNSIGNED_SHORT:
2772 break;
2773 case GL_UNSIGNED_INT:
2774 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2775 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002776 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002777 return false;
2778 }
2779 break;
2780 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002781 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002782 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002783 }
2784
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002785 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002786
2787 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002788 if (curTransformFeedback && curTransformFeedback->isActive() &&
2789 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002790 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002791 // It is an invalid operation to call DrawElements, DrawRangeElements or
2792 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002793 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002794 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002795 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002796 }
2797
Jiajia Qind9671222016-11-29 16:30:31 +08002798 return true;
2799}
2800
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002801bool ValidateDrawElementsCommon(ValidationContext *context,
2802 GLenum mode,
2803 GLsizei count,
2804 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002805 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002806 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002807{
2808 if (!ValidateDrawElementsBase(context, type))
2809 return false;
2810
2811 const State &state = context->getGLState();
2812
Corentin Wallez170efbf2017-05-02 13:45:01 -04002813 if (!ValidateDrawBase(context, mode, count))
2814 {
2815 return false;
2816 }
2817
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002818 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2819 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2820 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2821 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002822 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002823 // Check for mapped buffers
2824 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002825 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002826 {
2827 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2828 return false;
2829 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002830 }
2831
He Yunchaoced53ae2016-11-29 15:00:51 +08002832 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002833 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002834
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002835 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2836
2837 if (context->getExtensions().webglCompatibility)
2838 {
2839 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2840 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2841 {
2842 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2843 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2844 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002845 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002846 return false;
2847 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002848
2849 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2850 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2851 // error is generated.
2852 if (reinterpret_cast<intptr_t>(indices) < 0)
2853 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002854 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002855 return false;
2856 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002857 }
2858
2859 if (context->getExtensions().webglCompatibility ||
2860 !context->getGLState().areClientArraysEnabled())
2861 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002862 if (!elementArrayBuffer && count > 0)
2863 {
2864 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2865 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2866 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002867 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002868 return false;
2869 }
2870 }
2871
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002872 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002873 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002874 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002875 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002876 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2877 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2878 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2879 constexpr uint64_t kMaxTypeSize = 8;
2880 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2881 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2882 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002883
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002884 uint64_t typeSize = typeBytes;
2885 uint64_t elementCount = static_cast<uint64_t>(count);
2886 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2887
2888 // Doing the multiplication here is overflow-safe
2889 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2890
2891 // The offset can be any value, check for overflows
2892 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2893 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002894 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002895 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002896 return false;
2897 }
2898
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002899 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2900 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002901 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002902 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002903 return false;
2904 }
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002905
Corentin Wallez487653b2017-09-01 17:17:55 -04002906 ASSERT(isPow2(typeSize) && typeSize > 0);
2907 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002908 {
2909 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
2910 return false;
2911 }
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002912 }
2913 else if (!indices)
2914 {
2915 // This is an application error that would normally result in a crash,
2916 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002917 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04002918 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002919 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002920 }
2921
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002922 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002923 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002924 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2925 // access is enabled.
2926 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2927 {
2928 return false;
2929 }
2930 }
2931 else
2932 {
2933 // Use the parameter buffer to retrieve and cache the index range.
2934 const auto &params = context->getParams<HasIndexRange>();
2935 const auto &indexRangeOpt = params.getIndexRange();
2936 if (!indexRangeOpt.valid())
2937 {
2938 // Unexpected error.
2939 return false;
2940 }
2941
2942 // If we use an index greater than our maximum supported index range, return an error.
2943 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2944 // return an error if possible here.
2945 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2946 {
2947 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2948 return false;
2949 }
2950
2951 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2952 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2953 {
2954 return false;
2955 }
2956
2957 // No op if there are no real indices in the index data (all are primitive restart).
2958 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002959 }
2960
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002961 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002962}
2963
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002964bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2965 GLenum mode,
2966 GLsizei count,
2967 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002968 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002969 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002970{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002971 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002972}
2973
Geoff Lang3edfe032015-09-04 16:38:24 -04002974bool ValidateDrawElementsInstancedANGLE(Context *context,
2975 GLenum mode,
2976 GLsizei count,
2977 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002978 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002979 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002980{
Geoff Lang63c5a592017-09-27 14:08:16 -04002981 if (!context->getExtensions().instancedArrays)
2982 {
2983 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2984 return false;
2985 }
2986
Corentin Wallez170efbf2017-05-02 13:45:01 -04002987 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002988 {
2989 return false;
2990 }
2991
Corentin Wallez0dc97812017-06-22 14:38:44 -04002992 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002993}
2994
He Yunchaoced53ae2016-11-29 15:00:51 +08002995bool ValidateFramebufferTextureBase(Context *context,
2996 GLenum target,
2997 GLenum attachment,
2998 GLuint texture,
2999 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003000{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003001 if (!ValidFramebufferTarget(target))
3002 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003003 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003004 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003005 }
3006
3007 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003008 {
3009 return false;
3010 }
3011
Jamie Madill55ec3b12014-07-03 10:38:57 -04003012 if (texture != 0)
3013 {
3014 gl::Texture *tex = context->getTexture(texture);
3015
Jamie Madillbe849e42017-05-02 15:49:00 -04003016 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003017 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003018 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003019 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003020 }
3021
3022 if (level < 0)
3023 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003024 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003025 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003026 }
3027 }
3028
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003029 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003030 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003031
Jamie Madill84115c92015-04-23 15:00:07 -04003032 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003033 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003034 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003035 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003036 }
3037
3038 return true;
3039}
3040
Geoff Langb1196682014-07-23 13:47:29 -04003041bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003042{
3043 if (program == 0)
3044 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003045 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003046 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003047 }
3048
Dian Xiang769769a2015-09-09 15:20:08 -07003049 gl::Program *programObject = GetValidProgram(context, program);
3050 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003051 {
3052 return false;
3053 }
3054
Jamie Madill0063c512014-08-25 15:47:53 -04003055 if (!programObject || !programObject->isLinked())
3056 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003057 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003058 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003059 }
3060
Geoff Lang7dd2e102014-11-10 15:19:26 -05003061 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003062 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003063 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003064 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003065 }
3066
Jamie Madill0063c512014-08-25 15:47:53 -04003067 return true;
3068}
3069
Geoff Langf41d0ee2016-10-07 13:04:23 -04003070static bool ValidateSizedGetUniform(Context *context,
3071 GLuint program,
3072 GLint location,
3073 GLsizei bufSize,
3074 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003075{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003076 if (length)
3077 {
3078 *length = 0;
3079 }
3080
Jamie Madill78f41802014-08-25 15:47:55 -04003081 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003082 {
Jamie Madill78f41802014-08-25 15:47:55 -04003083 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003084 }
3085
Geoff Langf41d0ee2016-10-07 13:04:23 -04003086 if (bufSize < 0)
3087 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003088 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003089 return false;
3090 }
3091
Jamie Madilla502c742014-08-28 17:19:13 -04003092 gl::Program *programObject = context->getProgram(program);
3093 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003094
Jamie Madill78f41802014-08-25 15:47:55 -04003095 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003096 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003097 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003098 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003099 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003100 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003101 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003102 }
3103
Geoff Langf41d0ee2016-10-07 13:04:23 -04003104 if (length)
3105 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003106 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003107 }
3108
Jamie Madill0063c512014-08-25 15:47:53 -04003109 return true;
3110}
3111
He Yunchaoced53ae2016-11-29 15:00:51 +08003112bool ValidateGetnUniformfvEXT(Context *context,
3113 GLuint program,
3114 GLint location,
3115 GLsizei bufSize,
3116 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003117{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003118 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003119}
3120
He Yunchaoced53ae2016-11-29 15:00:51 +08003121bool ValidateGetnUniformivEXT(Context *context,
3122 GLuint program,
3123 GLint location,
3124 GLsizei bufSize,
3125 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003126{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003127 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3128}
3129
3130bool ValidateGetUniformfvRobustANGLE(Context *context,
3131 GLuint program,
3132 GLint location,
3133 GLsizei bufSize,
3134 GLsizei *length,
3135 GLfloat *params)
3136{
3137 if (!ValidateRobustEntryPoint(context, bufSize))
3138 {
3139 return false;
3140 }
3141
3142 // bufSize is validated in ValidateSizedGetUniform
3143 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3144}
3145
3146bool ValidateGetUniformivRobustANGLE(Context *context,
3147 GLuint program,
3148 GLint location,
3149 GLsizei bufSize,
3150 GLsizei *length,
3151 GLint *params)
3152{
3153 if (!ValidateRobustEntryPoint(context, bufSize))
3154 {
3155 return false;
3156 }
3157
3158 // bufSize is validated in ValidateSizedGetUniform
3159 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3160}
3161
3162bool ValidateGetUniformuivRobustANGLE(Context *context,
3163 GLuint program,
3164 GLint location,
3165 GLsizei bufSize,
3166 GLsizei *length,
3167 GLuint *params)
3168{
3169 if (!ValidateRobustEntryPoint(context, bufSize))
3170 {
3171 return false;
3172 }
3173
3174 if (context->getClientMajorVersion() < 3)
3175 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003176 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003177 return false;
3178 }
3179
3180 // bufSize is validated in ValidateSizedGetUniform
3181 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003182}
3183
He Yunchaoced53ae2016-11-29 15:00:51 +08003184bool ValidateDiscardFramebufferBase(Context *context,
3185 GLenum target,
3186 GLsizei numAttachments,
3187 const GLenum *attachments,
3188 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003189{
3190 if (numAttachments < 0)
3191 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003192 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003193 return false;
3194 }
3195
3196 for (GLsizei i = 0; i < numAttachments; ++i)
3197 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003198 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003199 {
3200 if (defaultFramebuffer)
3201 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003202 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003203 return false;
3204 }
3205
3206 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3207 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003208 context->handleError(InvalidOperation() << "Requested color attachment is "
3209 "greater than the maximum supported "
3210 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003211 return false;
3212 }
3213 }
3214 else
3215 {
3216 switch (attachments[i])
3217 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003218 case GL_DEPTH_ATTACHMENT:
3219 case GL_STENCIL_ATTACHMENT:
3220 case GL_DEPTH_STENCIL_ATTACHMENT:
3221 if (defaultFramebuffer)
3222 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003223 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3224 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003225 return false;
3226 }
3227 break;
3228 case GL_COLOR:
3229 case GL_DEPTH:
3230 case GL_STENCIL:
3231 if (!defaultFramebuffer)
3232 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003233 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3234 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003235 return false;
3236 }
3237 break;
3238 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003239 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003240 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003241 }
3242 }
3243 }
3244
3245 return true;
3246}
3247
Austin Kinross6ee1e782015-05-29 17:05:37 -07003248bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3249{
3250 // Note that debug marker calls must not set error state
3251
3252 if (length < 0)
3253 {
3254 return false;
3255 }
3256
3257 if (marker == nullptr)
3258 {
3259 return false;
3260 }
3261
3262 return true;
3263}
3264
3265bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3266{
3267 // Note that debug marker calls must not set error state
3268
3269 if (length < 0)
3270 {
3271 return false;
3272 }
3273
3274 if (length > 0 && marker == nullptr)
3275 {
3276 return false;
3277 }
3278
3279 return true;
3280}
3281
Geoff Langdcab33b2015-07-21 13:03:16 -04003282bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003283 GLenum target,
3284 egl::Image *image)
3285{
Geoff Langa8406172015-07-21 16:53:39 -04003286 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3287 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003288 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003289 return false;
3290 }
3291
3292 switch (target)
3293 {
3294 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003295 if (!context->getExtensions().eglImage)
3296 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003297 context->handleError(InvalidEnum()
3298 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003299 }
3300 break;
3301
3302 case GL_TEXTURE_EXTERNAL_OES:
3303 if (!context->getExtensions().eglImageExternal)
3304 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003305 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3306 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003307 }
Geoff Langa8406172015-07-21 16:53:39 -04003308 break;
3309
3310 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003311 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003312 return false;
3313 }
3314
Jamie Madill61e16b42017-06-19 11:13:23 -04003315 ASSERT(context->getCurrentDisplay());
3316 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003318 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003319 return false;
3320 }
3321
3322 if (image->getSamples() > 0)
3323 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003324 context->handleError(InvalidOperation()
3325 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003326 return false;
3327 }
3328
Geoff Langca271392017-04-05 12:30:00 -04003329 const TextureCaps &textureCaps =
3330 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003331 if (!textureCaps.texturable)
3332 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003333 context->handleError(InvalidOperation()
3334 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003335 return false;
3336 }
3337
Geoff Langdcab33b2015-07-21 13:03:16 -04003338 return true;
3339}
3340
3341bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003342 GLenum target,
3343 egl::Image *image)
3344{
Geoff Langa8406172015-07-21 16:53:39 -04003345 if (!context->getExtensions().eglImage)
3346 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003347 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003348 return false;
3349 }
3350
3351 switch (target)
3352 {
3353 case GL_RENDERBUFFER:
3354 break;
3355
3356 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003357 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003358 return false;
3359 }
3360
Jamie Madill61e16b42017-06-19 11:13:23 -04003361 ASSERT(context->getCurrentDisplay());
3362 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003363 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003364 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003365 return false;
3366 }
3367
Geoff Langca271392017-04-05 12:30:00 -04003368 const TextureCaps &textureCaps =
3369 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003370 if (!textureCaps.renderable)
3371 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003372 context->handleError(InvalidOperation()
3373 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003374 return false;
3375 }
3376
Geoff Langdcab33b2015-07-21 13:03:16 -04003377 return true;
3378}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003379
3380bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3381{
Geoff Lang36167ab2015-12-07 10:27:14 -05003382 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003383 {
3384 // The default VAO should always exist
3385 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003386 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003387 return false;
3388 }
3389
3390 return true;
3391}
3392
Geoff Langc5629752015-12-07 16:29:04 -05003393bool ValidateProgramBinaryBase(Context *context,
3394 GLuint program,
3395 GLenum binaryFormat,
3396 const void *binary,
3397 GLint length)
3398{
3399 Program *programObject = GetValidProgram(context, program);
3400 if (programObject == nullptr)
3401 {
3402 return false;
3403 }
3404
3405 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3406 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3407 programBinaryFormats.end())
3408 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003409 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003410 return false;
3411 }
3412
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003413 if (context->hasActiveTransformFeedback(program))
3414 {
3415 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003416 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3417 "is associated with an active transform "
3418 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003419 return false;
3420 }
3421
Geoff Langc5629752015-12-07 16:29:04 -05003422 return true;
3423}
3424
3425bool ValidateGetProgramBinaryBase(Context *context,
3426 GLuint program,
3427 GLsizei bufSize,
3428 GLsizei *length,
3429 GLenum *binaryFormat,
3430 void *binary)
3431{
3432 Program *programObject = GetValidProgram(context, program);
3433 if (programObject == nullptr)
3434 {
3435 return false;
3436 }
3437
3438 if (!programObject->isLinked())
3439 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003440 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003441 return false;
3442 }
3443
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003444 if (context->getCaps().programBinaryFormats.empty())
3445 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003446 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003447 return false;
3448 }
3449
Geoff Langc5629752015-12-07 16:29:04 -05003450 return true;
3451}
Jamie Madillc29968b2016-01-20 11:17:23 -05003452
Jamie Madillc29968b2016-01-20 11:17:23 -05003453bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3454{
3455 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003456 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003457 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003458 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3459 return false;
3460 }
3461 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3462 {
3463 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003464 return false;
3465 }
3466
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003467 ASSERT(context->getGLState().getDrawFramebuffer());
3468 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003469 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3470
3471 // This should come first before the check for the default frame buffer
3472 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3473 // rather than INVALID_OPERATION
3474 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3475 {
3476 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3477
3478 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003479 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3480 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003481 {
3482 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003483 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3484 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3485 // 3.1 is still a bit ambiguous about the error, but future specs are
3486 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003487 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003488 return false;
3489 }
3490 else if (bufs[colorAttachment] >= maxColorAttachment)
3491 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003492 context->handleError(InvalidOperation()
3493 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003494 return false;
3495 }
3496 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3497 frameBufferId != 0)
3498 {
3499 // INVALID_OPERATION-GL is bound to buffer and ith argument
3500 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003501 context->handleError(InvalidOperation()
3502 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003503 return false;
3504 }
3505 }
3506
3507 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3508 // and n is not 1 or bufs is bound to value other than BACK and NONE
3509 if (frameBufferId == 0)
3510 {
3511 if (n != 1)
3512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003513 context->handleError(InvalidOperation()
3514 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003515 return false;
3516 }
3517
3518 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3519 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003520 context->handleError(
3521 InvalidOperation()
3522 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003523 return false;
3524 }
3525 }
3526
3527 return true;
3528}
3529
Geoff Lang496c02d2016-10-20 11:38:11 -07003530bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003531 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003532 GLenum pname,
3533 GLsizei *length,
3534 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003535{
Geoff Lang496c02d2016-10-20 11:38:11 -07003536 if (length)
3537 {
3538 *length = 0;
3539 }
3540
3541 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3542 {
3543 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003544 InvalidOperation()
3545 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003546 return false;
3547 }
3548
Corentin Wallez336129f2017-10-17 15:55:40 -04003549 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003550 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003551 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003552 return false;
3553 }
3554
Geoff Lang496c02d2016-10-20 11:38:11 -07003555 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003556 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003557 case GL_BUFFER_MAP_POINTER:
3558 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003559
Geoff Lang496c02d2016-10-20 11:38:11 -07003560 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003561 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003562 return false;
3563 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003564
3565 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3566 // target bound to zero generate an INVALID_OPERATION error."
3567 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003568 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003569 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003570 context->handleError(InvalidOperation()
3571 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003572 return false;
3573 }
3574
Geoff Lang496c02d2016-10-20 11:38:11 -07003575 if (length)
3576 {
3577 *length = 1;
3578 }
3579
Olli Etuaho4f667482016-03-30 15:56:35 +03003580 return true;
3581}
3582
Corentin Wallez336129f2017-10-17 15:55:40 -04003583bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003584{
Corentin Wallez336129f2017-10-17 15:55:40 -04003585 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003586 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003587 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
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 == nullptr || !buffer->isMapped())
3594 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003595 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003596 return false;
3597 }
3598
3599 return true;
3600}
3601
3602bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003603 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003604 GLintptr offset,
3605 GLsizeiptr length,
3606 GLbitfield access)
3607{
Corentin Wallez336129f2017-10-17 15:55:40 -04003608 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003609 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003610 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003611 return false;
3612 }
3613
Brandon Jones6cad5662017-06-14 13:25:13 -07003614 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003615 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003616 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3617 return false;
3618 }
3619
3620 if (length < 0)
3621 {
3622 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003623 return false;
3624 }
3625
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003626 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003627
3628 if (!buffer)
3629 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003630 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003631 return false;
3632 }
3633
3634 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003635 CheckedNumeric<size_t> checkedOffset(offset);
3636 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003637
Jamie Madille2e406c2016-06-02 13:04:10 -04003638 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003639 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003640 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003641 return false;
3642 }
3643
3644 // Check for invalid bits in the mask
3645 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3646 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3647 GL_MAP_UNSYNCHRONIZED_BIT;
3648
3649 if (access & ~(allAccessBits))
3650 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003651 context->handleError(InvalidValue()
3652 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003653 return false;
3654 }
3655
3656 if (length == 0)
3657 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003658 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003659 return false;
3660 }
3661
3662 if (buffer->isMapped())
3663 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003664 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003665 return false;
3666 }
3667
3668 // Check for invalid bit combinations
3669 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003671 context->handleError(InvalidOperation()
3672 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003673 return false;
3674 }
3675
3676 GLbitfield writeOnlyBits =
3677 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3678
3679 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3680 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003681 context->handleError(InvalidOperation()
3682 << "Invalid access bits when mapping buffer for reading: 0x"
3683 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003684 return false;
3685 }
3686
3687 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3688 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003689 context->handleError(
3690 InvalidOperation()
3691 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003692 return false;
3693 }
Geoff Lang79f71042017-08-14 16:43:43 -04003694
3695 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003696}
3697
3698bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003699 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003700 GLintptr offset,
3701 GLsizeiptr length)
3702{
Brandon Jones6cad5662017-06-14 13:25:13 -07003703 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003704 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003705 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3706 return false;
3707 }
3708
3709 if (length < 0)
3710 {
3711 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003712 return false;
3713 }
3714
Corentin Wallez336129f2017-10-17 15:55:40 -04003715 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003716 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003717 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003718 return false;
3719 }
3720
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003721 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003722
3723 if (buffer == nullptr)
3724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003725 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003726 return false;
3727 }
3728
3729 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3730 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003731 context->handleError(InvalidOperation()
3732 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003733 return false;
3734 }
3735
3736 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003737 CheckedNumeric<size_t> checkedOffset(offset);
3738 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003739
Jamie Madille2e406c2016-06-02 13:04:10 -04003740 if (!checkedSize.IsValid() ||
3741 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003743 context->handleError(InvalidValue()
3744 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003745 return false;
3746 }
3747
3748 return true;
3749}
3750
Olli Etuaho41997e72016-03-10 13:38:39 +02003751bool ValidateGenOrDelete(Context *context, GLint n)
3752{
3753 if (n < 0)
3754 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003755 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003756 return false;
3757 }
3758 return true;
3759}
3760
Geoff Langff5b2d52016-09-07 11:32:23 -04003761bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3762{
3763 if (!context->getExtensions().robustClientMemory)
3764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003765 context->handleError(InvalidOperation()
3766 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003767 return false;
3768 }
3769
3770 if (bufSize < 0)
3771 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003772 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003773 return false;
3774 }
3775
3776 return true;
3777}
3778
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003779bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3780{
3781 if (bufSize < numParams)
3782 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003783 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3784 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003785 return false;
3786 }
3787
3788 return true;
3789}
3790
Jamie Madillbe849e42017-05-02 15:49:00 -04003791bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3792 GLenum target,
3793 GLenum attachment,
3794 GLenum pname,
3795 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003796{
Geoff Langff5b2d52016-09-07 11:32:23 -04003797 if (!ValidFramebufferTarget(target))
3798 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003799 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003800 return false;
3801 }
3802
3803 int clientVersion = context->getClientMajorVersion();
3804
3805 switch (pname)
3806 {
3807 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3808 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3809 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3810 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3811 break;
3812
Martin Radeve5285d22017-07-14 16:23:53 +03003813 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3814 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3815 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3816 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3817 if (clientVersion < 3 || !context->getExtensions().multiview)
3818 {
3819 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3820 return false;
3821 }
3822 break;
3823
Geoff Langff5b2d52016-09-07 11:32:23 -04003824 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3825 if (clientVersion < 3 && !context->getExtensions().sRGB)
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_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3833 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3834 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3835 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3836 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3837 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3838 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3839 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3840 if (clientVersion < 3)
3841 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003842 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003843 return false;
3844 }
3845 break;
3846
3847 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003848 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003849 return false;
3850 }
3851
3852 // Determine if the attachment is a valid enum
3853 switch (attachment)
3854 {
3855 case GL_BACK:
3856 case GL_FRONT:
3857 case GL_DEPTH:
3858 case GL_STENCIL:
3859 case GL_DEPTH_STENCIL_ATTACHMENT:
3860 if (clientVersion < 3)
3861 {
Geoff Langfa125c92017-10-24 13:01:46 -04003862 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003863 return false;
3864 }
3865 break;
3866
Geoff Langfa125c92017-10-24 13:01:46 -04003867 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003868 case GL_DEPTH_ATTACHMENT:
3869 case GL_STENCIL_ATTACHMENT:
3870 break;
3871
3872 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003873 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3874 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003875 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3876 {
Geoff Langfa125c92017-10-24 13:01:46 -04003877 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003878 return false;
3879 }
3880 break;
3881 }
3882
3883 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3884 ASSERT(framebuffer);
3885
3886 if (framebuffer->id() == 0)
3887 {
3888 if (clientVersion < 3)
3889 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003890 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003891 return false;
3892 }
3893
3894 switch (attachment)
3895 {
3896 case GL_BACK:
3897 case GL_DEPTH:
3898 case GL_STENCIL:
3899 break;
3900
3901 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003902 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003903 return false;
3904 }
3905 }
3906 else
3907 {
3908 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3909 {
3910 // Valid attachment query
3911 }
3912 else
3913 {
3914 switch (attachment)
3915 {
3916 case GL_DEPTH_ATTACHMENT:
3917 case GL_STENCIL_ATTACHMENT:
3918 break;
3919
3920 case GL_DEPTH_STENCIL_ATTACHMENT:
3921 if (!framebuffer->hasValidDepthStencil())
3922 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003923 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003924 return false;
3925 }
3926 break;
3927
3928 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003929 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003930 return false;
3931 }
3932 }
3933 }
3934
3935 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3936 if (attachmentObject)
3937 {
3938 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3939 attachmentObject->type() == GL_TEXTURE ||
3940 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3941
3942 switch (pname)
3943 {
3944 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3945 if (attachmentObject->type() != GL_RENDERBUFFER &&
3946 attachmentObject->type() != GL_TEXTURE)
3947 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003948 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003949 return false;
3950 }
3951 break;
3952
3953 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3954 if (attachmentObject->type() != GL_TEXTURE)
3955 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003956 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003957 return false;
3958 }
3959 break;
3960
3961 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3962 if (attachmentObject->type() != GL_TEXTURE)
3963 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003964 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003965 return false;
3966 }
3967 break;
3968
3969 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3970 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3971 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003972 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003973 return false;
3974 }
3975 break;
3976
3977 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3978 if (attachmentObject->type() != GL_TEXTURE)
3979 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003980 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003981 return false;
3982 }
3983 break;
3984
3985 default:
3986 break;
3987 }
3988 }
3989 else
3990 {
3991 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3992 // is NONE, then querying any other pname will generate INVALID_ENUM.
3993
3994 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3995 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3996 // INVALID_OPERATION for all other pnames
3997
3998 switch (pname)
3999 {
4000 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4001 break;
4002
4003 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4004 if (clientVersion < 3)
4005 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004006 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004007 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004008 return false;
4009 }
4010 break;
4011
4012 default:
4013 if (clientVersion < 3)
4014 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004015 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004016 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004017 return false;
4018 }
4019 else
4020 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004021 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004022 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004023 return false;
4024 }
4025 }
4026 }
4027
Martin Radeve5285d22017-07-14 16:23:53 +03004028 if (numParams)
4029 {
4030 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4031 {
4032 // Only when the viewport offsets are queried we can have a varying number of output
4033 // parameters.
4034 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4035 *numParams = numViews * 2;
4036 }
4037 else
4038 {
4039 // For all other queries we can have only one output parameter.
4040 *numParams = 1;
4041 }
4042 }
4043
Geoff Langff5b2d52016-09-07 11:32:23 -04004044 return true;
4045}
4046
4047bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4048 GLenum target,
4049 GLenum attachment,
4050 GLenum pname,
4051 GLsizei bufSize,
4052 GLsizei *numParams)
4053{
4054 if (!ValidateRobustEntryPoint(context, bufSize))
4055 {
4056 return false;
4057 }
4058
Jamie Madillbe849e42017-05-02 15:49:00 -04004059 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4060 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004061 {
4062 return false;
4063 }
4064
4065 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4066 {
4067 return false;
4068 }
4069
4070 return true;
4071}
4072
Geoff Langff5b2d52016-09-07 11:32:23 -04004073bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004074 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004075 GLenum pname,
4076 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004077 GLsizei *length,
4078 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004079{
4080 if (!ValidateRobustEntryPoint(context, bufSize))
4081 {
4082 return false;
4083 }
4084
Geoff Langebebe1c2016-10-14 12:01:31 -04004085 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004086 {
4087 return false;
4088 }
4089
Geoff Langebebe1c2016-10-14 12:01:31 -04004090 if (!ValidateRobustBufferSize(context, bufSize, *length))
4091 {
4092 return false;
4093 }
4094
4095 return true;
4096}
4097
Geoff Langebebe1c2016-10-14 12:01:31 -04004098bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004099 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004100 GLenum pname,
4101 GLsizei bufSize,
4102 GLsizei *length,
4103 GLint64 *params)
4104{
4105 if (!ValidateRobustEntryPoint(context, bufSize))
4106 {
4107 return false;
4108 }
4109
4110 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4111 {
4112 return false;
4113 }
4114
4115 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004116 {
4117 return false;
4118 }
4119
4120 return true;
4121}
4122
Jamie Madillbe849e42017-05-02 15:49:00 -04004123bool ValidateGetProgramivBase(ValidationContext *context,
4124 GLuint program,
4125 GLenum pname,
4126 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004127{
4128 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004129 if (numParams)
4130 {
4131 *numParams = 1;
4132 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004133
4134 Program *programObject = GetValidProgram(context, program);
4135 if (!programObject)
4136 {
4137 return false;
4138 }
4139
4140 switch (pname)
4141 {
4142 case GL_DELETE_STATUS:
4143 case GL_LINK_STATUS:
4144 case GL_VALIDATE_STATUS:
4145 case GL_INFO_LOG_LENGTH:
4146 case GL_ATTACHED_SHADERS:
4147 case GL_ACTIVE_ATTRIBUTES:
4148 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4149 case GL_ACTIVE_UNIFORMS:
4150 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4151 break;
4152
4153 case GL_PROGRAM_BINARY_LENGTH:
4154 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4155 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004156 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4157 "requires GL_OES_get_program_binary or "
4158 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004159 return false;
4160 }
4161 break;
4162
4163 case GL_ACTIVE_UNIFORM_BLOCKS:
4164 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4165 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4166 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4167 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4168 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4169 if (context->getClientMajorVersion() < 3)
4170 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004171 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004172 return false;
4173 }
4174 break;
4175
Yunchao He61afff12017-03-14 15:34:03 +08004176 case GL_PROGRAM_SEPARABLE:
Xinghua Cao971f8502017-10-17 13:01:24 +08004177 case GL_COMPUTE_WORK_GROUP_SIZE:
jchen1058f67be2017-10-27 08:59:27 +08004178 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004179 if (context->getClientVersion() < Version(3, 1))
4180 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004181 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004182 return false;
4183 }
4184 break;
4185
Geoff Langff5b2d52016-09-07 11:32:23 -04004186 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004187 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004188 return false;
4189 }
4190
4191 return true;
4192}
4193
4194bool ValidateGetProgramivRobustANGLE(Context *context,
4195 GLuint program,
4196 GLenum pname,
4197 GLsizei bufSize,
4198 GLsizei *numParams)
4199{
4200 if (!ValidateRobustEntryPoint(context, bufSize))
4201 {
4202 return false;
4203 }
4204
Jamie Madillbe849e42017-05-02 15:49:00 -04004205 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004206 {
4207 return false;
4208 }
4209
4210 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4211 {
4212 return false;
4213 }
4214
4215 return true;
4216}
4217
Geoff Lang740d9022016-10-07 11:20:52 -04004218bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4219 GLenum target,
4220 GLenum pname,
4221 GLsizei bufSize,
4222 GLsizei *length,
4223 GLint *params)
4224{
4225 if (!ValidateRobustEntryPoint(context, bufSize))
4226 {
4227 return false;
4228 }
4229
4230 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4231 {
4232 return false;
4233 }
4234
4235 if (!ValidateRobustBufferSize(context, bufSize, *length))
4236 {
4237 return false;
4238 }
4239
4240 return true;
4241}
4242
Geoff Langd7d0ed32016-10-07 11:33:51 -04004243bool ValidateGetShaderivRobustANGLE(Context *context,
4244 GLuint shader,
4245 GLenum pname,
4246 GLsizei bufSize,
4247 GLsizei *length,
4248 GLint *params)
4249{
4250 if (!ValidateRobustEntryPoint(context, bufSize))
4251 {
4252 return false;
4253 }
4254
4255 if (!ValidateGetShaderivBase(context, shader, pname, length))
4256 {
4257 return false;
4258 }
4259
4260 if (!ValidateRobustBufferSize(context, bufSize, *length))
4261 {
4262 return false;
4263 }
4264
4265 return true;
4266}
4267
Geoff Langc1984ed2016-10-07 12:41:00 -04004268bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4269 GLenum target,
4270 GLenum pname,
4271 GLsizei bufSize,
4272 GLsizei *length,
4273 GLfloat *params)
4274{
4275 if (!ValidateRobustEntryPoint(context, bufSize))
4276 {
4277 return false;
4278 }
4279
4280 if (!ValidateGetTexParameterBase(context, target, pname, length))
4281 {
4282 return false;
4283 }
4284
4285 if (!ValidateRobustBufferSize(context, bufSize, *length))
4286 {
4287 return false;
4288 }
4289
4290 return true;
4291}
4292
Geoff Langc1984ed2016-10-07 12:41:00 -04004293bool ValidateGetTexParameterivRobustANGLE(Context *context,
4294 GLenum target,
4295 GLenum pname,
4296 GLsizei bufSize,
4297 GLsizei *length,
4298 GLint *params)
4299{
4300 if (!ValidateRobustEntryPoint(context, bufSize))
4301 {
4302 return false;
4303 }
4304
4305 if (!ValidateGetTexParameterBase(context, target, pname, length))
4306 {
4307 return false;
4308 }
4309
4310 if (!ValidateRobustBufferSize(context, bufSize, *length))
4311 {
4312 return false;
4313 }
4314
4315 return true;
4316}
4317
Geoff Langc1984ed2016-10-07 12:41:00 -04004318bool ValidateTexParameterfvRobustANGLE(Context *context,
4319 GLenum target,
4320 GLenum pname,
4321 GLsizei bufSize,
4322 const GLfloat *params)
4323{
4324 if (!ValidateRobustEntryPoint(context, bufSize))
4325 {
4326 return false;
4327 }
4328
4329 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4330}
4331
Geoff Langc1984ed2016-10-07 12:41:00 -04004332bool ValidateTexParameterivRobustANGLE(Context *context,
4333 GLenum target,
4334 GLenum pname,
4335 GLsizei bufSize,
4336 const GLint *params)
4337{
4338 if (!ValidateRobustEntryPoint(context, bufSize))
4339 {
4340 return false;
4341 }
4342
4343 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4344}
4345
Geoff Langc1984ed2016-10-07 12:41:00 -04004346bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4347 GLuint sampler,
4348 GLenum pname,
4349 GLuint bufSize,
4350 GLsizei *length,
4351 GLfloat *params)
4352{
4353 if (!ValidateRobustEntryPoint(context, bufSize))
4354 {
4355 return false;
4356 }
4357
4358 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4359 {
4360 return false;
4361 }
4362
4363 if (!ValidateRobustBufferSize(context, bufSize, *length))
4364 {
4365 return false;
4366 }
4367
4368 return true;
4369}
4370
Geoff Langc1984ed2016-10-07 12:41:00 -04004371bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4372 GLuint sampler,
4373 GLenum pname,
4374 GLuint bufSize,
4375 GLsizei *length,
4376 GLint *params)
4377{
4378 if (!ValidateRobustEntryPoint(context, bufSize))
4379 {
4380 return false;
4381 }
4382
4383 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4384 {
4385 return false;
4386 }
4387
4388 if (!ValidateRobustBufferSize(context, bufSize, *length))
4389 {
4390 return false;
4391 }
4392
4393 return true;
4394}
4395
Geoff Langc1984ed2016-10-07 12:41:00 -04004396bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4397 GLuint sampler,
4398 GLenum pname,
4399 GLsizei bufSize,
4400 const GLfloat *params)
4401{
4402 if (!ValidateRobustEntryPoint(context, bufSize))
4403 {
4404 return false;
4405 }
4406
4407 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4408}
4409
Geoff Langc1984ed2016-10-07 12:41:00 -04004410bool ValidateSamplerParameterivRobustANGLE(Context *context,
4411 GLuint sampler,
4412 GLenum pname,
4413 GLsizei bufSize,
4414 const GLint *params)
4415{
4416 if (!ValidateRobustEntryPoint(context, bufSize))
4417 {
4418 return false;
4419 }
4420
4421 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4422}
4423
Geoff Lang0b031062016-10-13 14:30:04 -04004424bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4425 GLuint index,
4426 GLenum pname,
4427 GLsizei bufSize,
4428 GLsizei *length,
4429 GLfloat *params)
4430{
4431 if (!ValidateRobustEntryPoint(context, bufSize))
4432 {
4433 return false;
4434 }
4435
4436 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4437 {
4438 return false;
4439 }
4440
4441 if (!ValidateRobustBufferSize(context, bufSize, *length))
4442 {
4443 return false;
4444 }
4445
4446 return true;
4447}
4448
Geoff Lang0b031062016-10-13 14:30:04 -04004449bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4450 GLuint index,
4451 GLenum pname,
4452 GLsizei bufSize,
4453 GLsizei *length,
4454 GLint *params)
4455{
4456 if (!ValidateRobustEntryPoint(context, bufSize))
4457 {
4458 return false;
4459 }
4460
4461 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4462 {
4463 return false;
4464 }
4465
4466 if (!ValidateRobustBufferSize(context, bufSize, *length))
4467 {
4468 return false;
4469 }
4470
4471 return true;
4472}
4473
Geoff Lang0b031062016-10-13 14:30:04 -04004474bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4475 GLuint index,
4476 GLenum pname,
4477 GLsizei bufSize,
4478 GLsizei *length,
4479 void **pointer)
4480{
4481 if (!ValidateRobustEntryPoint(context, bufSize))
4482 {
4483 return false;
4484 }
4485
4486 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4487 {
4488 return false;
4489 }
4490
4491 if (!ValidateRobustBufferSize(context, bufSize, *length))
4492 {
4493 return false;
4494 }
4495
4496 return true;
4497}
4498
Geoff Lang0b031062016-10-13 14:30:04 -04004499bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4500 GLuint index,
4501 GLenum pname,
4502 GLsizei bufSize,
4503 GLsizei *length,
4504 GLint *params)
4505{
4506 if (!ValidateRobustEntryPoint(context, bufSize))
4507 {
4508 return false;
4509 }
4510
4511 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4512 {
4513 return false;
4514 }
4515
4516 if (!ValidateRobustBufferSize(context, bufSize, *length))
4517 {
4518 return false;
4519 }
4520
4521 return true;
4522}
4523
Geoff Lang0b031062016-10-13 14:30:04 -04004524bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4525 GLuint index,
4526 GLenum pname,
4527 GLsizei bufSize,
4528 GLsizei *length,
4529 GLuint *params)
4530{
4531 if (!ValidateRobustEntryPoint(context, bufSize))
4532 {
4533 return false;
4534 }
4535
4536 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4537 {
4538 return false;
4539 }
4540
4541 if (!ValidateRobustBufferSize(context, bufSize, *length))
4542 {
4543 return false;
4544 }
4545
4546 return true;
4547}
4548
Geoff Lang6899b872016-10-14 11:30:13 -04004549bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4550 GLuint program,
4551 GLuint uniformBlockIndex,
4552 GLenum pname,
4553 GLsizei bufSize,
4554 GLsizei *length,
4555 GLint *params)
4556{
4557 if (!ValidateRobustEntryPoint(context, bufSize))
4558 {
4559 return false;
4560 }
4561
4562 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4563 {
4564 return false;
4565 }
4566
4567 if (!ValidateRobustBufferSize(context, bufSize, *length))
4568 {
4569 return false;
4570 }
4571
4572 return true;
4573}
4574
Geoff Lang0a9661f2016-10-20 10:59:20 -07004575bool ValidateGetInternalFormativRobustANGLE(Context *context,
4576 GLenum target,
4577 GLenum internalformat,
4578 GLenum pname,
4579 GLsizei bufSize,
4580 GLsizei *length,
4581 GLint *params)
4582{
4583 if (!ValidateRobustEntryPoint(context, bufSize))
4584 {
4585 return false;
4586 }
4587
4588 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4589 {
4590 return false;
4591 }
4592
4593 if (!ValidateRobustBufferSize(context, bufSize, *length))
4594 {
4595 return false;
4596 }
4597
4598 return true;
4599}
4600
Shao80957d92017-02-20 21:25:59 +08004601bool ValidateVertexFormatBase(ValidationContext *context,
4602 GLuint attribIndex,
4603 GLint size,
4604 GLenum type,
4605 GLboolean pureInteger)
4606{
4607 const Caps &caps = context->getCaps();
4608 if (attribIndex >= caps.maxVertexAttributes)
4609 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004610 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004611 return false;
4612 }
4613
4614 if (size < 1 || size > 4)
4615 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004616 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004617 return false;
Shao80957d92017-02-20 21:25:59 +08004618 }
4619
4620 switch (type)
4621 {
4622 case GL_BYTE:
4623 case GL_UNSIGNED_BYTE:
4624 case GL_SHORT:
4625 case GL_UNSIGNED_SHORT:
4626 break;
4627
4628 case GL_INT:
4629 case GL_UNSIGNED_INT:
4630 if (context->getClientMajorVersion() < 3)
4631 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004632 context->handleError(InvalidEnum()
4633 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004634 return false;
4635 }
4636 break;
4637
4638 case GL_FIXED:
4639 case GL_FLOAT:
4640 if (pureInteger)
4641 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004642 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004643 return false;
4644 }
4645 break;
4646
4647 case GL_HALF_FLOAT:
4648 if (context->getClientMajorVersion() < 3)
4649 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004650 context->handleError(InvalidEnum()
4651 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004652 return false;
4653 }
4654 if (pureInteger)
4655 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004656 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004657 return false;
4658 }
4659 break;
4660
4661 case GL_INT_2_10_10_10_REV:
4662 case GL_UNSIGNED_INT_2_10_10_10_REV:
4663 if (context->getClientMajorVersion() < 3)
4664 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004665 context->handleError(InvalidEnum()
4666 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004667 return false;
4668 }
4669 if (pureInteger)
4670 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004671 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004672 return false;
4673 }
4674 if (size != 4)
4675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004676 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4677 "UNSIGNED_INT_2_10_10_10_REV and "
4678 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004679 return false;
4680 }
4681 break;
4682
4683 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004684 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004685 return false;
4686 }
4687
4688 return true;
4689}
4690
Geoff Lang76e65652017-03-27 14:58:02 -04004691// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4692// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4693// specified clear value and the type of a buffer that is being cleared generates an
4694// INVALID_OPERATION error instead of producing undefined results
4695bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4696 GLint drawbuffer,
4697 const GLenum *validComponentTypes,
4698 size_t validComponentTypeCount)
4699{
4700 const FramebufferAttachment *attachment =
4701 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4702 if (attachment)
4703 {
4704 GLenum componentType = attachment->getFormat().info->componentType;
4705 const GLenum *end = validComponentTypes + validComponentTypeCount;
4706 if (std::find(validComponentTypes, end, componentType) == end)
4707 {
4708 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004709 InvalidOperation()
4710 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004711 return false;
4712 }
4713 }
4714
4715 return true;
4716}
4717
Corentin Wallezb2931602017-04-11 15:58:57 -04004718bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4719 GLsizei imageSize,
4720 GLsizei dataSize)
4721{
4722 if (!ValidateRobustEntryPoint(context, dataSize))
4723 {
4724 return false;
4725 }
4726
Corentin Wallez336129f2017-10-17 15:55:40 -04004727 gl::Buffer *pixelUnpackBuffer =
4728 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004729 if (pixelUnpackBuffer == nullptr)
4730 {
4731 if (dataSize < imageSize)
4732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004733 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004734 }
4735 }
4736 return true;
4737}
4738
Jamie Madillbe849e42017-05-02 15:49:00 -04004739bool ValidateGetBufferParameterBase(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004740 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004741 GLenum pname,
4742 bool pointerVersion,
4743 GLsizei *numParams)
4744{
4745 if (numParams)
4746 {
4747 *numParams = 0;
4748 }
4749
Corentin Wallez336129f2017-10-17 15:55:40 -04004750 if (!ValidBufferType(context, target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004751 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004752 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004753 return false;
4754 }
4755
4756 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4757 if (!buffer)
4758 {
4759 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004760 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004761 return false;
4762 }
4763
4764 const Extensions &extensions = context->getExtensions();
4765
4766 switch (pname)
4767 {
4768 case GL_BUFFER_USAGE:
4769 case GL_BUFFER_SIZE:
4770 break;
4771
4772 case GL_BUFFER_ACCESS_OES:
4773 if (!extensions.mapBuffer)
4774 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004775 context->handleError(InvalidEnum()
4776 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004777 return false;
4778 }
4779 break;
4780
4781 case GL_BUFFER_MAPPED:
4782 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4783 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4784 !extensions.mapBufferRange)
4785 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004786 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4787 "GL_OES_mapbuffer or "
4788 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004789 return false;
4790 }
4791 break;
4792
4793 case GL_BUFFER_MAP_POINTER:
4794 if (!pointerVersion)
4795 {
4796 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004797 InvalidEnum()
4798 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004799 return false;
4800 }
4801 break;
4802
4803 case GL_BUFFER_ACCESS_FLAGS:
4804 case GL_BUFFER_MAP_OFFSET:
4805 case GL_BUFFER_MAP_LENGTH:
4806 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4807 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004808 context->handleError(InvalidEnum()
4809 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004810 return false;
4811 }
4812 break;
4813
4814 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004815 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004816 return false;
4817 }
4818
4819 // All buffer parameter queries return one value.
4820 if (numParams)
4821 {
4822 *numParams = 1;
4823 }
4824
4825 return true;
4826}
4827
4828bool ValidateGetRenderbufferParameterivBase(Context *context,
4829 GLenum target,
4830 GLenum pname,
4831 GLsizei *length)
4832{
4833 if (length)
4834 {
4835 *length = 0;
4836 }
4837
4838 if (target != GL_RENDERBUFFER)
4839 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004840 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004841 return false;
4842 }
4843
4844 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4845 if (renderbuffer == nullptr)
4846 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004847 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004848 return false;
4849 }
4850
4851 switch (pname)
4852 {
4853 case GL_RENDERBUFFER_WIDTH:
4854 case GL_RENDERBUFFER_HEIGHT:
4855 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4856 case GL_RENDERBUFFER_RED_SIZE:
4857 case GL_RENDERBUFFER_GREEN_SIZE:
4858 case GL_RENDERBUFFER_BLUE_SIZE:
4859 case GL_RENDERBUFFER_ALPHA_SIZE:
4860 case GL_RENDERBUFFER_DEPTH_SIZE:
4861 case GL_RENDERBUFFER_STENCIL_SIZE:
4862 break;
4863
4864 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4865 if (!context->getExtensions().framebufferMultisample)
4866 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004867 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004868 return false;
4869 }
4870 break;
4871
4872 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004873 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004874 return false;
4875 }
4876
4877 if (length)
4878 {
4879 *length = 1;
4880 }
4881 return true;
4882}
4883
4884bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4885{
4886 if (length)
4887 {
4888 *length = 0;
4889 }
4890
4891 if (GetValidShader(context, shader) == nullptr)
4892 {
4893 return false;
4894 }
4895
4896 switch (pname)
4897 {
4898 case GL_SHADER_TYPE:
4899 case GL_DELETE_STATUS:
4900 case GL_COMPILE_STATUS:
4901 case GL_INFO_LOG_LENGTH:
4902 case GL_SHADER_SOURCE_LENGTH:
4903 break;
4904
4905 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4906 if (!context->getExtensions().translatedShaderSource)
4907 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004908 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004909 return false;
4910 }
4911 break;
4912
4913 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004914 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004915 return false;
4916 }
4917
4918 if (length)
4919 {
4920 *length = 1;
4921 }
4922 return true;
4923}
4924
4925bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4926{
4927 if (length)
4928 {
4929 *length = 0;
4930 }
4931
4932 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4933 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004934 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004935 return false;
4936 }
4937
4938 if (context->getTargetTexture(target) == nullptr)
4939 {
4940 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004941 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004942 return false;
4943 }
4944
4945 switch (pname)
4946 {
4947 case GL_TEXTURE_MAG_FILTER:
4948 case GL_TEXTURE_MIN_FILTER:
4949 case GL_TEXTURE_WRAP_S:
4950 case GL_TEXTURE_WRAP_T:
4951 break;
4952
4953 case GL_TEXTURE_USAGE_ANGLE:
4954 if (!context->getExtensions().textureUsage)
4955 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004956 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004957 return false;
4958 }
4959 break;
4960
4961 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4962 if (!context->getExtensions().textureFilterAnisotropic)
4963 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004964 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004965 return false;
4966 }
4967 break;
4968
4969 case GL_TEXTURE_IMMUTABLE_FORMAT:
4970 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4971 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004972 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004973 return false;
4974 }
4975 break;
4976
4977 case GL_TEXTURE_WRAP_R:
4978 case GL_TEXTURE_IMMUTABLE_LEVELS:
4979 case GL_TEXTURE_SWIZZLE_R:
4980 case GL_TEXTURE_SWIZZLE_G:
4981 case GL_TEXTURE_SWIZZLE_B:
4982 case GL_TEXTURE_SWIZZLE_A:
4983 case GL_TEXTURE_BASE_LEVEL:
4984 case GL_TEXTURE_MAX_LEVEL:
4985 case GL_TEXTURE_MIN_LOD:
4986 case GL_TEXTURE_MAX_LOD:
4987 case GL_TEXTURE_COMPARE_MODE:
4988 case GL_TEXTURE_COMPARE_FUNC:
4989 if (context->getClientMajorVersion() < 3)
4990 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004991 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004992 return false;
4993 }
4994 break;
4995
4996 case GL_TEXTURE_SRGB_DECODE_EXT:
4997 if (!context->getExtensions().textureSRGBDecode)
4998 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004999 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005000 return false;
5001 }
5002 break;
5003
5004 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005005 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005006 return false;
5007 }
5008
5009 if (length)
5010 {
5011 *length = 1;
5012 }
5013 return true;
5014}
5015
5016bool ValidateGetVertexAttribBase(Context *context,
5017 GLuint index,
5018 GLenum pname,
5019 GLsizei *length,
5020 bool pointer,
5021 bool pureIntegerEntryPoint)
5022{
5023 if (length)
5024 {
5025 *length = 0;
5026 }
5027
5028 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5029 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005030 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005031 return false;
5032 }
5033
5034 if (index >= context->getCaps().maxVertexAttributes)
5035 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005036 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005037 return false;
5038 }
5039
5040 if (pointer)
5041 {
5042 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5043 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005044 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005045 return false;
5046 }
5047 }
5048 else
5049 {
5050 switch (pname)
5051 {
5052 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5053 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5054 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5055 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5056 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5057 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5058 case GL_CURRENT_VERTEX_ATTRIB:
5059 break;
5060
5061 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5062 static_assert(
5063 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5064 "ANGLE extension enums not equal to GL enums.");
5065 if (context->getClientMajorVersion() < 3 &&
5066 !context->getExtensions().instancedArrays)
5067 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005068 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5069 "requires OpenGL ES 3.0 or "
5070 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005071 return false;
5072 }
5073 break;
5074
5075 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5076 if (context->getClientMajorVersion() < 3)
5077 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005078 context->handleError(
5079 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005080 return false;
5081 }
5082 break;
5083
5084 case GL_VERTEX_ATTRIB_BINDING:
5085 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5086 if (context->getClientVersion() < ES_3_1)
5087 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005088 context->handleError(InvalidEnum()
5089 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005090 return false;
5091 }
5092 break;
5093
5094 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005095 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005096 return false;
5097 }
5098 }
5099
5100 if (length)
5101 {
5102 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5103 {
5104 *length = 4;
5105 }
5106 else
5107 {
5108 *length = 1;
5109 }
5110 }
5111
5112 return true;
5113}
5114
Jamie Madill4928b7c2017-06-20 12:57:39 -04005115bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005116 GLint x,
5117 GLint y,
5118 GLsizei width,
5119 GLsizei height,
5120 GLenum format,
5121 GLenum type,
5122 GLsizei bufSize,
5123 GLsizei *length,
5124 GLsizei *columns,
5125 GLsizei *rows,
5126 void *pixels)
5127{
5128 if (length != nullptr)
5129 {
5130 *length = 0;
5131 }
5132 if (rows != nullptr)
5133 {
5134 *rows = 0;
5135 }
5136 if (columns != nullptr)
5137 {
5138 *columns = 0;
5139 }
5140
5141 if (width < 0 || height < 0)
5142 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005143 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005144 return false;
5145 }
5146
5147 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5148
5149 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5150 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005151 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005152 return false;
5153 }
5154
5155 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5156 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005157 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005158 return false;
5159 }
5160
5161 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5162 ASSERT(framebuffer);
5163
5164 if (framebuffer->getReadBufferState() == GL_NONE)
5165 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005166 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005167 return false;
5168 }
5169
5170 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5171 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5172 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5173 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5174 // situation is an application error that would lead to a crash in ANGLE.
5175 if (readBuffer == nullptr)
5176 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005177 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005178 return false;
5179 }
5180
Martin Radev28031682017-07-28 14:47:56 +03005181 // ANGLE_multiview, Revision 1:
5182 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5183 // current read framebuffer is not NONE.
5184 if (readBuffer->getMultiviewLayout() != GL_NONE)
5185 {
5186 context->handleError(InvalidFramebufferOperation()
5187 << "Attempting to read from a multi-view framebuffer.");
5188 return false;
5189 }
5190
Geoff Lang280ba992017-04-18 16:30:58 -04005191 if (context->getExtensions().webglCompatibility)
5192 {
5193 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5194 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5195 // and type before validating the combination of format and type. However, the
5196 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5197 // verifies that GL_INVALID_OPERATION is generated.
5198 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5199 // dEQP/WebGL.
5200 if (!ValidReadPixelsFormatEnum(context, format))
5201 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005202 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005203 return false;
5204 }
5205
5206 if (!ValidReadPixelsTypeEnum(context, type))
5207 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005208 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005209 return false;
5210 }
5211 }
5212
Jamie Madill4928b7c2017-06-20 12:57:39 -04005213 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5214 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005215 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5216
5217 bool validFormatTypeCombination =
5218 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5219
5220 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5221 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005222 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005223 return false;
5224 }
5225
5226 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005227 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005228 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5229 {
5230 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005231 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005232 return false;
5233 }
5234
5235 // .. the data would be packed to the buffer object such that the memory writes required
5236 // would exceed the data store size.
5237 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5238 const gl::Extents size(width, height, 1);
5239 const auto &pack = context->getGLState().getPackState();
5240
5241 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5242 if (endByteOrErr.isError())
5243 {
5244 context->handleError(endByteOrErr.getError());
5245 return false;
5246 }
5247
5248 size_t endByte = endByteOrErr.getResult();
5249 if (bufSize >= 0)
5250 {
5251 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5252 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005253 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005254 return false;
5255 }
5256 }
5257
5258 if (pixelPackBuffer != nullptr)
5259 {
5260 CheckedNumeric<size_t> checkedEndByte(endByte);
5261 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5262 checkedEndByte += checkedOffset;
5263
5264 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5265 {
5266 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005267 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005268 return false;
5269 }
5270 }
5271
5272 if (pixelPackBuffer == nullptr && length != nullptr)
5273 {
5274 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5275 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005276 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005277 return false;
5278 }
5279
5280 *length = static_cast<GLsizei>(endByte);
5281 }
5282
5283 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5284 angle::CheckedNumeric<int> clippedExtent(length);
5285 if (start < 0)
5286 {
5287 // "subtract" the area that is less than 0
5288 clippedExtent += start;
5289 }
5290
5291 const int readExtent = start + length;
5292 if (readExtent > bufferSize)
5293 {
5294 // Subtract the region to the right of the read buffer
5295 clippedExtent -= (readExtent - bufferSize);
5296 }
5297
5298 if (!clippedExtent.IsValid())
5299 {
5300 return 0;
5301 }
5302
5303 return std::max(clippedExtent.ValueOrDie(), 0);
5304 };
5305
5306 if (columns != nullptr)
5307 {
5308 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5309 }
5310
5311 if (rows != nullptr)
5312 {
5313 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5314 }
5315
5316 return true;
5317}
5318
5319template <typename ParamType>
5320bool ValidateTexParameterBase(Context *context,
5321 GLenum target,
5322 GLenum pname,
5323 GLsizei bufSize,
5324 const ParamType *params)
5325{
5326 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5327 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005328 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005329 return false;
5330 }
5331
5332 if (context->getTargetTexture(target) == nullptr)
5333 {
5334 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005335 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005336 return false;
5337 }
5338
5339 const GLsizei minBufSize = 1;
5340 if (bufSize >= 0 && bufSize < minBufSize)
5341 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005342 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005343 return false;
5344 }
5345
5346 switch (pname)
5347 {
5348 case GL_TEXTURE_WRAP_R:
5349 case GL_TEXTURE_SWIZZLE_R:
5350 case GL_TEXTURE_SWIZZLE_G:
5351 case GL_TEXTURE_SWIZZLE_B:
5352 case GL_TEXTURE_SWIZZLE_A:
5353 case GL_TEXTURE_BASE_LEVEL:
5354 case GL_TEXTURE_MAX_LEVEL:
5355 case GL_TEXTURE_COMPARE_MODE:
5356 case GL_TEXTURE_COMPARE_FUNC:
5357 case GL_TEXTURE_MIN_LOD:
5358 case GL_TEXTURE_MAX_LOD:
5359 if (context->getClientMajorVersion() < 3)
5360 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005361 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005362 return false;
5363 }
5364 if (target == GL_TEXTURE_EXTERNAL_OES &&
5365 !context->getExtensions().eglImageExternalEssl3)
5366 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005367 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5368 "available without "
5369 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005370 return false;
5371 }
5372 break;
5373
5374 default:
5375 break;
5376 }
5377
JiangYizhou4cff8d62017-07-06 14:54:09 +08005378 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5379 {
5380 switch (pname)
5381 {
5382 case GL_TEXTURE_MIN_FILTER:
5383 case GL_TEXTURE_MAG_FILTER:
5384 case GL_TEXTURE_WRAP_S:
5385 case GL_TEXTURE_WRAP_T:
5386 case GL_TEXTURE_WRAP_R:
5387 case GL_TEXTURE_MIN_LOD:
5388 case GL_TEXTURE_MAX_LOD:
5389 case GL_TEXTURE_COMPARE_MODE:
5390 case GL_TEXTURE_COMPARE_FUNC:
5391 context->handleError(InvalidEnum()
5392 << "Invalid parameter for 2D multisampled textures.");
5393 return false;
5394 }
5395 }
5396
Jamie Madillbe849e42017-05-02 15:49:00 -04005397 switch (pname)
5398 {
5399 case GL_TEXTURE_WRAP_S:
5400 case GL_TEXTURE_WRAP_T:
5401 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005402 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005403 bool restrictedWrapModes =
5404 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5405 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5406 {
5407 return false;
5408 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005409 }
5410 break;
5411
5412 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005413 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005414 bool restrictedMinFilter =
5415 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5416 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5417 {
5418 return false;
5419 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005420 }
5421 break;
5422
5423 case GL_TEXTURE_MAG_FILTER:
5424 if (!ValidateTextureMagFilterValue(context, params))
5425 {
5426 return false;
5427 }
5428 break;
5429
5430 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005431 if (!context->getExtensions().textureUsage)
5432 {
5433 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5434 return false;
5435 }
5436
Jamie Madillbe849e42017-05-02 15:49:00 -04005437 switch (ConvertToGLenum(params[0]))
5438 {
5439 case GL_NONE:
5440 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5441 break;
5442
5443 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005444 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005445 return false;
5446 }
5447 break;
5448
5449 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5450 if (!context->getExtensions().textureFilterAnisotropic)
5451 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005452 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005453 return false;
5454 }
5455
5456 // we assume the parameter passed to this validation method is truncated, not rounded
5457 if (params[0] < 1)
5458 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005459 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005460 return false;
5461 }
5462 break;
5463
5464 case GL_TEXTURE_MIN_LOD:
5465 case GL_TEXTURE_MAX_LOD:
5466 // any value is permissible
5467 break;
5468
5469 case GL_TEXTURE_COMPARE_MODE:
5470 if (!ValidateTextureCompareModeValue(context, params))
5471 {
5472 return false;
5473 }
5474 break;
5475
5476 case GL_TEXTURE_COMPARE_FUNC:
5477 if (!ValidateTextureCompareFuncValue(context, params))
5478 {
5479 return false;
5480 }
5481 break;
5482
5483 case GL_TEXTURE_SWIZZLE_R:
5484 case GL_TEXTURE_SWIZZLE_G:
5485 case GL_TEXTURE_SWIZZLE_B:
5486 case GL_TEXTURE_SWIZZLE_A:
5487 switch (ConvertToGLenum(params[0]))
5488 {
5489 case GL_RED:
5490 case GL_GREEN:
5491 case GL_BLUE:
5492 case GL_ALPHA:
5493 case GL_ZERO:
5494 case GL_ONE:
5495 break;
5496
5497 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005498 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005499 return false;
5500 }
5501 break;
5502
5503 case GL_TEXTURE_BASE_LEVEL:
5504 if (params[0] < 0)
5505 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005506 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005507 return false;
5508 }
5509 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5510 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005511 context->handleError(InvalidOperation()
5512 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005513 return false;
5514 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005515 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5516 {
5517 context->handleError(InvalidOperation()
5518 << "Base level must be 0 for multisampled textures.");
5519 return false;
5520 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005521 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5522 {
5523 context->handleError(InvalidOperation()
5524 << "Base level must be 0 for rectangle textures.");
5525 return false;
5526 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005527 break;
5528
5529 case GL_TEXTURE_MAX_LEVEL:
5530 if (params[0] < 0)
5531 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005532 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005533 return false;
5534 }
5535 break;
5536
5537 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5538 if (context->getClientVersion() < Version(3, 1))
5539 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005540 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005541 return false;
5542 }
5543 switch (ConvertToGLenum(params[0]))
5544 {
5545 case GL_DEPTH_COMPONENT:
5546 case GL_STENCIL_INDEX:
5547 break;
5548
5549 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005550 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005551 return false;
5552 }
5553 break;
5554
5555 case GL_TEXTURE_SRGB_DECODE_EXT:
5556 if (!ValidateTextureSRGBDecodeValue(context, params))
5557 {
5558 return false;
5559 }
5560 break;
5561
5562 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005563 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005564 return false;
5565 }
5566
5567 return true;
5568}
5569
5570template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5571template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5572
Jamie Madill12e957f2017-08-26 21:42:26 -04005573bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5574{
5575 if (index >= MAX_VERTEX_ATTRIBS)
5576 {
5577 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5578 return false;
5579 }
5580
5581 return true;
5582}
5583
5584bool ValidateGetActiveUniformBlockivBase(Context *context,
5585 GLuint program,
5586 GLuint uniformBlockIndex,
5587 GLenum pname,
5588 GLsizei *length)
5589{
5590 if (length)
5591 {
5592 *length = 0;
5593 }
5594
5595 if (context->getClientMajorVersion() < 3)
5596 {
5597 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5598 return false;
5599 }
5600
5601 Program *programObject = GetValidProgram(context, program);
5602 if (!programObject)
5603 {
5604 return false;
5605 }
5606
5607 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5608 {
5609 context->handleError(InvalidValue()
5610 << "uniformBlockIndex exceeds active uniform block count.");
5611 return false;
5612 }
5613
5614 switch (pname)
5615 {
5616 case GL_UNIFORM_BLOCK_BINDING:
5617 case GL_UNIFORM_BLOCK_DATA_SIZE:
5618 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5619 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5620 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5621 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5622 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5623 break;
5624
5625 default:
5626 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5627 return false;
5628 }
5629
5630 if (length)
5631 {
5632 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5633 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005634 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005635 programObject->getUniformBlockByIndex(uniformBlockIndex);
5636 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5637 }
5638 else
5639 {
5640 *length = 1;
5641 }
5642 }
5643
5644 return true;
5645}
5646
Jamie Madill9696d072017-08-26 23:19:57 -04005647template <typename ParamType>
5648bool ValidateSamplerParameterBase(Context *context,
5649 GLuint sampler,
5650 GLenum pname,
5651 GLsizei bufSize,
5652 ParamType *params)
5653{
5654 if (context->getClientMajorVersion() < 3)
5655 {
5656 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5657 return false;
5658 }
5659
5660 if (!context->isSampler(sampler))
5661 {
5662 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5663 return false;
5664 }
5665
5666 const GLsizei minBufSize = 1;
5667 if (bufSize >= 0 && bufSize < minBufSize)
5668 {
5669 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5670 return false;
5671 }
5672
5673 switch (pname)
5674 {
5675 case GL_TEXTURE_WRAP_S:
5676 case GL_TEXTURE_WRAP_T:
5677 case GL_TEXTURE_WRAP_R:
5678 if (!ValidateTextureWrapModeValue(context, params, false))
5679 {
5680 return false;
5681 }
5682 break;
5683
5684 case GL_TEXTURE_MIN_FILTER:
5685 if (!ValidateTextureMinFilterValue(context, params, false))
5686 {
5687 return false;
5688 }
5689 break;
5690
5691 case GL_TEXTURE_MAG_FILTER:
5692 if (!ValidateTextureMagFilterValue(context, params))
5693 {
5694 return false;
5695 }
5696 break;
5697
5698 case GL_TEXTURE_MIN_LOD:
5699 case GL_TEXTURE_MAX_LOD:
5700 // any value is permissible
5701 break;
5702
5703 case GL_TEXTURE_COMPARE_MODE:
5704 if (!ValidateTextureCompareModeValue(context, params))
5705 {
5706 return false;
5707 }
5708 break;
5709
5710 case GL_TEXTURE_COMPARE_FUNC:
5711 if (!ValidateTextureCompareFuncValue(context, params))
5712 {
5713 return false;
5714 }
5715 break;
5716
5717 case GL_TEXTURE_SRGB_DECODE_EXT:
5718 if (!ValidateTextureSRGBDecodeValue(context, params))
5719 {
5720 return false;
5721 }
5722 break;
5723
5724 default:
5725 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5726 return false;
5727 }
5728
5729 return true;
5730}
5731
5732template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5733template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5734
5735bool ValidateGetSamplerParameterBase(Context *context,
5736 GLuint sampler,
5737 GLenum pname,
5738 GLsizei *length)
5739{
5740 if (length)
5741 {
5742 *length = 0;
5743 }
5744
5745 if (context->getClientMajorVersion() < 3)
5746 {
5747 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5748 return false;
5749 }
5750
5751 if (!context->isSampler(sampler))
5752 {
5753 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5754 return false;
5755 }
5756
5757 switch (pname)
5758 {
5759 case GL_TEXTURE_WRAP_S:
5760 case GL_TEXTURE_WRAP_T:
5761 case GL_TEXTURE_WRAP_R:
5762 case GL_TEXTURE_MIN_FILTER:
5763 case GL_TEXTURE_MAG_FILTER:
5764 case GL_TEXTURE_MIN_LOD:
5765 case GL_TEXTURE_MAX_LOD:
5766 case GL_TEXTURE_COMPARE_MODE:
5767 case GL_TEXTURE_COMPARE_FUNC:
5768 break;
5769
5770 case GL_TEXTURE_SRGB_DECODE_EXT:
5771 if (!context->getExtensions().textureSRGBDecode)
5772 {
5773 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5774 return false;
5775 }
5776 break;
5777
5778 default:
5779 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5780 return false;
5781 }
5782
5783 if (length)
5784 {
5785 *length = 1;
5786 }
5787 return true;
5788}
5789
5790bool ValidateGetInternalFormativBase(Context *context,
5791 GLenum target,
5792 GLenum internalformat,
5793 GLenum pname,
5794 GLsizei bufSize,
5795 GLsizei *numParams)
5796{
5797 if (numParams)
5798 {
5799 *numParams = 0;
5800 }
5801
5802 if (context->getClientMajorVersion() < 3)
5803 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005804 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005805 return false;
5806 }
5807
5808 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5809 if (!formatCaps.renderable)
5810 {
5811 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5812 return false;
5813 }
5814
5815 switch (target)
5816 {
5817 case GL_RENDERBUFFER:
5818 break;
5819
5820 case GL_TEXTURE_2D_MULTISAMPLE:
5821 if (context->getClientVersion() < ES_3_1)
5822 {
5823 context->handleError(InvalidOperation()
5824 << "Texture target requires at least OpenGL ES 3.1.");
5825 return false;
5826 }
5827 break;
5828
5829 default:
5830 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5831 return false;
5832 }
5833
5834 if (bufSize < 0)
5835 {
5836 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5837 return false;
5838 }
5839
5840 GLsizei maxWriteParams = 0;
5841 switch (pname)
5842 {
5843 case GL_NUM_SAMPLE_COUNTS:
5844 maxWriteParams = 1;
5845 break;
5846
5847 case GL_SAMPLES:
5848 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5849 break;
5850
5851 default:
5852 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5853 return false;
5854 }
5855
5856 if (numParams)
5857 {
5858 // glGetInternalFormativ will not overflow bufSize
5859 *numParams = std::min(bufSize, maxWriteParams);
5860 }
5861
5862 return true;
5863}
5864
Jamie Madillc29968b2016-01-20 11:17:23 -05005865} // namespace gl