blob: 615fac4d600576505e93a2a22d7604e40489a2d3 [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{
Geoff Langfa125c92017-10-24 13:01:46 -04001173 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001174 {
Geoff Langfa125c92017-10-24 13:01:46 -04001175 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1176 {
1177 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1178 return false;
1179 }
Jamie Madillb4472272014-07-03 10:38:55 -04001180
Geoff Langfa125c92017-10-24 13:01:46 -04001181 // Color attachment 0 is validated below because it is always valid
1182 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001183 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001184 {
Geoff Langfa125c92017-10-24 13:01:46 -04001185 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001186 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001187 }
1188 }
1189 else
1190 {
1191 switch (attachment)
1192 {
Geoff Langfa125c92017-10-24 13:01:46 -04001193 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001194 case GL_DEPTH_ATTACHMENT:
1195 case GL_STENCIL_ATTACHMENT:
1196 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001197
He Yunchaoced53ae2016-11-29 15:00:51 +08001198 case GL_DEPTH_STENCIL_ATTACHMENT:
1199 if (!context->getExtensions().webglCompatibility &&
1200 context->getClientMajorVersion() < 3)
1201 {
Geoff Langfa125c92017-10-24 13:01:46 -04001202 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001203 return false;
1204 }
1205 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001206
He Yunchaoced53ae2016-11-29 15:00:51 +08001207 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001208 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001209 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001210 }
1211 }
1212
1213 return true;
1214}
1215
Jamie Madille8fb6402017-02-14 17:56:40 -05001216bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001217 GLenum target,
1218 GLsizei samples,
1219 GLenum internalformat,
1220 GLsizei width,
1221 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001222{
1223 switch (target)
1224 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001225 case GL_RENDERBUFFER:
1226 break;
1227 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001228 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001229 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001230 }
1231
1232 if (width < 0 || height < 0 || samples < 0)
1233 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001234 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001235 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001236 }
1237
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001238 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1239 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1240
1241 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001242 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001243 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001244 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001245 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001246 }
1247
1248 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1249 // 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 -08001250 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001251 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1252 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001253 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001254 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001255 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001256 }
1257
Geoff Langaae65a42014-05-26 12:43:44 -04001258 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001259 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001260 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001261 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001262 }
1263
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001264 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001265 if (handle == 0)
1266 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001267 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001268 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001269 }
1270
1271 return true;
1272}
1273
He Yunchaoced53ae2016-11-29 15:00:51 +08001274bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1275 GLenum target,
1276 GLenum attachment,
1277 GLenum renderbuffertarget,
1278 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001279{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001280 if (!ValidFramebufferTarget(target))
1281 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001282 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001283 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001284 }
1285
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001286 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001287
Jamie Madill84115c92015-04-23 15:00:07 -04001288 ASSERT(framebuffer);
1289 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001290 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001291 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001292 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001293 }
1294
Jamie Madillb4472272014-07-03 10:38:55 -04001295 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001296 {
Jamie Madillb4472272014-07-03 10:38:55 -04001297 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001298 }
1299
Jamie Madillab9d82c2014-01-21 16:38:14 -05001300 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1301 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1302 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1303 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1304 if (renderbuffer != 0)
1305 {
1306 if (!context->getRenderbuffer(renderbuffer))
1307 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001308 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001309 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001310 }
1311 }
1312
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001313 return true;
1314}
1315
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001316bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001317 GLint srcX0,
1318 GLint srcY0,
1319 GLint srcX1,
1320 GLint srcY1,
1321 GLint dstX0,
1322 GLint dstY0,
1323 GLint dstX1,
1324 GLint dstY1,
1325 GLbitfield mask,
1326 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001327{
1328 switch (filter)
1329 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001330 case GL_NEAREST:
1331 break;
1332 case GL_LINEAR:
1333 break;
1334 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001335 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001336 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001337 }
1338
1339 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1340 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001341 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001342 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001343 }
1344
1345 if (mask == 0)
1346 {
1347 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1348 // buffers are copied.
1349 return false;
1350 }
1351
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001352 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1353 // color buffer, leaving only nearest being unfiltered from above
1354 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1355 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001356 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001357 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001358 }
1359
Jamie Madill51f40ec2016-06-15 14:06:00 -04001360 const auto &glState = context->getGLState();
1361 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1362 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001363
1364 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001365 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001366 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001367 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001368 }
1369
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001370 if (readFramebuffer->id() == drawFramebuffer->id())
1371 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001372 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001373 return false;
1374 }
1375
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001376 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001377 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001378 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001379 return false;
1380 }
1381
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001382 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001383 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001384 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001385 return false;
1386 }
1387
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001388 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001389 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001390 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001391 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001392 }
1393
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001394 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1395
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001396 if (mask & GL_COLOR_BUFFER_BIT)
1397 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001398 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001399 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001400
He Yunchao66a41a22016-12-15 16:45:05 +08001401 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001402 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001403 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001404
Geoff Langa15472a2015-08-11 11:48:03 -04001405 for (size_t drawbufferIdx = 0;
1406 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001407 {
Geoff Langa15472a2015-08-11 11:48:03 -04001408 const FramebufferAttachment *attachment =
1409 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1410 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001411 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001412 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001413
Geoff Langb2f3d052013-08-13 12:49:27 -04001414 // The GL ES 3.0.2 spec (pg 193) states that:
1415 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001416 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1417 // as well
1418 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1419 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001420 // Changes with EXT_color_buffer_float:
1421 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001422 GLenum readComponentType = readFormat.info->componentType;
1423 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001424 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001425 readComponentType == GL_SIGNED_NORMALIZED);
1426 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1427 drawComponentType == GL_SIGNED_NORMALIZED);
1428
1429 if (extensions.colorBufferFloat)
1430 {
1431 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1432 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1433
1434 if (readFixedOrFloat != drawFixedOrFloat)
1435 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001436 context->handleError(InvalidOperation()
1437 << "If the read buffer contains fixed-point or "
1438 "floating-point values, the draw buffer must "
1439 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001440 return false;
1441 }
1442 }
1443 else if (readFixedPoint != drawFixedPoint)
1444 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001445 context->handleError(InvalidOperation()
1446 << "If the read buffer contains fixed-point values, "
1447 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001448 return false;
1449 }
1450
1451 if (readComponentType == GL_UNSIGNED_INT &&
1452 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001453 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001454 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001455 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001456 }
1457
Jamie Madill6163c752015-12-07 16:32:59 -05001458 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001459 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001460 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001461 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001462 }
1463
Jamie Madilla3944d42016-07-22 22:13:26 -04001464 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001465 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001466 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001467 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001468 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001469 }
Geoff Lange4915782017-04-12 15:19:07 -04001470
1471 if (context->getExtensions().webglCompatibility &&
1472 *readColorBuffer == *attachment)
1473 {
1474 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001475 InvalidOperation()
1476 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001477 return false;
1478 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001479 }
1480 }
1481
Jamie Madilla3944d42016-07-22 22:13:26 -04001482 if ((readFormat.info->componentType == GL_INT ||
1483 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1484 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001485 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001486 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001487 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001488 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001489 }
He Yunchao66a41a22016-12-15 16:45:05 +08001490 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1491 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1492 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1493 // situation is an application error that would lead to a crash in ANGLE.
1494 else if (drawFramebuffer->hasEnabledDrawBuffer())
1495 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001496 context->handleError(
1497 InvalidOperation()
1498 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001499 return false;
1500 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001501 }
1502
He Yunchaoced53ae2016-11-29 15:00:51 +08001503 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001504 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1505 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001506 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001507 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001508 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001509 const gl::FramebufferAttachment *readBuffer =
1510 readFramebuffer->getAttachment(attachments[i]);
1511 const gl::FramebufferAttachment *drawBuffer =
1512 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001513
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001514 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001515 {
Kenneth Russell69382852017-07-21 16:38:44 -04001516 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001517 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001518 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001519 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001520 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001521
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001522 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001523 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001524 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001525 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001526 }
Geoff Lange4915782017-04-12 15:19:07 -04001527
1528 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1529 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001530 context->handleError(
1531 InvalidOperation()
1532 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001533 return false;
1534 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001535 }
He Yunchao66a41a22016-12-15 16:45:05 +08001536 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1537 else if (drawBuffer)
1538 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001539 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1540 "depth/stencil attachment of a "
1541 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001542 return false;
1543 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001544 }
1545 }
1546
Martin Radeva3ed4572017-07-27 18:29:37 +03001547 // ANGLE_multiview, Revision 1:
1548 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1549 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1550 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1551 {
1552 context->handleError(InvalidFramebufferOperation()
1553 << "Attempt to read from a multi-view framebuffer.");
1554 return false;
1555 }
1556 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1557 {
1558 context->handleError(InvalidFramebufferOperation()
1559 << "Attempt to write to a multi-view framebuffer.");
1560 return false;
1561 }
1562
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001563 return true;
1564}
1565
Jamie Madill4928b7c2017-06-20 12:57:39 -04001566bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001567 GLint x,
1568 GLint y,
1569 GLsizei width,
1570 GLsizei height,
1571 GLenum format,
1572 GLenum type,
1573 GLsizei bufSize,
1574 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001575 GLsizei *columns,
1576 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001577 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001578{
1579 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001580 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001581 return false;
1582 }
1583
Geoff Lang62fce5b2016-09-30 10:46:35 -04001584 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001585 columns, rows, pixels))
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
Geoff Lang62fce5b2016-09-30 10:46:35 -04001590 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001591 {
Geoff Langb1196682014-07-23 13:47:29 -04001592 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001593 }
1594
Jamie Madillc29968b2016-01-20 11:17:23 -05001595 return true;
1596}
1597
1598bool ValidateReadnPixelsEXT(Context *context,
1599 GLint x,
1600 GLint y,
1601 GLsizei width,
1602 GLsizei height,
1603 GLenum format,
1604 GLenum type,
1605 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001606 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001607{
1608 if (bufSize < 0)
1609 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001610 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001611 return false;
1612 }
1613
Geoff Lang62fce5b2016-09-30 10:46:35 -04001614 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001615 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001616}
Jamie Madill26e91952014-03-05 15:01:27 -05001617
Jamie Madill4928b7c2017-06-20 12:57:39 -04001618bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001619 GLint x,
1620 GLint y,
1621 GLsizei width,
1622 GLsizei height,
1623 GLenum format,
1624 GLenum type,
1625 GLsizei bufSize,
1626 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001627 GLsizei *columns,
1628 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001629 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001630{
1631 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001632 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001633 return false;
1634 }
1635
Geoff Lange93daba2017-03-30 13:54:40 -04001636 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1637 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001638 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001639 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001640 }
1641
Geoff Lang62fce5b2016-09-30 10:46:35 -04001642 if (!ValidateRobustBufferSize(context, bufSize, *length))
1643 {
1644 return false;
1645 }
1646
1647 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001648}
1649
Jamie Madillf0e04492017-08-26 15:28:42 -04001650bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001651{
1652 if (!context->getExtensions().occlusionQueryBoolean &&
1653 !context->getExtensions().disjointTimerQuery)
1654 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001655 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001656 return false;
1657 }
1658
Olli Etuaho41997e72016-03-10 13:38:39 +02001659 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001660}
1661
Jamie Madillf0e04492017-08-26 15:28:42 -04001662bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001663{
1664 if (!context->getExtensions().occlusionQueryBoolean &&
1665 !context->getExtensions().disjointTimerQuery)
1666 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001667 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001668 return false;
1669 }
1670
Olli Etuaho41997e72016-03-10 13:38:39 +02001671 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001672}
1673
Jamie Madillf0e04492017-08-26 15:28:42 -04001674bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1675{
1676 if (!context->getExtensions().occlusionQueryBoolean &&
1677 !context->getExtensions().disjointTimerQuery)
1678 {
1679 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1680 return false;
1681 }
1682
1683 return true;
1684}
1685
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001686bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001687{
1688 if (!ValidQueryType(context, target))
1689 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001690 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001691 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001692 }
1693
1694 if (id == 0)
1695 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001696 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001697 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001698 }
1699
1700 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1701 // of zero, if the active query object name for <target> is non-zero (for the
1702 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1703 // the active query for either target is non-zero), if <id> is the name of an
1704 // existing query object whose type does not match <target>, or if <id> is the
1705 // active query object name for any query type, the error INVALID_OPERATION is
1706 // generated.
1707
1708 // Ensure no other queries are active
1709 // NOTE: If other queries than occlusion are supported, we will need to check
1710 // separately that:
1711 // a) The query ID passed is not the current active query for any target/type
1712 // b) There are no active queries for the requested target (and in the case
1713 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1714 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001715
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001716 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001717 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001718 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001719 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001720 }
1721
1722 Query *queryObject = context->getQuery(id, true, target);
1723
1724 // check that name was obtained with glGenQueries
1725 if (!queryObject)
1726 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001727 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001728 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001729 }
1730
1731 // check for type mismatch
1732 if (queryObject->getType() != target)
1733 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001734 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001735 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001736 }
1737
1738 return true;
1739}
1740
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001741bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1742{
1743 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001744 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001745 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001746 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001747 return false;
1748 }
1749
1750 return ValidateBeginQueryBase(context, target, id);
1751}
1752
1753bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001754{
1755 if (!ValidQueryType(context, target))
1756 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001757 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001758 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001759 }
1760
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001761 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001762
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001763 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001765 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001766 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001767 }
1768
Jamie Madill45c785d2014-05-13 14:09:34 -04001769 return true;
1770}
1771
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001772bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1773{
1774 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001775 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001776 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001777 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001778 return false;
1779 }
1780
1781 return ValidateEndQueryBase(context, target);
1782}
1783
1784bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1785{
1786 if (!context->getExtensions().disjointTimerQuery)
1787 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001788 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001789 return false;
1790 }
1791
1792 if (target != GL_TIMESTAMP_EXT)
1793 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001794 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001795 return false;
1796 }
1797
1798 Query *queryObject = context->getQuery(id, true, target);
1799 if (queryObject == nullptr)
1800 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001801 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001802 return false;
1803 }
1804
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001805 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001806 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001807 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001808 return false;
1809 }
1810
1811 return true;
1812}
1813
Geoff Lang2186c382016-10-14 10:54:54 -04001814bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001815{
Geoff Lang2186c382016-10-14 10:54:54 -04001816 if (numParams)
1817 {
1818 *numParams = 0;
1819 }
1820
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001821 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1822 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001823 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001824 return false;
1825 }
1826
1827 switch (pname)
1828 {
1829 case GL_CURRENT_QUERY_EXT:
1830 if (target == GL_TIMESTAMP_EXT)
1831 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001832 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001833 return false;
1834 }
1835 break;
1836 case GL_QUERY_COUNTER_BITS_EXT:
1837 if (!context->getExtensions().disjointTimerQuery ||
1838 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1839 {
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 break;
1844 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001845 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001846 return false;
1847 }
1848
Geoff Lang2186c382016-10-14 10:54:54 -04001849 if (numParams)
1850 {
1851 // All queries return only one value
1852 *numParams = 1;
1853 }
1854
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001855 return true;
1856}
1857
1858bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1859{
1860 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001861 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001862 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001863 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001864 return false;
1865 }
1866
Geoff Lang2186c382016-10-14 10:54:54 -04001867 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001868}
1869
Geoff Lang2186c382016-10-14 10:54:54 -04001870bool ValidateGetQueryivRobustANGLE(Context *context,
1871 GLenum target,
1872 GLenum pname,
1873 GLsizei bufSize,
1874 GLsizei *length,
1875 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001876{
Geoff Lang2186c382016-10-14 10:54:54 -04001877 if (!ValidateRobustEntryPoint(context, bufSize))
1878 {
1879 return false;
1880 }
1881
1882 if (!ValidateGetQueryivBase(context, target, pname, length))
1883 {
1884 return false;
1885 }
1886
1887 if (!ValidateRobustBufferSize(context, bufSize, *length))
1888 {
1889 return false;
1890 }
1891
1892 return true;
1893}
1894
1895bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1896{
1897 if (numParams)
1898 {
1899 *numParams = 0;
1900 }
1901
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001902 Query *queryObject = context->getQuery(id, false, GL_NONE);
1903
1904 if (!queryObject)
1905 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001906 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001907 return false;
1908 }
1909
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001910 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001911 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001912 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001913 return false;
1914 }
1915
1916 switch (pname)
1917 {
1918 case GL_QUERY_RESULT_EXT:
1919 case GL_QUERY_RESULT_AVAILABLE_EXT:
1920 break;
1921
1922 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001923 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001924 return false;
1925 }
1926
Geoff Lang2186c382016-10-14 10:54:54 -04001927 if (numParams)
1928 {
1929 *numParams = 1;
1930 }
1931
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001932 return true;
1933}
1934
1935bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1936{
1937 if (!context->getExtensions().disjointTimerQuery)
1938 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001939 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001940 return false;
1941 }
Geoff Lang2186c382016-10-14 10:54:54 -04001942 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1943}
1944
1945bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1946 GLuint id,
1947 GLenum pname,
1948 GLsizei bufSize,
1949 GLsizei *length,
1950 GLint *params)
1951{
1952 if (!context->getExtensions().disjointTimerQuery)
1953 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001954 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001955 return false;
1956 }
1957
1958 if (!ValidateRobustEntryPoint(context, bufSize))
1959 {
1960 return false;
1961 }
1962
1963 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1964 {
1965 return false;
1966 }
1967
1968 if (!ValidateRobustBufferSize(context, bufSize, *length))
1969 {
1970 return false;
1971 }
1972
1973 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001974}
1975
1976bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1977{
1978 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001979 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001980 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001981 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001982 return false;
1983 }
Geoff Lang2186c382016-10-14 10:54:54 -04001984 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1985}
1986
1987bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1988 GLuint id,
1989 GLenum pname,
1990 GLsizei bufSize,
1991 GLsizei *length,
1992 GLuint *params)
1993{
1994 if (!context->getExtensions().disjointTimerQuery &&
1995 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1996 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001997 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001998 return false;
1999 }
2000
2001 if (!ValidateRobustEntryPoint(context, bufSize))
2002 {
2003 return false;
2004 }
2005
2006 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2007 {
2008 return false;
2009 }
2010
2011 if (!ValidateRobustBufferSize(context, bufSize, *length))
2012 {
2013 return false;
2014 }
2015
2016 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002017}
2018
2019bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2020{
2021 if (!context->getExtensions().disjointTimerQuery)
2022 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002023 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002024 return false;
2025 }
Geoff Lang2186c382016-10-14 10:54:54 -04002026 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2027}
2028
2029bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2030 GLuint id,
2031 GLenum pname,
2032 GLsizei bufSize,
2033 GLsizei *length,
2034 GLint64 *params)
2035{
2036 if (!context->getExtensions().disjointTimerQuery)
2037 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002038 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002039 return false;
2040 }
2041
2042 if (!ValidateRobustEntryPoint(context, bufSize))
2043 {
2044 return false;
2045 }
2046
2047 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2048 {
2049 return false;
2050 }
2051
2052 if (!ValidateRobustBufferSize(context, bufSize, *length))
2053 {
2054 return false;
2055 }
2056
2057 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002058}
2059
2060bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2061{
2062 if (!context->getExtensions().disjointTimerQuery)
2063 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002064 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002065 return false;
2066 }
Geoff Lang2186c382016-10-14 10:54:54 -04002067 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2068}
2069
2070bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2071 GLuint id,
2072 GLenum pname,
2073 GLsizei bufSize,
2074 GLsizei *length,
2075 GLuint64 *params)
2076{
2077 if (!context->getExtensions().disjointTimerQuery)
2078 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002079 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002080 return false;
2081 }
2082
2083 if (!ValidateRobustEntryPoint(context, bufSize))
2084 {
2085 return false;
2086 }
2087
2088 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2089 {
2090 return false;
2091 }
2092
2093 if (!ValidateRobustBufferSize(context, bufSize, *length))
2094 {
2095 return false;
2096 }
2097
2098 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002099}
2100
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002101bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002102 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002103 GLuint program,
2104 GLint location,
2105 GLsizei count)
2106{
2107 // Check for ES31 program uniform entry points
2108 if (context->getClientVersion() < Version(3, 1))
2109 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002110 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002111 return false;
2112 }
2113
2114 const LinkedUniform *uniform = nullptr;
2115 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002116 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2117 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002118}
2119
Frank Henigmana98a6472017-02-02 21:38:32 -05002120bool ValidateProgramUniform1iv(gl::Context *context,
2121 GLuint program,
2122 GLint location,
2123 GLsizei count,
2124 const GLint *value)
2125{
2126 // Check for ES31 program uniform entry points
2127 if (context->getClientVersion() < Version(3, 1))
2128 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002129 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Frank Henigmana98a6472017-02-02 21:38:32 -05002130 return false;
2131 }
2132
2133 const LinkedUniform *uniform = nullptr;
2134 gl::Program *programObject = GetValidProgram(context, program);
2135 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2136 ValidateUniform1ivValue(context, uniform->type, count, value);
2137}
2138
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002139bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002140 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002141 GLuint program,
2142 GLint location,
2143 GLsizei count,
2144 GLboolean transpose)
2145{
2146 // Check for ES31 program uniform entry points
2147 if (context->getClientVersion() < Version(3, 1))
2148 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002149 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002150 return false;
2151 }
2152
2153 const LinkedUniform *uniform = nullptr;
2154 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002155 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2156 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002157}
2158
Jamie Madillc1d770e2017-04-13 17:31:24 -04002159bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002160{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002161 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002162 gl::Program *programObject = context->getGLState().getProgram();
2163 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2164 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002165}
2166
Jamie Madillbe849e42017-05-02 15:49:00 -04002167bool ValidateUniform1iv(ValidationContext *context,
2168 GLint location,
2169 GLsizei count,
2170 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002171{
2172 const LinkedUniform *uniform = nullptr;
2173 gl::Program *programObject = context->getGLState().getProgram();
2174 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2175 ValidateUniform1ivValue(context, uniform->type, count, value);
2176}
2177
Jamie Madillc1d770e2017-04-13 17:31:24 -04002178bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002179 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002180 GLint location,
2181 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002182 GLboolean transpose)
2183{
Martin Radev1be913c2016-07-11 17:59:16 +03002184 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002185 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002186 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002187 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002188 }
2189
Jamie Madill62d31cb2015-09-11 13:25:51 -04002190 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002191 gl::Program *programObject = context->getGLState().getProgram();
2192 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2193 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002194}
2195
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002196bool ValidateStateQuery(ValidationContext *context,
2197 GLenum pname,
2198 GLenum *nativeType,
2199 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002200{
2201 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2202 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002203 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002204 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002205 }
2206
Jamie Madill0af26e12015-03-05 19:54:33 -05002207 const Caps &caps = context->getCaps();
2208
Jamie Madill893ab082014-05-16 16:56:10 -04002209 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2210 {
2211 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2212
Jamie Madill0af26e12015-03-05 19:54:33 -05002213 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002214 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002215 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002216 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002217 }
2218 }
2219
2220 switch (pname)
2221 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002222 case GL_TEXTURE_BINDING_2D:
2223 case GL_TEXTURE_BINDING_CUBE_MAP:
2224 case GL_TEXTURE_BINDING_3D:
2225 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002226 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002227 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002228 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2229 if (!context->getExtensions().textureRectangle)
2230 {
2231 context->handleError(InvalidEnum()
2232 << "ANGLE_texture_rectangle extension not present");
2233 return false;
2234 }
2235 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002236 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2237 if (!context->getExtensions().eglStreamConsumerExternal &&
2238 !context->getExtensions().eglImageExternal)
2239 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002240 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2241 "nor GL_OES_EGL_image_external "
2242 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002243 return false;
2244 }
2245 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002246
He Yunchaoced53ae2016-11-29 15:00:51 +08002247 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2248 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002249 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002250 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2251 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002252 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002253 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002254 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002255 }
2256
Jamie Madill51f40ec2016-06-15 14:06:00 -04002257 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2258 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002259
2260 if (framebuffer->getReadBufferState() == GL_NONE)
2261 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002262 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002263 return false;
2264 }
2265
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002266 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002267 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002268 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002269 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002270 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002271 }
2272 }
2273 break;
2274
He Yunchaoced53ae2016-11-29 15:00:51 +08002275 default:
2276 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002277 }
2278
2279 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002280 if (*numParams == 0)
2281 {
2282 return false;
2283 }
2284
2285 return true;
2286}
2287
2288bool ValidateRobustStateQuery(ValidationContext *context,
2289 GLenum pname,
2290 GLsizei bufSize,
2291 GLenum *nativeType,
2292 unsigned int *numParams)
2293{
2294 if (!ValidateRobustEntryPoint(context, bufSize))
2295 {
2296 return false;
2297 }
2298
2299 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2300 {
2301 return false;
2302 }
2303
2304 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002305 {
2306 return false;
2307 }
2308
2309 return true;
2310}
2311
Jamie Madillc29968b2016-01-20 11:17:23 -05002312bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2313 GLenum target,
2314 GLint level,
2315 GLenum internalformat,
2316 bool isSubImage,
2317 GLint xoffset,
2318 GLint yoffset,
2319 GLint zoffset,
2320 GLint x,
2321 GLint y,
2322 GLsizei width,
2323 GLsizei height,
2324 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002325 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002326{
Brandon Jones6cad5662017-06-14 13:25:13 -07002327 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002328 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002329 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2330 return false;
2331 }
2332
2333 if (width < 0 || height < 0)
2334 {
2335 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002336 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002337 }
2338
He Yunchaoced53ae2016-11-29 15:00:51 +08002339 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2340 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002341 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002342 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002343 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002344 }
2345
2346 if (border != 0)
2347 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002348 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002349 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002350 }
2351
2352 if (!ValidMipLevel(context, target, level))
2353 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002354 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002355 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002356 }
2357
Jamie Madill51f40ec2016-06-15 14:06:00 -04002358 const auto &state = context->getGLState();
2359 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002360 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002361 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002362 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002363 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002364 }
2365
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002366 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002367 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002368 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002369 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002370 }
2371
Martin Radev138064f2016-07-15 12:03:41 +03002372 if (readFramebuffer->getReadBufferState() == GL_NONE)
2373 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002374 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002375 return false;
2376 }
2377
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002378 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2379 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002380 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002381 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002382 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2383 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002384 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002385 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002386 return false;
2387 }
2388
Martin Radev04e2c3b2017-07-27 16:54:35 +03002389 // ANGLE_multiview spec, Revision 1:
2390 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2391 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2392 // is not NONE.
2393 if (source->getMultiviewLayout() != GL_NONE)
2394 {
2395 context->handleError(InvalidFramebufferOperation()
2396 << "The active read framebuffer object has multiview attachments.");
2397 return false;
2398 }
2399
Geoff Langaae65a42014-05-26 12:43:44 -04002400 const gl::Caps &caps = context->getCaps();
2401
Geoff Langaae65a42014-05-26 12:43:44 -04002402 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002403 switch (target)
2404 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002405 case GL_TEXTURE_2D:
2406 maxDimension = caps.max2DTextureSize;
2407 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002408
He Yunchaoced53ae2016-11-29 15:00:51 +08002409 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2410 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2411 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2412 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2413 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2414 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2415 maxDimension = caps.maxCubeMapTextureSize;
2416 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002417
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002418 case GL_TEXTURE_RECTANGLE_ANGLE:
2419 maxDimension = caps.maxRectangleTextureSize;
2420 break;
2421
He Yunchaoced53ae2016-11-29 15:00:51 +08002422 case GL_TEXTURE_2D_ARRAY:
2423 maxDimension = caps.max2DTextureSize;
2424 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002425
He Yunchaoced53ae2016-11-29 15:00:51 +08002426 case GL_TEXTURE_3D:
2427 maxDimension = caps.max3DTextureSize;
2428 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002429
He Yunchaoced53ae2016-11-29 15:00:51 +08002430 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002431 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002432 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002433 }
2434
Jamie Madillc29968b2016-01-20 11:17:23 -05002435 gl::Texture *texture =
2436 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002437 if (!texture)
2438 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002439 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002440 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002441 }
2442
Geoff Lang69cce582015-09-17 13:20:36 -04002443 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002444 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002445 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002446 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002447 }
2448
Geoff Langca271392017-04-05 12:30:00 -04002449 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002450 isSubImage ? *texture->getFormat(target, level).info
2451 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002452
Geoff Lang966c9402017-04-18 12:38:27 -04002453 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002454 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002455 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002456 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002457 }
2458
2459 if (isSubImage)
2460 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002461 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2462 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2463 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002464 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002465 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002466 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002467 }
2468 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002469 else
2470 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002471 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002472 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002473 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002474 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002475 }
2476
Geoff Langeb66a6e2016-10-31 13:06:12 -04002477 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002478 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002479 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002480 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002481 }
2482
2483 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002484 if (static_cast<int>(width) > maxLevelDimension ||
2485 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002486 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002487 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002488 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002489 }
2490 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002491
Jamie Madill0c8abca2016-07-22 20:21:26 -04002492 if (textureFormatOut)
2493 {
2494 *textureFormatOut = texture->getFormat(target, level);
2495 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002496
2497 // Detect texture copying feedback loops for WebGL.
2498 if (context->getExtensions().webglCompatibility)
2499 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002500 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002501 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002502 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002503 return false;
2504 }
2505 }
2506
Jamie Madill560a8d82014-05-21 13:06:20 -04002507 return true;
2508}
2509
Jiajia Qind9671222016-11-29 16:30:31 +08002510bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002511{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002512 switch (mode)
2513 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002514 case GL_POINTS:
2515 case GL_LINES:
2516 case GL_LINE_LOOP:
2517 case GL_LINE_STRIP:
2518 case GL_TRIANGLES:
2519 case GL_TRIANGLE_STRIP:
2520 case GL_TRIANGLE_FAN:
2521 break;
2522 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002523 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002524 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002525 }
2526
Jamie Madill250d33f2014-06-06 17:09:03 -04002527 if (count < 0)
2528 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002529 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002530 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002531 }
2532
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002533 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002534
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002535 const Extensions &extensions = context->getExtensions();
2536
2537 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2538 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2539 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2540 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002541 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002542 // Check for mapped buffers
2543 // TODO(jmadill): Optimize this check for non - WebGL contexts.
2544 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
2545 {
2546 context->handleError(InvalidOperation());
2547 return false;
2548 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002549 }
2550
Jamie Madillcbcde722017-01-06 14:50:00 -05002551 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2552 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002553 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002554 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002555 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002556 const FramebufferAttachment *dsAttachment =
2557 framebuffer->getStencilOrDepthStencilAttachment();
2558 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002559 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002560 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002561
2562 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2563 bool differentWritemasks =
2564 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2565 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2566 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2567 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2568
2569 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002570 {
Martin Radevffe754b2017-07-31 10:38:07 +03002571 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002572 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002573 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2574 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002575 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002576 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002577 return false;
2578 }
Jamie Madillac528012014-06-20 13:21:23 -04002579 }
2580
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002581 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002582 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002583 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002584 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002585 }
2586
Geoff Lang7dd2e102014-11-10 15:19:26 -05002587 gl::Program *program = state.getProgram();
2588 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002589 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002590 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002591 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002592 }
2593
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002594 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002595 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002596 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002597 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002598 }
2599
Martin Radevffe754b2017-07-31 10:38:07 +03002600 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002601 {
Martin Radevda8e2572017-09-12 17:21:16 +03002602 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002603 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002604 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002605 {
2606 context->handleError(InvalidOperation() << "The number of views in the active program "
2607 "and draw framebuffer does not match.");
2608 return false;
2609 }
Martin Radev7e69f762017-07-27 14:54:13 +03002610
2611 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2612 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2613 framebufferNumViews > 1)
2614 {
2615 context->handleError(InvalidOperation()
2616 << "There is an active transform feedback object "
2617 "when the number of views in the active draw "
2618 "framebuffer is greater than 1.");
2619 return false;
2620 }
Martin Radevffe754b2017-07-31 10:38:07 +03002621
2622 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2623 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2624 {
2625 context->handleError(InvalidOperation() << "There is an active query for target "
2626 "GL_TIME_ELAPSED_EXT when the number of "
2627 "views in the active draw framebuffer is "
2628 "greater than 1.");
2629 return false;
2630 }
Martin Radev7cf61662017-07-26 17:10:53 +03002631 }
2632
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002633 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002634 for (unsigned int uniformBlockIndex = 0;
2635 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002636 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002637 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002638 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002639 const OffsetBindingPointer<Buffer> &uniformBuffer =
2640 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002641
Geoff Lang5d124a62015-09-15 13:03:27 -04002642 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002643 {
2644 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002645 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002646 InvalidOperation()
2647 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002648 return false;
2649 }
2650
Geoff Lang5d124a62015-09-15 13:03:27 -04002651 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002652 if (uniformBufferSize == 0)
2653 {
2654 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002655 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002656 }
2657
Jamie Madill62d31cb2015-09-11 13:25:51 -04002658 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002659 {
2660 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002661 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002662 InvalidOperation()
2663 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002664 return false;
2665 }
2666 }
2667
Geoff Lange0cff192017-05-30 13:04:56 -04002668 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002669 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002670 {
Geoff Lange0cff192017-05-30 13:04:56 -04002671 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002672 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2673 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002674 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002675 return false;
2676 }
Geoff Lange0cff192017-05-30 13:04:56 -04002677
Geoff Lang9ab5b822017-05-30 16:19:23 -04002678 // Detect that the vertex shader input types match the attribute types
2679 if (!ValidateVertexShaderAttributeTypeMatch(context))
2680 {
2681 return false;
2682 }
2683
Geoff Lange0cff192017-05-30 13:04:56 -04002684 // Detect that the color buffer types match the fragment shader output types
2685 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2686 {
2687 return false;
2688 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002689 }
2690
Jamie Madill250d33f2014-06-06 17:09:03 -04002691 // No-op if zero count
2692 return (count > 0);
2693}
2694
Jamie Madillc1d770e2017-04-13 17:31:24 -04002695bool ValidateDrawArraysCommon(ValidationContext *context,
2696 GLenum mode,
2697 GLint first,
2698 GLsizei count,
2699 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002700{
Jamie Madillfd716582014-06-06 17:09:04 -04002701 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002702 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002703 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002704 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002705 }
2706
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002707 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002708 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002709 if (curTransformFeedback && curTransformFeedback->isActive() &&
2710 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002711 {
2712 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002713 // that does not match the current transform feedback object's draw mode (if transform
2714 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002715 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002716 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002717 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002718 }
2719
Jiajia Qind9671222016-11-29 16:30:31 +08002720 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002721 {
2722 return false;
2723 }
2724
Corentin Wallez71168a02016-12-19 15:11:18 -08002725 // Check the computation of maxVertex doesn't overflow.
2726 // - first < 0 or count < 0 have been checked as an error condition
2727 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2728 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2729 ASSERT(count > 0 && first >= 0);
2730 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2731 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002732 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002733 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002734 return false;
2735 }
2736
Corentin Wallez71168a02016-12-19 15:11:18 -08002737 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002738 {
2739 return false;
2740 }
2741
2742 return true;
2743}
2744
He Yunchaoced53ae2016-11-29 15:00:51 +08002745bool ValidateDrawArraysInstancedANGLE(Context *context,
2746 GLenum mode,
2747 GLint first,
2748 GLsizei count,
2749 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002750{
Geoff Lang63c5a592017-09-27 14:08:16 -04002751 if (!context->getExtensions().instancedArrays)
2752 {
2753 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2754 return false;
2755 }
2756
Corentin Wallez170efbf2017-05-02 13:45:01 -04002757 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002758 {
2759 return false;
2760 }
2761
Corentin Wallez0dc97812017-06-22 14:38:44 -04002762 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002763}
2764
Jiajia Qind9671222016-11-29 16:30:31 +08002765bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002766{
Jamie Madill250d33f2014-06-06 17:09:03 -04002767 switch (type)
2768 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002769 case GL_UNSIGNED_BYTE:
2770 case GL_UNSIGNED_SHORT:
2771 break;
2772 case GL_UNSIGNED_INT:
2773 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2774 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002775 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002776 return false;
2777 }
2778 break;
2779 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002780 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002781 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002782 }
2783
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002784 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002785
2786 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002787 if (curTransformFeedback && curTransformFeedback->isActive() &&
2788 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002789 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002790 // It is an invalid operation to call DrawElements, DrawRangeElements or
2791 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002792 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002793 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002794 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002795 }
2796
Jiajia Qind9671222016-11-29 16:30:31 +08002797 return true;
2798}
2799
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002800bool ValidateDrawElementsCommon(ValidationContext *context,
2801 GLenum mode,
2802 GLsizei count,
2803 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002804 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002805 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002806{
2807 if (!ValidateDrawElementsBase(context, type))
2808 return false;
2809
2810 const State &state = context->getGLState();
2811
Corentin Wallez170efbf2017-05-02 13:45:01 -04002812 if (!ValidateDrawBase(context, mode, count))
2813 {
2814 return false;
2815 }
2816
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002817 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2818 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2819 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2820 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002821 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002822 // Check for mapped buffers
2823 // TODO(jmadill): Optimize this check for non - WebGL contexts.
2824 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
2825 {
2826 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2827 return false;
2828 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002829 }
2830
He Yunchaoced53ae2016-11-29 15:00:51 +08002831 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002832 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002833
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002834 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2835
2836 if (context->getExtensions().webglCompatibility)
2837 {
2838 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2839 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2840 {
2841 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2842 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2843 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002844 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002845 return false;
2846 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002847
2848 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2849 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2850 // error is generated.
2851 if (reinterpret_cast<intptr_t>(indices) < 0)
2852 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002853 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002854 return false;
2855 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002856 }
2857
2858 if (context->getExtensions().webglCompatibility ||
2859 !context->getGLState().areClientArraysEnabled())
2860 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002861 if (!elementArrayBuffer && count > 0)
2862 {
2863 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2864 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2865 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002866 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002867 return false;
2868 }
2869 }
2870
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002871 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002872 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002873 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002874 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002875 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2876 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2877 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2878 constexpr uint64_t kMaxTypeSize = 8;
2879 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2880 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2881 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002882
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002883 uint64_t typeSize = typeBytes;
2884 uint64_t elementCount = static_cast<uint64_t>(count);
2885 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2886
2887 // Doing the multiplication here is overflow-safe
2888 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2889
2890 // The offset can be any value, check for overflows
2891 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2892 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002893 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002894 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002895 return false;
2896 }
2897
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002898 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2899 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002900 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002901 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002902 return false;
2903 }
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002904
Corentin Wallez487653b2017-09-01 17:17:55 -04002905 ASSERT(isPow2(typeSize) && typeSize > 0);
2906 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002907 {
2908 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
2909 return false;
2910 }
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002911 }
2912 else if (!indices)
2913 {
2914 // This is an application error that would normally result in a crash,
2915 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002916 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04002917 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002918 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002919 }
2920
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002921 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002922 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002923 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2924 // access is enabled.
2925 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2926 {
2927 return false;
2928 }
2929 }
2930 else
2931 {
2932 // Use the parameter buffer to retrieve and cache the index range.
2933 const auto &params = context->getParams<HasIndexRange>();
2934 const auto &indexRangeOpt = params.getIndexRange();
2935 if (!indexRangeOpt.valid())
2936 {
2937 // Unexpected error.
2938 return false;
2939 }
2940
2941 // If we use an index greater than our maximum supported index range, return an error.
2942 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2943 // return an error if possible here.
2944 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2945 {
2946 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2947 return false;
2948 }
2949
2950 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2951 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2952 {
2953 return false;
2954 }
2955
2956 // No op if there are no real indices in the index data (all are primitive restart).
2957 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002958 }
2959
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002960 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002961}
2962
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002963bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2964 GLenum mode,
2965 GLsizei count,
2966 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002967 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002968 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002969{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002970 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002971}
2972
Geoff Lang3edfe032015-09-04 16:38:24 -04002973bool ValidateDrawElementsInstancedANGLE(Context *context,
2974 GLenum mode,
2975 GLsizei count,
2976 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002977 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002978 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002979{
Geoff Lang63c5a592017-09-27 14:08:16 -04002980 if (!context->getExtensions().instancedArrays)
2981 {
2982 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2983 return false;
2984 }
2985
Corentin Wallez170efbf2017-05-02 13:45:01 -04002986 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002987 {
2988 return false;
2989 }
2990
Corentin Wallez0dc97812017-06-22 14:38:44 -04002991 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002992}
2993
He Yunchaoced53ae2016-11-29 15:00:51 +08002994bool ValidateFramebufferTextureBase(Context *context,
2995 GLenum target,
2996 GLenum attachment,
2997 GLuint texture,
2998 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002999{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003000 if (!ValidFramebufferTarget(target))
3001 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003002 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003003 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003004 }
3005
3006 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003007 {
3008 return false;
3009 }
3010
Jamie Madill55ec3b12014-07-03 10:38:57 -04003011 if (texture != 0)
3012 {
3013 gl::Texture *tex = context->getTexture(texture);
3014
Jamie Madillbe849e42017-05-02 15:49:00 -04003015 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003016 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003017 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003018 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003019 }
3020
3021 if (level < 0)
3022 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003023 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003024 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003025 }
3026 }
3027
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003028 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003029 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003030
Jamie Madill84115c92015-04-23 15:00:07 -04003031 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003032 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003033 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003034 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003035 }
3036
3037 return true;
3038}
3039
Geoff Langb1196682014-07-23 13:47:29 -04003040bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003041{
3042 if (program == 0)
3043 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003044 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003045 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003046 }
3047
Dian Xiang769769a2015-09-09 15:20:08 -07003048 gl::Program *programObject = GetValidProgram(context, program);
3049 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003050 {
3051 return false;
3052 }
3053
Jamie Madill0063c512014-08-25 15:47:53 -04003054 if (!programObject || !programObject->isLinked())
3055 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003056 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003057 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003058 }
3059
Geoff Lang7dd2e102014-11-10 15:19:26 -05003060 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003061 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003062 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003063 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003064 }
3065
Jamie Madill0063c512014-08-25 15:47:53 -04003066 return true;
3067}
3068
Geoff Langf41d0ee2016-10-07 13:04:23 -04003069static bool ValidateSizedGetUniform(Context *context,
3070 GLuint program,
3071 GLint location,
3072 GLsizei bufSize,
3073 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003074{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003075 if (length)
3076 {
3077 *length = 0;
3078 }
3079
Jamie Madill78f41802014-08-25 15:47:55 -04003080 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003081 {
Jamie Madill78f41802014-08-25 15:47:55 -04003082 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003083 }
3084
Geoff Langf41d0ee2016-10-07 13:04:23 -04003085 if (bufSize < 0)
3086 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003087 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003088 return false;
3089 }
3090
Jamie Madilla502c742014-08-28 17:19:13 -04003091 gl::Program *programObject = context->getProgram(program);
3092 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003093
Jamie Madill78f41802014-08-25 15:47:55 -04003094 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003095 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003096 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003097 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003098 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003099 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003100 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003101 }
3102
Geoff Langf41d0ee2016-10-07 13:04:23 -04003103 if (length)
3104 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003105 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003106 }
3107
Jamie Madill0063c512014-08-25 15:47:53 -04003108 return true;
3109}
3110
He Yunchaoced53ae2016-11-29 15:00:51 +08003111bool ValidateGetnUniformfvEXT(Context *context,
3112 GLuint program,
3113 GLint location,
3114 GLsizei bufSize,
3115 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003116{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003117 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003118}
3119
He Yunchaoced53ae2016-11-29 15:00:51 +08003120bool ValidateGetnUniformivEXT(Context *context,
3121 GLuint program,
3122 GLint location,
3123 GLsizei bufSize,
3124 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003125{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003126 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3127}
3128
3129bool ValidateGetUniformfvRobustANGLE(Context *context,
3130 GLuint program,
3131 GLint location,
3132 GLsizei bufSize,
3133 GLsizei *length,
3134 GLfloat *params)
3135{
3136 if (!ValidateRobustEntryPoint(context, bufSize))
3137 {
3138 return false;
3139 }
3140
3141 // bufSize is validated in ValidateSizedGetUniform
3142 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3143}
3144
3145bool ValidateGetUniformivRobustANGLE(Context *context,
3146 GLuint program,
3147 GLint location,
3148 GLsizei bufSize,
3149 GLsizei *length,
3150 GLint *params)
3151{
3152 if (!ValidateRobustEntryPoint(context, bufSize))
3153 {
3154 return false;
3155 }
3156
3157 // bufSize is validated in ValidateSizedGetUniform
3158 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3159}
3160
3161bool ValidateGetUniformuivRobustANGLE(Context *context,
3162 GLuint program,
3163 GLint location,
3164 GLsizei bufSize,
3165 GLsizei *length,
3166 GLuint *params)
3167{
3168 if (!ValidateRobustEntryPoint(context, bufSize))
3169 {
3170 return false;
3171 }
3172
3173 if (context->getClientMajorVersion() < 3)
3174 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003175 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003176 return false;
3177 }
3178
3179 // bufSize is validated in ValidateSizedGetUniform
3180 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003181}
3182
He Yunchaoced53ae2016-11-29 15:00:51 +08003183bool ValidateDiscardFramebufferBase(Context *context,
3184 GLenum target,
3185 GLsizei numAttachments,
3186 const GLenum *attachments,
3187 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003188{
3189 if (numAttachments < 0)
3190 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003191 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003192 return false;
3193 }
3194
3195 for (GLsizei i = 0; i < numAttachments; ++i)
3196 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003197 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003198 {
3199 if (defaultFramebuffer)
3200 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003201 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003202 return false;
3203 }
3204
3205 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3206 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003207 context->handleError(InvalidOperation() << "Requested color attachment is "
3208 "greater than the maximum supported "
3209 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003210 return false;
3211 }
3212 }
3213 else
3214 {
3215 switch (attachments[i])
3216 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003217 case GL_DEPTH_ATTACHMENT:
3218 case GL_STENCIL_ATTACHMENT:
3219 case GL_DEPTH_STENCIL_ATTACHMENT:
3220 if (defaultFramebuffer)
3221 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003222 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3223 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003224 return false;
3225 }
3226 break;
3227 case GL_COLOR:
3228 case GL_DEPTH:
3229 case GL_STENCIL:
3230 if (!defaultFramebuffer)
3231 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003232 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3233 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003234 return false;
3235 }
3236 break;
3237 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003238 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003239 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003240 }
3241 }
3242 }
3243
3244 return true;
3245}
3246
Austin Kinross6ee1e782015-05-29 17:05:37 -07003247bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3248{
3249 // Note that debug marker calls must not set error state
3250
3251 if (length < 0)
3252 {
3253 return false;
3254 }
3255
3256 if (marker == nullptr)
3257 {
3258 return false;
3259 }
3260
3261 return true;
3262}
3263
3264bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3265{
3266 // Note that debug marker calls must not set error state
3267
3268 if (length < 0)
3269 {
3270 return false;
3271 }
3272
3273 if (length > 0 && marker == nullptr)
3274 {
3275 return false;
3276 }
3277
3278 return true;
3279}
3280
Geoff Langdcab33b2015-07-21 13:03:16 -04003281bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003282 GLenum target,
3283 egl::Image *image)
3284{
Geoff Langa8406172015-07-21 16:53:39 -04003285 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3286 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003287 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003288 return false;
3289 }
3290
3291 switch (target)
3292 {
3293 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003294 if (!context->getExtensions().eglImage)
3295 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003296 context->handleError(InvalidEnum()
3297 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003298 }
3299 break;
3300
3301 case GL_TEXTURE_EXTERNAL_OES:
3302 if (!context->getExtensions().eglImageExternal)
3303 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003304 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3305 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003306 }
Geoff Langa8406172015-07-21 16:53:39 -04003307 break;
3308
3309 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003310 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003311 return false;
3312 }
3313
Jamie Madill61e16b42017-06-19 11:13:23 -04003314 ASSERT(context->getCurrentDisplay());
3315 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003316 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003317 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003318 return false;
3319 }
3320
3321 if (image->getSamples() > 0)
3322 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003323 context->handleError(InvalidOperation()
3324 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003325 return false;
3326 }
3327
Geoff Langca271392017-04-05 12:30:00 -04003328 const TextureCaps &textureCaps =
3329 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003330 if (!textureCaps.texturable)
3331 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003332 context->handleError(InvalidOperation()
3333 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003334 return false;
3335 }
3336
Geoff Langdcab33b2015-07-21 13:03:16 -04003337 return true;
3338}
3339
3340bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003341 GLenum target,
3342 egl::Image *image)
3343{
Geoff Langa8406172015-07-21 16:53:39 -04003344 if (!context->getExtensions().eglImage)
3345 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003346 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003347 return false;
3348 }
3349
3350 switch (target)
3351 {
3352 case GL_RENDERBUFFER:
3353 break;
3354
3355 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003356 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003357 return false;
3358 }
3359
Jamie Madill61e16b42017-06-19 11:13:23 -04003360 ASSERT(context->getCurrentDisplay());
3361 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003363 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003364 return false;
3365 }
3366
Geoff Langca271392017-04-05 12:30:00 -04003367 const TextureCaps &textureCaps =
3368 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003369 if (!textureCaps.renderable)
3370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003371 context->handleError(InvalidOperation()
3372 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003373 return false;
3374 }
3375
Geoff Langdcab33b2015-07-21 13:03:16 -04003376 return true;
3377}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003378
3379bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3380{
Geoff Lang36167ab2015-12-07 10:27:14 -05003381 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003382 {
3383 // The default VAO should always exist
3384 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003385 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003386 return false;
3387 }
3388
3389 return true;
3390}
3391
Geoff Langc5629752015-12-07 16:29:04 -05003392bool ValidateProgramBinaryBase(Context *context,
3393 GLuint program,
3394 GLenum binaryFormat,
3395 const void *binary,
3396 GLint length)
3397{
3398 Program *programObject = GetValidProgram(context, program);
3399 if (programObject == nullptr)
3400 {
3401 return false;
3402 }
3403
3404 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3405 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3406 programBinaryFormats.end())
3407 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003408 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003409 return false;
3410 }
3411
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003412 if (context->hasActiveTransformFeedback(program))
3413 {
3414 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003415 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3416 "is associated with an active transform "
3417 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003418 return false;
3419 }
3420
Geoff Langc5629752015-12-07 16:29:04 -05003421 return true;
3422}
3423
3424bool ValidateGetProgramBinaryBase(Context *context,
3425 GLuint program,
3426 GLsizei bufSize,
3427 GLsizei *length,
3428 GLenum *binaryFormat,
3429 void *binary)
3430{
3431 Program *programObject = GetValidProgram(context, program);
3432 if (programObject == nullptr)
3433 {
3434 return false;
3435 }
3436
3437 if (!programObject->isLinked())
3438 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003439 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003440 return false;
3441 }
3442
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003443 if (context->getCaps().programBinaryFormats.empty())
3444 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003445 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003446 return false;
3447 }
3448
Geoff Langc5629752015-12-07 16:29:04 -05003449 return true;
3450}
Jamie Madillc29968b2016-01-20 11:17:23 -05003451
Jamie Madillc29968b2016-01-20 11:17:23 -05003452bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3453{
3454 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003455 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003456 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003457 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3458 return false;
3459 }
3460 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3461 {
3462 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003463 return false;
3464 }
3465
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003466 ASSERT(context->getGLState().getDrawFramebuffer());
3467 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003468 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3469
3470 // This should come first before the check for the default frame buffer
3471 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3472 // rather than INVALID_OPERATION
3473 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3474 {
3475 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3476
3477 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003478 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3479 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003480 {
3481 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003482 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3483 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3484 // 3.1 is still a bit ambiguous about the error, but future specs are
3485 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003486 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003487 return false;
3488 }
3489 else if (bufs[colorAttachment] >= maxColorAttachment)
3490 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003491 context->handleError(InvalidOperation()
3492 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003493 return false;
3494 }
3495 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3496 frameBufferId != 0)
3497 {
3498 // INVALID_OPERATION-GL is bound to buffer and ith argument
3499 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003500 context->handleError(InvalidOperation()
3501 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003502 return false;
3503 }
3504 }
3505
3506 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3507 // and n is not 1 or bufs is bound to value other than BACK and NONE
3508 if (frameBufferId == 0)
3509 {
3510 if (n != 1)
3511 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003512 context->handleError(InvalidOperation()
3513 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003514 return false;
3515 }
3516
3517 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3518 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003519 context->handleError(
3520 InvalidOperation()
3521 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003522 return false;
3523 }
3524 }
3525
3526 return true;
3527}
3528
Geoff Lang496c02d2016-10-20 11:38:11 -07003529bool ValidateGetBufferPointervBase(Context *context,
3530 GLenum target,
3531 GLenum pname,
3532 GLsizei *length,
3533 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003534{
Geoff Lang496c02d2016-10-20 11:38:11 -07003535 if (length)
3536 {
3537 *length = 0;
3538 }
3539
3540 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3541 {
3542 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003543 InvalidOperation()
3544 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003545 return false;
3546 }
3547
Olli Etuaho4f667482016-03-30 15:56:35 +03003548 if (!ValidBufferTarget(context, target))
3549 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003550 context->handleError(InvalidEnum() << "Buffer target not valid: 0x" << std::hex
3551 << std::uppercase << target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003552 return false;
3553 }
3554
Geoff Lang496c02d2016-10-20 11:38:11 -07003555 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003556 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003557 case GL_BUFFER_MAP_POINTER:
3558 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003559
Geoff Lang496c02d2016-10-20 11:38:11 -07003560 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003561 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003562 return false;
3563 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003564
3565 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3566 // target bound to zero generate an INVALID_OPERATION error."
3567 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003568 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003569 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003570 context->handleError(InvalidOperation()
3571 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003572 return false;
3573 }
3574
Geoff Lang496c02d2016-10-20 11:38:11 -07003575 if (length)
3576 {
3577 *length = 1;
3578 }
3579
Olli Etuaho4f667482016-03-30 15:56:35 +03003580 return true;
3581}
3582
3583bool ValidateUnmapBufferBase(Context *context, GLenum target)
3584{
3585 if (!ValidBufferTarget(context, target))
3586 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003587 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003588 return false;
3589 }
3590
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003591 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003592
3593 if (buffer == nullptr || !buffer->isMapped())
3594 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003595 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003596 return false;
3597 }
3598
3599 return true;
3600}
3601
3602bool ValidateMapBufferRangeBase(Context *context,
3603 GLenum target,
3604 GLintptr offset,
3605 GLsizeiptr length,
3606 GLbitfield access)
3607{
3608 if (!ValidBufferTarget(context, target))
3609 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003610 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003611 return false;
3612 }
3613
Brandon Jones6cad5662017-06-14 13:25:13 -07003614 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003615 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003616 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3617 return false;
3618 }
3619
3620 if (length < 0)
3621 {
3622 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003623 return false;
3624 }
3625
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003626 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003627
3628 if (!buffer)
3629 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003630 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003631 return false;
3632 }
3633
3634 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003635 CheckedNumeric<size_t> checkedOffset(offset);
3636 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003637
Jamie Madille2e406c2016-06-02 13:04:10 -04003638 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003639 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003640 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003641 return false;
3642 }
3643
3644 // Check for invalid bits in the mask
3645 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3646 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3647 GL_MAP_UNSYNCHRONIZED_BIT;
3648
3649 if (access & ~(allAccessBits))
3650 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003651 context->handleError(InvalidValue()
3652 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003653 return false;
3654 }
3655
3656 if (length == 0)
3657 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003658 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003659 return false;
3660 }
3661
3662 if (buffer->isMapped())
3663 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003664 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003665 return false;
3666 }
3667
3668 // Check for invalid bit combinations
3669 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003671 context->handleError(InvalidOperation()
3672 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003673 return false;
3674 }
3675
3676 GLbitfield writeOnlyBits =
3677 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3678
3679 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3680 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003681 context->handleError(InvalidOperation()
3682 << "Invalid access bits when mapping buffer for reading: 0x"
3683 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003684 return false;
3685 }
3686
3687 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3688 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003689 context->handleError(
3690 InvalidOperation()
3691 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003692 return false;
3693 }
Geoff Lang79f71042017-08-14 16:43:43 -04003694
3695 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003696}
3697
3698bool ValidateFlushMappedBufferRangeBase(Context *context,
3699 GLenum target,
3700 GLintptr offset,
3701 GLsizeiptr length)
3702{
Brandon Jones6cad5662017-06-14 13:25:13 -07003703 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003704 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003705 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3706 return false;
3707 }
3708
3709 if (length < 0)
3710 {
3711 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003712 return false;
3713 }
3714
3715 if (!ValidBufferTarget(context, target))
3716 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003717 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003718 return false;
3719 }
3720
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003721 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003722
3723 if (buffer == nullptr)
3724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003725 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003726 return false;
3727 }
3728
3729 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3730 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003731 context->handleError(InvalidOperation()
3732 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003733 return false;
3734 }
3735
3736 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003737 CheckedNumeric<size_t> checkedOffset(offset);
3738 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003739
Jamie Madille2e406c2016-06-02 13:04:10 -04003740 if (!checkedSize.IsValid() ||
3741 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003743 context->handleError(InvalidValue()
3744 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003745 return false;
3746 }
3747
3748 return true;
3749}
3750
Olli Etuaho41997e72016-03-10 13:38:39 +02003751bool ValidateGenOrDelete(Context *context, GLint n)
3752{
3753 if (n < 0)
3754 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003755 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003756 return false;
3757 }
3758 return true;
3759}
3760
Geoff Langff5b2d52016-09-07 11:32:23 -04003761bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3762{
3763 if (!context->getExtensions().robustClientMemory)
3764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003765 context->handleError(InvalidOperation()
3766 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003767 return false;
3768 }
3769
3770 if (bufSize < 0)
3771 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003772 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003773 return false;
3774 }
3775
3776 return true;
3777}
3778
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003779bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3780{
3781 if (bufSize < numParams)
3782 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003783 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3784 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003785 return false;
3786 }
3787
3788 return true;
3789}
3790
Jamie Madillbe849e42017-05-02 15:49:00 -04003791bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3792 GLenum target,
3793 GLenum attachment,
3794 GLenum pname,
3795 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003796{
Geoff Langff5b2d52016-09-07 11:32:23 -04003797 if (!ValidFramebufferTarget(target))
3798 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003799 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003800 return false;
3801 }
3802
3803 int clientVersion = context->getClientMajorVersion();
3804
3805 switch (pname)
3806 {
3807 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3808 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3809 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3810 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3811 break;
3812
Martin Radeve5285d22017-07-14 16:23:53 +03003813 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3814 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3815 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3816 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3817 if (clientVersion < 3 || !context->getExtensions().multiview)
3818 {
3819 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3820 return false;
3821 }
3822 break;
3823
Geoff Langff5b2d52016-09-07 11:32:23 -04003824 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3825 if (clientVersion < 3 && !context->getExtensions().sRGB)
3826 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003827 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003828 return false;
3829 }
3830 break;
3831
3832 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3833 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3834 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3835 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3836 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3837 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3838 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3839 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3840 if (clientVersion < 3)
3841 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003842 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003843 return false;
3844 }
3845 break;
3846
3847 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003848 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003849 return false;
3850 }
3851
3852 // Determine if the attachment is a valid enum
3853 switch (attachment)
3854 {
3855 case GL_BACK:
3856 case GL_FRONT:
3857 case GL_DEPTH:
3858 case GL_STENCIL:
3859 case GL_DEPTH_STENCIL_ATTACHMENT:
3860 if (clientVersion < 3)
3861 {
Geoff Langfa125c92017-10-24 13:01:46 -04003862 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003863 return false;
3864 }
3865 break;
3866
Geoff Langfa125c92017-10-24 13:01:46 -04003867 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003868 case GL_DEPTH_ATTACHMENT:
3869 case GL_STENCIL_ATTACHMENT:
3870 break;
3871
3872 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003873 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3874 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003875 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3876 {
Geoff Langfa125c92017-10-24 13:01:46 -04003877 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003878 return false;
3879 }
3880 break;
3881 }
3882
3883 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3884 ASSERT(framebuffer);
3885
3886 if (framebuffer->id() == 0)
3887 {
3888 if (clientVersion < 3)
3889 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003890 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003891 return false;
3892 }
3893
3894 switch (attachment)
3895 {
3896 case GL_BACK:
3897 case GL_DEPTH:
3898 case GL_STENCIL:
3899 break;
3900
3901 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003902 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003903 return false;
3904 }
3905 }
3906 else
3907 {
3908 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3909 {
3910 // Valid attachment query
3911 }
3912 else
3913 {
3914 switch (attachment)
3915 {
3916 case GL_DEPTH_ATTACHMENT:
3917 case GL_STENCIL_ATTACHMENT:
3918 break;
3919
3920 case GL_DEPTH_STENCIL_ATTACHMENT:
3921 if (!framebuffer->hasValidDepthStencil())
3922 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003923 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003924 return false;
3925 }
3926 break;
3927
3928 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003929 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003930 return false;
3931 }
3932 }
3933 }
3934
3935 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3936 if (attachmentObject)
3937 {
3938 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3939 attachmentObject->type() == GL_TEXTURE ||
3940 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3941
3942 switch (pname)
3943 {
3944 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3945 if (attachmentObject->type() != GL_RENDERBUFFER &&
3946 attachmentObject->type() != GL_TEXTURE)
3947 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003948 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003949 return false;
3950 }
3951 break;
3952
3953 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3954 if (attachmentObject->type() != GL_TEXTURE)
3955 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003956 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003957 return false;
3958 }
3959 break;
3960
3961 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3962 if (attachmentObject->type() != GL_TEXTURE)
3963 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003964 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003965 return false;
3966 }
3967 break;
3968
3969 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3970 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3971 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003972 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003973 return false;
3974 }
3975 break;
3976
3977 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3978 if (attachmentObject->type() != GL_TEXTURE)
3979 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003980 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003981 return false;
3982 }
3983 break;
3984
3985 default:
3986 break;
3987 }
3988 }
3989 else
3990 {
3991 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3992 // is NONE, then querying any other pname will generate INVALID_ENUM.
3993
3994 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3995 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3996 // INVALID_OPERATION for all other pnames
3997
3998 switch (pname)
3999 {
4000 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4001 break;
4002
4003 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4004 if (clientVersion < 3)
4005 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004006 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004007 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004008 return false;
4009 }
4010 break;
4011
4012 default:
4013 if (clientVersion < 3)
4014 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004015 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004016 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004017 return false;
4018 }
4019 else
4020 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004021 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004022 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004023 return false;
4024 }
4025 }
4026 }
4027
Martin Radeve5285d22017-07-14 16:23:53 +03004028 if (numParams)
4029 {
4030 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4031 {
4032 // Only when the viewport offsets are queried we can have a varying number of output
4033 // parameters.
4034 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4035 *numParams = numViews * 2;
4036 }
4037 else
4038 {
4039 // For all other queries we can have only one output parameter.
4040 *numParams = 1;
4041 }
4042 }
4043
Geoff Langff5b2d52016-09-07 11:32:23 -04004044 return true;
4045}
4046
4047bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4048 GLenum target,
4049 GLenum attachment,
4050 GLenum pname,
4051 GLsizei bufSize,
4052 GLsizei *numParams)
4053{
4054 if (!ValidateRobustEntryPoint(context, bufSize))
4055 {
4056 return false;
4057 }
4058
Jamie Madillbe849e42017-05-02 15:49:00 -04004059 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4060 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004061 {
4062 return false;
4063 }
4064
4065 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4066 {
4067 return false;
4068 }
4069
4070 return true;
4071}
4072
Geoff Langff5b2d52016-09-07 11:32:23 -04004073bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4074 GLenum target,
4075 GLenum pname,
4076 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004077 GLsizei *length,
4078 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004079{
4080 if (!ValidateRobustEntryPoint(context, bufSize))
4081 {
4082 return false;
4083 }
4084
Geoff Langebebe1c2016-10-14 12:01:31 -04004085 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004086 {
4087 return false;
4088 }
4089
Geoff Langebebe1c2016-10-14 12:01:31 -04004090 if (!ValidateRobustBufferSize(context, bufSize, *length))
4091 {
4092 return false;
4093 }
4094
4095 return true;
4096}
4097
Geoff Langebebe1c2016-10-14 12:01:31 -04004098bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4099 GLenum target,
4100 GLenum pname,
4101 GLsizei bufSize,
4102 GLsizei *length,
4103 GLint64 *params)
4104{
4105 if (!ValidateRobustEntryPoint(context, bufSize))
4106 {
4107 return false;
4108 }
4109
4110 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4111 {
4112 return false;
4113 }
4114
4115 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004116 {
4117 return false;
4118 }
4119
4120 return true;
4121}
4122
Jamie Madillbe849e42017-05-02 15:49:00 -04004123bool ValidateGetProgramivBase(ValidationContext *context,
4124 GLuint program,
4125 GLenum pname,
4126 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004127{
4128 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004129 if (numParams)
4130 {
4131 *numParams = 1;
4132 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004133
4134 Program *programObject = GetValidProgram(context, program);
4135 if (!programObject)
4136 {
4137 return false;
4138 }
4139
4140 switch (pname)
4141 {
4142 case GL_DELETE_STATUS:
4143 case GL_LINK_STATUS:
4144 case GL_VALIDATE_STATUS:
4145 case GL_INFO_LOG_LENGTH:
4146 case GL_ATTACHED_SHADERS:
4147 case GL_ACTIVE_ATTRIBUTES:
4148 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4149 case GL_ACTIVE_UNIFORMS:
4150 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4151 break;
4152
4153 case GL_PROGRAM_BINARY_LENGTH:
4154 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4155 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004156 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4157 "requires GL_OES_get_program_binary or "
4158 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004159 return false;
4160 }
4161 break;
4162
4163 case GL_ACTIVE_UNIFORM_BLOCKS:
4164 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4165 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4166 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4167 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4168 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4169 if (context->getClientMajorVersion() < 3)
4170 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004171 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004172 return false;
4173 }
4174 break;
4175
Yunchao He61afff12017-03-14 15:34:03 +08004176 case GL_PROGRAM_SEPARABLE:
Xinghua Cao971f8502017-10-17 13:01:24 +08004177 case GL_COMPUTE_WORK_GROUP_SIZE:
jchen1058f67be2017-10-27 08:59:27 +08004178 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004179 if (context->getClientVersion() < Version(3, 1))
4180 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004181 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004182 return false;
4183 }
4184 break;
4185
Geoff Langff5b2d52016-09-07 11:32:23 -04004186 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004187 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004188 return false;
4189 }
4190
4191 return true;
4192}
4193
4194bool ValidateGetProgramivRobustANGLE(Context *context,
4195 GLuint program,
4196 GLenum pname,
4197 GLsizei bufSize,
4198 GLsizei *numParams)
4199{
4200 if (!ValidateRobustEntryPoint(context, bufSize))
4201 {
4202 return false;
4203 }
4204
Jamie Madillbe849e42017-05-02 15:49:00 -04004205 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004206 {
4207 return false;
4208 }
4209
4210 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4211 {
4212 return false;
4213 }
4214
4215 return true;
4216}
4217
Geoff Lang740d9022016-10-07 11:20:52 -04004218bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4219 GLenum target,
4220 GLenum pname,
4221 GLsizei bufSize,
4222 GLsizei *length,
4223 GLint *params)
4224{
4225 if (!ValidateRobustEntryPoint(context, bufSize))
4226 {
4227 return false;
4228 }
4229
4230 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4231 {
4232 return false;
4233 }
4234
4235 if (!ValidateRobustBufferSize(context, bufSize, *length))
4236 {
4237 return false;
4238 }
4239
4240 return true;
4241}
4242
Geoff Langd7d0ed32016-10-07 11:33:51 -04004243bool ValidateGetShaderivRobustANGLE(Context *context,
4244 GLuint shader,
4245 GLenum pname,
4246 GLsizei bufSize,
4247 GLsizei *length,
4248 GLint *params)
4249{
4250 if (!ValidateRobustEntryPoint(context, bufSize))
4251 {
4252 return false;
4253 }
4254
4255 if (!ValidateGetShaderivBase(context, shader, pname, length))
4256 {
4257 return false;
4258 }
4259
4260 if (!ValidateRobustBufferSize(context, bufSize, *length))
4261 {
4262 return false;
4263 }
4264
4265 return true;
4266}
4267
Geoff Langc1984ed2016-10-07 12:41:00 -04004268bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4269 GLenum target,
4270 GLenum pname,
4271 GLsizei bufSize,
4272 GLsizei *length,
4273 GLfloat *params)
4274{
4275 if (!ValidateRobustEntryPoint(context, bufSize))
4276 {
4277 return false;
4278 }
4279
4280 if (!ValidateGetTexParameterBase(context, target, pname, length))
4281 {
4282 return false;
4283 }
4284
4285 if (!ValidateRobustBufferSize(context, bufSize, *length))
4286 {
4287 return false;
4288 }
4289
4290 return true;
4291}
4292
Geoff Langc1984ed2016-10-07 12:41:00 -04004293bool ValidateGetTexParameterivRobustANGLE(Context *context,
4294 GLenum target,
4295 GLenum pname,
4296 GLsizei bufSize,
4297 GLsizei *length,
4298 GLint *params)
4299{
4300 if (!ValidateRobustEntryPoint(context, bufSize))
4301 {
4302 return false;
4303 }
4304
4305 if (!ValidateGetTexParameterBase(context, target, pname, length))
4306 {
4307 return false;
4308 }
4309
4310 if (!ValidateRobustBufferSize(context, bufSize, *length))
4311 {
4312 return false;
4313 }
4314
4315 return true;
4316}
4317
Geoff Langc1984ed2016-10-07 12:41:00 -04004318bool ValidateTexParameterfvRobustANGLE(Context *context,
4319 GLenum target,
4320 GLenum pname,
4321 GLsizei bufSize,
4322 const GLfloat *params)
4323{
4324 if (!ValidateRobustEntryPoint(context, bufSize))
4325 {
4326 return false;
4327 }
4328
4329 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4330}
4331
Geoff Langc1984ed2016-10-07 12:41:00 -04004332bool ValidateTexParameterivRobustANGLE(Context *context,
4333 GLenum target,
4334 GLenum pname,
4335 GLsizei bufSize,
4336 const GLint *params)
4337{
4338 if (!ValidateRobustEntryPoint(context, bufSize))
4339 {
4340 return false;
4341 }
4342
4343 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4344}
4345
Geoff Langc1984ed2016-10-07 12:41:00 -04004346bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4347 GLuint sampler,
4348 GLenum pname,
4349 GLuint bufSize,
4350 GLsizei *length,
4351 GLfloat *params)
4352{
4353 if (!ValidateRobustEntryPoint(context, bufSize))
4354 {
4355 return false;
4356 }
4357
4358 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4359 {
4360 return false;
4361 }
4362
4363 if (!ValidateRobustBufferSize(context, bufSize, *length))
4364 {
4365 return false;
4366 }
4367
4368 return true;
4369}
4370
Geoff Langc1984ed2016-10-07 12:41:00 -04004371bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4372 GLuint sampler,
4373 GLenum pname,
4374 GLuint bufSize,
4375 GLsizei *length,
4376 GLint *params)
4377{
4378 if (!ValidateRobustEntryPoint(context, bufSize))
4379 {
4380 return false;
4381 }
4382
4383 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4384 {
4385 return false;
4386 }
4387
4388 if (!ValidateRobustBufferSize(context, bufSize, *length))
4389 {
4390 return false;
4391 }
4392
4393 return true;
4394}
4395
Geoff Langc1984ed2016-10-07 12:41:00 -04004396bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4397 GLuint sampler,
4398 GLenum pname,
4399 GLsizei bufSize,
4400 const GLfloat *params)
4401{
4402 if (!ValidateRobustEntryPoint(context, bufSize))
4403 {
4404 return false;
4405 }
4406
4407 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4408}
4409
Geoff Langc1984ed2016-10-07 12:41:00 -04004410bool ValidateSamplerParameterivRobustANGLE(Context *context,
4411 GLuint sampler,
4412 GLenum pname,
4413 GLsizei bufSize,
4414 const GLint *params)
4415{
4416 if (!ValidateRobustEntryPoint(context, bufSize))
4417 {
4418 return false;
4419 }
4420
4421 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4422}
4423
Geoff Lang0b031062016-10-13 14:30:04 -04004424bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4425 GLuint index,
4426 GLenum pname,
4427 GLsizei bufSize,
4428 GLsizei *length,
4429 GLfloat *params)
4430{
4431 if (!ValidateRobustEntryPoint(context, bufSize))
4432 {
4433 return false;
4434 }
4435
4436 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4437 {
4438 return false;
4439 }
4440
4441 if (!ValidateRobustBufferSize(context, bufSize, *length))
4442 {
4443 return false;
4444 }
4445
4446 return true;
4447}
4448
Geoff Lang0b031062016-10-13 14:30:04 -04004449bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4450 GLuint index,
4451 GLenum pname,
4452 GLsizei bufSize,
4453 GLsizei *length,
4454 GLint *params)
4455{
4456 if (!ValidateRobustEntryPoint(context, bufSize))
4457 {
4458 return false;
4459 }
4460
4461 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4462 {
4463 return false;
4464 }
4465
4466 if (!ValidateRobustBufferSize(context, bufSize, *length))
4467 {
4468 return false;
4469 }
4470
4471 return true;
4472}
4473
Geoff Lang0b031062016-10-13 14:30:04 -04004474bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4475 GLuint index,
4476 GLenum pname,
4477 GLsizei bufSize,
4478 GLsizei *length,
4479 void **pointer)
4480{
4481 if (!ValidateRobustEntryPoint(context, bufSize))
4482 {
4483 return false;
4484 }
4485
4486 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4487 {
4488 return false;
4489 }
4490
4491 if (!ValidateRobustBufferSize(context, bufSize, *length))
4492 {
4493 return false;
4494 }
4495
4496 return true;
4497}
4498
Geoff Lang0b031062016-10-13 14:30:04 -04004499bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4500 GLuint index,
4501 GLenum pname,
4502 GLsizei bufSize,
4503 GLsizei *length,
4504 GLint *params)
4505{
4506 if (!ValidateRobustEntryPoint(context, bufSize))
4507 {
4508 return false;
4509 }
4510
4511 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4512 {
4513 return false;
4514 }
4515
4516 if (!ValidateRobustBufferSize(context, bufSize, *length))
4517 {
4518 return false;
4519 }
4520
4521 return true;
4522}
4523
Geoff Lang0b031062016-10-13 14:30:04 -04004524bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4525 GLuint index,
4526 GLenum pname,
4527 GLsizei bufSize,
4528 GLsizei *length,
4529 GLuint *params)
4530{
4531 if (!ValidateRobustEntryPoint(context, bufSize))
4532 {
4533 return false;
4534 }
4535
4536 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4537 {
4538 return false;
4539 }
4540
4541 if (!ValidateRobustBufferSize(context, bufSize, *length))
4542 {
4543 return false;
4544 }
4545
4546 return true;
4547}
4548
Geoff Lang6899b872016-10-14 11:30:13 -04004549bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4550 GLuint program,
4551 GLuint uniformBlockIndex,
4552 GLenum pname,
4553 GLsizei bufSize,
4554 GLsizei *length,
4555 GLint *params)
4556{
4557 if (!ValidateRobustEntryPoint(context, bufSize))
4558 {
4559 return false;
4560 }
4561
4562 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4563 {
4564 return false;
4565 }
4566
4567 if (!ValidateRobustBufferSize(context, bufSize, *length))
4568 {
4569 return false;
4570 }
4571
4572 return true;
4573}
4574
Geoff Lang0a9661f2016-10-20 10:59:20 -07004575bool ValidateGetInternalFormativRobustANGLE(Context *context,
4576 GLenum target,
4577 GLenum internalformat,
4578 GLenum pname,
4579 GLsizei bufSize,
4580 GLsizei *length,
4581 GLint *params)
4582{
4583 if (!ValidateRobustEntryPoint(context, bufSize))
4584 {
4585 return false;
4586 }
4587
4588 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4589 {
4590 return false;
4591 }
4592
4593 if (!ValidateRobustBufferSize(context, bufSize, *length))
4594 {
4595 return false;
4596 }
4597
4598 return true;
4599}
4600
Shao80957d92017-02-20 21:25:59 +08004601bool ValidateVertexFormatBase(ValidationContext *context,
4602 GLuint attribIndex,
4603 GLint size,
4604 GLenum type,
4605 GLboolean pureInteger)
4606{
4607 const Caps &caps = context->getCaps();
4608 if (attribIndex >= caps.maxVertexAttributes)
4609 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004610 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004611 return false;
4612 }
4613
4614 if (size < 1 || size > 4)
4615 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004616 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004617 return false;
Shao80957d92017-02-20 21:25:59 +08004618 }
4619
4620 switch (type)
4621 {
4622 case GL_BYTE:
4623 case GL_UNSIGNED_BYTE:
4624 case GL_SHORT:
4625 case GL_UNSIGNED_SHORT:
4626 break;
4627
4628 case GL_INT:
4629 case GL_UNSIGNED_INT:
4630 if (context->getClientMajorVersion() < 3)
4631 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004632 context->handleError(InvalidEnum()
4633 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004634 return false;
4635 }
4636 break;
4637
4638 case GL_FIXED:
4639 case GL_FLOAT:
4640 if (pureInteger)
4641 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004642 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004643 return false;
4644 }
4645 break;
4646
4647 case GL_HALF_FLOAT:
4648 if (context->getClientMajorVersion() < 3)
4649 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004650 context->handleError(InvalidEnum()
4651 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004652 return false;
4653 }
4654 if (pureInteger)
4655 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004656 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004657 return false;
4658 }
4659 break;
4660
4661 case GL_INT_2_10_10_10_REV:
4662 case GL_UNSIGNED_INT_2_10_10_10_REV:
4663 if (context->getClientMajorVersion() < 3)
4664 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004665 context->handleError(InvalidEnum()
4666 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004667 return false;
4668 }
4669 if (pureInteger)
4670 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004671 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004672 return false;
4673 }
4674 if (size != 4)
4675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004676 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4677 "UNSIGNED_INT_2_10_10_10_REV and "
4678 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004679 return false;
4680 }
4681 break;
4682
4683 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004684 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004685 return false;
4686 }
4687
4688 return true;
4689}
4690
Geoff Lang76e65652017-03-27 14:58:02 -04004691// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4692// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4693// specified clear value and the type of a buffer that is being cleared generates an
4694// INVALID_OPERATION error instead of producing undefined results
4695bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4696 GLint drawbuffer,
4697 const GLenum *validComponentTypes,
4698 size_t validComponentTypeCount)
4699{
4700 const FramebufferAttachment *attachment =
4701 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4702 if (attachment)
4703 {
4704 GLenum componentType = attachment->getFormat().info->componentType;
4705 const GLenum *end = validComponentTypes + validComponentTypeCount;
4706 if (std::find(validComponentTypes, end, componentType) == end)
4707 {
4708 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004709 InvalidOperation()
4710 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004711 return false;
4712 }
4713 }
4714
4715 return true;
4716}
4717
Corentin Wallezb2931602017-04-11 15:58:57 -04004718bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4719 GLsizei imageSize,
4720 GLsizei dataSize)
4721{
4722 if (!ValidateRobustEntryPoint(context, dataSize))
4723 {
4724 return false;
4725 }
4726
4727 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
4728 if (pixelUnpackBuffer == nullptr)
4729 {
4730 if (dataSize < imageSize)
4731 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004732 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004733 }
4734 }
4735 return true;
4736}
4737
Jamie Madillbe849e42017-05-02 15:49:00 -04004738bool ValidateGetBufferParameterBase(ValidationContext *context,
4739 GLenum target,
4740 GLenum pname,
4741 bool pointerVersion,
4742 GLsizei *numParams)
4743{
4744 if (numParams)
4745 {
4746 *numParams = 0;
4747 }
4748
4749 if (!ValidBufferTarget(context, target))
4750 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004751 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004752 return false;
4753 }
4754
4755 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4756 if (!buffer)
4757 {
4758 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004759 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004760 return false;
4761 }
4762
4763 const Extensions &extensions = context->getExtensions();
4764
4765 switch (pname)
4766 {
4767 case GL_BUFFER_USAGE:
4768 case GL_BUFFER_SIZE:
4769 break;
4770
4771 case GL_BUFFER_ACCESS_OES:
4772 if (!extensions.mapBuffer)
4773 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004774 context->handleError(InvalidEnum()
4775 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004776 return false;
4777 }
4778 break;
4779
4780 case GL_BUFFER_MAPPED:
4781 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4782 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4783 !extensions.mapBufferRange)
4784 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004785 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4786 "GL_OES_mapbuffer or "
4787 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004788 return false;
4789 }
4790 break;
4791
4792 case GL_BUFFER_MAP_POINTER:
4793 if (!pointerVersion)
4794 {
4795 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004796 InvalidEnum()
4797 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004798 return false;
4799 }
4800 break;
4801
4802 case GL_BUFFER_ACCESS_FLAGS:
4803 case GL_BUFFER_MAP_OFFSET:
4804 case GL_BUFFER_MAP_LENGTH:
4805 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4806 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004807 context->handleError(InvalidEnum()
4808 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004809 return false;
4810 }
4811 break;
4812
4813 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004814 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004815 return false;
4816 }
4817
4818 // All buffer parameter queries return one value.
4819 if (numParams)
4820 {
4821 *numParams = 1;
4822 }
4823
4824 return true;
4825}
4826
4827bool ValidateGetRenderbufferParameterivBase(Context *context,
4828 GLenum target,
4829 GLenum pname,
4830 GLsizei *length)
4831{
4832 if (length)
4833 {
4834 *length = 0;
4835 }
4836
4837 if (target != GL_RENDERBUFFER)
4838 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004839 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004840 return false;
4841 }
4842
4843 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4844 if (renderbuffer == nullptr)
4845 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004846 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004847 return false;
4848 }
4849
4850 switch (pname)
4851 {
4852 case GL_RENDERBUFFER_WIDTH:
4853 case GL_RENDERBUFFER_HEIGHT:
4854 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4855 case GL_RENDERBUFFER_RED_SIZE:
4856 case GL_RENDERBUFFER_GREEN_SIZE:
4857 case GL_RENDERBUFFER_BLUE_SIZE:
4858 case GL_RENDERBUFFER_ALPHA_SIZE:
4859 case GL_RENDERBUFFER_DEPTH_SIZE:
4860 case GL_RENDERBUFFER_STENCIL_SIZE:
4861 break;
4862
4863 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4864 if (!context->getExtensions().framebufferMultisample)
4865 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004866 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004867 return false;
4868 }
4869 break;
4870
4871 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004872 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004873 return false;
4874 }
4875
4876 if (length)
4877 {
4878 *length = 1;
4879 }
4880 return true;
4881}
4882
4883bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4884{
4885 if (length)
4886 {
4887 *length = 0;
4888 }
4889
4890 if (GetValidShader(context, shader) == nullptr)
4891 {
4892 return false;
4893 }
4894
4895 switch (pname)
4896 {
4897 case GL_SHADER_TYPE:
4898 case GL_DELETE_STATUS:
4899 case GL_COMPILE_STATUS:
4900 case GL_INFO_LOG_LENGTH:
4901 case GL_SHADER_SOURCE_LENGTH:
4902 break;
4903
4904 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4905 if (!context->getExtensions().translatedShaderSource)
4906 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004907 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004908 return false;
4909 }
4910 break;
4911
4912 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004913 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004914 return false;
4915 }
4916
4917 if (length)
4918 {
4919 *length = 1;
4920 }
4921 return true;
4922}
4923
4924bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4925{
4926 if (length)
4927 {
4928 *length = 0;
4929 }
4930
4931 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4932 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004933 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004934 return false;
4935 }
4936
4937 if (context->getTargetTexture(target) == nullptr)
4938 {
4939 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004940 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004941 return false;
4942 }
4943
4944 switch (pname)
4945 {
4946 case GL_TEXTURE_MAG_FILTER:
4947 case GL_TEXTURE_MIN_FILTER:
4948 case GL_TEXTURE_WRAP_S:
4949 case GL_TEXTURE_WRAP_T:
4950 break;
4951
4952 case GL_TEXTURE_USAGE_ANGLE:
4953 if (!context->getExtensions().textureUsage)
4954 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004955 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004956 return false;
4957 }
4958 break;
4959
4960 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4961 if (!context->getExtensions().textureFilterAnisotropic)
4962 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004963 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004964 return false;
4965 }
4966 break;
4967
4968 case GL_TEXTURE_IMMUTABLE_FORMAT:
4969 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4970 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004971 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004972 return false;
4973 }
4974 break;
4975
4976 case GL_TEXTURE_WRAP_R:
4977 case GL_TEXTURE_IMMUTABLE_LEVELS:
4978 case GL_TEXTURE_SWIZZLE_R:
4979 case GL_TEXTURE_SWIZZLE_G:
4980 case GL_TEXTURE_SWIZZLE_B:
4981 case GL_TEXTURE_SWIZZLE_A:
4982 case GL_TEXTURE_BASE_LEVEL:
4983 case GL_TEXTURE_MAX_LEVEL:
4984 case GL_TEXTURE_MIN_LOD:
4985 case GL_TEXTURE_MAX_LOD:
4986 case GL_TEXTURE_COMPARE_MODE:
4987 case GL_TEXTURE_COMPARE_FUNC:
4988 if (context->getClientMajorVersion() < 3)
4989 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004990 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004991 return false;
4992 }
4993 break;
4994
4995 case GL_TEXTURE_SRGB_DECODE_EXT:
4996 if (!context->getExtensions().textureSRGBDecode)
4997 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004998 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004999 return false;
5000 }
5001 break;
5002
5003 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005004 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005005 return false;
5006 }
5007
5008 if (length)
5009 {
5010 *length = 1;
5011 }
5012 return true;
5013}
5014
5015bool ValidateGetVertexAttribBase(Context *context,
5016 GLuint index,
5017 GLenum pname,
5018 GLsizei *length,
5019 bool pointer,
5020 bool pureIntegerEntryPoint)
5021{
5022 if (length)
5023 {
5024 *length = 0;
5025 }
5026
5027 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5028 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005029 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005030 return false;
5031 }
5032
5033 if (index >= context->getCaps().maxVertexAttributes)
5034 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005035 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005036 return false;
5037 }
5038
5039 if (pointer)
5040 {
5041 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5042 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005043 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005044 return false;
5045 }
5046 }
5047 else
5048 {
5049 switch (pname)
5050 {
5051 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5052 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5053 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5054 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5055 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5056 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5057 case GL_CURRENT_VERTEX_ATTRIB:
5058 break;
5059
5060 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5061 static_assert(
5062 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5063 "ANGLE extension enums not equal to GL enums.");
5064 if (context->getClientMajorVersion() < 3 &&
5065 !context->getExtensions().instancedArrays)
5066 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005067 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5068 "requires OpenGL ES 3.0 or "
5069 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005070 return false;
5071 }
5072 break;
5073
5074 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5075 if (context->getClientMajorVersion() < 3)
5076 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005077 context->handleError(
5078 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005079 return false;
5080 }
5081 break;
5082
5083 case GL_VERTEX_ATTRIB_BINDING:
5084 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5085 if (context->getClientVersion() < ES_3_1)
5086 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005087 context->handleError(InvalidEnum()
5088 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005089 return false;
5090 }
5091 break;
5092
5093 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005094 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005095 return false;
5096 }
5097 }
5098
5099 if (length)
5100 {
5101 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5102 {
5103 *length = 4;
5104 }
5105 else
5106 {
5107 *length = 1;
5108 }
5109 }
5110
5111 return true;
5112}
5113
Jamie Madill4928b7c2017-06-20 12:57:39 -04005114bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005115 GLint x,
5116 GLint y,
5117 GLsizei width,
5118 GLsizei height,
5119 GLenum format,
5120 GLenum type,
5121 GLsizei bufSize,
5122 GLsizei *length,
5123 GLsizei *columns,
5124 GLsizei *rows,
5125 void *pixels)
5126{
5127 if (length != nullptr)
5128 {
5129 *length = 0;
5130 }
5131 if (rows != nullptr)
5132 {
5133 *rows = 0;
5134 }
5135 if (columns != nullptr)
5136 {
5137 *columns = 0;
5138 }
5139
5140 if (width < 0 || height < 0)
5141 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005142 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005143 return false;
5144 }
5145
5146 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5147
5148 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5149 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005150 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005151 return false;
5152 }
5153
5154 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5155 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005156 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005157 return false;
5158 }
5159
5160 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5161 ASSERT(framebuffer);
5162
5163 if (framebuffer->getReadBufferState() == GL_NONE)
5164 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005165 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005166 return false;
5167 }
5168
5169 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5170 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5171 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5172 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5173 // situation is an application error that would lead to a crash in ANGLE.
5174 if (readBuffer == nullptr)
5175 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005176 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005177 return false;
5178 }
5179
Martin Radev28031682017-07-28 14:47:56 +03005180 // ANGLE_multiview, Revision 1:
5181 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5182 // current read framebuffer is not NONE.
5183 if (readBuffer->getMultiviewLayout() != GL_NONE)
5184 {
5185 context->handleError(InvalidFramebufferOperation()
5186 << "Attempting to read from a multi-view framebuffer.");
5187 return false;
5188 }
5189
Geoff Lang280ba992017-04-18 16:30:58 -04005190 if (context->getExtensions().webglCompatibility)
5191 {
5192 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5193 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5194 // and type before validating the combination of format and type. However, the
5195 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5196 // verifies that GL_INVALID_OPERATION is generated.
5197 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5198 // dEQP/WebGL.
5199 if (!ValidReadPixelsFormatEnum(context, format))
5200 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005201 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005202 return false;
5203 }
5204
5205 if (!ValidReadPixelsTypeEnum(context, type))
5206 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005207 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005208 return false;
5209 }
5210 }
5211
Jamie Madill4928b7c2017-06-20 12:57:39 -04005212 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5213 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005214 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5215
5216 bool validFormatTypeCombination =
5217 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5218
5219 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5220 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005221 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005222 return false;
5223 }
5224
5225 // Check for pixel pack buffer related API errors
5226 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5227 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5228 {
5229 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005230 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005231 return false;
5232 }
5233
5234 // .. the data would be packed to the buffer object such that the memory writes required
5235 // would exceed the data store size.
5236 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5237 const gl::Extents size(width, height, 1);
5238 const auto &pack = context->getGLState().getPackState();
5239
5240 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5241 if (endByteOrErr.isError())
5242 {
5243 context->handleError(endByteOrErr.getError());
5244 return false;
5245 }
5246
5247 size_t endByte = endByteOrErr.getResult();
5248 if (bufSize >= 0)
5249 {
5250 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5251 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005252 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005253 return false;
5254 }
5255 }
5256
5257 if (pixelPackBuffer != nullptr)
5258 {
5259 CheckedNumeric<size_t> checkedEndByte(endByte);
5260 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5261 checkedEndByte += checkedOffset;
5262
5263 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5264 {
5265 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005266 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005267 return false;
5268 }
5269 }
5270
5271 if (pixelPackBuffer == nullptr && length != nullptr)
5272 {
5273 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5274 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005275 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005276 return false;
5277 }
5278
5279 *length = static_cast<GLsizei>(endByte);
5280 }
5281
5282 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5283 angle::CheckedNumeric<int> clippedExtent(length);
5284 if (start < 0)
5285 {
5286 // "subtract" the area that is less than 0
5287 clippedExtent += start;
5288 }
5289
5290 const int readExtent = start + length;
5291 if (readExtent > bufferSize)
5292 {
5293 // Subtract the region to the right of the read buffer
5294 clippedExtent -= (readExtent - bufferSize);
5295 }
5296
5297 if (!clippedExtent.IsValid())
5298 {
5299 return 0;
5300 }
5301
5302 return std::max(clippedExtent.ValueOrDie(), 0);
5303 };
5304
5305 if (columns != nullptr)
5306 {
5307 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5308 }
5309
5310 if (rows != nullptr)
5311 {
5312 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5313 }
5314
5315 return true;
5316}
5317
5318template <typename ParamType>
5319bool ValidateTexParameterBase(Context *context,
5320 GLenum target,
5321 GLenum pname,
5322 GLsizei bufSize,
5323 const ParamType *params)
5324{
5325 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5326 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005327 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005328 return false;
5329 }
5330
5331 if (context->getTargetTexture(target) == nullptr)
5332 {
5333 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005334 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005335 return false;
5336 }
5337
5338 const GLsizei minBufSize = 1;
5339 if (bufSize >= 0 && bufSize < minBufSize)
5340 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005341 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005342 return false;
5343 }
5344
5345 switch (pname)
5346 {
5347 case GL_TEXTURE_WRAP_R:
5348 case GL_TEXTURE_SWIZZLE_R:
5349 case GL_TEXTURE_SWIZZLE_G:
5350 case GL_TEXTURE_SWIZZLE_B:
5351 case GL_TEXTURE_SWIZZLE_A:
5352 case GL_TEXTURE_BASE_LEVEL:
5353 case GL_TEXTURE_MAX_LEVEL:
5354 case GL_TEXTURE_COMPARE_MODE:
5355 case GL_TEXTURE_COMPARE_FUNC:
5356 case GL_TEXTURE_MIN_LOD:
5357 case GL_TEXTURE_MAX_LOD:
5358 if (context->getClientMajorVersion() < 3)
5359 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005360 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005361 return false;
5362 }
5363 if (target == GL_TEXTURE_EXTERNAL_OES &&
5364 !context->getExtensions().eglImageExternalEssl3)
5365 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005366 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5367 "available without "
5368 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005369 return false;
5370 }
5371 break;
5372
5373 default:
5374 break;
5375 }
5376
JiangYizhou4cff8d62017-07-06 14:54:09 +08005377 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5378 {
5379 switch (pname)
5380 {
5381 case GL_TEXTURE_MIN_FILTER:
5382 case GL_TEXTURE_MAG_FILTER:
5383 case GL_TEXTURE_WRAP_S:
5384 case GL_TEXTURE_WRAP_T:
5385 case GL_TEXTURE_WRAP_R:
5386 case GL_TEXTURE_MIN_LOD:
5387 case GL_TEXTURE_MAX_LOD:
5388 case GL_TEXTURE_COMPARE_MODE:
5389 case GL_TEXTURE_COMPARE_FUNC:
5390 context->handleError(InvalidEnum()
5391 << "Invalid parameter for 2D multisampled textures.");
5392 return false;
5393 }
5394 }
5395
Jamie Madillbe849e42017-05-02 15:49:00 -04005396 switch (pname)
5397 {
5398 case GL_TEXTURE_WRAP_S:
5399 case GL_TEXTURE_WRAP_T:
5400 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005401 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005402 bool restrictedWrapModes =
5403 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5404 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5405 {
5406 return false;
5407 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005408 }
5409 break;
5410
5411 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005412 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005413 bool restrictedMinFilter =
5414 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5415 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5416 {
5417 return false;
5418 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005419 }
5420 break;
5421
5422 case GL_TEXTURE_MAG_FILTER:
5423 if (!ValidateTextureMagFilterValue(context, params))
5424 {
5425 return false;
5426 }
5427 break;
5428
5429 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005430 if (!context->getExtensions().textureUsage)
5431 {
5432 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5433 return false;
5434 }
5435
Jamie Madillbe849e42017-05-02 15:49:00 -04005436 switch (ConvertToGLenum(params[0]))
5437 {
5438 case GL_NONE:
5439 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5440 break;
5441
5442 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005443 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005444 return false;
5445 }
5446 break;
5447
5448 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5449 if (!context->getExtensions().textureFilterAnisotropic)
5450 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005451 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005452 return false;
5453 }
5454
5455 // we assume the parameter passed to this validation method is truncated, not rounded
5456 if (params[0] < 1)
5457 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005458 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005459 return false;
5460 }
5461 break;
5462
5463 case GL_TEXTURE_MIN_LOD:
5464 case GL_TEXTURE_MAX_LOD:
5465 // any value is permissible
5466 break;
5467
5468 case GL_TEXTURE_COMPARE_MODE:
5469 if (!ValidateTextureCompareModeValue(context, params))
5470 {
5471 return false;
5472 }
5473 break;
5474
5475 case GL_TEXTURE_COMPARE_FUNC:
5476 if (!ValidateTextureCompareFuncValue(context, params))
5477 {
5478 return false;
5479 }
5480 break;
5481
5482 case GL_TEXTURE_SWIZZLE_R:
5483 case GL_TEXTURE_SWIZZLE_G:
5484 case GL_TEXTURE_SWIZZLE_B:
5485 case GL_TEXTURE_SWIZZLE_A:
5486 switch (ConvertToGLenum(params[0]))
5487 {
5488 case GL_RED:
5489 case GL_GREEN:
5490 case GL_BLUE:
5491 case GL_ALPHA:
5492 case GL_ZERO:
5493 case GL_ONE:
5494 break;
5495
5496 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005497 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005498 return false;
5499 }
5500 break;
5501
5502 case GL_TEXTURE_BASE_LEVEL:
5503 if (params[0] < 0)
5504 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005505 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005506 return false;
5507 }
5508 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5509 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005510 context->handleError(InvalidOperation()
5511 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005512 return false;
5513 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005514 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5515 {
5516 context->handleError(InvalidOperation()
5517 << "Base level must be 0 for multisampled textures.");
5518 return false;
5519 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005520 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5521 {
5522 context->handleError(InvalidOperation()
5523 << "Base level must be 0 for rectangle textures.");
5524 return false;
5525 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005526 break;
5527
5528 case GL_TEXTURE_MAX_LEVEL:
5529 if (params[0] < 0)
5530 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005531 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005532 return false;
5533 }
5534 break;
5535
5536 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5537 if (context->getClientVersion() < Version(3, 1))
5538 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005539 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005540 return false;
5541 }
5542 switch (ConvertToGLenum(params[0]))
5543 {
5544 case GL_DEPTH_COMPONENT:
5545 case GL_STENCIL_INDEX:
5546 break;
5547
5548 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005549 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005550 return false;
5551 }
5552 break;
5553
5554 case GL_TEXTURE_SRGB_DECODE_EXT:
5555 if (!ValidateTextureSRGBDecodeValue(context, params))
5556 {
5557 return false;
5558 }
5559 break;
5560
5561 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005562 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005563 return false;
5564 }
5565
5566 return true;
5567}
5568
5569template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5570template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5571
Jamie Madill12e957f2017-08-26 21:42:26 -04005572bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5573{
5574 if (index >= MAX_VERTEX_ATTRIBS)
5575 {
5576 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5577 return false;
5578 }
5579
5580 return true;
5581}
5582
5583bool ValidateGetActiveUniformBlockivBase(Context *context,
5584 GLuint program,
5585 GLuint uniformBlockIndex,
5586 GLenum pname,
5587 GLsizei *length)
5588{
5589 if (length)
5590 {
5591 *length = 0;
5592 }
5593
5594 if (context->getClientMajorVersion() < 3)
5595 {
5596 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5597 return false;
5598 }
5599
5600 Program *programObject = GetValidProgram(context, program);
5601 if (!programObject)
5602 {
5603 return false;
5604 }
5605
5606 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5607 {
5608 context->handleError(InvalidValue()
5609 << "uniformBlockIndex exceeds active uniform block count.");
5610 return false;
5611 }
5612
5613 switch (pname)
5614 {
5615 case GL_UNIFORM_BLOCK_BINDING:
5616 case GL_UNIFORM_BLOCK_DATA_SIZE:
5617 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5618 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5619 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5620 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5621 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5622 break;
5623
5624 default:
5625 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5626 return false;
5627 }
5628
5629 if (length)
5630 {
5631 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5632 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005633 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005634 programObject->getUniformBlockByIndex(uniformBlockIndex);
5635 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5636 }
5637 else
5638 {
5639 *length = 1;
5640 }
5641 }
5642
5643 return true;
5644}
5645
Jamie Madill9696d072017-08-26 23:19:57 -04005646template <typename ParamType>
5647bool ValidateSamplerParameterBase(Context *context,
5648 GLuint sampler,
5649 GLenum pname,
5650 GLsizei bufSize,
5651 ParamType *params)
5652{
5653 if (context->getClientMajorVersion() < 3)
5654 {
5655 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5656 return false;
5657 }
5658
5659 if (!context->isSampler(sampler))
5660 {
5661 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5662 return false;
5663 }
5664
5665 const GLsizei minBufSize = 1;
5666 if (bufSize >= 0 && bufSize < minBufSize)
5667 {
5668 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5669 return false;
5670 }
5671
5672 switch (pname)
5673 {
5674 case GL_TEXTURE_WRAP_S:
5675 case GL_TEXTURE_WRAP_T:
5676 case GL_TEXTURE_WRAP_R:
5677 if (!ValidateTextureWrapModeValue(context, params, false))
5678 {
5679 return false;
5680 }
5681 break;
5682
5683 case GL_TEXTURE_MIN_FILTER:
5684 if (!ValidateTextureMinFilterValue(context, params, false))
5685 {
5686 return false;
5687 }
5688 break;
5689
5690 case GL_TEXTURE_MAG_FILTER:
5691 if (!ValidateTextureMagFilterValue(context, params))
5692 {
5693 return false;
5694 }
5695 break;
5696
5697 case GL_TEXTURE_MIN_LOD:
5698 case GL_TEXTURE_MAX_LOD:
5699 // any value is permissible
5700 break;
5701
5702 case GL_TEXTURE_COMPARE_MODE:
5703 if (!ValidateTextureCompareModeValue(context, params))
5704 {
5705 return false;
5706 }
5707 break;
5708
5709 case GL_TEXTURE_COMPARE_FUNC:
5710 if (!ValidateTextureCompareFuncValue(context, params))
5711 {
5712 return false;
5713 }
5714 break;
5715
5716 case GL_TEXTURE_SRGB_DECODE_EXT:
5717 if (!ValidateTextureSRGBDecodeValue(context, params))
5718 {
5719 return false;
5720 }
5721 break;
5722
5723 default:
5724 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5725 return false;
5726 }
5727
5728 return true;
5729}
5730
5731template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5732template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5733
5734bool ValidateGetSamplerParameterBase(Context *context,
5735 GLuint sampler,
5736 GLenum pname,
5737 GLsizei *length)
5738{
5739 if (length)
5740 {
5741 *length = 0;
5742 }
5743
5744 if (context->getClientMajorVersion() < 3)
5745 {
5746 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5747 return false;
5748 }
5749
5750 if (!context->isSampler(sampler))
5751 {
5752 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5753 return false;
5754 }
5755
5756 switch (pname)
5757 {
5758 case GL_TEXTURE_WRAP_S:
5759 case GL_TEXTURE_WRAP_T:
5760 case GL_TEXTURE_WRAP_R:
5761 case GL_TEXTURE_MIN_FILTER:
5762 case GL_TEXTURE_MAG_FILTER:
5763 case GL_TEXTURE_MIN_LOD:
5764 case GL_TEXTURE_MAX_LOD:
5765 case GL_TEXTURE_COMPARE_MODE:
5766 case GL_TEXTURE_COMPARE_FUNC:
5767 break;
5768
5769 case GL_TEXTURE_SRGB_DECODE_EXT:
5770 if (!context->getExtensions().textureSRGBDecode)
5771 {
5772 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5773 return false;
5774 }
5775 break;
5776
5777 default:
5778 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5779 return false;
5780 }
5781
5782 if (length)
5783 {
5784 *length = 1;
5785 }
5786 return true;
5787}
5788
5789bool ValidateGetInternalFormativBase(Context *context,
5790 GLenum target,
5791 GLenum internalformat,
5792 GLenum pname,
5793 GLsizei bufSize,
5794 GLsizei *numParams)
5795{
5796 if (numParams)
5797 {
5798 *numParams = 0;
5799 }
5800
5801 if (context->getClientMajorVersion() < 3)
5802 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005803 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005804 return false;
5805 }
5806
5807 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5808 if (!formatCaps.renderable)
5809 {
5810 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5811 return false;
5812 }
5813
5814 switch (target)
5815 {
5816 case GL_RENDERBUFFER:
5817 break;
5818
5819 case GL_TEXTURE_2D_MULTISAMPLE:
5820 if (context->getClientVersion() < ES_3_1)
5821 {
5822 context->handleError(InvalidOperation()
5823 << "Texture target requires at least OpenGL ES 3.1.");
5824 return false;
5825 }
5826 break;
5827
5828 default:
5829 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5830 return false;
5831 }
5832
5833 if (bufSize < 0)
5834 {
5835 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5836 return false;
5837 }
5838
5839 GLsizei maxWriteParams = 0;
5840 switch (pname)
5841 {
5842 case GL_NUM_SAMPLE_COUNTS:
5843 maxWriteParams = 1;
5844 break;
5845
5846 case GL_SAMPLES:
5847 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5848 break;
5849
5850 default:
5851 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5852 return false;
5853 }
5854
5855 if (numParams)
5856 {
5857 // glGetInternalFormativ will not overflow bufSize
5858 *numParams = std::min(bufSize, maxWriteParams);
5859 }
5860
5861 return true;
5862}
5863
Jamie Madillc29968b2016-01-20 11:17:23 -05005864} // namespace gl