blob: 619b6381d6e6482513eebe34f30cf6b3a07cc265 [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
Jamie Madill29639852016-09-02 15:00:09 -0400777bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -0500778{
779 switch (target)
780 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800781 case GL_ARRAY_BUFFER:
782 case GL_ELEMENT_ARRAY_BUFFER:
783 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -0500784
He Yunchaoced53ae2016-11-29 15:00:51 +0800785 case GL_PIXEL_PACK_BUFFER:
786 case GL_PIXEL_UNPACK_BUFFER:
787 return (context->getExtensions().pixelBufferObject ||
788 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -0400789
He Yunchaoced53ae2016-11-29 15:00:51 +0800790 case GL_COPY_READ_BUFFER:
791 case GL_COPY_WRITE_BUFFER:
792 case GL_TRANSFORM_FEEDBACK_BUFFER:
793 case GL_UNIFORM_BUFFER:
794 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -0500795
He Yunchaoced53ae2016-11-29 15:00:51 +0800796 case GL_ATOMIC_COUNTER_BUFFER:
797 case GL_SHADER_STORAGE_BUFFER:
798 case GL_DRAW_INDIRECT_BUFFER:
799 case GL_DISPATCH_INDIRECT_BUFFER:
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{
1000 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1001 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1002 {
1003 // Checks are not required
1004 return true;
1005 }
1006
1007 // ...the data would be unpacked from the buffer object such that the memory reads required
1008 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -04001009 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
1010 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -04001011 const gl::Extents size(width, height, depth);
1012 const auto &unpack = context->getGLState().getUnpackState();
1013
1014 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1015 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1016 if (endByteOrErr.isError())
1017 {
1018 context->handleError(endByteOrErr.getError());
1019 return false;
1020 }
1021
1022 GLuint endByte = endByteOrErr.getResult();
1023
1024 if (pixelUnpackBuffer)
1025 {
1026 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1027 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1028 checkedEndByte += checkedOffset;
1029
1030 if (!checkedEndByte.IsValid() ||
1031 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1032 {
1033 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001034 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04001035 return false;
1036 }
1037 }
1038 else
1039 {
1040 ASSERT(imageSize >= 0);
1041 if (pixels == nullptr && imageSize != 0)
1042 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001043 context->handleError(InvalidOperation()
1044 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001045 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001046 }
1047
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001048 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001049 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001050 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001051 return false;
1052 }
1053 }
1054
1055 return true;
1056}
1057
Geoff Lang37dde692014-01-31 16:34:54 -05001058bool ValidQueryType(const Context *context, GLenum queryType)
1059{
He Yunchaoced53ae2016-11-29 15:00:51 +08001060 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1061 "GL extension enums not equal.");
1062 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1063 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001064
1065 switch (queryType)
1066 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001067 case GL_ANY_SAMPLES_PASSED:
1068 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001069 return context->getClientMajorVersion() >= 3 ||
1070 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +08001071 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1072 return (context->getClientMajorVersion() >= 3);
1073 case GL_TIME_ELAPSED_EXT:
1074 return context->getExtensions().disjointTimerQuery;
1075 case GL_COMMANDS_COMPLETED_CHROMIUM:
1076 return context->getExtensions().syncQuery;
1077 default:
1078 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001079 }
1080}
1081
Geoff Lang2d62ab72017-03-23 16:54:40 -04001082bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
1083 GLenum type,
1084 GLboolean normalized,
1085 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001086 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001087 bool pureInteger)
1088{
1089 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001090 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1091 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1092 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1093 // parameter exceeds 255.
1094 constexpr GLsizei kMaxWebGLStride = 255;
1095 if (stride > kMaxWebGLStride)
1096 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001097 context->handleError(InvalidValue()
1098 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001099 return false;
1100 }
1101
1102 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1103 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1104 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1105 // or an INVALID_OPERATION error is generated.
1106 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1107 size_t typeSize = GetVertexFormatTypeSize(internalType);
1108
1109 ASSERT(isPow2(typeSize) && typeSize > 0);
1110 size_t sizeMask = (typeSize - 1);
1111 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1112 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001113 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001114 return false;
1115 }
1116
1117 if ((stride & sizeMask) != 0)
1118 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001119 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001120 return false;
1121 }
1122
1123 return true;
1124}
1125
Jamie Madillef300b12016-10-07 15:12:09 -04001126Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001127{
He Yunchaoced53ae2016-11-29 15:00:51 +08001128 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1129 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1130 // or program object and INVALID_OPERATION if the provided name identifies an object
1131 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001132
Dian Xiang769769a2015-09-09 15:20:08 -07001133 Program *validProgram = context->getProgram(id);
1134
1135 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001136 {
Dian Xiang769769a2015-09-09 15:20:08 -07001137 if (context->getShader(id))
1138 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001139 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001140 }
1141 else
1142 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001143 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001144 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001145 }
Dian Xiang769769a2015-09-09 15:20:08 -07001146
1147 return validProgram;
1148}
1149
Jamie Madillef300b12016-10-07 15:12:09 -04001150Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001151{
1152 // See ValidProgram for spec details.
1153
1154 Shader *validShader = context->getShader(id);
1155
1156 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001157 {
Dian Xiang769769a2015-09-09 15:20:08 -07001158 if (context->getProgram(id))
1159 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001160 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001161 }
1162 else
1163 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001164 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001165 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001166 }
Dian Xiang769769a2015-09-09 15:20:08 -07001167
1168 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001169}
1170
Geoff Langb1196682014-07-23 13:47:29 -04001171bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001172{
1173 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1174 {
1175 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1176
Geoff Langaae65a42014-05-26 12:43:44 -04001177 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001178 {
Martin Radevd178aa42017-07-13 14:03:22 +03001179 context->handleError(
1180 InvalidOperation()
1181 << "attachment index cannot be greater or equal to MAX_COLOR_ATTACHMENTS.");
Geoff Langb1196682014-07-23 13:47:29 -04001182 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001183 }
1184 }
1185 else
1186 {
1187 switch (attachment)
1188 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001189 case GL_DEPTH_ATTACHMENT:
1190 case GL_STENCIL_ATTACHMENT:
1191 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001192
He Yunchaoced53ae2016-11-29 15:00:51 +08001193 case GL_DEPTH_STENCIL_ATTACHMENT:
1194 if (!context->getExtensions().webglCompatibility &&
1195 context->getClientMajorVersion() < 3)
1196 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001197 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001198 return false;
1199 }
1200 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001201
He Yunchaoced53ae2016-11-29 15:00:51 +08001202 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001203 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001204 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001205 }
1206 }
1207
1208 return true;
1209}
1210
Jamie Madille8fb6402017-02-14 17:56:40 -05001211bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001212 GLenum target,
1213 GLsizei samples,
1214 GLenum internalformat,
1215 GLsizei width,
1216 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001217{
1218 switch (target)
1219 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001220 case GL_RENDERBUFFER:
1221 break;
1222 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001223 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001224 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001225 }
1226
1227 if (width < 0 || height < 0 || samples < 0)
1228 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001229 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001230 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001231 }
1232
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001233 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1234 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1235
1236 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001237 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001238 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001239 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001240 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001241 }
1242
1243 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1244 // 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 -08001245 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001246 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1247 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001248 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001249 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001250 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001251 }
1252
Geoff Langaae65a42014-05-26 12:43:44 -04001253 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001254 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001255 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001256 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001257 }
1258
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001259 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001260 if (handle == 0)
1261 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001262 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001263 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001264 }
1265
1266 return true;
1267}
1268
He Yunchaoced53ae2016-11-29 15:00:51 +08001269bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1270 GLenum target,
1271 GLenum attachment,
1272 GLenum renderbuffertarget,
1273 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001274{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001275 if (!ValidFramebufferTarget(target))
1276 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001277 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001278 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001279 }
1280
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001281 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001282
Jamie Madill84115c92015-04-23 15:00:07 -04001283 ASSERT(framebuffer);
1284 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001285 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001286 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001287 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001288 }
1289
Jamie Madillb4472272014-07-03 10:38:55 -04001290 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001291 {
Jamie Madillb4472272014-07-03 10:38:55 -04001292 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001293 }
1294
Jamie Madillab9d82c2014-01-21 16:38:14 -05001295 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1296 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1297 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1298 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1299 if (renderbuffer != 0)
1300 {
1301 if (!context->getRenderbuffer(renderbuffer))
1302 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001303 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001304 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001305 }
1306 }
1307
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001308 return true;
1309}
1310
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001311bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001312 GLint srcX0,
1313 GLint srcY0,
1314 GLint srcX1,
1315 GLint srcY1,
1316 GLint dstX0,
1317 GLint dstY0,
1318 GLint dstX1,
1319 GLint dstY1,
1320 GLbitfield mask,
1321 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001322{
1323 switch (filter)
1324 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001325 case GL_NEAREST:
1326 break;
1327 case GL_LINEAR:
1328 break;
1329 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001330 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001331 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001332 }
1333
1334 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1335 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001336 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001337 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001338 }
1339
1340 if (mask == 0)
1341 {
1342 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1343 // buffers are copied.
1344 return false;
1345 }
1346
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001347 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1348 // color buffer, leaving only nearest being unfiltered from above
1349 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1350 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001351 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001352 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001353 }
1354
Jamie Madill51f40ec2016-06-15 14:06:00 -04001355 const auto &glState = context->getGLState();
1356 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1357 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001358
1359 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001360 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001361 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001362 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001363 }
1364
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001365 if (readFramebuffer->id() == drawFramebuffer->id())
1366 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001367 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001368 return false;
1369 }
1370
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001371 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001372 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001373 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001374 return false;
1375 }
1376
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001377 if (drawFramebuffer->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->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001385 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001386 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001387 }
1388
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001389 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1390
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001391 if (mask & GL_COLOR_BUFFER_BIT)
1392 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001393 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001394 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001395
He Yunchao66a41a22016-12-15 16:45:05 +08001396 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001397 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001398 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001399
Geoff Langa15472a2015-08-11 11:48:03 -04001400 for (size_t drawbufferIdx = 0;
1401 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001402 {
Geoff Langa15472a2015-08-11 11:48:03 -04001403 const FramebufferAttachment *attachment =
1404 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1405 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001406 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001407 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001408
Geoff Langb2f3d052013-08-13 12:49:27 -04001409 // The GL ES 3.0.2 spec (pg 193) states that:
1410 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001411 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1412 // as well
1413 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1414 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001415 // Changes with EXT_color_buffer_float:
1416 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001417 GLenum readComponentType = readFormat.info->componentType;
1418 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001419 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001420 readComponentType == GL_SIGNED_NORMALIZED);
1421 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1422 drawComponentType == GL_SIGNED_NORMALIZED);
1423
1424 if (extensions.colorBufferFloat)
1425 {
1426 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1427 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1428
1429 if (readFixedOrFloat != drawFixedOrFloat)
1430 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001431 context->handleError(InvalidOperation()
1432 << "If the read buffer contains fixed-point or "
1433 "floating-point values, the draw buffer must "
1434 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001435 return false;
1436 }
1437 }
1438 else if (readFixedPoint != drawFixedPoint)
1439 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001440 context->handleError(InvalidOperation()
1441 << "If the read buffer contains fixed-point values, "
1442 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001443 return false;
1444 }
1445
1446 if (readComponentType == GL_UNSIGNED_INT &&
1447 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001448 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001449 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001450 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001451 }
1452
Jamie Madill6163c752015-12-07 16:32:59 -05001453 if (readComponentType == GL_INT && drawComponentType != GL_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 Madilla3944d42016-07-22 22:13:26 -04001459 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001460 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001461 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001462 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001463 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001464 }
Geoff Lange4915782017-04-12 15:19:07 -04001465
1466 if (context->getExtensions().webglCompatibility &&
1467 *readColorBuffer == *attachment)
1468 {
1469 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001470 InvalidOperation()
1471 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001472 return false;
1473 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001474 }
1475 }
1476
Jamie Madilla3944d42016-07-22 22:13:26 -04001477 if ((readFormat.info->componentType == GL_INT ||
1478 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1479 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001480 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001481 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001482 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001483 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001484 }
He Yunchao66a41a22016-12-15 16:45:05 +08001485 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1486 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1487 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1488 // situation is an application error that would lead to a crash in ANGLE.
1489 else if (drawFramebuffer->hasEnabledDrawBuffer())
1490 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001491 context->handleError(
1492 InvalidOperation()
1493 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001494 return false;
1495 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001496 }
1497
He Yunchaoced53ae2016-11-29 15:00:51 +08001498 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001499 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1500 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001501 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001502 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001503 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001504 const gl::FramebufferAttachment *readBuffer =
1505 readFramebuffer->getAttachment(attachments[i]);
1506 const gl::FramebufferAttachment *drawBuffer =
1507 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001508
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001509 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001510 {
Kenneth Russell69382852017-07-21 16:38:44 -04001511 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001513 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001514 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001515 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001516
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001517 if (readBuffer->getSamples() > 0 && !sameBounds)
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 Lange4915782017-04-12 15:19:07 -04001522
1523 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1524 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001525 context->handleError(
1526 InvalidOperation()
1527 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001528 return false;
1529 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001530 }
He Yunchao66a41a22016-12-15 16:45:05 +08001531 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1532 else if (drawBuffer)
1533 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001534 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1535 "depth/stencil attachment of a "
1536 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001537 return false;
1538 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001539 }
1540 }
1541
Martin Radeva3ed4572017-07-27 18:29:37 +03001542 // ANGLE_multiview, Revision 1:
1543 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1544 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1545 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1546 {
1547 context->handleError(InvalidFramebufferOperation()
1548 << "Attempt to read from a multi-view framebuffer.");
1549 return false;
1550 }
1551 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1552 {
1553 context->handleError(InvalidFramebufferOperation()
1554 << "Attempt to write to a multi-view framebuffer.");
1555 return false;
1556 }
1557
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001558 return true;
1559}
1560
Jamie Madill4928b7c2017-06-20 12:57:39 -04001561bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001562 GLint x,
1563 GLint y,
1564 GLsizei width,
1565 GLsizei height,
1566 GLenum format,
1567 GLenum type,
1568 GLsizei bufSize,
1569 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001570 GLsizei *columns,
1571 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001572 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001573{
1574 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001575 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001576 return false;
1577 }
1578
Geoff Lang62fce5b2016-09-30 10:46:35 -04001579 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001580 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001581 {
Geoff Langb1196682014-07-23 13:47:29 -04001582 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001583 }
1584
Geoff Lang62fce5b2016-09-30 10:46:35 -04001585 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001586 {
Geoff Langb1196682014-07-23 13:47:29 -04001587 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001588 }
1589
Jamie Madillc29968b2016-01-20 11:17:23 -05001590 return true;
1591}
1592
1593bool ValidateReadnPixelsEXT(Context *context,
1594 GLint x,
1595 GLint y,
1596 GLsizei width,
1597 GLsizei height,
1598 GLenum format,
1599 GLenum type,
1600 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001601 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001602{
1603 if (bufSize < 0)
1604 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001605 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001606 return false;
1607 }
1608
Geoff Lang62fce5b2016-09-30 10:46:35 -04001609 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001610 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001611}
Jamie Madill26e91952014-03-05 15:01:27 -05001612
Jamie Madill4928b7c2017-06-20 12:57:39 -04001613bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001614 GLint x,
1615 GLint y,
1616 GLsizei width,
1617 GLsizei height,
1618 GLenum format,
1619 GLenum type,
1620 GLsizei bufSize,
1621 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001622 GLsizei *columns,
1623 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001624 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001625{
1626 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001627 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001628 return false;
1629 }
1630
Geoff Lange93daba2017-03-30 13:54:40 -04001631 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1632 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001633 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001634 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001635 }
1636
Geoff Lang62fce5b2016-09-30 10:46:35 -04001637 if (!ValidateRobustBufferSize(context, bufSize, *length))
1638 {
1639 return false;
1640 }
1641
1642 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001643}
1644
Jamie Madillf0e04492017-08-26 15:28:42 -04001645bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001646{
1647 if (!context->getExtensions().occlusionQueryBoolean &&
1648 !context->getExtensions().disjointTimerQuery)
1649 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001650 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001651 return false;
1652 }
1653
Olli Etuaho41997e72016-03-10 13:38:39 +02001654 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001655}
1656
Jamie Madillf0e04492017-08-26 15:28:42 -04001657bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001658{
1659 if (!context->getExtensions().occlusionQueryBoolean &&
1660 !context->getExtensions().disjointTimerQuery)
1661 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001662 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001663 return false;
1664 }
1665
Olli Etuaho41997e72016-03-10 13:38:39 +02001666 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001667}
1668
Jamie Madillf0e04492017-08-26 15:28:42 -04001669bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1670{
1671 if (!context->getExtensions().occlusionQueryBoolean &&
1672 !context->getExtensions().disjointTimerQuery)
1673 {
1674 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1675 return false;
1676 }
1677
1678 return true;
1679}
1680
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001681bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001682{
1683 if (!ValidQueryType(context, target))
1684 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001685 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001686 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001687 }
1688
1689 if (id == 0)
1690 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001691 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001692 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001693 }
1694
1695 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1696 // of zero, if the active query object name for <target> is non-zero (for the
1697 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1698 // the active query for either target is non-zero), if <id> is the name of an
1699 // existing query object whose type does not match <target>, or if <id> is the
1700 // active query object name for any query type, the error INVALID_OPERATION is
1701 // generated.
1702
1703 // Ensure no other queries are active
1704 // NOTE: If other queries than occlusion are supported, we will need to check
1705 // separately that:
1706 // a) The query ID passed is not the current active query for any target/type
1707 // b) There are no active queries for the requested target (and in the case
1708 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1709 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001710
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001711 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001712 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001713 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001714 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001715 }
1716
1717 Query *queryObject = context->getQuery(id, true, target);
1718
1719 // check that name was obtained with glGenQueries
1720 if (!queryObject)
1721 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001722 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001723 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001724 }
1725
1726 // check for type mismatch
1727 if (queryObject->getType() != target)
1728 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001729 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001730 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001731 }
1732
1733 return true;
1734}
1735
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001736bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1737{
1738 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001739 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001740 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001741 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001742 return false;
1743 }
1744
1745 return ValidateBeginQueryBase(context, target, id);
1746}
1747
1748bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001749{
1750 if (!ValidQueryType(context, target))
1751 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001752 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001753 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001754 }
1755
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001756 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001757
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001758 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001759 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001760 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001761 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001762 }
1763
Jamie Madill45c785d2014-05-13 14:09:34 -04001764 return true;
1765}
1766
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001767bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1768{
1769 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001770 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001771 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001772 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001773 return false;
1774 }
1775
1776 return ValidateEndQueryBase(context, target);
1777}
1778
1779bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1780{
1781 if (!context->getExtensions().disjointTimerQuery)
1782 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001783 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001784 return false;
1785 }
1786
1787 if (target != GL_TIMESTAMP_EXT)
1788 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001789 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001790 return false;
1791 }
1792
1793 Query *queryObject = context->getQuery(id, true, target);
1794 if (queryObject == nullptr)
1795 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001796 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001797 return false;
1798 }
1799
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001800 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001801 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001802 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001803 return false;
1804 }
1805
1806 return true;
1807}
1808
Geoff Lang2186c382016-10-14 10:54:54 -04001809bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001810{
Geoff Lang2186c382016-10-14 10:54:54 -04001811 if (numParams)
1812 {
1813 *numParams = 0;
1814 }
1815
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001816 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1817 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001818 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001819 return false;
1820 }
1821
1822 switch (pname)
1823 {
1824 case GL_CURRENT_QUERY_EXT:
1825 if (target == GL_TIMESTAMP_EXT)
1826 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001827 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001828 return false;
1829 }
1830 break;
1831 case GL_QUERY_COUNTER_BITS_EXT:
1832 if (!context->getExtensions().disjointTimerQuery ||
1833 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1834 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001835 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001836 return false;
1837 }
1838 break;
1839 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001840 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001841 return false;
1842 }
1843
Geoff Lang2186c382016-10-14 10:54:54 -04001844 if (numParams)
1845 {
1846 // All queries return only one value
1847 *numParams = 1;
1848 }
1849
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001850 return true;
1851}
1852
1853bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1854{
1855 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001856 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001857 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001858 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001859 return false;
1860 }
1861
Geoff Lang2186c382016-10-14 10:54:54 -04001862 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001863}
1864
Geoff Lang2186c382016-10-14 10:54:54 -04001865bool ValidateGetQueryivRobustANGLE(Context *context,
1866 GLenum target,
1867 GLenum pname,
1868 GLsizei bufSize,
1869 GLsizei *length,
1870 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001871{
Geoff Lang2186c382016-10-14 10:54:54 -04001872 if (!ValidateRobustEntryPoint(context, bufSize))
1873 {
1874 return false;
1875 }
1876
1877 if (!ValidateGetQueryivBase(context, target, pname, length))
1878 {
1879 return false;
1880 }
1881
1882 if (!ValidateRobustBufferSize(context, bufSize, *length))
1883 {
1884 return false;
1885 }
1886
1887 return true;
1888}
1889
1890bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1891{
1892 if (numParams)
1893 {
1894 *numParams = 0;
1895 }
1896
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001897 Query *queryObject = context->getQuery(id, false, GL_NONE);
1898
1899 if (!queryObject)
1900 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001901 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001902 return false;
1903 }
1904
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001905 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001906 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001907 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001908 return false;
1909 }
1910
1911 switch (pname)
1912 {
1913 case GL_QUERY_RESULT_EXT:
1914 case GL_QUERY_RESULT_AVAILABLE_EXT:
1915 break;
1916
1917 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001918 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001919 return false;
1920 }
1921
Geoff Lang2186c382016-10-14 10:54:54 -04001922 if (numParams)
1923 {
1924 *numParams = 1;
1925 }
1926
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001927 return true;
1928}
1929
1930bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1931{
1932 if (!context->getExtensions().disjointTimerQuery)
1933 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001934 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001935 return false;
1936 }
Geoff Lang2186c382016-10-14 10:54:54 -04001937 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1938}
1939
1940bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1941 GLuint id,
1942 GLenum pname,
1943 GLsizei bufSize,
1944 GLsizei *length,
1945 GLint *params)
1946{
1947 if (!context->getExtensions().disjointTimerQuery)
1948 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001949 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001950 return false;
1951 }
1952
1953 if (!ValidateRobustEntryPoint(context, bufSize))
1954 {
1955 return false;
1956 }
1957
1958 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1959 {
1960 return false;
1961 }
1962
1963 if (!ValidateRobustBufferSize(context, bufSize, *length))
1964 {
1965 return false;
1966 }
1967
1968 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001969}
1970
1971bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1972{
1973 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001974 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001975 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001976 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001977 return false;
1978 }
Geoff Lang2186c382016-10-14 10:54:54 -04001979 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1980}
1981
1982bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1983 GLuint id,
1984 GLenum pname,
1985 GLsizei bufSize,
1986 GLsizei *length,
1987 GLuint *params)
1988{
1989 if (!context->getExtensions().disjointTimerQuery &&
1990 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1991 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001992 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001993 return false;
1994 }
1995
1996 if (!ValidateRobustEntryPoint(context, bufSize))
1997 {
1998 return false;
1999 }
2000
2001 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2002 {
2003 return false;
2004 }
2005
2006 if (!ValidateRobustBufferSize(context, bufSize, *length))
2007 {
2008 return false;
2009 }
2010
2011 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002012}
2013
2014bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2015{
2016 if (!context->getExtensions().disjointTimerQuery)
2017 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002018 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002019 return false;
2020 }
Geoff Lang2186c382016-10-14 10:54:54 -04002021 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2022}
2023
2024bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2025 GLuint id,
2026 GLenum pname,
2027 GLsizei bufSize,
2028 GLsizei *length,
2029 GLint64 *params)
2030{
2031 if (!context->getExtensions().disjointTimerQuery)
2032 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002033 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002034 return false;
2035 }
2036
2037 if (!ValidateRobustEntryPoint(context, bufSize))
2038 {
2039 return false;
2040 }
2041
2042 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2043 {
2044 return false;
2045 }
2046
2047 if (!ValidateRobustBufferSize(context, bufSize, *length))
2048 {
2049 return false;
2050 }
2051
2052 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002053}
2054
2055bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2056{
2057 if (!context->getExtensions().disjointTimerQuery)
2058 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002059 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002060 return false;
2061 }
Geoff Lang2186c382016-10-14 10:54:54 -04002062 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2063}
2064
2065bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2066 GLuint id,
2067 GLenum pname,
2068 GLsizei bufSize,
2069 GLsizei *length,
2070 GLuint64 *params)
2071{
2072 if (!context->getExtensions().disjointTimerQuery)
2073 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002074 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002075 return false;
2076 }
2077
2078 if (!ValidateRobustEntryPoint(context, bufSize))
2079 {
2080 return false;
2081 }
2082
2083 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2084 {
2085 return false;
2086 }
2087
2088 if (!ValidateRobustBufferSize(context, bufSize, *length))
2089 {
2090 return false;
2091 }
2092
2093 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002094}
2095
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002096bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002097 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002098 GLuint program,
2099 GLint location,
2100 GLsizei count)
2101{
2102 // Check for ES31 program uniform entry points
2103 if (context->getClientVersion() < Version(3, 1))
2104 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002106 return false;
2107 }
2108
2109 const LinkedUniform *uniform = nullptr;
2110 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002111 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2112 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002113}
2114
Frank Henigmana98a6472017-02-02 21:38:32 -05002115bool ValidateProgramUniform1iv(gl::Context *context,
2116 GLuint program,
2117 GLint location,
2118 GLsizei count,
2119 const GLint *value)
2120{
2121 // Check for ES31 program uniform entry points
2122 if (context->getClientVersion() < Version(3, 1))
2123 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002124 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Frank Henigmana98a6472017-02-02 21:38:32 -05002125 return false;
2126 }
2127
2128 const LinkedUniform *uniform = nullptr;
2129 gl::Program *programObject = GetValidProgram(context, program);
2130 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2131 ValidateUniform1ivValue(context, uniform->type, count, value);
2132}
2133
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002134bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002135 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002136 GLuint program,
2137 GLint location,
2138 GLsizei count,
2139 GLboolean transpose)
2140{
2141 // Check for ES31 program uniform entry points
2142 if (context->getClientVersion() < Version(3, 1))
2143 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002144 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002145 return false;
2146 }
2147
2148 const LinkedUniform *uniform = nullptr;
2149 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002150 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2151 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002152}
2153
Jamie Madillc1d770e2017-04-13 17:31:24 -04002154bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002155{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002156 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002157 gl::Program *programObject = context->getGLState().getProgram();
2158 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2159 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002160}
2161
Jamie Madillbe849e42017-05-02 15:49:00 -04002162bool ValidateUniform1iv(ValidationContext *context,
2163 GLint location,
2164 GLsizei count,
2165 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002166{
2167 const LinkedUniform *uniform = nullptr;
2168 gl::Program *programObject = context->getGLState().getProgram();
2169 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2170 ValidateUniform1ivValue(context, uniform->type, count, value);
2171}
2172
Jamie Madillc1d770e2017-04-13 17:31:24 -04002173bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002174 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002175 GLint location,
2176 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002177 GLboolean transpose)
2178{
Martin Radev1be913c2016-07-11 17:59:16 +03002179 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002180 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002181 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002182 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002183 }
2184
Jamie Madill62d31cb2015-09-11 13:25:51 -04002185 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002186 gl::Program *programObject = context->getGLState().getProgram();
2187 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2188 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002189}
2190
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002191bool ValidateStateQuery(ValidationContext *context,
2192 GLenum pname,
2193 GLenum *nativeType,
2194 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002195{
2196 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2197 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002198 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002199 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002200 }
2201
Jamie Madill0af26e12015-03-05 19:54:33 -05002202 const Caps &caps = context->getCaps();
2203
Jamie Madill893ab082014-05-16 16:56:10 -04002204 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2205 {
2206 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2207
Jamie Madill0af26e12015-03-05 19:54:33 -05002208 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002209 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002210 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002211 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002212 }
2213 }
2214
2215 switch (pname)
2216 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002217 case GL_TEXTURE_BINDING_2D:
2218 case GL_TEXTURE_BINDING_CUBE_MAP:
2219 case GL_TEXTURE_BINDING_3D:
2220 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002221 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002222 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002223 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2224 if (!context->getExtensions().textureRectangle)
2225 {
2226 context->handleError(InvalidEnum()
2227 << "ANGLE_texture_rectangle extension not present");
2228 return false;
2229 }
2230 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002231 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2232 if (!context->getExtensions().eglStreamConsumerExternal &&
2233 !context->getExtensions().eglImageExternal)
2234 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002235 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2236 "nor GL_OES_EGL_image_external "
2237 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002238 return false;
2239 }
2240 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002241
He Yunchaoced53ae2016-11-29 15:00:51 +08002242 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2243 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002244 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002245 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2246 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002247 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002248 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002249 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002250 }
2251
Jamie Madill51f40ec2016-06-15 14:06:00 -04002252 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2253 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002254
2255 if (framebuffer->getReadBufferState() == GL_NONE)
2256 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002257 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002258 return false;
2259 }
2260
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002261 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002262 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002263 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002264 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002265 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002266 }
2267 }
2268 break;
2269
He Yunchaoced53ae2016-11-29 15:00:51 +08002270 default:
2271 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002272 }
2273
2274 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002275 if (*numParams == 0)
2276 {
2277 return false;
2278 }
2279
2280 return true;
2281}
2282
2283bool ValidateRobustStateQuery(ValidationContext *context,
2284 GLenum pname,
2285 GLsizei bufSize,
2286 GLenum *nativeType,
2287 unsigned int *numParams)
2288{
2289 if (!ValidateRobustEntryPoint(context, bufSize))
2290 {
2291 return false;
2292 }
2293
2294 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2295 {
2296 return false;
2297 }
2298
2299 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002300 {
2301 return false;
2302 }
2303
2304 return true;
2305}
2306
Jamie Madillc29968b2016-01-20 11:17:23 -05002307bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2308 GLenum target,
2309 GLint level,
2310 GLenum internalformat,
2311 bool isSubImage,
2312 GLint xoffset,
2313 GLint yoffset,
2314 GLint zoffset,
2315 GLint x,
2316 GLint y,
2317 GLsizei width,
2318 GLsizei height,
2319 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002320 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002321{
Brandon Jones6cad5662017-06-14 13:25:13 -07002322 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002323 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002324 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2325 return false;
2326 }
2327
2328 if (width < 0 || height < 0)
2329 {
2330 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002331 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002332 }
2333
He Yunchaoced53ae2016-11-29 15:00:51 +08002334 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2335 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002336 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002337 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002338 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002339 }
2340
2341 if (border != 0)
2342 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002343 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002344 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002345 }
2346
2347 if (!ValidMipLevel(context, target, level))
2348 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002349 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002350 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002351 }
2352
Jamie Madill51f40ec2016-06-15 14:06:00 -04002353 const auto &state = context->getGLState();
2354 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002355 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002356 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002357 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002358 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002359 }
2360
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002361 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002363 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002364 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002365 }
2366
Martin Radev138064f2016-07-15 12:03:41 +03002367 if (readFramebuffer->getReadBufferState() == GL_NONE)
2368 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002369 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002370 return false;
2371 }
2372
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002373 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2374 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002375 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002376 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002377 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2378 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002379 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002380 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002381 return false;
2382 }
2383
Martin Radev04e2c3b2017-07-27 16:54:35 +03002384 // ANGLE_multiview spec, Revision 1:
2385 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2386 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2387 // is not NONE.
2388 if (source->getMultiviewLayout() != GL_NONE)
2389 {
2390 context->handleError(InvalidFramebufferOperation()
2391 << "The active read framebuffer object has multiview attachments.");
2392 return false;
2393 }
2394
Geoff Langaae65a42014-05-26 12:43:44 -04002395 const gl::Caps &caps = context->getCaps();
2396
Geoff Langaae65a42014-05-26 12:43:44 -04002397 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002398 switch (target)
2399 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002400 case GL_TEXTURE_2D:
2401 maxDimension = caps.max2DTextureSize;
2402 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002403
He Yunchaoced53ae2016-11-29 15:00:51 +08002404 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2405 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2406 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2407 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2408 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2409 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2410 maxDimension = caps.maxCubeMapTextureSize;
2411 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002412
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002413 case GL_TEXTURE_RECTANGLE_ANGLE:
2414 maxDimension = caps.maxRectangleTextureSize;
2415 break;
2416
He Yunchaoced53ae2016-11-29 15:00:51 +08002417 case GL_TEXTURE_2D_ARRAY:
2418 maxDimension = caps.max2DTextureSize;
2419 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002420
He Yunchaoced53ae2016-11-29 15:00:51 +08002421 case GL_TEXTURE_3D:
2422 maxDimension = caps.max3DTextureSize;
2423 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002424
He Yunchaoced53ae2016-11-29 15:00:51 +08002425 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002426 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002427 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002428 }
2429
Jamie Madillc29968b2016-01-20 11:17:23 -05002430 gl::Texture *texture =
2431 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002432 if (!texture)
2433 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002434 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002435 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002436 }
2437
Geoff Lang69cce582015-09-17 13:20:36 -04002438 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002439 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002440 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002441 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002442 }
2443
Geoff Langca271392017-04-05 12:30:00 -04002444 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002445 isSubImage ? *texture->getFormat(target, level).info
2446 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002447
Geoff Lang966c9402017-04-18 12:38:27 -04002448 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002449 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002450 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002451 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002452 }
2453
2454 if (isSubImage)
2455 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002456 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2457 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2458 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002459 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002460 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002461 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002462 }
2463 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002464 else
2465 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002466 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002467 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002468 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002469 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002470 }
2471
Geoff Langeb66a6e2016-10-31 13:06:12 -04002472 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002473 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002474 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002475 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002476 }
2477
2478 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002479 if (static_cast<int>(width) > maxLevelDimension ||
2480 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002481 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002482 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002483 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002484 }
2485 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002486
Jamie Madill0c8abca2016-07-22 20:21:26 -04002487 if (textureFormatOut)
2488 {
2489 *textureFormatOut = texture->getFormat(target, level);
2490 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002491
2492 // Detect texture copying feedback loops for WebGL.
2493 if (context->getExtensions().webglCompatibility)
2494 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002495 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002496 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002497 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002498 return false;
2499 }
2500 }
2501
Jamie Madill560a8d82014-05-21 13:06:20 -04002502 return true;
2503}
2504
Jiajia Qind9671222016-11-29 16:30:31 +08002505bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002506{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002507 switch (mode)
2508 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002509 case GL_POINTS:
2510 case GL_LINES:
2511 case GL_LINE_LOOP:
2512 case GL_LINE_STRIP:
2513 case GL_TRIANGLES:
2514 case GL_TRIANGLE_STRIP:
2515 case GL_TRIANGLE_FAN:
2516 break;
2517 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002518 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002519 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002520 }
2521
Jamie Madill250d33f2014-06-06 17:09:03 -04002522 if (count < 0)
2523 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002524 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002525 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002526 }
2527
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002528 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002529
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002530 const Extensions &extensions = context->getExtensions();
2531
2532 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2533 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2534 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2535 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002536 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002537 // Check for mapped buffers
2538 // TODO(jmadill): Optimize this check for non - WebGL contexts.
2539 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
2540 {
2541 context->handleError(InvalidOperation());
2542 return false;
2543 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002544 }
2545
Jamie Madillcbcde722017-01-06 14:50:00 -05002546 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2547 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002548 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002549 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002550 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002551 const FramebufferAttachment *dsAttachment =
2552 framebuffer->getStencilOrDepthStencilAttachment();
2553 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002554 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002555 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002556
2557 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2558 bool differentWritemasks =
2559 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2560 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2561 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2562 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2563
2564 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002565 {
Martin Radevffe754b2017-07-31 10:38:07 +03002566 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002567 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002568 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2569 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002570 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002571 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002572 return false;
2573 }
Jamie Madillac528012014-06-20 13:21:23 -04002574 }
2575
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002576 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002577 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002578 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002579 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002580 }
2581
Geoff Lang7dd2e102014-11-10 15:19:26 -05002582 gl::Program *program = state.getProgram();
2583 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002584 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002585 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002586 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002587 }
2588
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002589 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002590 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002591 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002592 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002593 }
2594
Martin Radevffe754b2017-07-31 10:38:07 +03002595 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002596 {
Martin Radevda8e2572017-09-12 17:21:16 +03002597 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002598 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002599 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002600 {
2601 context->handleError(InvalidOperation() << "The number of views in the active program "
2602 "and draw framebuffer does not match.");
2603 return false;
2604 }
Martin Radev7e69f762017-07-27 14:54:13 +03002605
2606 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2607 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2608 framebufferNumViews > 1)
2609 {
2610 context->handleError(InvalidOperation()
2611 << "There is an active transform feedback object "
2612 "when the number of views in the active draw "
2613 "framebuffer is greater than 1.");
2614 return false;
2615 }
Martin Radevffe754b2017-07-31 10:38:07 +03002616
2617 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2618 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2619 {
2620 context->handleError(InvalidOperation() << "There is an active query for target "
2621 "GL_TIME_ELAPSED_EXT when the number of "
2622 "views in the active draw framebuffer is "
2623 "greater than 1.");
2624 return false;
2625 }
Martin Radev7cf61662017-07-26 17:10:53 +03002626 }
2627
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002628 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002629 for (unsigned int uniformBlockIndex = 0;
2630 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002631 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002632 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002633 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002634 const OffsetBindingPointer<Buffer> &uniformBuffer =
2635 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002636
Geoff Lang5d124a62015-09-15 13:03:27 -04002637 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002638 {
2639 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002640 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002641 InvalidOperation()
2642 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002643 return false;
2644 }
2645
Geoff Lang5d124a62015-09-15 13:03:27 -04002646 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002647 if (uniformBufferSize == 0)
2648 {
2649 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002650 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002651 }
2652
Jamie Madill62d31cb2015-09-11 13:25:51 -04002653 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002654 {
2655 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002656 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002657 InvalidOperation()
2658 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002659 return false;
2660 }
2661 }
2662
Geoff Lange0cff192017-05-30 13:04:56 -04002663 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002664 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002665 {
Geoff Lange0cff192017-05-30 13:04:56 -04002666 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002667 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2668 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002669 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002670 return false;
2671 }
Geoff Lange0cff192017-05-30 13:04:56 -04002672
Geoff Lang9ab5b822017-05-30 16:19:23 -04002673 // Detect that the vertex shader input types match the attribute types
2674 if (!ValidateVertexShaderAttributeTypeMatch(context))
2675 {
2676 return false;
2677 }
2678
Geoff Lange0cff192017-05-30 13:04:56 -04002679 // Detect that the color buffer types match the fragment shader output types
2680 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2681 {
2682 return false;
2683 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002684 }
2685
Jamie Madill250d33f2014-06-06 17:09:03 -04002686 // No-op if zero count
2687 return (count > 0);
2688}
2689
Jamie Madillc1d770e2017-04-13 17:31:24 -04002690bool ValidateDrawArraysCommon(ValidationContext *context,
2691 GLenum mode,
2692 GLint first,
2693 GLsizei count,
2694 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002695{
Jamie Madillfd716582014-06-06 17:09:04 -04002696 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002697 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002698 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002699 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002700 }
2701
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002702 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002703 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002704 if (curTransformFeedback && curTransformFeedback->isActive() &&
2705 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002706 {
2707 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002708 // that does not match the current transform feedback object's draw mode (if transform
2709 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002710 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002711 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002712 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002713 }
2714
Jiajia Qind9671222016-11-29 16:30:31 +08002715 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002716 {
2717 return false;
2718 }
2719
Corentin Wallez71168a02016-12-19 15:11:18 -08002720 // Check the computation of maxVertex doesn't overflow.
2721 // - first < 0 or count < 0 have been checked as an error condition
2722 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2723 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2724 ASSERT(count > 0 && first >= 0);
2725 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2726 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002727 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002728 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002729 return false;
2730 }
2731
Corentin Wallez71168a02016-12-19 15:11:18 -08002732 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002733 {
2734 return false;
2735 }
2736
2737 return true;
2738}
2739
He Yunchaoced53ae2016-11-29 15:00:51 +08002740bool ValidateDrawArraysInstancedANGLE(Context *context,
2741 GLenum mode,
2742 GLint first,
2743 GLsizei count,
2744 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002745{
Geoff Lang63c5a592017-09-27 14:08:16 -04002746 if (!context->getExtensions().instancedArrays)
2747 {
2748 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2749 return false;
2750 }
2751
Corentin Wallez170efbf2017-05-02 13:45:01 -04002752 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002753 {
2754 return false;
2755 }
2756
Corentin Wallez0dc97812017-06-22 14:38:44 -04002757 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002758}
2759
Jiajia Qind9671222016-11-29 16:30:31 +08002760bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002761{
Jamie Madill250d33f2014-06-06 17:09:03 -04002762 switch (type)
2763 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002764 case GL_UNSIGNED_BYTE:
2765 case GL_UNSIGNED_SHORT:
2766 break;
2767 case GL_UNSIGNED_INT:
2768 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2769 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002770 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002771 return false;
2772 }
2773 break;
2774 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002775 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002776 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002777 }
2778
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002779 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002780
2781 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002782 if (curTransformFeedback && curTransformFeedback->isActive() &&
2783 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002784 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002785 // It is an invalid operation to call DrawElements, DrawRangeElements or
2786 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002787 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002788 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002789 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002790 }
2791
Jiajia Qind9671222016-11-29 16:30:31 +08002792 return true;
2793}
2794
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002795bool ValidateDrawElementsCommon(ValidationContext *context,
2796 GLenum mode,
2797 GLsizei count,
2798 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002799 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002800 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002801{
2802 if (!ValidateDrawElementsBase(context, type))
2803 return false;
2804
2805 const State &state = context->getGLState();
2806
Corentin Wallez170efbf2017-05-02 13:45:01 -04002807 if (!ValidateDrawBase(context, mode, count))
2808 {
2809 return false;
2810 }
2811
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002812 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2813 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2814 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2815 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002816 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002817 // Check for mapped buffers
2818 // TODO(jmadill): Optimize this check for non - WebGL contexts.
2819 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
2820 {
2821 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2822 return false;
2823 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002824 }
2825
He Yunchaoced53ae2016-11-29 15:00:51 +08002826 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002827 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002828
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002829 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2830
2831 if (context->getExtensions().webglCompatibility)
2832 {
2833 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2834 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2835 {
2836 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2837 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2838 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002839 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002840 return false;
2841 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002842
2843 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2844 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2845 // error is generated.
2846 if (reinterpret_cast<intptr_t>(indices) < 0)
2847 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002848 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002849 return false;
2850 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002851 }
2852
2853 if (context->getExtensions().webglCompatibility ||
2854 !context->getGLState().areClientArraysEnabled())
2855 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002856 if (!elementArrayBuffer && count > 0)
2857 {
2858 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2859 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2860 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002861 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002862 return false;
2863 }
2864 }
2865
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002866 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002867 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002868 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002869 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002870 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2871 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2872 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2873 constexpr uint64_t kMaxTypeSize = 8;
2874 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2875 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2876 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002877
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002878 uint64_t typeSize = typeBytes;
2879 uint64_t elementCount = static_cast<uint64_t>(count);
2880 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2881
2882 // Doing the multiplication here is overflow-safe
2883 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2884
2885 // The offset can be any value, check for overflows
2886 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2887 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002888 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002889 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002890 return false;
2891 }
2892
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002893 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2894 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002895 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002896 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002897 return false;
2898 }
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002899
Corentin Wallez487653b2017-09-01 17:17:55 -04002900 ASSERT(isPow2(typeSize) && typeSize > 0);
2901 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002902 {
2903 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
2904 return false;
2905 }
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002906 }
2907 else if (!indices)
2908 {
2909 // This is an application error that would normally result in a crash,
2910 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002911 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04002912 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002913 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002914 }
2915
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002916 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002917 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002918 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2919 // access is enabled.
2920 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2921 {
2922 return false;
2923 }
2924 }
2925 else
2926 {
2927 // Use the parameter buffer to retrieve and cache the index range.
2928 const auto &params = context->getParams<HasIndexRange>();
2929 const auto &indexRangeOpt = params.getIndexRange();
2930 if (!indexRangeOpt.valid())
2931 {
2932 // Unexpected error.
2933 return false;
2934 }
2935
2936 // If we use an index greater than our maximum supported index range, return an error.
2937 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2938 // return an error if possible here.
2939 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2940 {
2941 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2942 return false;
2943 }
2944
2945 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2946 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2947 {
2948 return false;
2949 }
2950
2951 // No op if there are no real indices in the index data (all are primitive restart).
2952 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002953 }
2954
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002955 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002956}
2957
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002958bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2959 GLenum mode,
2960 GLsizei count,
2961 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002962 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002963 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002964{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002965 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002966}
2967
Geoff Lang3edfe032015-09-04 16:38:24 -04002968bool ValidateDrawElementsInstancedANGLE(Context *context,
2969 GLenum mode,
2970 GLsizei count,
2971 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002972 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002973 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002974{
Geoff Lang63c5a592017-09-27 14:08:16 -04002975 if (!context->getExtensions().instancedArrays)
2976 {
2977 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2978 return false;
2979 }
2980
Corentin Wallez170efbf2017-05-02 13:45:01 -04002981 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002982 {
2983 return false;
2984 }
2985
Corentin Wallez0dc97812017-06-22 14:38:44 -04002986 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002987}
2988
He Yunchaoced53ae2016-11-29 15:00:51 +08002989bool ValidateFramebufferTextureBase(Context *context,
2990 GLenum target,
2991 GLenum attachment,
2992 GLuint texture,
2993 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002994{
Jamie Madill55ec3b12014-07-03 10:38:57 -04002995 if (!ValidFramebufferTarget(target))
2996 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002997 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002998 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002999 }
3000
3001 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003002 {
3003 return false;
3004 }
3005
Jamie Madill55ec3b12014-07-03 10:38:57 -04003006 if (texture != 0)
3007 {
3008 gl::Texture *tex = context->getTexture(texture);
3009
Jamie Madillbe849e42017-05-02 15:49:00 -04003010 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003011 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003012 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003013 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003014 }
3015
3016 if (level < 0)
3017 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003018 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003019 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003020 }
3021 }
3022
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003023 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003024 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003025
Jamie Madill84115c92015-04-23 15:00:07 -04003026 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003027 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003028 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003029 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003030 }
3031
3032 return true;
3033}
3034
Geoff Langb1196682014-07-23 13:47:29 -04003035bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003036{
3037 if (program == 0)
3038 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003039 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003040 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003041 }
3042
Dian Xiang769769a2015-09-09 15:20:08 -07003043 gl::Program *programObject = GetValidProgram(context, program);
3044 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003045 {
3046 return false;
3047 }
3048
Jamie Madill0063c512014-08-25 15:47:53 -04003049 if (!programObject || !programObject->isLinked())
3050 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003051 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003052 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003053 }
3054
Geoff Lang7dd2e102014-11-10 15:19:26 -05003055 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003056 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003057 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003058 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003059 }
3060
Jamie Madill0063c512014-08-25 15:47:53 -04003061 return true;
3062}
3063
Geoff Langf41d0ee2016-10-07 13:04:23 -04003064static bool ValidateSizedGetUniform(Context *context,
3065 GLuint program,
3066 GLint location,
3067 GLsizei bufSize,
3068 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003069{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003070 if (length)
3071 {
3072 *length = 0;
3073 }
3074
Jamie Madill78f41802014-08-25 15:47:55 -04003075 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003076 {
Jamie Madill78f41802014-08-25 15:47:55 -04003077 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003078 }
3079
Geoff Langf41d0ee2016-10-07 13:04:23 -04003080 if (bufSize < 0)
3081 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003082 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003083 return false;
3084 }
3085
Jamie Madilla502c742014-08-28 17:19:13 -04003086 gl::Program *programObject = context->getProgram(program);
3087 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003088
Jamie Madill78f41802014-08-25 15:47:55 -04003089 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003090 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003091 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003092 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003093 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003094 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003095 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003096 }
3097
Geoff Langf41d0ee2016-10-07 13:04:23 -04003098 if (length)
3099 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003100 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003101 }
3102
Jamie Madill0063c512014-08-25 15:47:53 -04003103 return true;
3104}
3105
He Yunchaoced53ae2016-11-29 15:00:51 +08003106bool ValidateGetnUniformfvEXT(Context *context,
3107 GLuint program,
3108 GLint location,
3109 GLsizei bufSize,
3110 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003111{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003112 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003113}
3114
He Yunchaoced53ae2016-11-29 15:00:51 +08003115bool ValidateGetnUniformivEXT(Context *context,
3116 GLuint program,
3117 GLint location,
3118 GLsizei bufSize,
3119 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003120{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003121 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3122}
3123
3124bool ValidateGetUniformfvRobustANGLE(Context *context,
3125 GLuint program,
3126 GLint location,
3127 GLsizei bufSize,
3128 GLsizei *length,
3129 GLfloat *params)
3130{
3131 if (!ValidateRobustEntryPoint(context, bufSize))
3132 {
3133 return false;
3134 }
3135
3136 // bufSize is validated in ValidateSizedGetUniform
3137 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3138}
3139
3140bool ValidateGetUniformivRobustANGLE(Context *context,
3141 GLuint program,
3142 GLint location,
3143 GLsizei bufSize,
3144 GLsizei *length,
3145 GLint *params)
3146{
3147 if (!ValidateRobustEntryPoint(context, bufSize))
3148 {
3149 return false;
3150 }
3151
3152 // bufSize is validated in ValidateSizedGetUniform
3153 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3154}
3155
3156bool ValidateGetUniformuivRobustANGLE(Context *context,
3157 GLuint program,
3158 GLint location,
3159 GLsizei bufSize,
3160 GLsizei *length,
3161 GLuint *params)
3162{
3163 if (!ValidateRobustEntryPoint(context, bufSize))
3164 {
3165 return false;
3166 }
3167
3168 if (context->getClientMajorVersion() < 3)
3169 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003170 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003171 return false;
3172 }
3173
3174 // bufSize is validated in ValidateSizedGetUniform
3175 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003176}
3177
He Yunchaoced53ae2016-11-29 15:00:51 +08003178bool ValidateDiscardFramebufferBase(Context *context,
3179 GLenum target,
3180 GLsizei numAttachments,
3181 const GLenum *attachments,
3182 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003183{
3184 if (numAttachments < 0)
3185 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003186 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003187 return false;
3188 }
3189
3190 for (GLsizei i = 0; i < numAttachments; ++i)
3191 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003192 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003193 {
3194 if (defaultFramebuffer)
3195 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003196 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003197 return false;
3198 }
3199
3200 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3201 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003202 context->handleError(InvalidOperation() << "Requested color attachment is "
3203 "greater than the maximum supported "
3204 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003205 return false;
3206 }
3207 }
3208 else
3209 {
3210 switch (attachments[i])
3211 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003212 case GL_DEPTH_ATTACHMENT:
3213 case GL_STENCIL_ATTACHMENT:
3214 case GL_DEPTH_STENCIL_ATTACHMENT:
3215 if (defaultFramebuffer)
3216 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003217 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3218 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003219 return false;
3220 }
3221 break;
3222 case GL_COLOR:
3223 case GL_DEPTH:
3224 case GL_STENCIL:
3225 if (!defaultFramebuffer)
3226 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003227 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3228 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003229 return false;
3230 }
3231 break;
3232 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003233 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003234 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003235 }
3236 }
3237 }
3238
3239 return true;
3240}
3241
Austin Kinross6ee1e782015-05-29 17:05:37 -07003242bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3243{
3244 // Note that debug marker calls must not set error state
3245
3246 if (length < 0)
3247 {
3248 return false;
3249 }
3250
3251 if (marker == nullptr)
3252 {
3253 return false;
3254 }
3255
3256 return true;
3257}
3258
3259bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3260{
3261 // Note that debug marker calls must not set error state
3262
3263 if (length < 0)
3264 {
3265 return false;
3266 }
3267
3268 if (length > 0 && marker == nullptr)
3269 {
3270 return false;
3271 }
3272
3273 return true;
3274}
3275
Geoff Langdcab33b2015-07-21 13:03:16 -04003276bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003277 GLenum target,
3278 egl::Image *image)
3279{
Geoff Langa8406172015-07-21 16:53:39 -04003280 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3281 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003282 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003283 return false;
3284 }
3285
3286 switch (target)
3287 {
3288 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003289 if (!context->getExtensions().eglImage)
3290 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003291 context->handleError(InvalidEnum()
3292 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003293 }
3294 break;
3295
3296 case GL_TEXTURE_EXTERNAL_OES:
3297 if (!context->getExtensions().eglImageExternal)
3298 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003299 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3300 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003301 }
Geoff Langa8406172015-07-21 16:53:39 -04003302 break;
3303
3304 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003305 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003306 return false;
3307 }
3308
Jamie Madill61e16b42017-06-19 11:13:23 -04003309 ASSERT(context->getCurrentDisplay());
3310 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003311 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003312 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003313 return false;
3314 }
3315
3316 if (image->getSamples() > 0)
3317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003318 context->handleError(InvalidOperation()
3319 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003320 return false;
3321 }
3322
Geoff Langca271392017-04-05 12:30:00 -04003323 const TextureCaps &textureCaps =
3324 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003325 if (!textureCaps.texturable)
3326 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003327 context->handleError(InvalidOperation()
3328 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003329 return false;
3330 }
3331
Geoff Langdcab33b2015-07-21 13:03:16 -04003332 return true;
3333}
3334
3335bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003336 GLenum target,
3337 egl::Image *image)
3338{
Geoff Langa8406172015-07-21 16:53:39 -04003339 if (!context->getExtensions().eglImage)
3340 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003341 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003342 return false;
3343 }
3344
3345 switch (target)
3346 {
3347 case GL_RENDERBUFFER:
3348 break;
3349
3350 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003351 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003352 return false;
3353 }
3354
Jamie Madill61e16b42017-06-19 11:13:23 -04003355 ASSERT(context->getCurrentDisplay());
3356 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003357 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003358 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003359 return false;
3360 }
3361
Geoff Langca271392017-04-05 12:30:00 -04003362 const TextureCaps &textureCaps =
3363 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003364 if (!textureCaps.renderable)
3365 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003366 context->handleError(InvalidOperation()
3367 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003368 return false;
3369 }
3370
Geoff Langdcab33b2015-07-21 13:03:16 -04003371 return true;
3372}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003373
3374bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3375{
Geoff Lang36167ab2015-12-07 10:27:14 -05003376 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003377 {
3378 // The default VAO should always exist
3379 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003380 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003381 return false;
3382 }
3383
3384 return true;
3385}
3386
Geoff Langc5629752015-12-07 16:29:04 -05003387bool ValidateProgramBinaryBase(Context *context,
3388 GLuint program,
3389 GLenum binaryFormat,
3390 const void *binary,
3391 GLint length)
3392{
3393 Program *programObject = GetValidProgram(context, program);
3394 if (programObject == nullptr)
3395 {
3396 return false;
3397 }
3398
3399 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3400 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3401 programBinaryFormats.end())
3402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003403 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003404 return false;
3405 }
3406
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003407 if (context->hasActiveTransformFeedback(program))
3408 {
3409 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003410 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3411 "is associated with an active transform "
3412 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003413 return false;
3414 }
3415
Geoff Langc5629752015-12-07 16:29:04 -05003416 return true;
3417}
3418
3419bool ValidateGetProgramBinaryBase(Context *context,
3420 GLuint program,
3421 GLsizei bufSize,
3422 GLsizei *length,
3423 GLenum *binaryFormat,
3424 void *binary)
3425{
3426 Program *programObject = GetValidProgram(context, program);
3427 if (programObject == nullptr)
3428 {
3429 return false;
3430 }
3431
3432 if (!programObject->isLinked())
3433 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003434 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003435 return false;
3436 }
3437
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003438 if (context->getCaps().programBinaryFormats.empty())
3439 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003440 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003441 return false;
3442 }
3443
Geoff Langc5629752015-12-07 16:29:04 -05003444 return true;
3445}
Jamie Madillc29968b2016-01-20 11:17:23 -05003446
Jamie Madillc29968b2016-01-20 11:17:23 -05003447bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3448{
3449 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003450 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003451 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003452 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3453 return false;
3454 }
3455 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3456 {
3457 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003458 return false;
3459 }
3460
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003461 ASSERT(context->getGLState().getDrawFramebuffer());
3462 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003463 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3464
3465 // This should come first before the check for the default frame buffer
3466 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3467 // rather than INVALID_OPERATION
3468 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3469 {
3470 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3471
3472 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003473 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3474 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003475 {
3476 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003477 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3478 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3479 // 3.1 is still a bit ambiguous about the error, but future specs are
3480 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003481 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003482 return false;
3483 }
3484 else if (bufs[colorAttachment] >= maxColorAttachment)
3485 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003486 context->handleError(InvalidOperation()
3487 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003488 return false;
3489 }
3490 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3491 frameBufferId != 0)
3492 {
3493 // INVALID_OPERATION-GL is bound to buffer and ith argument
3494 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003495 context->handleError(InvalidOperation()
3496 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003497 return false;
3498 }
3499 }
3500
3501 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3502 // and n is not 1 or bufs is bound to value other than BACK and NONE
3503 if (frameBufferId == 0)
3504 {
3505 if (n != 1)
3506 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003507 context->handleError(InvalidOperation()
3508 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003509 return false;
3510 }
3511
3512 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003514 context->handleError(
3515 InvalidOperation()
3516 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003517 return false;
3518 }
3519 }
3520
3521 return true;
3522}
3523
Geoff Lang496c02d2016-10-20 11:38:11 -07003524bool ValidateGetBufferPointervBase(Context *context,
3525 GLenum target,
3526 GLenum pname,
3527 GLsizei *length,
3528 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003529{
Geoff Lang496c02d2016-10-20 11:38:11 -07003530 if (length)
3531 {
3532 *length = 0;
3533 }
3534
3535 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3536 {
3537 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003538 InvalidOperation()
3539 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003540 return false;
3541 }
3542
Olli Etuaho4f667482016-03-30 15:56:35 +03003543 if (!ValidBufferTarget(context, target))
3544 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003545 context->handleError(InvalidEnum() << "Buffer target not valid: 0x" << std::hex
3546 << std::uppercase << target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003547 return false;
3548 }
3549
Geoff Lang496c02d2016-10-20 11:38:11 -07003550 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003551 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003552 case GL_BUFFER_MAP_POINTER:
3553 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003554
Geoff Lang496c02d2016-10-20 11:38:11 -07003555 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003556 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003557 return false;
3558 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003559
3560 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3561 // target bound to zero generate an INVALID_OPERATION error."
3562 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003563 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003564 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003565 context->handleError(InvalidOperation()
3566 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003567 return false;
3568 }
3569
Geoff Lang496c02d2016-10-20 11:38:11 -07003570 if (length)
3571 {
3572 *length = 1;
3573 }
3574
Olli Etuaho4f667482016-03-30 15:56:35 +03003575 return true;
3576}
3577
3578bool ValidateUnmapBufferBase(Context *context, GLenum target)
3579{
3580 if (!ValidBufferTarget(context, target))
3581 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003582 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003583 return false;
3584 }
3585
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003586 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003587
3588 if (buffer == nullptr || !buffer->isMapped())
3589 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003590 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003591 return false;
3592 }
3593
3594 return true;
3595}
3596
3597bool ValidateMapBufferRangeBase(Context *context,
3598 GLenum target,
3599 GLintptr offset,
3600 GLsizeiptr length,
3601 GLbitfield access)
3602{
3603 if (!ValidBufferTarget(context, target))
3604 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003605 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003606 return false;
3607 }
3608
Brandon Jones6cad5662017-06-14 13:25:13 -07003609 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003610 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003611 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3612 return false;
3613 }
3614
3615 if (length < 0)
3616 {
3617 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003618 return false;
3619 }
3620
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003621 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003622
3623 if (!buffer)
3624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003625 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003626 return false;
3627 }
3628
3629 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003630 CheckedNumeric<size_t> checkedOffset(offset);
3631 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003632
Jamie Madille2e406c2016-06-02 13:04:10 -04003633 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003634 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003635 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003636 return false;
3637 }
3638
3639 // Check for invalid bits in the mask
3640 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3641 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3642 GL_MAP_UNSYNCHRONIZED_BIT;
3643
3644 if (access & ~(allAccessBits))
3645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003646 context->handleError(InvalidValue()
3647 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003648 return false;
3649 }
3650
3651 if (length == 0)
3652 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003653 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003654 return false;
3655 }
3656
3657 if (buffer->isMapped())
3658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003659 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003660 return false;
3661 }
3662
3663 // Check for invalid bit combinations
3664 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3665 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003666 context->handleError(InvalidOperation()
3667 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003668 return false;
3669 }
3670
3671 GLbitfield writeOnlyBits =
3672 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3673
3674 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003676 context->handleError(InvalidOperation()
3677 << "Invalid access bits when mapping buffer for reading: 0x"
3678 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003679 return false;
3680 }
3681
3682 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3683 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003684 context->handleError(
3685 InvalidOperation()
3686 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003687 return false;
3688 }
Geoff Lang79f71042017-08-14 16:43:43 -04003689
3690 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003691}
3692
3693bool ValidateFlushMappedBufferRangeBase(Context *context,
3694 GLenum target,
3695 GLintptr offset,
3696 GLsizeiptr length)
3697{
Brandon Jones6cad5662017-06-14 13:25:13 -07003698 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003699 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003700 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3701 return false;
3702 }
3703
3704 if (length < 0)
3705 {
3706 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003707 return false;
3708 }
3709
3710 if (!ValidBufferTarget(context, target))
3711 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003712 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003713 return false;
3714 }
3715
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003716 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003717
3718 if (buffer == nullptr)
3719 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003720 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003721 return false;
3722 }
3723
3724 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3725 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003726 context->handleError(InvalidOperation()
3727 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003728 return false;
3729 }
3730
3731 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003732 CheckedNumeric<size_t> checkedOffset(offset);
3733 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003734
Jamie Madille2e406c2016-06-02 13:04:10 -04003735 if (!checkedSize.IsValid() ||
3736 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003737 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003738 context->handleError(InvalidValue()
3739 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003740 return false;
3741 }
3742
3743 return true;
3744}
3745
Olli Etuaho41997e72016-03-10 13:38:39 +02003746bool ValidateGenOrDelete(Context *context, GLint n)
3747{
3748 if (n < 0)
3749 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003750 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003751 return false;
3752 }
3753 return true;
3754}
3755
Geoff Langff5b2d52016-09-07 11:32:23 -04003756bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3757{
3758 if (!context->getExtensions().robustClientMemory)
3759 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003760 context->handleError(InvalidOperation()
3761 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003762 return false;
3763 }
3764
3765 if (bufSize < 0)
3766 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003767 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003768 return false;
3769 }
3770
3771 return true;
3772}
3773
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003774bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3775{
3776 if (bufSize < numParams)
3777 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003778 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3779 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003780 return false;
3781 }
3782
3783 return true;
3784}
3785
Jamie Madillbe849e42017-05-02 15:49:00 -04003786bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3787 GLenum target,
3788 GLenum attachment,
3789 GLenum pname,
3790 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003791{
Geoff Langff5b2d52016-09-07 11:32:23 -04003792 if (!ValidFramebufferTarget(target))
3793 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003794 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003795 return false;
3796 }
3797
3798 int clientVersion = context->getClientMajorVersion();
3799
3800 switch (pname)
3801 {
3802 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3803 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3804 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3805 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3806 break;
3807
Martin Radeve5285d22017-07-14 16:23:53 +03003808 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3809 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3810 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3811 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3812 if (clientVersion < 3 || !context->getExtensions().multiview)
3813 {
3814 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3815 return false;
3816 }
3817 break;
3818
Geoff Langff5b2d52016-09-07 11:32:23 -04003819 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3820 if (clientVersion < 3 && !context->getExtensions().sRGB)
3821 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003822 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003823 return false;
3824 }
3825 break;
3826
3827 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3828 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3829 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3830 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3831 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3832 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3833 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3834 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3835 if (clientVersion < 3)
3836 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003837 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003838 return false;
3839 }
3840 break;
3841
3842 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003843 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003844 return false;
3845 }
3846
3847 // Determine if the attachment is a valid enum
3848 switch (attachment)
3849 {
3850 case GL_BACK:
3851 case GL_FRONT:
3852 case GL_DEPTH:
3853 case GL_STENCIL:
3854 case GL_DEPTH_STENCIL_ATTACHMENT:
3855 if (clientVersion < 3)
3856 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003857 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003858 return false;
3859 }
3860 break;
3861
3862 case GL_DEPTH_ATTACHMENT:
3863 case GL_STENCIL_ATTACHMENT:
3864 break;
3865
3866 default:
3867 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
3868 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3869 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003870 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003871 return false;
3872 }
3873 break;
3874 }
3875
3876 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3877 ASSERT(framebuffer);
3878
3879 if (framebuffer->id() == 0)
3880 {
3881 if (clientVersion < 3)
3882 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003883 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003884 return false;
3885 }
3886
3887 switch (attachment)
3888 {
3889 case GL_BACK:
3890 case GL_DEPTH:
3891 case GL_STENCIL:
3892 break;
3893
3894 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003895 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003896 return false;
3897 }
3898 }
3899 else
3900 {
3901 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3902 {
3903 // Valid attachment query
3904 }
3905 else
3906 {
3907 switch (attachment)
3908 {
3909 case GL_DEPTH_ATTACHMENT:
3910 case GL_STENCIL_ATTACHMENT:
3911 break;
3912
3913 case GL_DEPTH_STENCIL_ATTACHMENT:
3914 if (!framebuffer->hasValidDepthStencil())
3915 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003916 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003917 return false;
3918 }
3919 break;
3920
3921 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003922 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003923 return false;
3924 }
3925 }
3926 }
3927
3928 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3929 if (attachmentObject)
3930 {
3931 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3932 attachmentObject->type() == GL_TEXTURE ||
3933 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3934
3935 switch (pname)
3936 {
3937 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3938 if (attachmentObject->type() != GL_RENDERBUFFER &&
3939 attachmentObject->type() != GL_TEXTURE)
3940 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003941 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003942 return false;
3943 }
3944 break;
3945
3946 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3947 if (attachmentObject->type() != GL_TEXTURE)
3948 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003949 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003950 return false;
3951 }
3952 break;
3953
3954 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3955 if (attachmentObject->type() != GL_TEXTURE)
3956 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003957 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003958 return false;
3959 }
3960 break;
3961
3962 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3963 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3964 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003965 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003966 return false;
3967 }
3968 break;
3969
3970 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3971 if (attachmentObject->type() != GL_TEXTURE)
3972 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003973 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003974 return false;
3975 }
3976 break;
3977
3978 default:
3979 break;
3980 }
3981 }
3982 else
3983 {
3984 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3985 // is NONE, then querying any other pname will generate INVALID_ENUM.
3986
3987 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3988 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3989 // INVALID_OPERATION for all other pnames
3990
3991 switch (pname)
3992 {
3993 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3994 break;
3995
3996 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3997 if (clientVersion < 3)
3998 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003999 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004000 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004001 return false;
4002 }
4003 break;
4004
4005 default:
4006 if (clientVersion < 3)
4007 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004008 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004009 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004010 return false;
4011 }
4012 else
4013 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004014 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004015 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004016 return false;
4017 }
4018 }
4019 }
4020
Martin Radeve5285d22017-07-14 16:23:53 +03004021 if (numParams)
4022 {
4023 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4024 {
4025 // Only when the viewport offsets are queried we can have a varying number of output
4026 // parameters.
4027 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4028 *numParams = numViews * 2;
4029 }
4030 else
4031 {
4032 // For all other queries we can have only one output parameter.
4033 *numParams = 1;
4034 }
4035 }
4036
Geoff Langff5b2d52016-09-07 11:32:23 -04004037 return true;
4038}
4039
4040bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4041 GLenum target,
4042 GLenum attachment,
4043 GLenum pname,
4044 GLsizei bufSize,
4045 GLsizei *numParams)
4046{
4047 if (!ValidateRobustEntryPoint(context, bufSize))
4048 {
4049 return false;
4050 }
4051
Jamie Madillbe849e42017-05-02 15:49:00 -04004052 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4053 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004054 {
4055 return false;
4056 }
4057
4058 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4059 {
4060 return false;
4061 }
4062
4063 return true;
4064}
4065
Geoff Langff5b2d52016-09-07 11:32:23 -04004066bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4067 GLenum target,
4068 GLenum pname,
4069 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004070 GLsizei *length,
4071 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004072{
4073 if (!ValidateRobustEntryPoint(context, bufSize))
4074 {
4075 return false;
4076 }
4077
Geoff Langebebe1c2016-10-14 12:01:31 -04004078 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004079 {
4080 return false;
4081 }
4082
Geoff Langebebe1c2016-10-14 12:01:31 -04004083 if (!ValidateRobustBufferSize(context, bufSize, *length))
4084 {
4085 return false;
4086 }
4087
4088 return true;
4089}
4090
Geoff Langebebe1c2016-10-14 12:01:31 -04004091bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4092 GLenum target,
4093 GLenum pname,
4094 GLsizei bufSize,
4095 GLsizei *length,
4096 GLint64 *params)
4097{
4098 if (!ValidateRobustEntryPoint(context, bufSize))
4099 {
4100 return false;
4101 }
4102
4103 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4104 {
4105 return false;
4106 }
4107
4108 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004109 {
4110 return false;
4111 }
4112
4113 return true;
4114}
4115
Jamie Madillbe849e42017-05-02 15:49:00 -04004116bool ValidateGetProgramivBase(ValidationContext *context,
4117 GLuint program,
4118 GLenum pname,
4119 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004120{
4121 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004122 if (numParams)
4123 {
4124 *numParams = 1;
4125 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004126
4127 Program *programObject = GetValidProgram(context, program);
4128 if (!programObject)
4129 {
4130 return false;
4131 }
4132
4133 switch (pname)
4134 {
4135 case GL_DELETE_STATUS:
4136 case GL_LINK_STATUS:
4137 case GL_VALIDATE_STATUS:
4138 case GL_INFO_LOG_LENGTH:
4139 case GL_ATTACHED_SHADERS:
4140 case GL_ACTIVE_ATTRIBUTES:
4141 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4142 case GL_ACTIVE_UNIFORMS:
4143 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4144 break;
4145
4146 case GL_PROGRAM_BINARY_LENGTH:
4147 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4148 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004149 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4150 "requires GL_OES_get_program_binary or "
4151 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004152 return false;
4153 }
4154 break;
4155
4156 case GL_ACTIVE_UNIFORM_BLOCKS:
4157 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4158 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4159 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4160 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4161 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4162 if (context->getClientMajorVersion() < 3)
4163 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004164 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004165 return false;
4166 }
4167 break;
4168
Yunchao He61afff12017-03-14 15:34:03 +08004169 case GL_PROGRAM_SEPARABLE:
Xinghua Cao971f8502017-10-17 13:01:24 +08004170 case GL_COMPUTE_WORK_GROUP_SIZE:
jchen1058f67be2017-10-27 08:59:27 +08004171 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004172 if (context->getClientVersion() < Version(3, 1))
4173 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004174 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004175 return false;
4176 }
4177 break;
4178
Geoff Langff5b2d52016-09-07 11:32:23 -04004179 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004180 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004181 return false;
4182 }
4183
4184 return true;
4185}
4186
4187bool ValidateGetProgramivRobustANGLE(Context *context,
4188 GLuint program,
4189 GLenum pname,
4190 GLsizei bufSize,
4191 GLsizei *numParams)
4192{
4193 if (!ValidateRobustEntryPoint(context, bufSize))
4194 {
4195 return false;
4196 }
4197
Jamie Madillbe849e42017-05-02 15:49:00 -04004198 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004199 {
4200 return false;
4201 }
4202
4203 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4204 {
4205 return false;
4206 }
4207
4208 return true;
4209}
4210
Geoff Lang740d9022016-10-07 11:20:52 -04004211bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4212 GLenum target,
4213 GLenum pname,
4214 GLsizei bufSize,
4215 GLsizei *length,
4216 GLint *params)
4217{
4218 if (!ValidateRobustEntryPoint(context, bufSize))
4219 {
4220 return false;
4221 }
4222
4223 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4224 {
4225 return false;
4226 }
4227
4228 if (!ValidateRobustBufferSize(context, bufSize, *length))
4229 {
4230 return false;
4231 }
4232
4233 return true;
4234}
4235
Geoff Langd7d0ed32016-10-07 11:33:51 -04004236bool ValidateGetShaderivRobustANGLE(Context *context,
4237 GLuint shader,
4238 GLenum pname,
4239 GLsizei bufSize,
4240 GLsizei *length,
4241 GLint *params)
4242{
4243 if (!ValidateRobustEntryPoint(context, bufSize))
4244 {
4245 return false;
4246 }
4247
4248 if (!ValidateGetShaderivBase(context, shader, pname, length))
4249 {
4250 return false;
4251 }
4252
4253 if (!ValidateRobustBufferSize(context, bufSize, *length))
4254 {
4255 return false;
4256 }
4257
4258 return true;
4259}
4260
Geoff Langc1984ed2016-10-07 12:41:00 -04004261bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4262 GLenum target,
4263 GLenum pname,
4264 GLsizei bufSize,
4265 GLsizei *length,
4266 GLfloat *params)
4267{
4268 if (!ValidateRobustEntryPoint(context, bufSize))
4269 {
4270 return false;
4271 }
4272
4273 if (!ValidateGetTexParameterBase(context, target, pname, length))
4274 {
4275 return false;
4276 }
4277
4278 if (!ValidateRobustBufferSize(context, bufSize, *length))
4279 {
4280 return false;
4281 }
4282
4283 return true;
4284}
4285
Geoff Langc1984ed2016-10-07 12:41:00 -04004286bool ValidateGetTexParameterivRobustANGLE(Context *context,
4287 GLenum target,
4288 GLenum pname,
4289 GLsizei bufSize,
4290 GLsizei *length,
4291 GLint *params)
4292{
4293 if (!ValidateRobustEntryPoint(context, bufSize))
4294 {
4295 return false;
4296 }
4297
4298 if (!ValidateGetTexParameterBase(context, target, pname, length))
4299 {
4300 return false;
4301 }
4302
4303 if (!ValidateRobustBufferSize(context, bufSize, *length))
4304 {
4305 return false;
4306 }
4307
4308 return true;
4309}
4310
Geoff Langc1984ed2016-10-07 12:41:00 -04004311bool ValidateTexParameterfvRobustANGLE(Context *context,
4312 GLenum target,
4313 GLenum pname,
4314 GLsizei bufSize,
4315 const GLfloat *params)
4316{
4317 if (!ValidateRobustEntryPoint(context, bufSize))
4318 {
4319 return false;
4320 }
4321
4322 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4323}
4324
Geoff Langc1984ed2016-10-07 12:41:00 -04004325bool ValidateTexParameterivRobustANGLE(Context *context,
4326 GLenum target,
4327 GLenum pname,
4328 GLsizei bufSize,
4329 const GLint *params)
4330{
4331 if (!ValidateRobustEntryPoint(context, bufSize))
4332 {
4333 return false;
4334 }
4335
4336 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4337}
4338
Geoff Langc1984ed2016-10-07 12:41:00 -04004339bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4340 GLuint sampler,
4341 GLenum pname,
4342 GLuint bufSize,
4343 GLsizei *length,
4344 GLfloat *params)
4345{
4346 if (!ValidateRobustEntryPoint(context, bufSize))
4347 {
4348 return false;
4349 }
4350
4351 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4352 {
4353 return false;
4354 }
4355
4356 if (!ValidateRobustBufferSize(context, bufSize, *length))
4357 {
4358 return false;
4359 }
4360
4361 return true;
4362}
4363
Geoff Langc1984ed2016-10-07 12:41:00 -04004364bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4365 GLuint sampler,
4366 GLenum pname,
4367 GLuint bufSize,
4368 GLsizei *length,
4369 GLint *params)
4370{
4371 if (!ValidateRobustEntryPoint(context, bufSize))
4372 {
4373 return false;
4374 }
4375
4376 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4377 {
4378 return false;
4379 }
4380
4381 if (!ValidateRobustBufferSize(context, bufSize, *length))
4382 {
4383 return false;
4384 }
4385
4386 return true;
4387}
4388
Geoff Langc1984ed2016-10-07 12:41:00 -04004389bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4390 GLuint sampler,
4391 GLenum pname,
4392 GLsizei bufSize,
4393 const GLfloat *params)
4394{
4395 if (!ValidateRobustEntryPoint(context, bufSize))
4396 {
4397 return false;
4398 }
4399
4400 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4401}
4402
Geoff Langc1984ed2016-10-07 12:41:00 -04004403bool ValidateSamplerParameterivRobustANGLE(Context *context,
4404 GLuint sampler,
4405 GLenum pname,
4406 GLsizei bufSize,
4407 const GLint *params)
4408{
4409 if (!ValidateRobustEntryPoint(context, bufSize))
4410 {
4411 return false;
4412 }
4413
4414 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4415}
4416
Geoff Lang0b031062016-10-13 14:30:04 -04004417bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4418 GLuint index,
4419 GLenum pname,
4420 GLsizei bufSize,
4421 GLsizei *length,
4422 GLfloat *params)
4423{
4424 if (!ValidateRobustEntryPoint(context, bufSize))
4425 {
4426 return false;
4427 }
4428
4429 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4430 {
4431 return false;
4432 }
4433
4434 if (!ValidateRobustBufferSize(context, bufSize, *length))
4435 {
4436 return false;
4437 }
4438
4439 return true;
4440}
4441
Geoff Lang0b031062016-10-13 14:30:04 -04004442bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4443 GLuint index,
4444 GLenum pname,
4445 GLsizei bufSize,
4446 GLsizei *length,
4447 GLint *params)
4448{
4449 if (!ValidateRobustEntryPoint(context, bufSize))
4450 {
4451 return false;
4452 }
4453
4454 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4455 {
4456 return false;
4457 }
4458
4459 if (!ValidateRobustBufferSize(context, bufSize, *length))
4460 {
4461 return false;
4462 }
4463
4464 return true;
4465}
4466
Geoff Lang0b031062016-10-13 14:30:04 -04004467bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4468 GLuint index,
4469 GLenum pname,
4470 GLsizei bufSize,
4471 GLsizei *length,
4472 void **pointer)
4473{
4474 if (!ValidateRobustEntryPoint(context, bufSize))
4475 {
4476 return false;
4477 }
4478
4479 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4480 {
4481 return false;
4482 }
4483
4484 if (!ValidateRobustBufferSize(context, bufSize, *length))
4485 {
4486 return false;
4487 }
4488
4489 return true;
4490}
4491
Geoff Lang0b031062016-10-13 14:30:04 -04004492bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4493 GLuint index,
4494 GLenum pname,
4495 GLsizei bufSize,
4496 GLsizei *length,
4497 GLint *params)
4498{
4499 if (!ValidateRobustEntryPoint(context, bufSize))
4500 {
4501 return false;
4502 }
4503
4504 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4505 {
4506 return false;
4507 }
4508
4509 if (!ValidateRobustBufferSize(context, bufSize, *length))
4510 {
4511 return false;
4512 }
4513
4514 return true;
4515}
4516
Geoff Lang0b031062016-10-13 14:30:04 -04004517bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4518 GLuint index,
4519 GLenum pname,
4520 GLsizei bufSize,
4521 GLsizei *length,
4522 GLuint *params)
4523{
4524 if (!ValidateRobustEntryPoint(context, bufSize))
4525 {
4526 return false;
4527 }
4528
4529 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4530 {
4531 return false;
4532 }
4533
4534 if (!ValidateRobustBufferSize(context, bufSize, *length))
4535 {
4536 return false;
4537 }
4538
4539 return true;
4540}
4541
Geoff Lang6899b872016-10-14 11:30:13 -04004542bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4543 GLuint program,
4544 GLuint uniformBlockIndex,
4545 GLenum pname,
4546 GLsizei bufSize,
4547 GLsizei *length,
4548 GLint *params)
4549{
4550 if (!ValidateRobustEntryPoint(context, bufSize))
4551 {
4552 return false;
4553 }
4554
4555 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4556 {
4557 return false;
4558 }
4559
4560 if (!ValidateRobustBufferSize(context, bufSize, *length))
4561 {
4562 return false;
4563 }
4564
4565 return true;
4566}
4567
Geoff Lang0a9661f2016-10-20 10:59:20 -07004568bool ValidateGetInternalFormativRobustANGLE(Context *context,
4569 GLenum target,
4570 GLenum internalformat,
4571 GLenum pname,
4572 GLsizei bufSize,
4573 GLsizei *length,
4574 GLint *params)
4575{
4576 if (!ValidateRobustEntryPoint(context, bufSize))
4577 {
4578 return false;
4579 }
4580
4581 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4582 {
4583 return false;
4584 }
4585
4586 if (!ValidateRobustBufferSize(context, bufSize, *length))
4587 {
4588 return false;
4589 }
4590
4591 return true;
4592}
4593
Shao80957d92017-02-20 21:25:59 +08004594bool ValidateVertexFormatBase(ValidationContext *context,
4595 GLuint attribIndex,
4596 GLint size,
4597 GLenum type,
4598 GLboolean pureInteger)
4599{
4600 const Caps &caps = context->getCaps();
4601 if (attribIndex >= caps.maxVertexAttributes)
4602 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004603 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004604 return false;
4605 }
4606
4607 if (size < 1 || size > 4)
4608 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004609 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004610 return false;
Shao80957d92017-02-20 21:25:59 +08004611 }
4612
4613 switch (type)
4614 {
4615 case GL_BYTE:
4616 case GL_UNSIGNED_BYTE:
4617 case GL_SHORT:
4618 case GL_UNSIGNED_SHORT:
4619 break;
4620
4621 case GL_INT:
4622 case GL_UNSIGNED_INT:
4623 if (context->getClientMajorVersion() < 3)
4624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004625 context->handleError(InvalidEnum()
4626 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004627 return false;
4628 }
4629 break;
4630
4631 case GL_FIXED:
4632 case GL_FLOAT:
4633 if (pureInteger)
4634 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004635 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004636 return false;
4637 }
4638 break;
4639
4640 case GL_HALF_FLOAT:
4641 if (context->getClientMajorVersion() < 3)
4642 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004643 context->handleError(InvalidEnum()
4644 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004645 return false;
4646 }
4647 if (pureInteger)
4648 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004649 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004650 return false;
4651 }
4652 break;
4653
4654 case GL_INT_2_10_10_10_REV:
4655 case GL_UNSIGNED_INT_2_10_10_10_REV:
4656 if (context->getClientMajorVersion() < 3)
4657 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004658 context->handleError(InvalidEnum()
4659 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004660 return false;
4661 }
4662 if (pureInteger)
4663 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004664 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004665 return false;
4666 }
4667 if (size != 4)
4668 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004669 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4670 "UNSIGNED_INT_2_10_10_10_REV and "
4671 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004672 return false;
4673 }
4674 break;
4675
4676 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004677 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004678 return false;
4679 }
4680
4681 return true;
4682}
4683
Geoff Lang76e65652017-03-27 14:58:02 -04004684// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4685// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4686// specified clear value and the type of a buffer that is being cleared generates an
4687// INVALID_OPERATION error instead of producing undefined results
4688bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4689 GLint drawbuffer,
4690 const GLenum *validComponentTypes,
4691 size_t validComponentTypeCount)
4692{
4693 const FramebufferAttachment *attachment =
4694 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4695 if (attachment)
4696 {
4697 GLenum componentType = attachment->getFormat().info->componentType;
4698 const GLenum *end = validComponentTypes + validComponentTypeCount;
4699 if (std::find(validComponentTypes, end, componentType) == end)
4700 {
4701 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004702 InvalidOperation()
4703 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004704 return false;
4705 }
4706 }
4707
4708 return true;
4709}
4710
Corentin Wallezb2931602017-04-11 15:58:57 -04004711bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4712 GLsizei imageSize,
4713 GLsizei dataSize)
4714{
4715 if (!ValidateRobustEntryPoint(context, dataSize))
4716 {
4717 return false;
4718 }
4719
4720 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
4721 if (pixelUnpackBuffer == nullptr)
4722 {
4723 if (dataSize < imageSize)
4724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004725 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004726 }
4727 }
4728 return true;
4729}
4730
Jamie Madillbe849e42017-05-02 15:49:00 -04004731bool ValidateGetBufferParameterBase(ValidationContext *context,
4732 GLenum target,
4733 GLenum pname,
4734 bool pointerVersion,
4735 GLsizei *numParams)
4736{
4737 if (numParams)
4738 {
4739 *numParams = 0;
4740 }
4741
4742 if (!ValidBufferTarget(context, target))
4743 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004744 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004745 return false;
4746 }
4747
4748 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4749 if (!buffer)
4750 {
4751 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004752 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004753 return false;
4754 }
4755
4756 const Extensions &extensions = context->getExtensions();
4757
4758 switch (pname)
4759 {
4760 case GL_BUFFER_USAGE:
4761 case GL_BUFFER_SIZE:
4762 break;
4763
4764 case GL_BUFFER_ACCESS_OES:
4765 if (!extensions.mapBuffer)
4766 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004767 context->handleError(InvalidEnum()
4768 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004769 return false;
4770 }
4771 break;
4772
4773 case GL_BUFFER_MAPPED:
4774 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4775 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4776 !extensions.mapBufferRange)
4777 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004778 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4779 "GL_OES_mapbuffer or "
4780 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004781 return false;
4782 }
4783 break;
4784
4785 case GL_BUFFER_MAP_POINTER:
4786 if (!pointerVersion)
4787 {
4788 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004789 InvalidEnum()
4790 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004791 return false;
4792 }
4793 break;
4794
4795 case GL_BUFFER_ACCESS_FLAGS:
4796 case GL_BUFFER_MAP_OFFSET:
4797 case GL_BUFFER_MAP_LENGTH:
4798 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4799 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004800 context->handleError(InvalidEnum()
4801 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004802 return false;
4803 }
4804 break;
4805
4806 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004807 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004808 return false;
4809 }
4810
4811 // All buffer parameter queries return one value.
4812 if (numParams)
4813 {
4814 *numParams = 1;
4815 }
4816
4817 return true;
4818}
4819
4820bool ValidateGetRenderbufferParameterivBase(Context *context,
4821 GLenum target,
4822 GLenum pname,
4823 GLsizei *length)
4824{
4825 if (length)
4826 {
4827 *length = 0;
4828 }
4829
4830 if (target != GL_RENDERBUFFER)
4831 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004832 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004833 return false;
4834 }
4835
4836 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4837 if (renderbuffer == nullptr)
4838 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004839 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004840 return false;
4841 }
4842
4843 switch (pname)
4844 {
4845 case GL_RENDERBUFFER_WIDTH:
4846 case GL_RENDERBUFFER_HEIGHT:
4847 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4848 case GL_RENDERBUFFER_RED_SIZE:
4849 case GL_RENDERBUFFER_GREEN_SIZE:
4850 case GL_RENDERBUFFER_BLUE_SIZE:
4851 case GL_RENDERBUFFER_ALPHA_SIZE:
4852 case GL_RENDERBUFFER_DEPTH_SIZE:
4853 case GL_RENDERBUFFER_STENCIL_SIZE:
4854 break;
4855
4856 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4857 if (!context->getExtensions().framebufferMultisample)
4858 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004859 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004860 return false;
4861 }
4862 break;
4863
4864 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004865 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004866 return false;
4867 }
4868
4869 if (length)
4870 {
4871 *length = 1;
4872 }
4873 return true;
4874}
4875
4876bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4877{
4878 if (length)
4879 {
4880 *length = 0;
4881 }
4882
4883 if (GetValidShader(context, shader) == nullptr)
4884 {
4885 return false;
4886 }
4887
4888 switch (pname)
4889 {
4890 case GL_SHADER_TYPE:
4891 case GL_DELETE_STATUS:
4892 case GL_COMPILE_STATUS:
4893 case GL_INFO_LOG_LENGTH:
4894 case GL_SHADER_SOURCE_LENGTH:
4895 break;
4896
4897 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4898 if (!context->getExtensions().translatedShaderSource)
4899 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004900 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004901 return false;
4902 }
4903 break;
4904
4905 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004906 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004907 return false;
4908 }
4909
4910 if (length)
4911 {
4912 *length = 1;
4913 }
4914 return true;
4915}
4916
4917bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4918{
4919 if (length)
4920 {
4921 *length = 0;
4922 }
4923
4924 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4925 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004926 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004927 return false;
4928 }
4929
4930 if (context->getTargetTexture(target) == nullptr)
4931 {
4932 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004933 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004934 return false;
4935 }
4936
4937 switch (pname)
4938 {
4939 case GL_TEXTURE_MAG_FILTER:
4940 case GL_TEXTURE_MIN_FILTER:
4941 case GL_TEXTURE_WRAP_S:
4942 case GL_TEXTURE_WRAP_T:
4943 break;
4944
4945 case GL_TEXTURE_USAGE_ANGLE:
4946 if (!context->getExtensions().textureUsage)
4947 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004948 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004949 return false;
4950 }
4951 break;
4952
4953 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4954 if (!context->getExtensions().textureFilterAnisotropic)
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_IMMUTABLE_FORMAT:
4962 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
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_WRAP_R:
4970 case GL_TEXTURE_IMMUTABLE_LEVELS:
4971 case GL_TEXTURE_SWIZZLE_R:
4972 case GL_TEXTURE_SWIZZLE_G:
4973 case GL_TEXTURE_SWIZZLE_B:
4974 case GL_TEXTURE_SWIZZLE_A:
4975 case GL_TEXTURE_BASE_LEVEL:
4976 case GL_TEXTURE_MAX_LEVEL:
4977 case GL_TEXTURE_MIN_LOD:
4978 case GL_TEXTURE_MAX_LOD:
4979 case GL_TEXTURE_COMPARE_MODE:
4980 case GL_TEXTURE_COMPARE_FUNC:
4981 if (context->getClientMajorVersion() < 3)
4982 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004983 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004984 return false;
4985 }
4986 break;
4987
4988 case GL_TEXTURE_SRGB_DECODE_EXT:
4989 if (!context->getExtensions().textureSRGBDecode)
4990 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004991 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004992 return false;
4993 }
4994 break;
4995
4996 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004997 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004998 return false;
4999 }
5000
5001 if (length)
5002 {
5003 *length = 1;
5004 }
5005 return true;
5006}
5007
5008bool ValidateGetVertexAttribBase(Context *context,
5009 GLuint index,
5010 GLenum pname,
5011 GLsizei *length,
5012 bool pointer,
5013 bool pureIntegerEntryPoint)
5014{
5015 if (length)
5016 {
5017 *length = 0;
5018 }
5019
5020 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5021 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005022 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005023 return false;
5024 }
5025
5026 if (index >= context->getCaps().maxVertexAttributes)
5027 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005028 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005029 return false;
5030 }
5031
5032 if (pointer)
5033 {
5034 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5035 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005036 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005037 return false;
5038 }
5039 }
5040 else
5041 {
5042 switch (pname)
5043 {
5044 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5045 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5046 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5047 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5048 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5049 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5050 case GL_CURRENT_VERTEX_ATTRIB:
5051 break;
5052
5053 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5054 static_assert(
5055 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5056 "ANGLE extension enums not equal to GL enums.");
5057 if (context->getClientMajorVersion() < 3 &&
5058 !context->getExtensions().instancedArrays)
5059 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005060 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5061 "requires OpenGL ES 3.0 or "
5062 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005063 return false;
5064 }
5065 break;
5066
5067 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5068 if (context->getClientMajorVersion() < 3)
5069 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005070 context->handleError(
5071 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005072 return false;
5073 }
5074 break;
5075
5076 case GL_VERTEX_ATTRIB_BINDING:
5077 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5078 if (context->getClientVersion() < ES_3_1)
5079 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005080 context->handleError(InvalidEnum()
5081 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005082 return false;
5083 }
5084 break;
5085
5086 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005087 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005088 return false;
5089 }
5090 }
5091
5092 if (length)
5093 {
5094 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5095 {
5096 *length = 4;
5097 }
5098 else
5099 {
5100 *length = 1;
5101 }
5102 }
5103
5104 return true;
5105}
5106
Jamie Madill4928b7c2017-06-20 12:57:39 -04005107bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005108 GLint x,
5109 GLint y,
5110 GLsizei width,
5111 GLsizei height,
5112 GLenum format,
5113 GLenum type,
5114 GLsizei bufSize,
5115 GLsizei *length,
5116 GLsizei *columns,
5117 GLsizei *rows,
5118 void *pixels)
5119{
5120 if (length != nullptr)
5121 {
5122 *length = 0;
5123 }
5124 if (rows != nullptr)
5125 {
5126 *rows = 0;
5127 }
5128 if (columns != nullptr)
5129 {
5130 *columns = 0;
5131 }
5132
5133 if (width < 0 || height < 0)
5134 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005135 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005136 return false;
5137 }
5138
5139 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5140
5141 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5142 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005143 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005144 return false;
5145 }
5146
5147 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5148 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005149 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005150 return false;
5151 }
5152
5153 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5154 ASSERT(framebuffer);
5155
5156 if (framebuffer->getReadBufferState() == GL_NONE)
5157 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005158 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005159 return false;
5160 }
5161
5162 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5163 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5164 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5165 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5166 // situation is an application error that would lead to a crash in ANGLE.
5167 if (readBuffer == nullptr)
5168 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005169 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005170 return false;
5171 }
5172
Martin Radev28031682017-07-28 14:47:56 +03005173 // ANGLE_multiview, Revision 1:
5174 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5175 // current read framebuffer is not NONE.
5176 if (readBuffer->getMultiviewLayout() != GL_NONE)
5177 {
5178 context->handleError(InvalidFramebufferOperation()
5179 << "Attempting to read from a multi-view framebuffer.");
5180 return false;
5181 }
5182
Geoff Lang280ba992017-04-18 16:30:58 -04005183 if (context->getExtensions().webglCompatibility)
5184 {
5185 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5186 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5187 // and type before validating the combination of format and type. However, the
5188 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5189 // verifies that GL_INVALID_OPERATION is generated.
5190 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5191 // dEQP/WebGL.
5192 if (!ValidReadPixelsFormatEnum(context, format))
5193 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005194 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005195 return false;
5196 }
5197
5198 if (!ValidReadPixelsTypeEnum(context, type))
5199 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005200 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005201 return false;
5202 }
5203 }
5204
Jamie Madill4928b7c2017-06-20 12:57:39 -04005205 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5206 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005207 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5208
5209 bool validFormatTypeCombination =
5210 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5211
5212 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5213 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005214 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005215 return false;
5216 }
5217
5218 // Check for pixel pack buffer related API errors
5219 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5220 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5221 {
5222 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005223 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005224 return false;
5225 }
5226
5227 // .. the data would be packed to the buffer object such that the memory writes required
5228 // would exceed the data store size.
5229 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5230 const gl::Extents size(width, height, 1);
5231 const auto &pack = context->getGLState().getPackState();
5232
5233 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5234 if (endByteOrErr.isError())
5235 {
5236 context->handleError(endByteOrErr.getError());
5237 return false;
5238 }
5239
5240 size_t endByte = endByteOrErr.getResult();
5241 if (bufSize >= 0)
5242 {
5243 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5244 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005245 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005246 return false;
5247 }
5248 }
5249
5250 if (pixelPackBuffer != nullptr)
5251 {
5252 CheckedNumeric<size_t> checkedEndByte(endByte);
5253 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5254 checkedEndByte += checkedOffset;
5255
5256 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5257 {
5258 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005259 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005260 return false;
5261 }
5262 }
5263
5264 if (pixelPackBuffer == nullptr && length != nullptr)
5265 {
5266 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5267 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005268 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005269 return false;
5270 }
5271
5272 *length = static_cast<GLsizei>(endByte);
5273 }
5274
5275 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5276 angle::CheckedNumeric<int> clippedExtent(length);
5277 if (start < 0)
5278 {
5279 // "subtract" the area that is less than 0
5280 clippedExtent += start;
5281 }
5282
5283 const int readExtent = start + length;
5284 if (readExtent > bufferSize)
5285 {
5286 // Subtract the region to the right of the read buffer
5287 clippedExtent -= (readExtent - bufferSize);
5288 }
5289
5290 if (!clippedExtent.IsValid())
5291 {
5292 return 0;
5293 }
5294
5295 return std::max(clippedExtent.ValueOrDie(), 0);
5296 };
5297
5298 if (columns != nullptr)
5299 {
5300 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5301 }
5302
5303 if (rows != nullptr)
5304 {
5305 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5306 }
5307
5308 return true;
5309}
5310
5311template <typename ParamType>
5312bool ValidateTexParameterBase(Context *context,
5313 GLenum target,
5314 GLenum pname,
5315 GLsizei bufSize,
5316 const ParamType *params)
5317{
5318 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5319 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005320 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005321 return false;
5322 }
5323
5324 if (context->getTargetTexture(target) == nullptr)
5325 {
5326 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005327 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005328 return false;
5329 }
5330
5331 const GLsizei minBufSize = 1;
5332 if (bufSize >= 0 && bufSize < minBufSize)
5333 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005334 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005335 return false;
5336 }
5337
5338 switch (pname)
5339 {
5340 case GL_TEXTURE_WRAP_R:
5341 case GL_TEXTURE_SWIZZLE_R:
5342 case GL_TEXTURE_SWIZZLE_G:
5343 case GL_TEXTURE_SWIZZLE_B:
5344 case GL_TEXTURE_SWIZZLE_A:
5345 case GL_TEXTURE_BASE_LEVEL:
5346 case GL_TEXTURE_MAX_LEVEL:
5347 case GL_TEXTURE_COMPARE_MODE:
5348 case GL_TEXTURE_COMPARE_FUNC:
5349 case GL_TEXTURE_MIN_LOD:
5350 case GL_TEXTURE_MAX_LOD:
5351 if (context->getClientMajorVersion() < 3)
5352 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005353 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005354 return false;
5355 }
5356 if (target == GL_TEXTURE_EXTERNAL_OES &&
5357 !context->getExtensions().eglImageExternalEssl3)
5358 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005359 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5360 "available without "
5361 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005362 return false;
5363 }
5364 break;
5365
5366 default:
5367 break;
5368 }
5369
JiangYizhou4cff8d62017-07-06 14:54:09 +08005370 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5371 {
5372 switch (pname)
5373 {
5374 case GL_TEXTURE_MIN_FILTER:
5375 case GL_TEXTURE_MAG_FILTER:
5376 case GL_TEXTURE_WRAP_S:
5377 case GL_TEXTURE_WRAP_T:
5378 case GL_TEXTURE_WRAP_R:
5379 case GL_TEXTURE_MIN_LOD:
5380 case GL_TEXTURE_MAX_LOD:
5381 case GL_TEXTURE_COMPARE_MODE:
5382 case GL_TEXTURE_COMPARE_FUNC:
5383 context->handleError(InvalidEnum()
5384 << "Invalid parameter for 2D multisampled textures.");
5385 return false;
5386 }
5387 }
5388
Jamie Madillbe849e42017-05-02 15:49:00 -04005389 switch (pname)
5390 {
5391 case GL_TEXTURE_WRAP_S:
5392 case GL_TEXTURE_WRAP_T:
5393 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005394 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005395 bool restrictedWrapModes =
5396 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5397 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5398 {
5399 return false;
5400 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005401 }
5402 break;
5403
5404 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005405 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005406 bool restrictedMinFilter =
5407 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5408 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5409 {
5410 return false;
5411 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005412 }
5413 break;
5414
5415 case GL_TEXTURE_MAG_FILTER:
5416 if (!ValidateTextureMagFilterValue(context, params))
5417 {
5418 return false;
5419 }
5420 break;
5421
5422 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005423 if (!context->getExtensions().textureUsage)
5424 {
5425 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5426 return false;
5427 }
5428
Jamie Madillbe849e42017-05-02 15:49:00 -04005429 switch (ConvertToGLenum(params[0]))
5430 {
5431 case GL_NONE:
5432 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5433 break;
5434
5435 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005436 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005437 return false;
5438 }
5439 break;
5440
5441 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5442 if (!context->getExtensions().textureFilterAnisotropic)
5443 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005444 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005445 return false;
5446 }
5447
5448 // we assume the parameter passed to this validation method is truncated, not rounded
5449 if (params[0] < 1)
5450 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005451 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005452 return false;
5453 }
5454 break;
5455
5456 case GL_TEXTURE_MIN_LOD:
5457 case GL_TEXTURE_MAX_LOD:
5458 // any value is permissible
5459 break;
5460
5461 case GL_TEXTURE_COMPARE_MODE:
5462 if (!ValidateTextureCompareModeValue(context, params))
5463 {
5464 return false;
5465 }
5466 break;
5467
5468 case GL_TEXTURE_COMPARE_FUNC:
5469 if (!ValidateTextureCompareFuncValue(context, params))
5470 {
5471 return false;
5472 }
5473 break;
5474
5475 case GL_TEXTURE_SWIZZLE_R:
5476 case GL_TEXTURE_SWIZZLE_G:
5477 case GL_TEXTURE_SWIZZLE_B:
5478 case GL_TEXTURE_SWIZZLE_A:
5479 switch (ConvertToGLenum(params[0]))
5480 {
5481 case GL_RED:
5482 case GL_GREEN:
5483 case GL_BLUE:
5484 case GL_ALPHA:
5485 case GL_ZERO:
5486 case GL_ONE:
5487 break;
5488
5489 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005490 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005491 return false;
5492 }
5493 break;
5494
5495 case GL_TEXTURE_BASE_LEVEL:
5496 if (params[0] < 0)
5497 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005498 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005499 return false;
5500 }
5501 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5502 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005503 context->handleError(InvalidOperation()
5504 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005505 return false;
5506 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005507 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5508 {
5509 context->handleError(InvalidOperation()
5510 << "Base level must be 0 for multisampled textures.");
5511 return false;
5512 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005513 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5514 {
5515 context->handleError(InvalidOperation()
5516 << "Base level must be 0 for rectangle textures.");
5517 return false;
5518 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005519 break;
5520
5521 case GL_TEXTURE_MAX_LEVEL:
5522 if (params[0] < 0)
5523 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005524 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005525 return false;
5526 }
5527 break;
5528
5529 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5530 if (context->getClientVersion() < Version(3, 1))
5531 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005532 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005533 return false;
5534 }
5535 switch (ConvertToGLenum(params[0]))
5536 {
5537 case GL_DEPTH_COMPONENT:
5538 case GL_STENCIL_INDEX:
5539 break;
5540
5541 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005542 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005543 return false;
5544 }
5545 break;
5546
5547 case GL_TEXTURE_SRGB_DECODE_EXT:
5548 if (!ValidateTextureSRGBDecodeValue(context, params))
5549 {
5550 return false;
5551 }
5552 break;
5553
5554 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005555 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005556 return false;
5557 }
5558
5559 return true;
5560}
5561
5562template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5563template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5564
Jamie Madill12e957f2017-08-26 21:42:26 -04005565bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5566{
5567 if (index >= MAX_VERTEX_ATTRIBS)
5568 {
5569 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5570 return false;
5571 }
5572
5573 return true;
5574}
5575
5576bool ValidateGetActiveUniformBlockivBase(Context *context,
5577 GLuint program,
5578 GLuint uniformBlockIndex,
5579 GLenum pname,
5580 GLsizei *length)
5581{
5582 if (length)
5583 {
5584 *length = 0;
5585 }
5586
5587 if (context->getClientMajorVersion() < 3)
5588 {
5589 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5590 return false;
5591 }
5592
5593 Program *programObject = GetValidProgram(context, program);
5594 if (!programObject)
5595 {
5596 return false;
5597 }
5598
5599 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5600 {
5601 context->handleError(InvalidValue()
5602 << "uniformBlockIndex exceeds active uniform block count.");
5603 return false;
5604 }
5605
5606 switch (pname)
5607 {
5608 case GL_UNIFORM_BLOCK_BINDING:
5609 case GL_UNIFORM_BLOCK_DATA_SIZE:
5610 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5611 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5612 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5613 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5614 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5615 break;
5616
5617 default:
5618 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5619 return false;
5620 }
5621
5622 if (length)
5623 {
5624 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5625 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005626 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005627 programObject->getUniformBlockByIndex(uniformBlockIndex);
5628 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5629 }
5630 else
5631 {
5632 *length = 1;
5633 }
5634 }
5635
5636 return true;
5637}
5638
Jamie Madill9696d072017-08-26 23:19:57 -04005639template <typename ParamType>
5640bool ValidateSamplerParameterBase(Context *context,
5641 GLuint sampler,
5642 GLenum pname,
5643 GLsizei bufSize,
5644 ParamType *params)
5645{
5646 if (context->getClientMajorVersion() < 3)
5647 {
5648 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5649 return false;
5650 }
5651
5652 if (!context->isSampler(sampler))
5653 {
5654 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5655 return false;
5656 }
5657
5658 const GLsizei minBufSize = 1;
5659 if (bufSize >= 0 && bufSize < minBufSize)
5660 {
5661 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5662 return false;
5663 }
5664
5665 switch (pname)
5666 {
5667 case GL_TEXTURE_WRAP_S:
5668 case GL_TEXTURE_WRAP_T:
5669 case GL_TEXTURE_WRAP_R:
5670 if (!ValidateTextureWrapModeValue(context, params, false))
5671 {
5672 return false;
5673 }
5674 break;
5675
5676 case GL_TEXTURE_MIN_FILTER:
5677 if (!ValidateTextureMinFilterValue(context, params, false))
5678 {
5679 return false;
5680 }
5681 break;
5682
5683 case GL_TEXTURE_MAG_FILTER:
5684 if (!ValidateTextureMagFilterValue(context, params))
5685 {
5686 return false;
5687 }
5688 break;
5689
5690 case GL_TEXTURE_MIN_LOD:
5691 case GL_TEXTURE_MAX_LOD:
5692 // any value is permissible
5693 break;
5694
5695 case GL_TEXTURE_COMPARE_MODE:
5696 if (!ValidateTextureCompareModeValue(context, params))
5697 {
5698 return false;
5699 }
5700 break;
5701
5702 case GL_TEXTURE_COMPARE_FUNC:
5703 if (!ValidateTextureCompareFuncValue(context, params))
5704 {
5705 return false;
5706 }
5707 break;
5708
5709 case GL_TEXTURE_SRGB_DECODE_EXT:
5710 if (!ValidateTextureSRGBDecodeValue(context, params))
5711 {
5712 return false;
5713 }
5714 break;
5715
5716 default:
5717 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5718 return false;
5719 }
5720
5721 return true;
5722}
5723
5724template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5725template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5726
5727bool ValidateGetSamplerParameterBase(Context *context,
5728 GLuint sampler,
5729 GLenum pname,
5730 GLsizei *length)
5731{
5732 if (length)
5733 {
5734 *length = 0;
5735 }
5736
5737 if (context->getClientMajorVersion() < 3)
5738 {
5739 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5740 return false;
5741 }
5742
5743 if (!context->isSampler(sampler))
5744 {
5745 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5746 return false;
5747 }
5748
5749 switch (pname)
5750 {
5751 case GL_TEXTURE_WRAP_S:
5752 case GL_TEXTURE_WRAP_T:
5753 case GL_TEXTURE_WRAP_R:
5754 case GL_TEXTURE_MIN_FILTER:
5755 case GL_TEXTURE_MAG_FILTER:
5756 case GL_TEXTURE_MIN_LOD:
5757 case GL_TEXTURE_MAX_LOD:
5758 case GL_TEXTURE_COMPARE_MODE:
5759 case GL_TEXTURE_COMPARE_FUNC:
5760 break;
5761
5762 case GL_TEXTURE_SRGB_DECODE_EXT:
5763 if (!context->getExtensions().textureSRGBDecode)
5764 {
5765 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5766 return false;
5767 }
5768 break;
5769
5770 default:
5771 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5772 return false;
5773 }
5774
5775 if (length)
5776 {
5777 *length = 1;
5778 }
5779 return true;
5780}
5781
5782bool ValidateGetInternalFormativBase(Context *context,
5783 GLenum target,
5784 GLenum internalformat,
5785 GLenum pname,
5786 GLsizei bufSize,
5787 GLsizei *numParams)
5788{
5789 if (numParams)
5790 {
5791 *numParams = 0;
5792 }
5793
5794 if (context->getClientMajorVersion() < 3)
5795 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005796 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005797 return false;
5798 }
5799
5800 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5801 if (!formatCaps.renderable)
5802 {
5803 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5804 return false;
5805 }
5806
5807 switch (target)
5808 {
5809 case GL_RENDERBUFFER:
5810 break;
5811
5812 case GL_TEXTURE_2D_MULTISAMPLE:
5813 if (context->getClientVersion() < ES_3_1)
5814 {
5815 context->handleError(InvalidOperation()
5816 << "Texture target requires at least OpenGL ES 3.1.");
5817 return false;
5818 }
5819 break;
5820
5821 default:
5822 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5823 return false;
5824 }
5825
5826 if (bufSize < 0)
5827 {
5828 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5829 return false;
5830 }
5831
5832 GLsizei maxWriteParams = 0;
5833 switch (pname)
5834 {
5835 case GL_NUM_SAMPLE_COUNTS:
5836 maxWriteParams = 1;
5837 break;
5838
5839 case GL_SAMPLES:
5840 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5841 break;
5842
5843 default:
5844 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5845 return false;
5846 }
5847
5848 if (numParams)
5849 {
5850 // glGetInternalFormativ will not overflow bufSize
5851 *numParams = std::min(bufSize, maxWriteParams);
5852 }
5853
5854 return true;
5855}
5856
Jamie Madillc29968b2016-01-20 11:17:23 -05005857} // namespace gl