blob: 16ccd0aabf4c38018ff5b8118f40f27936fb011e [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"
21#include "libANGLE/VertexArray.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040022#include "libANGLE/formatutils.h"
jchen10a99ed552017-09-22 08:10:32 +080023#include "libANGLE/queryconversions.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040024#include "libANGLE/validationES2.h"
25#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040026
27#include "common/mathutil.h"
28#include "common/utilities.h"
29
Jamie Madille2e406c2016-06-02 13:04:10 -040030using namespace angle;
31
Geoff Lange8ebe7f2013-08-05 15:03:13 -040032namespace gl
33{
Jamie Madill1ca74672015-07-21 15:14:11 -040034namespace
35{
jchen10a99ed552017-09-22 08:10:32 +080036
Corentin Wallez92db6942016-12-09 13:10:36 -050037bool ValidateDrawAttribs(ValidationContext *context,
38 GLint primcount,
39 GLint maxVertex,
40 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040041{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070042 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040043 const gl::Program *program = state.getProgram();
44
Corentin Wallez327411e2016-12-09 11:09:17 -050045 bool webglCompatibility = context->getExtensions().webglCompatibility;
46
Jamie Madill231c7f52017-04-26 13:45:37 -040047 const VertexArray *vao = state.getVertexArray();
48 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080049 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madilld078c682018-01-02 11:50:24 -050050 for (size_t attributeIndex : vao->getEnabledAttributesMask())
Jamie Madill1ca74672015-07-21 15:14:11 -040051 {
52 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallez672f7f32017-06-15 17:42:17 -040053
54 // No need to range check for disabled attribs.
55 if (!attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040056 {
Corentin Wallezfd456442016-12-21 17:57:00 -050057 continue;
58 }
Jamie Madill1ca74672015-07-21 15:14:11 -040059
Jamie Madill231c7f52017-04-26 13:45:37 -040060 // If we have no buffer, then we either get an error, or there are no more checks to be
61 // done.
Corentin Wallez672f7f32017-06-15 17:42:17 -040062 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
63 gl::Buffer *buffer = binding.getBuffer().get();
Corentin Wallezfd456442016-12-21 17:57:00 -050064 if (!buffer)
65 {
Geoff Langfeb8c682017-02-13 16:07:35 -050066 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050067 {
68 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050069 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
70 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
71 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
72 // error.
Brandon Jonesafa75152017-07-21 13:11:29 -070073 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
Corentin Wallezfd456442016-12-21 17:57:00 -050074 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050075 }
Corentin Wallezfd456442016-12-21 17:57:00 -050076 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040077 {
78 // This is an application error that would normally result in a crash,
79 // but we catch it and return an error
Brandon Jonesafa75152017-07-21 13:11:29 -070080 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
Jamie Madill1ca74672015-07-21 15:14:11 -040081 return false;
82 }
Corentin Wallezfd456442016-12-21 17:57:00 -050083 continue;
84 }
85
Corentin Wallez672f7f32017-06-15 17:42:17 -040086 // This needs to come after the check for client arrays as even unused attributes cannot use
87 // client-side arrays
88 if (!program->isAttribLocationActive(attributeIndex))
89 {
90 continue;
91 }
92
Corentin Wallezfd456442016-12-21 17:57:00 -050093 // If we're drawing zero vertices, we have enough data.
94 if (vertexCount <= 0 || primcount <= 0)
95 {
96 continue;
97 }
98
99 GLint maxVertexElement = 0;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300100 GLuint divisor = binding.getDivisor();
101 if (divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500102 {
103 maxVertexElement = maxVertex;
104 }
105 else
106 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300107 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500108 }
109
110 // We do manual overflow checks here instead of using safe_math.h because it was
111 // a bottleneck. Thanks to some properties of GL we know inequalities that can
112 // help us make the overflow checks faster.
113
114 // The max possible attribSize is 16 for a vector of 4 32 bit values.
115 constexpr uint64_t kMaxAttribSize = 16;
116 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
117 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
118
119 // We know attribStride is given as a GLsizei which is typedefed to int.
120 // We also know an upper bound for attribSize.
121 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800122 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500123 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
124 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
125
126 // Computing the max offset using uint64_t without attrib.offset is overflow
127 // safe. Note: Last vertex element does not take the full stride!
128 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
129 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
130
131 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800132 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
133 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500134 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700135 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500136 return false;
137 }
138 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
139
140 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
141 // We can return INVALID_OPERATION if our vertex attribute does not have
142 // enough backing data.
143 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
144 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700145 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500146 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400147 }
148 }
149
150 return true;
151}
152
Geoff Lang280ba992017-04-18 16:30:58 -0400153bool ValidReadPixelsTypeEnum(ValidationContext *context, GLenum type)
154{
155 switch (type)
156 {
157 // Types referenced in Table 3.4 of the ES 2.0.25 spec
158 case GL_UNSIGNED_BYTE:
159 case GL_UNSIGNED_SHORT_4_4_4_4:
160 case GL_UNSIGNED_SHORT_5_5_5_1:
161 case GL_UNSIGNED_SHORT_5_6_5:
162 return context->getClientVersion() >= ES_2_0;
163
164 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
165 case GL_BYTE:
166 case GL_INT:
167 case GL_SHORT:
168 case GL_UNSIGNED_INT:
169 case GL_UNSIGNED_INT_10F_11F_11F_REV:
170 case GL_UNSIGNED_INT_24_8:
171 case GL_UNSIGNED_INT_2_10_10_10_REV:
172 case GL_UNSIGNED_INT_5_9_9_9_REV:
173 case GL_UNSIGNED_SHORT:
174 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
175 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
176 return context->getClientVersion() >= ES_3_0;
177
178 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400179 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
180 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400181
182 case GL_HALF_FLOAT:
183 return context->getClientVersion() >= ES_3_0 ||
184 context->getExtensions().textureHalfFloat;
185
186 case GL_HALF_FLOAT_OES:
187 return context->getExtensions().colorBufferHalfFloat;
188
189 default:
190 return false;
191 }
192}
193
194bool ValidReadPixelsFormatEnum(ValidationContext *context, GLenum format)
195{
196 switch (format)
197 {
198 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
199 case GL_RGBA:
200 case GL_RGB:
201 case GL_ALPHA:
202 return context->getClientVersion() >= ES_2_0;
203
204 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
205 case GL_RG:
206 case GL_RED:
207 case GL_RGBA_INTEGER:
208 case GL_RGB_INTEGER:
209 case GL_RG_INTEGER:
210 case GL_RED_INTEGER:
211 return context->getClientVersion() >= ES_3_0;
212
213 case GL_SRGB_ALPHA_EXT:
214 case GL_SRGB_EXT:
215 return context->getExtensions().sRGB;
216
217 case GL_BGRA_EXT:
218 return context->getExtensions().readFormatBGRA;
219
220 default:
221 return false;
222 }
223}
224
Geoff Langf607c602016-09-21 11:46:48 -0400225bool ValidReadPixelsFormatType(ValidationContext *context,
226 GLenum framebufferComponentType,
227 GLenum format,
228 GLenum type)
229{
230 switch (framebufferComponentType)
231 {
232 case GL_UNSIGNED_NORMALIZED:
233 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
234 // ReadPixels with BGRA even if the extension is not present
235 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
236 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
237 type == GL_UNSIGNED_BYTE);
238
239 case GL_SIGNED_NORMALIZED:
240 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
241
242 case GL_INT:
243 return (format == GL_RGBA_INTEGER && type == GL_INT);
244
245 case GL_UNSIGNED_INT:
246 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
247
248 case GL_FLOAT:
249 return (format == GL_RGBA && type == GL_FLOAT);
250
251 default:
252 UNREACHABLE();
253 return false;
254 }
255}
256
Geoff Langc1984ed2016-10-07 12:41:00 -0400257template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400258bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400259{
260 switch (ConvertToGLenum(params[0]))
261 {
262 case GL_CLAMP_TO_EDGE:
263 break;
264
265 case GL_REPEAT:
266 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400267 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400268 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400269 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700270 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400271 return false;
272 }
273 break;
274
275 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700276 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400277 return false;
278 }
279
280 return true;
281}
282
283template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400284bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400285{
286 switch (ConvertToGLenum(params[0]))
287 {
288 case GL_NEAREST:
289 case GL_LINEAR:
290 break;
291
292 case GL_NEAREST_MIPMAP_NEAREST:
293 case GL_LINEAR_MIPMAP_NEAREST:
294 case GL_NEAREST_MIPMAP_LINEAR:
295 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400296 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400297 {
298 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700299 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400300 return false;
301 }
302 break;
303
304 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700305 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400306 return false;
307 }
308
309 return true;
310}
311
312template <typename ParamType>
313bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
314{
315 switch (ConvertToGLenum(params[0]))
316 {
317 case GL_NEAREST:
318 case GL_LINEAR:
319 break;
320
321 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700322 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400323 return false;
324 }
325
326 return true;
327}
328
329template <typename ParamType>
330bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
331{
332 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
333 switch (ConvertToGLenum(params[0]))
334 {
335 case GL_NONE:
336 case GL_COMPARE_REF_TO_TEXTURE:
337 break;
338
339 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700340 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400341 return false;
342 }
343
344 return true;
345}
346
347template <typename ParamType>
348bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
349{
350 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
351 switch (ConvertToGLenum(params[0]))
352 {
353 case GL_LEQUAL:
354 case GL_GEQUAL:
355 case GL_LESS:
356 case GL_GREATER:
357 case GL_EQUAL:
358 case GL_NOTEQUAL:
359 case GL_ALWAYS:
360 case GL_NEVER:
361 break;
362
363 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700364 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400365 return false;
366 }
367
368 return true;
369}
370
371template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700372bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
373{
374 if (!context->getExtensions().textureSRGBDecode)
375 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700376 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700377 return false;
378 }
379
380 switch (ConvertToGLenum(params[0]))
381 {
382 case GL_DECODE_EXT:
383 case GL_SKIP_DECODE_EXT:
384 break;
385
386 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700387 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700388 return false;
389 }
390
391 return true;
392}
393
Geoff Lange0cff192017-05-30 13:04:56 -0400394bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
395{
396 const Program *program = context->getGLState().getProgram();
397 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
398
Brandon Jones76746f92017-11-22 11:44:41 -0800399 if (!DrawBufferTypeMask::ProgramOutputsMatchFramebuffer(
400 program->getDrawBufferTypeMask(), framebuffer->getDrawBufferTypeMask(),
401 program->getActiveOutputVariables(), framebuffer->getDrawBufferMask()))
Geoff Lange0cff192017-05-30 13:04:56 -0400402 {
Brandon Jones76746f92017-11-22 11:44:41 -0800403 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
404 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400405 }
406
407 return true;
408}
409
Geoff Lang9ab5b822017-05-30 16:19:23 -0400410bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
411{
Jamie Madillcac94a92017-11-10 10:09:32 -0500412 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400413 const Program *program = context->getGLState().getProgram();
414 const VertexArray *vao = context->getGLState().getVertexArray();
Jamie Madillcac94a92017-11-10 10:09:32 -0500415 const auto &vertexAttribs = vao->getVertexAttributes();
416 const auto &currentValues = glState.getVertexAttribCurrentValues();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400417
Jamie Madillcac94a92017-11-10 10:09:32 -0500418 for (const sh::Attribute &shaderAttribute : program->getAttributes())
Geoff Lang9ab5b822017-05-30 16:19:23 -0400419 {
Geoff Lang69df2422017-07-05 12:42:31 -0400420 // gl_VertexID and gl_InstanceID are active attributes but don't have a bound attribute.
421 if (shaderAttribute.isBuiltIn())
422 {
423 continue;
424 }
425
Geoff Lang9ab5b822017-05-30 16:19:23 -0400426 GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
427
Jamie Madillcac94a92017-11-10 10:09:32 -0500428 const auto &attrib = vertexAttribs[shaderAttribute.location];
429 GLenum vertexType = attrib.enabled ? GetVertexAttributeBaseType(attrib)
430 : currentValues[shaderAttribute.location].Type;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400431
432 if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
433 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500434 context->handleError(InvalidOperation() << "Vertex shader input type does not "
435 "match the type of the bound vertex "
436 "attribute.");
Geoff Lang9ab5b822017-05-30 16:19:23 -0400437 return false;
438 }
439 }
440
441 return true;
442}
443
Geoff Langf41a7152016-09-19 15:11:17 -0400444} // anonymous namespace
445
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500446bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400447{
Jamie Madilld7460c72014-01-21 16:38:14 -0500448 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400449 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800450 case GL_TEXTURE_2D:
451 case GL_TEXTURE_CUBE_MAP:
452 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400453
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400454 case GL_TEXTURE_RECTANGLE_ANGLE:
455 return context->getExtensions().textureRectangle;
456
He Yunchaoced53ae2016-11-29 15:00:51 +0800457 case GL_TEXTURE_3D:
458 case GL_TEXTURE_2D_ARRAY:
459 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500460
He Yunchaoced53ae2016-11-29 15:00:51 +0800461 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800462 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400463
He Yunchaoced53ae2016-11-29 15:00:51 +0800464 default:
465 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500466 }
Jamie Madill35d15012013-10-07 10:46:37 -0400467}
468
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500469bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
470{
471 switch (target)
472 {
473 case GL_TEXTURE_2D:
474 case GL_TEXTURE_CUBE_MAP:
475 return true;
476
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400477 case GL_TEXTURE_RECTANGLE_ANGLE:
478 return context->getExtensions().textureRectangle;
479
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500480 default:
481 return false;
482 }
483}
484
485bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
486{
487 switch (target)
488 {
489 case GL_TEXTURE_3D:
490 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300491 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500492
493 default:
494 return false;
495 }
496}
497
Ian Ewellbda75592016-04-18 17:25:54 -0400498// Most texture GL calls are not compatible with external textures, so we have a separate validation
499// function for use in the GL calls that do
500bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
501{
502 return (target == GL_TEXTURE_EXTERNAL_OES) &&
503 (context->getExtensions().eglImageExternal ||
504 context->getExtensions().eglStreamConsumerExternal);
505}
506
Shannon Woods4dfed832014-03-17 20:03:39 -0400507// This function differs from ValidTextureTarget in that the target must be
508// usable as the destination of a 2D operation-- so a cube face is valid, but
509// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400510// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500511bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400512{
513 switch (target)
514 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800515 case GL_TEXTURE_2D:
516 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
517 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
518 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
519 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
520 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
521 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
522 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400523 case GL_TEXTURE_RECTANGLE_ANGLE:
524 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800525 default:
526 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500527 }
528}
529
Jamie Madillbe849e42017-05-02 15:49:00 -0400530bool ValidateDrawElementsInstancedBase(ValidationContext *context,
531 GLenum mode,
532 GLsizei count,
533 GLenum type,
534 const GLvoid *indices,
535 GLsizei primcount)
536{
537 if (primcount < 0)
538 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700539 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400540 return false;
541 }
542
543 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
544 {
545 return false;
546 }
547
548 // No-op zero primitive count
549 return (primcount > 0);
550}
551
552bool ValidateDrawArraysInstancedBase(Context *context,
553 GLenum mode,
554 GLint first,
555 GLsizei count,
556 GLsizei primcount)
557{
558 if (primcount < 0)
559 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700560 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400561 return false;
562 }
563
564 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
565 {
566 return false;
567 }
568
569 // No-op if zero primitive count
570 return (primcount > 0);
571}
572
Corentin Wallez0dc97812017-06-22 14:38:44 -0400573bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400574{
575 // Verify there is at least one active attribute with a divisor of zero
576 const State &state = context->getGLState();
577
578 Program *program = state.getProgram();
579
580 const auto &attribs = state.getVertexArray()->getVertexAttributes();
581 const auto &bindings = state.getVertexArray()->getVertexBindings();
582 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
583 {
584 const VertexAttribute &attrib = attribs[attributeIndex];
585 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300586 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400587 {
588 return true;
589 }
590 }
591
Brandon Jonesafa75152017-07-21 13:11:29 -0700592 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400593 return false;
594}
595
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500596bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
597{
598 switch (target)
599 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800600 case GL_TEXTURE_3D:
601 case GL_TEXTURE_2D_ARRAY:
602 return true;
603 default:
604 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400605 }
606}
607
He Yunchao11b038b2016-11-22 21:24:04 +0800608bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
609{
610 switch (target)
611 {
612 case GL_TEXTURE_2D:
613 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
614 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
615 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
616 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
617 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
618 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
619 case GL_TEXTURE_3D:
620 case GL_TEXTURE_2D_ARRAY:
621 case GL_TEXTURE_2D_MULTISAMPLE:
622 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400623 case GL_TEXTURE_RECTANGLE_ANGLE:
624 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800625 default:
626 return false;
627 }
628}
629
Geoff Lange8afa902017-09-27 15:00:43 -0400630bool ValidFramebufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500631{
He Yunchaoced53ae2016-11-29 15:00:51 +0800632 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
633 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400634 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500635
636 switch (target)
637 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800638 case GL_FRAMEBUFFER:
639 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400640
He Yunchaoced53ae2016-11-29 15:00:51 +0800641 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800642 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400643 return (context->getExtensions().framebufferBlit ||
644 context->getClientMajorVersion() >= 3);
645
He Yunchaoced53ae2016-11-29 15:00:51 +0800646 default:
647 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500648 }
649}
650
Jamie Madillc29968b2016-01-20 11:17:23 -0500651bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400652{
Jamie Madillc29968b2016-01-20 11:17:23 -0500653 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400654 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400655 switch (target)
656 {
Jamie Madillc29968b2016-01-20 11:17:23 -0500657 case GL_TEXTURE_2D:
658 maxDimension = caps.max2DTextureSize;
659 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800660 case GL_TEXTURE_CUBE_MAP:
661 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
662 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
663 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
664 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
665 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
666 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
667 maxDimension = caps.maxCubeMapTextureSize;
668 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400669 case GL_TEXTURE_RECTANGLE_ANGLE:
670 return level == 0;
He Yunchaoced53ae2016-11-29 15:00:51 +0800671 case GL_TEXTURE_3D:
672 maxDimension = caps.max3DTextureSize;
673 break;
674 case GL_TEXTURE_2D_ARRAY:
675 maxDimension = caps.max2DTextureSize;
676 break;
He Yunchao11b038b2016-11-22 21:24:04 +0800677 case GL_TEXTURE_2D_MULTISAMPLE:
678 maxDimension = caps.max2DTextureSize;
679 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800680 default:
681 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400682 }
683
Brandon Jones6cad5662017-06-14 13:25:13 -0700684 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400685}
686
Brandon Jones6cad5662017-06-14 13:25:13 -0700687bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -0700688 GLenum target,
689 GLint level,
690 GLsizei width,
691 GLsizei height,
692 GLsizei depth,
693 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400694{
Brandon Jones6cad5662017-06-14 13:25:13 -0700695 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400696 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700697 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400698 return false;
699 }
Austin Kinross08528e12015-10-07 16:24:40 -0700700 // TexSubImage parameters can be NPOT without textureNPOT extension,
701 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500702 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500703 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500704 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400705 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400706 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700707 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400708 return false;
709 }
710
711 if (!ValidMipLevel(context, target, level))
712 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700713 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400714 return false;
715 }
716
717 return true;
718}
719
Geoff Lang0d8b7242015-09-09 14:56:53 -0400720bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
721{
722 // List of compressed format that require that the texture size is smaller than or a multiple of
723 // the compressed block size.
724 switch (internalFormat)
725 {
726 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
727 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
728 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
729 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -0400730 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
731 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
732 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
733 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -0800734 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800735 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
736 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
737 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
738 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
739 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
740 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -0400741 return true;
742
743 default:
744 return false;
745 }
746}
747
Geoff Lang966c9402017-04-18 12:38:27 -0400748bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
749{
750 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
751 (size % blockSize == 0);
752}
753
Jamie Madillc29968b2016-01-20 11:17:23 -0500754bool ValidCompressedImageSize(const ValidationContext *context,
755 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400756 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500757 GLsizei width,
758 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400759{
Geoff Langca271392017-04-05 12:30:00 -0400760 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400761 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400762 {
763 return false;
764 }
765
Geoff Lang966c9402017-04-18 12:38:27 -0400766 if (width < 0 || height < 0)
767 {
768 return false;
769 }
770
771 if (CompressedTextureFormatRequiresExactSize(internalFormat))
772 {
773 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
774 // block size for level 0 but WebGL disallows this.
775 bool smallerThanBlockSizeAllowed =
776 level > 0 || !context->getExtensions().webglCompatibility;
777
778 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
779 smallerThanBlockSizeAllowed) ||
780 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
781 smallerThanBlockSizeAllowed))
782 {
783 return false;
784 }
785 }
786
787 return true;
788}
789
790bool ValidCompressedSubImageSize(const ValidationContext *context,
791 GLenum internalFormat,
792 GLint xoffset,
793 GLint yoffset,
794 GLsizei width,
795 GLsizei height,
796 size_t textureWidth,
797 size_t textureHeight)
798{
799 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
800 if (!formatInfo.compressed)
801 {
802 return false;
803 }
804
Geoff Lang44ff5a72017-02-03 15:15:43 -0500805 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400806 {
807 return false;
808 }
809
Geoff Lang0d8b7242015-09-09 14:56:53 -0400810 if (CompressedTextureFormatRequiresExactSize(internalFormat))
811 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500812 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400813 yoffset % formatInfo.compressedBlockHeight != 0)
814 {
815 return false;
816 }
817
818 // Allowed to either have data that is a multiple of block size or is smaller than the block
819 // size but fills the entire mip
820 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
821 static_cast<size_t>(width) == textureWidth &&
822 static_cast<size_t>(height) == textureHeight;
823 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
824 (height % formatInfo.compressedBlockHeight) == 0;
825 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400826 {
827 return false;
828 }
829 }
830
Geoff Langd4f180b2013-09-24 13:57:44 -0400831 return true;
832}
833
Geoff Langff5b2d52016-09-07 11:32:23 -0400834bool ValidImageDataSize(ValidationContext *context,
835 GLenum textureTarget,
836 GLsizei width,
837 GLsizei height,
838 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400839 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400840 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400841 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400842 GLsizei imageSize)
843{
Corentin Wallez336129f2017-10-17 15:55:40 -0400844 gl::Buffer *pixelUnpackBuffer =
845 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400846 if (pixelUnpackBuffer == nullptr && imageSize < 0)
847 {
848 // Checks are not required
849 return true;
850 }
851
852 // ...the data would be unpacked from the buffer object such that the memory reads required
853 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400854 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
855 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400856 const gl::Extents size(width, height, depth);
857 const auto &unpack = context->getGLState().getUnpackState();
858
859 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
860 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
861 if (endByteOrErr.isError())
862 {
863 context->handleError(endByteOrErr.getError());
864 return false;
865 }
866
867 GLuint endByte = endByteOrErr.getResult();
868
869 if (pixelUnpackBuffer)
870 {
871 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
872 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
873 checkedEndByte += checkedOffset;
874
875 if (!checkedEndByte.IsValid() ||
876 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
877 {
878 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500879 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400880 return false;
881 }
882 }
883 else
884 {
885 ASSERT(imageSize >= 0);
886 if (pixels == nullptr && imageSize != 0)
887 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500888 context->handleError(InvalidOperation()
889 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400890 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400891 }
892
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400893 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400894 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500895 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400896 return false;
897 }
898 }
899
900 return true;
901}
902
Geoff Lang37dde692014-01-31 16:34:54 -0500903bool ValidQueryType(const Context *context, GLenum queryType)
904{
He Yunchaoced53ae2016-11-29 15:00:51 +0800905 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
906 "GL extension enums not equal.");
907 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
908 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -0500909
910 switch (queryType)
911 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800912 case GL_ANY_SAMPLES_PASSED:
913 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400914 return context->getClientMajorVersion() >= 3 ||
915 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +0800916 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
917 return (context->getClientMajorVersion() >= 3);
918 case GL_TIME_ELAPSED_EXT:
919 return context->getExtensions().disjointTimerQuery;
920 case GL_COMMANDS_COMPLETED_CHROMIUM:
921 return context->getExtensions().syncQuery;
922 default:
923 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500924 }
925}
926
Geoff Lang2d62ab72017-03-23 16:54:40 -0400927bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
928 GLenum type,
929 GLboolean normalized,
930 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400931 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400932 bool pureInteger)
933{
934 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400935 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
936 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
937 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
938 // parameter exceeds 255.
939 constexpr GLsizei kMaxWebGLStride = 255;
940 if (stride > kMaxWebGLStride)
941 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500942 context->handleError(InvalidValue()
943 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -0400944 return false;
945 }
946
947 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
948 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
949 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
950 // or an INVALID_OPERATION error is generated.
951 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
952 size_t typeSize = GetVertexFormatTypeSize(internalType);
953
954 ASSERT(isPow2(typeSize) && typeSize > 0);
955 size_t sizeMask = (typeSize - 1);
956 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
957 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700958 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400959 return false;
960 }
961
962 if ((stride & sizeMask) != 0)
963 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700964 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400965 return false;
966 }
967
968 return true;
969}
970
Jamie Madillef300b12016-10-07 15:12:09 -0400971Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -0500972{
He Yunchaoced53ae2016-11-29 15:00:51 +0800973 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
974 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
975 // or program object and INVALID_OPERATION if the provided name identifies an object
976 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -0500977
Dian Xiang769769a2015-09-09 15:20:08 -0700978 Program *validProgram = context->getProgram(id);
979
980 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -0500981 {
Dian Xiang769769a2015-09-09 15:20:08 -0700982 if (context->getShader(id))
983 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700984 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -0700985 }
986 else
987 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700988 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -0700989 }
Geoff Lang48dcae72014-02-05 16:28:24 -0500990 }
Dian Xiang769769a2015-09-09 15:20:08 -0700991
992 return validProgram;
993}
994
Jamie Madillef300b12016-10-07 15:12:09 -0400995Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -0700996{
997 // See ValidProgram for spec details.
998
999 Shader *validShader = context->getShader(id);
1000
1001 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001002 {
Dian Xiang769769a2015-09-09 15:20:08 -07001003 if (context->getProgram(id))
1004 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001005 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001006 }
1007 else
1008 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001009 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001010 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001011 }
Dian Xiang769769a2015-09-09 15:20:08 -07001012
1013 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001014}
1015
Geoff Langb1196682014-07-23 13:47:29 -04001016bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001017{
Geoff Langfa125c92017-10-24 13:01:46 -04001018 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001019 {
Geoff Langfa125c92017-10-24 13:01:46 -04001020 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1021 {
1022 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1023 return false;
1024 }
Jamie Madillb4472272014-07-03 10:38:55 -04001025
Geoff Langfa125c92017-10-24 13:01:46 -04001026 // Color attachment 0 is validated below because it is always valid
1027 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001028 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001029 {
Geoff Langfa125c92017-10-24 13:01:46 -04001030 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001031 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001032 }
1033 }
1034 else
1035 {
1036 switch (attachment)
1037 {
Geoff Langfa125c92017-10-24 13:01:46 -04001038 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001039 case GL_DEPTH_ATTACHMENT:
1040 case GL_STENCIL_ATTACHMENT:
1041 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001042
He Yunchaoced53ae2016-11-29 15:00:51 +08001043 case GL_DEPTH_STENCIL_ATTACHMENT:
1044 if (!context->getExtensions().webglCompatibility &&
1045 context->getClientMajorVersion() < 3)
1046 {
Geoff Langfa125c92017-10-24 13:01:46 -04001047 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001048 return false;
1049 }
1050 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001051
He Yunchaoced53ae2016-11-29 15:00:51 +08001052 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001053 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001054 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001055 }
1056 }
1057
1058 return true;
1059}
1060
Jamie Madille8fb6402017-02-14 17:56:40 -05001061bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001062 GLenum target,
1063 GLsizei samples,
1064 GLenum internalformat,
1065 GLsizei width,
1066 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001067{
1068 switch (target)
1069 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001070 case GL_RENDERBUFFER:
1071 break;
1072 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001073 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001074 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001075 }
1076
1077 if (width < 0 || height < 0 || samples < 0)
1078 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001079 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001080 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001081 }
1082
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001083 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1084 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1085
1086 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001087 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001088 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001089 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001090 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001091 }
1092
1093 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1094 // 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 -08001095 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001096 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1097 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001098 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001099 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001100 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001101 }
1102
Geoff Langaae65a42014-05-26 12:43:44 -04001103 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001104 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001105 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001106 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001107 }
1108
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001109 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001110 if (handle == 0)
1111 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001112 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001113 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001114 }
1115
1116 return true;
1117}
1118
He Yunchaoced53ae2016-11-29 15:00:51 +08001119bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1120 GLenum target,
1121 GLenum attachment,
1122 GLenum renderbuffertarget,
1123 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001124{
Geoff Lange8afa902017-09-27 15:00:43 -04001125 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001126 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001127 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001128 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001129 }
1130
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001131 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001132
Jamie Madill84115c92015-04-23 15:00:07 -04001133 ASSERT(framebuffer);
1134 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001135 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001136 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001137 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001138 }
1139
Jamie Madillb4472272014-07-03 10:38:55 -04001140 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001141 {
Jamie Madillb4472272014-07-03 10:38:55 -04001142 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001143 }
1144
Jamie Madillab9d82c2014-01-21 16:38:14 -05001145 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1146 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1147 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1148 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1149 if (renderbuffer != 0)
1150 {
1151 if (!context->getRenderbuffer(renderbuffer))
1152 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001153 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001154 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001155 }
1156 }
1157
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001158 return true;
1159}
1160
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001161bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001162 GLint srcX0,
1163 GLint srcY0,
1164 GLint srcX1,
1165 GLint srcY1,
1166 GLint dstX0,
1167 GLint dstY0,
1168 GLint dstX1,
1169 GLint dstY1,
1170 GLbitfield mask,
1171 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001172{
1173 switch (filter)
1174 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001175 case GL_NEAREST:
1176 break;
1177 case GL_LINEAR:
1178 break;
1179 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001180 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001181 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001182 }
1183
1184 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1185 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001186 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001187 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001188 }
1189
1190 if (mask == 0)
1191 {
1192 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1193 // buffers are copied.
1194 return false;
1195 }
1196
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001197 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1198 // color buffer, leaving only nearest being unfiltered from above
1199 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1200 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001201 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001202 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001203 }
1204
Jamie Madill51f40ec2016-06-15 14:06:00 -04001205 const auto &glState = context->getGLState();
1206 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1207 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001208
1209 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001210 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001211 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001212 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001213 }
1214
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001215 if (readFramebuffer->id() == drawFramebuffer->id())
1216 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001217 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001218 return false;
1219 }
1220
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001221 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001222 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001223 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001224 return false;
1225 }
1226
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001227 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001228 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001229 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001230 return false;
1231 }
1232
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001233 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001234 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001235 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001236 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001237 }
1238
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001239 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1240
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001241 if (mask & GL_COLOR_BUFFER_BIT)
1242 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001243 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001244 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001245
He Yunchao66a41a22016-12-15 16:45:05 +08001246 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001247 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001248 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001249
Geoff Langa15472a2015-08-11 11:48:03 -04001250 for (size_t drawbufferIdx = 0;
1251 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001252 {
Geoff Langa15472a2015-08-11 11:48:03 -04001253 const FramebufferAttachment *attachment =
1254 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1255 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001256 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001257 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001258
Geoff Langb2f3d052013-08-13 12:49:27 -04001259 // The GL ES 3.0.2 spec (pg 193) states that:
1260 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001261 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1262 // as well
1263 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1264 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001265 // Changes with EXT_color_buffer_float:
1266 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001267 GLenum readComponentType = readFormat.info->componentType;
1268 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001269 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001270 readComponentType == GL_SIGNED_NORMALIZED);
1271 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1272 drawComponentType == GL_SIGNED_NORMALIZED);
1273
1274 if (extensions.colorBufferFloat)
1275 {
1276 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1277 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1278
1279 if (readFixedOrFloat != drawFixedOrFloat)
1280 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001281 context->handleError(InvalidOperation()
1282 << "If the read buffer contains fixed-point or "
1283 "floating-point values, the draw buffer must "
1284 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001285 return false;
1286 }
1287 }
1288 else if (readFixedPoint != drawFixedPoint)
1289 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001290 context->handleError(InvalidOperation()
1291 << "If the read buffer contains fixed-point values, "
1292 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001293 return false;
1294 }
1295
1296 if (readComponentType == GL_UNSIGNED_INT &&
1297 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001298 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001299 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001300 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001301 }
1302
Jamie Madill6163c752015-12-07 16:32:59 -05001303 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001304 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001305 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001306 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001307 }
1308
Jamie Madilla3944d42016-07-22 22:13:26 -04001309 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001310 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001311 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001312 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001313 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001314 }
Geoff Lange4915782017-04-12 15:19:07 -04001315
1316 if (context->getExtensions().webglCompatibility &&
1317 *readColorBuffer == *attachment)
1318 {
1319 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001320 InvalidOperation()
1321 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001322 return false;
1323 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001324 }
1325 }
1326
Jamie Madilla3944d42016-07-22 22:13:26 -04001327 if ((readFormat.info->componentType == GL_INT ||
1328 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1329 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001330 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001331 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001332 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001333 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001334 }
He Yunchao66a41a22016-12-15 16:45:05 +08001335 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1336 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1337 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1338 // situation is an application error that would lead to a crash in ANGLE.
1339 else if (drawFramebuffer->hasEnabledDrawBuffer())
1340 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001341 context->handleError(
1342 InvalidOperation()
1343 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001344 return false;
1345 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001346 }
1347
He Yunchaoced53ae2016-11-29 15:00:51 +08001348 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001349 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1350 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001351 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001352 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001353 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001354 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001355 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001356 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001357 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001358
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001359 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001360 {
Kenneth Russell69382852017-07-21 16:38:44 -04001361 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001363 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001364 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001365 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001366
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001367 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001368 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001369 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001370 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001371 }
Geoff Lange4915782017-04-12 15:19:07 -04001372
1373 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1374 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001375 context->handleError(
1376 InvalidOperation()
1377 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001378 return false;
1379 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001380 }
He Yunchao66a41a22016-12-15 16:45:05 +08001381 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1382 else if (drawBuffer)
1383 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001384 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1385 "depth/stencil attachment of a "
1386 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001387 return false;
1388 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001389 }
1390 }
1391
Martin Radeva3ed4572017-07-27 18:29:37 +03001392 // ANGLE_multiview, Revision 1:
1393 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1394 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1395 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1396 {
1397 context->handleError(InvalidFramebufferOperation()
1398 << "Attempt to read from a multi-view framebuffer.");
1399 return false;
1400 }
1401 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1402 {
1403 context->handleError(InvalidFramebufferOperation()
1404 << "Attempt to write to a multi-view framebuffer.");
1405 return false;
1406 }
1407
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001408 return true;
1409}
1410
Jamie Madill4928b7c2017-06-20 12:57:39 -04001411bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001412 GLint x,
1413 GLint y,
1414 GLsizei width,
1415 GLsizei height,
1416 GLenum format,
1417 GLenum type,
1418 GLsizei bufSize,
1419 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001420 GLsizei *columns,
1421 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001422 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001423{
1424 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001425 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001426 return false;
1427 }
1428
Geoff Lang62fce5b2016-09-30 10:46:35 -04001429 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001430 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001431 {
Geoff Langb1196682014-07-23 13:47:29 -04001432 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001433 }
1434
Geoff Lang62fce5b2016-09-30 10:46:35 -04001435 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001436 {
Geoff Langb1196682014-07-23 13:47:29 -04001437 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001438 }
1439
Jamie Madillc29968b2016-01-20 11:17:23 -05001440 return true;
1441}
1442
1443bool ValidateReadnPixelsEXT(Context *context,
1444 GLint x,
1445 GLint y,
1446 GLsizei width,
1447 GLsizei height,
1448 GLenum format,
1449 GLenum type,
1450 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001451 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001452{
1453 if (bufSize < 0)
1454 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001455 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001456 return false;
1457 }
1458
Geoff Lang62fce5b2016-09-30 10:46:35 -04001459 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001460 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001461}
Jamie Madill26e91952014-03-05 15:01:27 -05001462
Jamie Madill4928b7c2017-06-20 12:57:39 -04001463bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001464 GLint x,
1465 GLint y,
1466 GLsizei width,
1467 GLsizei height,
1468 GLenum format,
1469 GLenum type,
1470 GLsizei bufSize,
1471 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001472 GLsizei *columns,
1473 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001474 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001475{
1476 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001477 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001478 return false;
1479 }
1480
Geoff Lange93daba2017-03-30 13:54:40 -04001481 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1482 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001483 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001484 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001485 }
1486
Geoff Lang62fce5b2016-09-30 10:46:35 -04001487 if (!ValidateRobustBufferSize(context, bufSize, *length))
1488 {
1489 return false;
1490 }
1491
1492 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001493}
1494
Jamie Madillf0e04492017-08-26 15:28:42 -04001495bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001496{
1497 if (!context->getExtensions().occlusionQueryBoolean &&
1498 !context->getExtensions().disjointTimerQuery)
1499 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001500 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001501 return false;
1502 }
1503
Olli Etuaho41997e72016-03-10 13:38:39 +02001504 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001505}
1506
Jamie Madillf0e04492017-08-26 15:28:42 -04001507bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001508{
1509 if (!context->getExtensions().occlusionQueryBoolean &&
1510 !context->getExtensions().disjointTimerQuery)
1511 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001512 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001513 return false;
1514 }
1515
Olli Etuaho41997e72016-03-10 13:38:39 +02001516 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001517}
1518
Jamie Madillf0e04492017-08-26 15:28:42 -04001519bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1520{
1521 if (!context->getExtensions().occlusionQueryBoolean &&
1522 !context->getExtensions().disjointTimerQuery)
1523 {
1524 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1525 return false;
1526 }
1527
1528 return true;
1529}
1530
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001531bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001532{
1533 if (!ValidQueryType(context, target))
1534 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001535 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001536 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001537 }
1538
1539 if (id == 0)
1540 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001541 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001542 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001543 }
1544
1545 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1546 // of zero, if the active query object name for <target> is non-zero (for the
1547 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1548 // the active query for either target is non-zero), if <id> is the name of an
1549 // existing query object whose type does not match <target>, or if <id> is the
1550 // active query object name for any query type, the error INVALID_OPERATION is
1551 // generated.
1552
1553 // Ensure no other queries are active
1554 // NOTE: If other queries than occlusion are supported, we will need to check
1555 // separately that:
1556 // a) The query ID passed is not the current active query for any target/type
1557 // b) There are no active queries for the requested target (and in the case
1558 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1559 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001560
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001561 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001562 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001563 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001564 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001565 }
1566
1567 Query *queryObject = context->getQuery(id, true, target);
1568
1569 // check that name was obtained with glGenQueries
1570 if (!queryObject)
1571 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001572 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001573 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001574 }
1575
1576 // check for type mismatch
1577 if (queryObject->getType() != target)
1578 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001579 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001580 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001581 }
1582
1583 return true;
1584}
1585
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001586bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1587{
1588 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001589 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001590 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001591 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001592 return false;
1593 }
1594
1595 return ValidateBeginQueryBase(context, target, id);
1596}
1597
1598bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001599{
1600 if (!ValidQueryType(context, target))
1601 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001602 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001603 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001604 }
1605
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001606 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001607
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001608 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001610 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001611 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001612 }
1613
Jamie Madill45c785d2014-05-13 14:09:34 -04001614 return true;
1615}
1616
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001617bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1618{
1619 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001620 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001621 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001622 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001623 return false;
1624 }
1625
1626 return ValidateEndQueryBase(context, target);
1627}
1628
1629bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1630{
1631 if (!context->getExtensions().disjointTimerQuery)
1632 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001633 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001634 return false;
1635 }
1636
1637 if (target != GL_TIMESTAMP_EXT)
1638 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001639 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001640 return false;
1641 }
1642
1643 Query *queryObject = context->getQuery(id, true, target);
1644 if (queryObject == nullptr)
1645 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001646 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001647 return false;
1648 }
1649
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001650 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001651 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001652 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001653 return false;
1654 }
1655
1656 return true;
1657}
1658
Geoff Lang2186c382016-10-14 10:54:54 -04001659bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001660{
Geoff Lang2186c382016-10-14 10:54:54 -04001661 if (numParams)
1662 {
1663 *numParams = 0;
1664 }
1665
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001666 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1667 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001668 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001669 return false;
1670 }
1671
1672 switch (pname)
1673 {
1674 case GL_CURRENT_QUERY_EXT:
1675 if (target == GL_TIMESTAMP_EXT)
1676 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001677 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001678 return false;
1679 }
1680 break;
1681 case GL_QUERY_COUNTER_BITS_EXT:
1682 if (!context->getExtensions().disjointTimerQuery ||
1683 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1684 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001685 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001686 return false;
1687 }
1688 break;
1689 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001690 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001691 return false;
1692 }
1693
Geoff Lang2186c382016-10-14 10:54:54 -04001694 if (numParams)
1695 {
1696 // All queries return only one value
1697 *numParams = 1;
1698 }
1699
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001700 return true;
1701}
1702
1703bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1704{
1705 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001706 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001707 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001708 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001709 return false;
1710 }
1711
Geoff Lang2186c382016-10-14 10:54:54 -04001712 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001713}
1714
Geoff Lang2186c382016-10-14 10:54:54 -04001715bool ValidateGetQueryivRobustANGLE(Context *context,
1716 GLenum target,
1717 GLenum pname,
1718 GLsizei bufSize,
1719 GLsizei *length,
1720 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001721{
Geoff Lang2186c382016-10-14 10:54:54 -04001722 if (!ValidateRobustEntryPoint(context, bufSize))
1723 {
1724 return false;
1725 }
1726
1727 if (!ValidateGetQueryivBase(context, target, pname, length))
1728 {
1729 return false;
1730 }
1731
1732 if (!ValidateRobustBufferSize(context, bufSize, *length))
1733 {
1734 return false;
1735 }
1736
1737 return true;
1738}
1739
1740bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1741{
1742 if (numParams)
1743 {
1744 *numParams = 0;
1745 }
1746
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001747 Query *queryObject = context->getQuery(id, false, GL_NONE);
1748
1749 if (!queryObject)
1750 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001751 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001752 return false;
1753 }
1754
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001755 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001756 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001757 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001758 return false;
1759 }
1760
1761 switch (pname)
1762 {
1763 case GL_QUERY_RESULT_EXT:
1764 case GL_QUERY_RESULT_AVAILABLE_EXT:
1765 break;
1766
1767 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001768 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001769 return false;
1770 }
1771
Geoff Lang2186c382016-10-14 10:54:54 -04001772 if (numParams)
1773 {
1774 *numParams = 1;
1775 }
1776
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001777 return true;
1778}
1779
1780bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1781{
1782 if (!context->getExtensions().disjointTimerQuery)
1783 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001784 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001785 return false;
1786 }
Geoff Lang2186c382016-10-14 10:54:54 -04001787 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1788}
1789
1790bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1791 GLuint id,
1792 GLenum pname,
1793 GLsizei bufSize,
1794 GLsizei *length,
1795 GLint *params)
1796{
1797 if (!context->getExtensions().disjointTimerQuery)
1798 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001799 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001800 return false;
1801 }
1802
1803 if (!ValidateRobustEntryPoint(context, bufSize))
1804 {
1805 return false;
1806 }
1807
1808 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1809 {
1810 return false;
1811 }
1812
1813 if (!ValidateRobustBufferSize(context, bufSize, *length))
1814 {
1815 return false;
1816 }
1817
1818 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001819}
1820
1821bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1822{
1823 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001824 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001825 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001826 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001827 return false;
1828 }
Geoff Lang2186c382016-10-14 10:54:54 -04001829 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1830}
1831
1832bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1833 GLuint id,
1834 GLenum pname,
1835 GLsizei bufSize,
1836 GLsizei *length,
1837 GLuint *params)
1838{
1839 if (!context->getExtensions().disjointTimerQuery &&
1840 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1841 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001842 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001843 return false;
1844 }
1845
1846 if (!ValidateRobustEntryPoint(context, bufSize))
1847 {
1848 return false;
1849 }
1850
1851 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1852 {
1853 return false;
1854 }
1855
1856 if (!ValidateRobustBufferSize(context, bufSize, *length))
1857 {
1858 return false;
1859 }
1860
1861 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001862}
1863
1864bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1865{
1866 if (!context->getExtensions().disjointTimerQuery)
1867 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001868 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001869 return false;
1870 }
Geoff Lang2186c382016-10-14 10:54:54 -04001871 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1872}
1873
1874bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1875 GLuint id,
1876 GLenum pname,
1877 GLsizei bufSize,
1878 GLsizei *length,
1879 GLint64 *params)
1880{
1881 if (!context->getExtensions().disjointTimerQuery)
1882 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001883 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001884 return false;
1885 }
1886
1887 if (!ValidateRobustEntryPoint(context, bufSize))
1888 {
1889 return false;
1890 }
1891
1892 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1893 {
1894 return false;
1895 }
1896
1897 if (!ValidateRobustBufferSize(context, bufSize, *length))
1898 {
1899 return false;
1900 }
1901
1902 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001903}
1904
1905bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1906{
1907 if (!context->getExtensions().disjointTimerQuery)
1908 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001909 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001910 return false;
1911 }
Geoff Lang2186c382016-10-14 10:54:54 -04001912 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1913}
1914
1915bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1916 GLuint id,
1917 GLenum pname,
1918 GLsizei bufSize,
1919 GLsizei *length,
1920 GLuint64 *params)
1921{
1922 if (!context->getExtensions().disjointTimerQuery)
1923 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001924 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001925 return false;
1926 }
1927
1928 if (!ValidateRobustEntryPoint(context, bufSize))
1929 {
1930 return false;
1931 }
1932
1933 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1934 {
1935 return false;
1936 }
1937
1938 if (!ValidateRobustBufferSize(context, bufSize, *length))
1939 {
1940 return false;
1941 }
1942
1943 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001944}
1945
Jiajia Qin5451d532017-11-16 17:16:34 +08001946bool ValidateUniformCommonBase(ValidationContext *context,
1947 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05001948 GLint location,
1949 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08001950 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05001951{
Jiajia Qin5451d532017-11-16 17:16:34 +08001952 // TODO(Jiajia): Add image uniform check in future.
1953 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05001954 {
Jiajia Qin5451d532017-11-16 17:16:34 +08001955 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05001956 return false;
1957 }
1958
Jiajia Qin5451d532017-11-16 17:16:34 +08001959 if (!program)
1960 {
1961 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
1962 return false;
1963 }
1964
1965 if (!program->isLinked())
1966 {
1967 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
1968 return false;
1969 }
1970
1971 if (location == -1)
1972 {
1973 // Silently ignore the uniform command
1974 return false;
1975 }
1976
1977 const auto &uniformLocations = program->getUniformLocations();
1978 size_t castedLocation = static_cast<size_t>(location);
1979 if (castedLocation >= uniformLocations.size())
1980 {
1981 context->handleError(InvalidOperation() << "Invalid uniform location");
1982 return false;
1983 }
1984
1985 const auto &uniformLocation = uniformLocations[castedLocation];
1986 if (uniformLocation.ignored)
1987 {
1988 // Silently ignore the uniform command
1989 return false;
1990 }
1991
1992 if (!uniformLocation.used())
1993 {
1994 context->handleError(InvalidOperation());
1995 return false;
1996 }
1997
1998 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
1999
2000 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2001 if (!uniform.isArray() && count > 1)
2002 {
2003 context->handleError(InvalidOperation());
2004 return false;
2005 }
2006
2007 *uniformOut = &uniform;
2008 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002009}
2010
Jiajia Qin5451d532017-11-16 17:16:34 +08002011bool ValidateUniform1ivValue(ValidationContext *context,
2012 GLenum uniformType,
2013 GLsizei count,
2014 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002015{
Jiajia Qin5451d532017-11-16 17:16:34 +08002016 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2017 // It is compatible with INT or BOOL.
2018 // Do these cheap tests first, for a little extra speed.
2019 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002020 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002021 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002022 }
2023
Jiajia Qin5451d532017-11-16 17:16:34 +08002024 if (IsSamplerType(uniformType))
2025 {
2026 // Check that the values are in range.
2027 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2028 for (GLsizei i = 0; i < count; ++i)
2029 {
2030 if (value[i] < 0 || value[i] >= max)
2031 {
2032 context->handleError(InvalidValue() << "sampler uniform value out of range");
2033 return false;
2034 }
2035 }
2036 return true;
2037 }
2038
2039 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2040 return false;
2041}
2042
2043bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2044{
2045 // Check that the value type is compatible with uniform type.
2046 // Do the cheaper test first, for a little extra speed.
2047 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2048 {
2049 return true;
2050 }
2051
2052 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2053 return false;
2054}
2055
2056bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2057{
2058 // Check that the value type is compatible with uniform type.
2059 if (valueType == uniformType)
2060 {
2061 return true;
2062 }
2063
2064 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2065 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002066}
2067
Jamie Madillc1d770e2017-04-13 17:31:24 -04002068bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002069{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002070 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002071 gl::Program *programObject = context->getGLState().getProgram();
2072 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2073 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002074}
2075
Jamie Madillbe849e42017-05-02 15:49:00 -04002076bool ValidateUniform1iv(ValidationContext *context,
2077 GLint location,
2078 GLsizei count,
2079 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002080{
2081 const LinkedUniform *uniform = nullptr;
2082 gl::Program *programObject = context->getGLState().getProgram();
2083 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2084 ValidateUniform1ivValue(context, uniform->type, count, value);
2085}
2086
Jamie Madillc1d770e2017-04-13 17:31:24 -04002087bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002088 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002089 GLint location,
2090 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002091 GLboolean transpose)
2092{
Geoff Lang92019432017-11-20 13:09:34 -05002093 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002094 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002095 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002096 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002097 }
2098
Jamie Madill62d31cb2015-09-11 13:25:51 -04002099 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002100 gl::Program *programObject = context->getGLState().getProgram();
2101 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2102 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002103}
2104
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002105bool ValidateStateQuery(ValidationContext *context,
2106 GLenum pname,
2107 GLenum *nativeType,
2108 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002109{
2110 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2111 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002112 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002113 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002114 }
2115
Jamie Madill0af26e12015-03-05 19:54:33 -05002116 const Caps &caps = context->getCaps();
2117
Jamie Madill893ab082014-05-16 16:56:10 -04002118 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2119 {
2120 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2121
Jamie Madill0af26e12015-03-05 19:54:33 -05002122 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002123 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002124 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002125 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002126 }
2127 }
2128
2129 switch (pname)
2130 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002131 case GL_TEXTURE_BINDING_2D:
2132 case GL_TEXTURE_BINDING_CUBE_MAP:
2133 case GL_TEXTURE_BINDING_3D:
2134 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002135 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002136 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002137 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2138 if (!context->getExtensions().textureRectangle)
2139 {
2140 context->handleError(InvalidEnum()
2141 << "ANGLE_texture_rectangle extension not present");
2142 return false;
2143 }
2144 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002145 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2146 if (!context->getExtensions().eglStreamConsumerExternal &&
2147 !context->getExtensions().eglImageExternal)
2148 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002149 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2150 "nor GL_OES_EGL_image_external "
2151 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002152 return false;
2153 }
2154 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002155
He Yunchaoced53ae2016-11-29 15:00:51 +08002156 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2157 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002158 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002159 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2160 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002161 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002162 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002163 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002164 }
2165
Jamie Madill51f40ec2016-06-15 14:06:00 -04002166 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2167 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002168
2169 if (framebuffer->getReadBufferState() == GL_NONE)
2170 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002171 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002172 return false;
2173 }
2174
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002175 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002176 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002177 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002178 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002179 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002180 }
2181 }
2182 break;
2183
He Yunchaoced53ae2016-11-29 15:00:51 +08002184 default:
2185 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002186 }
2187
2188 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002189 if (*numParams == 0)
2190 {
2191 return false;
2192 }
2193
2194 return true;
2195}
2196
2197bool ValidateRobustStateQuery(ValidationContext *context,
2198 GLenum pname,
2199 GLsizei bufSize,
2200 GLenum *nativeType,
2201 unsigned int *numParams)
2202{
2203 if (!ValidateRobustEntryPoint(context, bufSize))
2204 {
2205 return false;
2206 }
2207
2208 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2209 {
2210 return false;
2211 }
2212
2213 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002214 {
2215 return false;
2216 }
2217
2218 return true;
2219}
2220
Jamie Madillc29968b2016-01-20 11:17:23 -05002221bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2222 GLenum target,
2223 GLint level,
2224 GLenum internalformat,
2225 bool isSubImage,
2226 GLint xoffset,
2227 GLint yoffset,
2228 GLint zoffset,
2229 GLint x,
2230 GLint y,
2231 GLsizei width,
2232 GLsizei height,
2233 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002234 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002235{
Brandon Jones6cad5662017-06-14 13:25:13 -07002236 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002237 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002238 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2239 return false;
2240 }
2241
2242 if (width < 0 || height < 0)
2243 {
2244 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002245 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002246 }
2247
He Yunchaoced53ae2016-11-29 15:00:51 +08002248 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2249 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002251 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002252 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002253 }
2254
2255 if (border != 0)
2256 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002257 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002258 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002259 }
2260
2261 if (!ValidMipLevel(context, target, level))
2262 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002263 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002264 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002265 }
2266
Jamie Madill51f40ec2016-06-15 14:06:00 -04002267 const auto &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002268 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002269 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002270 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002271 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002272 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002273 }
2274
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002275 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002276 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002277 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002278 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002279 }
2280
Martin Radev138064f2016-07-15 12:03:41 +03002281 if (readFramebuffer->getReadBufferState() == GL_NONE)
2282 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002283 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002284 return false;
2285 }
2286
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002287 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2288 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002289 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002290 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002291 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2292 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002293 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002294 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002295 return false;
2296 }
2297
Martin Radev04e2c3b2017-07-27 16:54:35 +03002298 // ANGLE_multiview spec, Revision 1:
2299 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2300 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2301 // is not NONE.
2302 if (source->getMultiviewLayout() != GL_NONE)
2303 {
2304 context->handleError(InvalidFramebufferOperation()
2305 << "The active read framebuffer object has multiview attachments.");
2306 return false;
2307 }
2308
Geoff Langaae65a42014-05-26 12:43:44 -04002309 const gl::Caps &caps = context->getCaps();
2310
Geoff Langaae65a42014-05-26 12:43:44 -04002311 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002312 switch (target)
2313 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002314 case GL_TEXTURE_2D:
2315 maxDimension = caps.max2DTextureSize;
2316 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002317
He Yunchaoced53ae2016-11-29 15:00:51 +08002318 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2319 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2320 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2321 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2322 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2323 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2324 maxDimension = caps.maxCubeMapTextureSize;
2325 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002326
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002327 case GL_TEXTURE_RECTANGLE_ANGLE:
2328 maxDimension = caps.maxRectangleTextureSize;
2329 break;
2330
He Yunchaoced53ae2016-11-29 15:00:51 +08002331 case GL_TEXTURE_2D_ARRAY:
2332 maxDimension = caps.max2DTextureSize;
2333 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002334
He Yunchaoced53ae2016-11-29 15:00:51 +08002335 case GL_TEXTURE_3D:
2336 maxDimension = caps.max3DTextureSize;
2337 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002338
He Yunchaoced53ae2016-11-29 15:00:51 +08002339 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002340 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002341 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002342 }
2343
Jamie Madillc29968b2016-01-20 11:17:23 -05002344 gl::Texture *texture =
2345 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002346 if (!texture)
2347 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002348 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002349 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002350 }
2351
Geoff Lang69cce582015-09-17 13:20:36 -04002352 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002353 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002354 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002355 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002356 }
2357
Geoff Langca271392017-04-05 12:30:00 -04002358 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002359 isSubImage ? *texture->getFormat(target, level).info
2360 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002361
Geoff Lang966c9402017-04-18 12:38:27 -04002362 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002363 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002364 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002365 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002366 }
2367
2368 if (isSubImage)
2369 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002370 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2371 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2372 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002373 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002374 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002375 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002376 }
2377 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002378 else
2379 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002380 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002381 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002382 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002383 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002384 }
2385
Geoff Langeb66a6e2016-10-31 13:06:12 -04002386 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002387 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002388 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002389 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002390 }
2391
2392 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002393 if (static_cast<int>(width) > maxLevelDimension ||
2394 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002395 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002396 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002397 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002398 }
2399 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002400
Jamie Madill0c8abca2016-07-22 20:21:26 -04002401 if (textureFormatOut)
2402 {
2403 *textureFormatOut = texture->getFormat(target, level);
2404 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002405
2406 // Detect texture copying feedback loops for WebGL.
2407 if (context->getExtensions().webglCompatibility)
2408 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002409 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002410 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002411 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002412 return false;
2413 }
2414 }
2415
Jamie Madill560a8d82014-05-21 13:06:20 -04002416 return true;
2417}
2418
Jiajia Qind9671222016-11-29 16:30:31 +08002419bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002420{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002421 switch (mode)
2422 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002423 case GL_POINTS:
2424 case GL_LINES:
2425 case GL_LINE_LOOP:
2426 case GL_LINE_STRIP:
2427 case GL_TRIANGLES:
2428 case GL_TRIANGLE_STRIP:
2429 case GL_TRIANGLE_FAN:
2430 break;
2431 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002432 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002433 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002434 }
2435
Jamie Madill250d33f2014-06-06 17:09:03 -04002436 if (count < 0)
2437 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002438 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002439 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002440 }
2441
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002442 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002443
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002444 const Extensions &extensions = context->getExtensions();
2445
2446 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2447 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2448 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2449 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002450 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002451 // Check for mapped buffers
2452 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002453 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002454 {
2455 context->handleError(InvalidOperation());
2456 return false;
2457 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002458 }
2459
Jamie Madillcbcde722017-01-06 14:50:00 -05002460 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2461 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002462 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002463 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002464 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002465 const FramebufferAttachment *dsAttachment =
2466 framebuffer->getStencilOrDepthStencilAttachment();
2467 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002468 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002469 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002470
2471 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2472 bool differentWritemasks =
2473 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2474 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2475 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2476 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2477
2478 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002479 {
Martin Radevffe754b2017-07-31 10:38:07 +03002480 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002481 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002482 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2483 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002484 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002485 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002486 return false;
2487 }
Jamie Madillac528012014-06-20 13:21:23 -04002488 }
2489
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002490 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002491 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002492 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002493 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002494 }
2495
Geoff Lang7dd2e102014-11-10 15:19:26 -05002496 gl::Program *program = state.getProgram();
2497 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002498 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002499 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002500 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002501 }
2502
Yunchao Hecddcb592017-11-13 15:27:35 +08002503 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2504 // vertex shader stage or fragment shader stage is a undefined behaviour.
2505 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2506 // produce undefined result.
Yunchao Heece12532017-11-21 15:50:21 +08002507 if (!program->hasLinkedVertexShader() || !program->hasLinkedFragmentShader())
Yunchao Hecddcb592017-11-13 15:27:35 +08002508 {
2509 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2510 "vertex shader stage or fragment shader stage.");
2511 return false;
2512 }
2513
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002514 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002515 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002516 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002517 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002518 }
2519
Martin Radevffe754b2017-07-31 10:38:07 +03002520 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002521 {
Martin Radevda8e2572017-09-12 17:21:16 +03002522 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002523 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002524 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002525 {
2526 context->handleError(InvalidOperation() << "The number of views in the active program "
2527 "and draw framebuffer does not match.");
2528 return false;
2529 }
Martin Radev7e69f762017-07-27 14:54:13 +03002530
2531 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2532 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2533 framebufferNumViews > 1)
2534 {
2535 context->handleError(InvalidOperation()
2536 << "There is an active transform feedback object "
2537 "when the number of views in the active draw "
2538 "framebuffer is greater than 1.");
2539 return false;
2540 }
Martin Radevffe754b2017-07-31 10:38:07 +03002541
2542 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2543 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2544 {
2545 context->handleError(InvalidOperation() << "There is an active query for target "
2546 "GL_TIME_ELAPSED_EXT when the number of "
2547 "views in the active draw framebuffer is "
2548 "greater than 1.");
2549 return false;
2550 }
Martin Radev7cf61662017-07-26 17:10:53 +03002551 }
2552
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002553 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002554 for (unsigned int uniformBlockIndex = 0;
2555 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002556 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002557 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002558 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002559 const OffsetBindingPointer<Buffer> &uniformBuffer =
2560 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002561
Geoff Lang5d124a62015-09-15 13:03:27 -04002562 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002563 {
2564 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002565 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002566 InvalidOperation()
2567 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002568 return false;
2569 }
2570
Geoff Lang5d124a62015-09-15 13:03:27 -04002571 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002572 if (uniformBufferSize == 0)
2573 {
2574 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002575 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002576 }
2577
Jamie Madill62d31cb2015-09-11 13:25:51 -04002578 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002579 {
2580 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002581 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002582 InvalidOperation()
2583 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002584 return false;
2585 }
2586 }
2587
Geoff Lange0cff192017-05-30 13:04:56 -04002588 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002589 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002590 {
Geoff Lange0cff192017-05-30 13:04:56 -04002591 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002592 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2593 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002594 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002595 return false;
2596 }
Geoff Lange0cff192017-05-30 13:04:56 -04002597
Geoff Lang9ab5b822017-05-30 16:19:23 -04002598 // Detect that the vertex shader input types match the attribute types
2599 if (!ValidateVertexShaderAttributeTypeMatch(context))
2600 {
2601 return false;
2602 }
2603
Geoff Lange0cff192017-05-30 13:04:56 -04002604 // Detect that the color buffer types match the fragment shader output types
2605 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2606 {
2607 return false;
2608 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002609 }
2610
Jamie Madill250d33f2014-06-06 17:09:03 -04002611 // No-op if zero count
2612 return (count > 0);
2613}
2614
Jamie Madillc1d770e2017-04-13 17:31:24 -04002615bool ValidateDrawArraysCommon(ValidationContext *context,
2616 GLenum mode,
2617 GLint first,
2618 GLsizei count,
2619 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002620{
Jamie Madillfd716582014-06-06 17:09:04 -04002621 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002622 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002623 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002624 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002625 }
2626
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002627 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002628 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002629 if (curTransformFeedback && curTransformFeedback->isActive() &&
2630 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002631 {
2632 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002633 // that does not match the current transform feedback object's draw mode (if transform
2634 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002635 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002636 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002637 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002638 }
2639
Jiajia Qind9671222016-11-29 16:30:31 +08002640 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002641 {
2642 return false;
2643 }
2644
Corentin Wallez71168a02016-12-19 15:11:18 -08002645 // Check the computation of maxVertex doesn't overflow.
2646 // - first < 0 or count < 0 have been checked as an error condition
2647 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2648 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2649 ASSERT(count > 0 && first >= 0);
2650 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2651 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002652 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002653 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002654 return false;
2655 }
2656
Corentin Wallez71168a02016-12-19 15:11:18 -08002657 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002658 {
2659 return false;
2660 }
2661
2662 return true;
2663}
2664
He Yunchaoced53ae2016-11-29 15:00:51 +08002665bool ValidateDrawArraysInstancedANGLE(Context *context,
2666 GLenum mode,
2667 GLint first,
2668 GLsizei count,
2669 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002670{
Geoff Lang63c5a592017-09-27 14:08:16 -04002671 if (!context->getExtensions().instancedArrays)
2672 {
2673 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2674 return false;
2675 }
2676
Corentin Wallez170efbf2017-05-02 13:45:01 -04002677 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002678 {
2679 return false;
2680 }
2681
Corentin Wallez0dc97812017-06-22 14:38:44 -04002682 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002683}
2684
Jiajia Qind9671222016-11-29 16:30:31 +08002685bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002686{
Jamie Madill250d33f2014-06-06 17:09:03 -04002687 switch (type)
2688 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002689 case GL_UNSIGNED_BYTE:
2690 case GL_UNSIGNED_SHORT:
2691 break;
2692 case GL_UNSIGNED_INT:
2693 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2694 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002695 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002696 return false;
2697 }
2698 break;
2699 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002700 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002701 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002702 }
2703
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002704 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002705
2706 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002707 if (curTransformFeedback && curTransformFeedback->isActive() &&
2708 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002709 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002710 // It is an invalid operation to call DrawElements, DrawRangeElements or
2711 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002712 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002713 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002714 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002715 }
2716
Jiajia Qind9671222016-11-29 16:30:31 +08002717 return true;
2718}
2719
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002720bool ValidateDrawElementsCommon(ValidationContext *context,
2721 GLenum mode,
2722 GLsizei count,
2723 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002724 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002725 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002726{
2727 if (!ValidateDrawElementsBase(context, type))
2728 return false;
2729
2730 const State &state = context->getGLState();
2731
Corentin Wallez170efbf2017-05-02 13:45:01 -04002732 if (!ValidateDrawBase(context, mode, count))
2733 {
2734 return false;
2735 }
2736
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002737 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2738 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2739 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2740 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002741 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002742 // Check for mapped buffers
2743 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002744 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002745 {
2746 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2747 return false;
2748 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002749 }
2750
He Yunchaoced53ae2016-11-29 15:00:51 +08002751 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002752 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002753
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002754 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2755
2756 if (context->getExtensions().webglCompatibility)
2757 {
2758 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2759 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2760 {
2761 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2762 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2763 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002764 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002765 return false;
2766 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002767
2768 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2769 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2770 // error is generated.
2771 if (reinterpret_cast<intptr_t>(indices) < 0)
2772 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002773 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002774 return false;
2775 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002776 }
2777
2778 if (context->getExtensions().webglCompatibility ||
2779 !context->getGLState().areClientArraysEnabled())
2780 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002781 if (!elementArrayBuffer && count > 0)
2782 {
2783 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2784 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2785 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002786 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002787 return false;
2788 }
2789 }
2790
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002791 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002792 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002793 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002794 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002795 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2796 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2797 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2798 constexpr uint64_t kMaxTypeSize = 8;
2799 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2800 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2801 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002802
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002803 uint64_t typeSize = typeBytes;
2804 uint64_t elementCount = static_cast<uint64_t>(count);
2805 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2806
2807 // Doing the multiplication here is overflow-safe
2808 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2809
2810 // The offset can be any value, check for overflows
2811 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2812 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002813 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002814 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002815 return false;
2816 }
2817
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002818 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2819 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002820 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002821 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002822 return false;
2823 }
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002824
Corentin Wallez487653b2017-09-01 17:17:55 -04002825 ASSERT(isPow2(typeSize) && typeSize > 0);
2826 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002827 {
2828 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
2829 return false;
2830 }
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002831 }
2832 else if (!indices)
2833 {
2834 // This is an application error that would normally result in a crash,
2835 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002836 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04002837 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002838 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002839 }
2840
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002841 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002842 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002843 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2844 // access is enabled.
2845 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2846 {
2847 return false;
2848 }
2849 }
2850 else
2851 {
2852 // Use the parameter buffer to retrieve and cache the index range.
2853 const auto &params = context->getParams<HasIndexRange>();
2854 const auto &indexRangeOpt = params.getIndexRange();
2855 if (!indexRangeOpt.valid())
2856 {
2857 // Unexpected error.
2858 return false;
2859 }
2860
2861 // If we use an index greater than our maximum supported index range, return an error.
2862 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2863 // return an error if possible here.
2864 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2865 {
2866 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2867 return false;
2868 }
2869
2870 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2871 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2872 {
2873 return false;
2874 }
2875
2876 // No op if there are no real indices in the index data (all are primitive restart).
2877 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002878 }
2879
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002880 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002881}
2882
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002883bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2884 GLenum mode,
2885 GLsizei count,
2886 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002887 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002888 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002889{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002890 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002891}
2892
Geoff Lang3edfe032015-09-04 16:38:24 -04002893bool ValidateDrawElementsInstancedANGLE(Context *context,
2894 GLenum mode,
2895 GLsizei count,
2896 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002897 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002898 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002899{
Geoff Lang63c5a592017-09-27 14:08:16 -04002900 if (!context->getExtensions().instancedArrays)
2901 {
2902 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2903 return false;
2904 }
2905
Corentin Wallez170efbf2017-05-02 13:45:01 -04002906 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002907 {
2908 return false;
2909 }
2910
Corentin Wallez0dc97812017-06-22 14:38:44 -04002911 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002912}
2913
He Yunchaoced53ae2016-11-29 15:00:51 +08002914bool ValidateFramebufferTextureBase(Context *context,
2915 GLenum target,
2916 GLenum attachment,
2917 GLuint texture,
2918 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002919{
Geoff Lange8afa902017-09-27 15:00:43 -04002920 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002921 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002922 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002923 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002924 }
2925
2926 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002927 {
2928 return false;
2929 }
2930
Jamie Madill55ec3b12014-07-03 10:38:57 -04002931 if (texture != 0)
2932 {
2933 gl::Texture *tex = context->getTexture(texture);
2934
Jamie Madillbe849e42017-05-02 15:49:00 -04002935 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002936 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002937 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002938 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002939 }
2940
2941 if (level < 0)
2942 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002943 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002944 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002945 }
2946 }
2947
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002948 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002949 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002950
Jamie Madill84115c92015-04-23 15:00:07 -04002951 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002952 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002953 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002954 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002955 }
2956
2957 return true;
2958}
2959
Geoff Langb1196682014-07-23 13:47:29 -04002960bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04002961{
2962 if (program == 0)
2963 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002964 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002965 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002966 }
2967
Dian Xiang769769a2015-09-09 15:20:08 -07002968 gl::Program *programObject = GetValidProgram(context, program);
2969 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05002970 {
2971 return false;
2972 }
2973
Jamie Madill0063c512014-08-25 15:47:53 -04002974 if (!programObject || !programObject->isLinked())
2975 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002976 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04002977 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002978 }
2979
Geoff Lang7dd2e102014-11-10 15:19:26 -05002980 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04002981 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002982 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002983 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04002984 }
2985
Jamie Madill0063c512014-08-25 15:47:53 -04002986 return true;
2987}
2988
Geoff Langf41d0ee2016-10-07 13:04:23 -04002989static bool ValidateSizedGetUniform(Context *context,
2990 GLuint program,
2991 GLint location,
2992 GLsizei bufSize,
2993 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04002994{
Geoff Langf41d0ee2016-10-07 13:04:23 -04002995 if (length)
2996 {
2997 *length = 0;
2998 }
2999
Jamie Madill78f41802014-08-25 15:47:55 -04003000 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003001 {
Jamie Madill78f41802014-08-25 15:47:55 -04003002 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003003 }
3004
Geoff Langf41d0ee2016-10-07 13:04:23 -04003005 if (bufSize < 0)
3006 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003007 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003008 return false;
3009 }
3010
Jamie Madilla502c742014-08-28 17:19:13 -04003011 gl::Program *programObject = context->getProgram(program);
3012 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003013
Jamie Madill78f41802014-08-25 15:47:55 -04003014 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003015 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003016 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003017 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003018 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003019 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003020 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003021 }
3022
Geoff Langf41d0ee2016-10-07 13:04:23 -04003023 if (length)
3024 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003025 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003026 }
3027
Jamie Madill0063c512014-08-25 15:47:53 -04003028 return true;
3029}
3030
He Yunchaoced53ae2016-11-29 15:00:51 +08003031bool ValidateGetnUniformfvEXT(Context *context,
3032 GLuint program,
3033 GLint location,
3034 GLsizei bufSize,
3035 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003036{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003037 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003038}
3039
He Yunchaoced53ae2016-11-29 15:00:51 +08003040bool ValidateGetnUniformivEXT(Context *context,
3041 GLuint program,
3042 GLint location,
3043 GLsizei bufSize,
3044 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003045{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003046 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3047}
3048
3049bool ValidateGetUniformfvRobustANGLE(Context *context,
3050 GLuint program,
3051 GLint location,
3052 GLsizei bufSize,
3053 GLsizei *length,
3054 GLfloat *params)
3055{
3056 if (!ValidateRobustEntryPoint(context, bufSize))
3057 {
3058 return false;
3059 }
3060
3061 // bufSize is validated in ValidateSizedGetUniform
3062 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3063}
3064
3065bool ValidateGetUniformivRobustANGLE(Context *context,
3066 GLuint program,
3067 GLint location,
3068 GLsizei bufSize,
3069 GLsizei *length,
3070 GLint *params)
3071{
3072 if (!ValidateRobustEntryPoint(context, bufSize))
3073 {
3074 return false;
3075 }
3076
3077 // bufSize is validated in ValidateSizedGetUniform
3078 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3079}
3080
3081bool ValidateGetUniformuivRobustANGLE(Context *context,
3082 GLuint program,
3083 GLint location,
3084 GLsizei bufSize,
3085 GLsizei *length,
3086 GLuint *params)
3087{
3088 if (!ValidateRobustEntryPoint(context, bufSize))
3089 {
3090 return false;
3091 }
3092
3093 if (context->getClientMajorVersion() < 3)
3094 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003095 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003096 return false;
3097 }
3098
3099 // bufSize is validated in ValidateSizedGetUniform
3100 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003101}
3102
He Yunchaoced53ae2016-11-29 15:00:51 +08003103bool ValidateDiscardFramebufferBase(Context *context,
3104 GLenum target,
3105 GLsizei numAttachments,
3106 const GLenum *attachments,
3107 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003108{
3109 if (numAttachments < 0)
3110 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003111 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003112 return false;
3113 }
3114
3115 for (GLsizei i = 0; i < numAttachments; ++i)
3116 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003117 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003118 {
3119 if (defaultFramebuffer)
3120 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003121 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003122 return false;
3123 }
3124
3125 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3126 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003127 context->handleError(InvalidOperation() << "Requested color attachment is "
3128 "greater than the maximum supported "
3129 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003130 return false;
3131 }
3132 }
3133 else
3134 {
3135 switch (attachments[i])
3136 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003137 case GL_DEPTH_ATTACHMENT:
3138 case GL_STENCIL_ATTACHMENT:
3139 case GL_DEPTH_STENCIL_ATTACHMENT:
3140 if (defaultFramebuffer)
3141 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003142 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3143 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003144 return false;
3145 }
3146 break;
3147 case GL_COLOR:
3148 case GL_DEPTH:
3149 case GL_STENCIL:
3150 if (!defaultFramebuffer)
3151 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003152 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3153 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003154 return false;
3155 }
3156 break;
3157 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003158 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003159 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003160 }
3161 }
3162 }
3163
3164 return true;
3165}
3166
Austin Kinross6ee1e782015-05-29 17:05:37 -07003167bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3168{
Jamie Madill007530e2017-12-28 14:27:04 -05003169 if (!context->getExtensions().debugMarker)
3170 {
3171 // The debug marker calls should not set error state
3172 // However, it seems reasonable to set an error state if the extension is not enabled
3173 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3174 return false;
3175 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003176
Jamie Madill007530e2017-12-28 14:27:04 -05003177 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003178 if (length < 0)
3179 {
3180 return false;
3181 }
3182
3183 if (marker == nullptr)
3184 {
3185 return false;
3186 }
3187
3188 return true;
3189}
3190
3191bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3192{
Jamie Madill007530e2017-12-28 14:27:04 -05003193 if (!context->getExtensions().debugMarker)
3194 {
3195 // The debug marker calls should not set error state
3196 // However, it seems reasonable to set an error state if the extension is not enabled
3197 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3198 return false;
3199 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003200
Jamie Madill007530e2017-12-28 14:27:04 -05003201 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003202 if (length < 0)
3203 {
3204 return false;
3205 }
3206
3207 if (length > 0 && marker == nullptr)
3208 {
3209 return false;
3210 }
3211
3212 return true;
3213}
3214
Jamie Madill007530e2017-12-28 14:27:04 -05003215bool ValidateEGLImageTargetTexture2DOES(Context *context, GLenum target, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003216{
Geoff Langa8406172015-07-21 16:53:39 -04003217 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3218 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003219 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003220 return false;
3221 }
3222
3223 switch (target)
3224 {
3225 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003226 if (!context->getExtensions().eglImage)
3227 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003228 context->handleError(InvalidEnum()
3229 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003230 }
3231 break;
3232
3233 case GL_TEXTURE_EXTERNAL_OES:
3234 if (!context->getExtensions().eglImageExternal)
3235 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003236 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3237 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003238 }
Geoff Langa8406172015-07-21 16:53:39 -04003239 break;
3240
3241 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003242 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003243 return false;
3244 }
3245
Jamie Madill007530e2017-12-28 14:27:04 -05003246 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3247
Jamie Madill61e16b42017-06-19 11:13:23 -04003248 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003249 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003251 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003252 return false;
3253 }
3254
Jamie Madill007530e2017-12-28 14:27:04 -05003255 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003256 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003257 context->handleError(InvalidOperation()
3258 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003259 return false;
3260 }
3261
Geoff Langca271392017-04-05 12:30:00 -04003262 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003263 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003264 if (!textureCaps.texturable)
3265 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003266 context->handleError(InvalidOperation()
3267 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003268 return false;
3269 }
3270
Geoff Langdcab33b2015-07-21 13:03:16 -04003271 return true;
3272}
3273
3274bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003275 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003276 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003277{
Geoff Langa8406172015-07-21 16:53:39 -04003278 if (!context->getExtensions().eglImage)
3279 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003280 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003281 return false;
3282 }
3283
3284 switch (target)
3285 {
3286 case GL_RENDERBUFFER:
3287 break;
3288
3289 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003290 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003291 return false;
3292 }
3293
Jamie Madill007530e2017-12-28 14:27:04 -05003294 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3295
Jamie Madill61e16b42017-06-19 11:13:23 -04003296 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003297 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003298 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003299 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003300 return false;
3301 }
3302
Geoff Langca271392017-04-05 12:30:00 -04003303 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003304 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003305 if (!textureCaps.renderable)
3306 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003307 context->handleError(InvalidOperation()
3308 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003309 return false;
3310 }
3311
Geoff Langdcab33b2015-07-21 13:03:16 -04003312 return true;
3313}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003314
3315bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3316{
Geoff Lang36167ab2015-12-07 10:27:14 -05003317 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003318 {
3319 // The default VAO should always exist
3320 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003321 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003322 return false;
3323 }
3324
3325 return true;
3326}
3327
Geoff Langc5629752015-12-07 16:29:04 -05003328bool ValidateProgramBinaryBase(Context *context,
3329 GLuint program,
3330 GLenum binaryFormat,
3331 const void *binary,
3332 GLint length)
3333{
3334 Program *programObject = GetValidProgram(context, program);
3335 if (programObject == nullptr)
3336 {
3337 return false;
3338 }
3339
3340 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3341 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3342 programBinaryFormats.end())
3343 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003344 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003345 return false;
3346 }
3347
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003348 if (context->hasActiveTransformFeedback(program))
3349 {
3350 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003351 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3352 "is associated with an active transform "
3353 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003354 return false;
3355 }
3356
Geoff Langc5629752015-12-07 16:29:04 -05003357 return true;
3358}
3359
3360bool ValidateGetProgramBinaryBase(Context *context,
3361 GLuint program,
3362 GLsizei bufSize,
3363 GLsizei *length,
3364 GLenum *binaryFormat,
3365 void *binary)
3366{
3367 Program *programObject = GetValidProgram(context, program);
3368 if (programObject == nullptr)
3369 {
3370 return false;
3371 }
3372
3373 if (!programObject->isLinked())
3374 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003375 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003376 return false;
3377 }
3378
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003379 if (context->getCaps().programBinaryFormats.empty())
3380 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003381 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003382 return false;
3383 }
3384
Geoff Langc5629752015-12-07 16:29:04 -05003385 return true;
3386}
Jamie Madillc29968b2016-01-20 11:17:23 -05003387
Jamie Madillc29968b2016-01-20 11:17:23 -05003388bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3389{
3390 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003391 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003392 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003393 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3394 return false;
3395 }
3396 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3397 {
3398 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003399 return false;
3400 }
3401
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003402 ASSERT(context->getGLState().getDrawFramebuffer());
3403 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003404 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3405
3406 // This should come first before the check for the default frame buffer
3407 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3408 // rather than INVALID_OPERATION
3409 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3410 {
3411 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3412
3413 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003414 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3415 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003416 {
3417 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003418 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3419 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3420 // 3.1 is still a bit ambiguous about the error, but future specs are
3421 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003422 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003423 return false;
3424 }
3425 else if (bufs[colorAttachment] >= maxColorAttachment)
3426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003427 context->handleError(InvalidOperation()
3428 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003429 return false;
3430 }
3431 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3432 frameBufferId != 0)
3433 {
3434 // INVALID_OPERATION-GL is bound to buffer and ith argument
3435 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003436 context->handleError(InvalidOperation()
3437 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003438 return false;
3439 }
3440 }
3441
3442 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3443 // and n is not 1 or bufs is bound to value other than BACK and NONE
3444 if (frameBufferId == 0)
3445 {
3446 if (n != 1)
3447 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003448 context->handleError(InvalidOperation()
3449 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003450 return false;
3451 }
3452
3453 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3454 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003455 context->handleError(
3456 InvalidOperation()
3457 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003458 return false;
3459 }
3460 }
3461
3462 return true;
3463}
3464
Geoff Lang496c02d2016-10-20 11:38:11 -07003465bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003466 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003467 GLenum pname,
3468 GLsizei *length,
3469 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003470{
Geoff Lang496c02d2016-10-20 11:38:11 -07003471 if (length)
3472 {
3473 *length = 0;
3474 }
3475
3476 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3477 {
3478 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003479 InvalidOperation()
3480 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003481 return false;
3482 }
3483
Corentin Walleze4477002017-12-01 14:39:58 -05003484 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003485 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003486 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003487 return false;
3488 }
3489
Geoff Lang496c02d2016-10-20 11:38:11 -07003490 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003491 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003492 case GL_BUFFER_MAP_POINTER:
3493 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003494
Geoff Lang496c02d2016-10-20 11:38:11 -07003495 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003496 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003497 return false;
3498 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003499
3500 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3501 // target bound to zero generate an INVALID_OPERATION error."
3502 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003503 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003504 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003505 context->handleError(InvalidOperation()
3506 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003507 return false;
3508 }
3509
Geoff Lang496c02d2016-10-20 11:38:11 -07003510 if (length)
3511 {
3512 *length = 1;
3513 }
3514
Olli Etuaho4f667482016-03-30 15:56:35 +03003515 return true;
3516}
3517
Corentin Wallez336129f2017-10-17 15:55:40 -04003518bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003519{
Corentin Walleze4477002017-12-01 14:39:58 -05003520 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003521 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003522 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003523 return false;
3524 }
3525
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003526 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003527
3528 if (buffer == nullptr || !buffer->isMapped())
3529 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003530 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003531 return false;
3532 }
3533
3534 return true;
3535}
3536
3537bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003538 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003539 GLintptr offset,
3540 GLsizeiptr length,
3541 GLbitfield access)
3542{
Corentin Walleze4477002017-12-01 14:39:58 -05003543 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003544 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003545 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003546 return false;
3547 }
3548
Brandon Jones6cad5662017-06-14 13:25:13 -07003549 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003550 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003551 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3552 return false;
3553 }
3554
3555 if (length < 0)
3556 {
3557 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003558 return false;
3559 }
3560
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003561 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003562
3563 if (!buffer)
3564 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003565 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003566 return false;
3567 }
3568
3569 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003570 CheckedNumeric<size_t> checkedOffset(offset);
3571 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003572
Jamie Madille2e406c2016-06-02 13:04:10 -04003573 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003574 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003575 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003576 return false;
3577 }
3578
3579 // Check for invalid bits in the mask
3580 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3581 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3582 GL_MAP_UNSYNCHRONIZED_BIT;
3583
3584 if (access & ~(allAccessBits))
3585 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003586 context->handleError(InvalidValue()
3587 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003588 return false;
3589 }
3590
3591 if (length == 0)
3592 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003593 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003594 return false;
3595 }
3596
3597 if (buffer->isMapped())
3598 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003599 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003600 return false;
3601 }
3602
3603 // Check for invalid bit combinations
3604 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3605 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003606 context->handleError(InvalidOperation()
3607 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003608 return false;
3609 }
3610
3611 GLbitfield writeOnlyBits =
3612 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3613
3614 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3615 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003616 context->handleError(InvalidOperation()
3617 << "Invalid access bits when mapping buffer for reading: 0x"
3618 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003619 return false;
3620 }
3621
3622 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3623 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003624 context->handleError(
3625 InvalidOperation()
3626 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003627 return false;
3628 }
Geoff Lang79f71042017-08-14 16:43:43 -04003629
3630 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003631}
3632
3633bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003634 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003635 GLintptr offset,
3636 GLsizeiptr length)
3637{
Brandon Jones6cad5662017-06-14 13:25:13 -07003638 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003639 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003640 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3641 return false;
3642 }
3643
3644 if (length < 0)
3645 {
3646 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003647 return false;
3648 }
3649
Corentin Walleze4477002017-12-01 14:39:58 -05003650 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003651 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003652 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003653 return false;
3654 }
3655
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003656 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003657
3658 if (buffer == nullptr)
3659 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003660 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003661 return false;
3662 }
3663
3664 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3665 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003666 context->handleError(InvalidOperation()
3667 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003668 return false;
3669 }
3670
3671 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003672 CheckedNumeric<size_t> checkedOffset(offset);
3673 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003674
Jamie Madille2e406c2016-06-02 13:04:10 -04003675 if (!checkedSize.IsValid() ||
3676 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003677 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003678 context->handleError(InvalidValue()
3679 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003680 return false;
3681 }
3682
3683 return true;
3684}
3685
Olli Etuaho41997e72016-03-10 13:38:39 +02003686bool ValidateGenOrDelete(Context *context, GLint n)
3687{
3688 if (n < 0)
3689 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003690 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003691 return false;
3692 }
3693 return true;
3694}
3695
Geoff Langff5b2d52016-09-07 11:32:23 -04003696bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3697{
3698 if (!context->getExtensions().robustClientMemory)
3699 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003700 context->handleError(InvalidOperation()
3701 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003702 return false;
3703 }
3704
3705 if (bufSize < 0)
3706 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003707 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003708 return false;
3709 }
3710
3711 return true;
3712}
3713
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003714bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3715{
3716 if (bufSize < numParams)
3717 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003718 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3719 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003720 return false;
3721 }
3722
3723 return true;
3724}
3725
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003726bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003727 GLenum target,
3728 GLenum attachment,
3729 GLenum pname,
3730 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003731{
Geoff Lange8afa902017-09-27 15:00:43 -04003732 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003733 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003734 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003735 return false;
3736 }
3737
3738 int clientVersion = context->getClientMajorVersion();
3739
3740 switch (pname)
3741 {
3742 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3743 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3744 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3745 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3746 break;
3747
Martin Radeve5285d22017-07-14 16:23:53 +03003748 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3749 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3750 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3751 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3752 if (clientVersion < 3 || !context->getExtensions().multiview)
3753 {
3754 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3755 return false;
3756 }
3757 break;
3758
Geoff Langff5b2d52016-09-07 11:32:23 -04003759 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3760 if (clientVersion < 3 && !context->getExtensions().sRGB)
3761 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003762 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003763 return false;
3764 }
3765 break;
3766
3767 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3768 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3769 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3770 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3771 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3772 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3773 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3774 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3775 if (clientVersion < 3)
3776 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003777 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003778 return false;
3779 }
3780 break;
3781
3782 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003783 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003784 return false;
3785 }
3786
3787 // Determine if the attachment is a valid enum
3788 switch (attachment)
3789 {
3790 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04003791 case GL_DEPTH:
3792 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04003793 if (clientVersion < 3)
3794 {
Geoff Langfa125c92017-10-24 13:01:46 -04003795 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003796 return false;
3797 }
3798 break;
3799
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003800 case GL_DEPTH_STENCIL_ATTACHMENT:
3801 if (clientVersion < 3 && !context->isWebGL1())
3802 {
3803 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3804 return false;
3805 }
3806 break;
3807
Geoff Langfa125c92017-10-24 13:01:46 -04003808 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003809 case GL_DEPTH_ATTACHMENT:
3810 case GL_STENCIL_ATTACHMENT:
3811 break;
3812
3813 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003814 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3815 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003816 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3817 {
Geoff Langfa125c92017-10-24 13:01:46 -04003818 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003819 return false;
3820 }
3821 break;
3822 }
3823
3824 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3825 ASSERT(framebuffer);
3826
3827 if (framebuffer->id() == 0)
3828 {
3829 if (clientVersion < 3)
3830 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003831 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003832 return false;
3833 }
3834
3835 switch (attachment)
3836 {
3837 case GL_BACK:
3838 case GL_DEPTH:
3839 case GL_STENCIL:
3840 break;
3841
3842 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003843 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003844 return false;
3845 }
3846 }
3847 else
3848 {
3849 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3850 {
3851 // Valid attachment query
3852 }
3853 else
3854 {
3855 switch (attachment)
3856 {
3857 case GL_DEPTH_ATTACHMENT:
3858 case GL_STENCIL_ATTACHMENT:
3859 break;
3860
3861 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003862 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04003863 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003864 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003865 return false;
3866 }
3867 break;
3868
3869 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003870 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003871 return false;
3872 }
3873 }
3874 }
3875
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003876 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003877 if (attachmentObject)
3878 {
3879 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3880 attachmentObject->type() == GL_TEXTURE ||
3881 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3882
3883 switch (pname)
3884 {
3885 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3886 if (attachmentObject->type() != GL_RENDERBUFFER &&
3887 attachmentObject->type() != GL_TEXTURE)
3888 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003889 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003890 return false;
3891 }
3892 break;
3893
3894 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3895 if (attachmentObject->type() != GL_TEXTURE)
3896 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003897 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003898 return false;
3899 }
3900 break;
3901
3902 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3903 if (attachmentObject->type() != GL_TEXTURE)
3904 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003905 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003906 return false;
3907 }
3908 break;
3909
3910 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3911 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3912 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003913 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003914 return false;
3915 }
3916 break;
3917
3918 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3919 if (attachmentObject->type() != GL_TEXTURE)
3920 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003921 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003922 return false;
3923 }
3924 break;
3925
3926 default:
3927 break;
3928 }
3929 }
3930 else
3931 {
3932 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3933 // is NONE, then querying any other pname will generate INVALID_ENUM.
3934
3935 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3936 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3937 // INVALID_OPERATION for all other pnames
3938
3939 switch (pname)
3940 {
3941 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3942 break;
3943
3944 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3945 if (clientVersion < 3)
3946 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003947 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003948 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003949 return false;
3950 }
3951 break;
3952
3953 default:
3954 if (clientVersion < 3)
3955 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003956 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003957 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003958 return false;
3959 }
3960 else
3961 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003962 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003963 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003964 return false;
3965 }
3966 }
3967 }
3968
Martin Radeve5285d22017-07-14 16:23:53 +03003969 if (numParams)
3970 {
3971 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
3972 {
3973 // Only when the viewport offsets are queried we can have a varying number of output
3974 // parameters.
3975 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
3976 *numParams = numViews * 2;
3977 }
3978 else
3979 {
3980 // For all other queries we can have only one output parameter.
3981 *numParams = 1;
3982 }
3983 }
3984
Geoff Langff5b2d52016-09-07 11:32:23 -04003985 return true;
3986}
3987
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003988bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04003989 GLenum target,
3990 GLenum attachment,
3991 GLenum pname,
3992 GLsizei bufSize,
3993 GLsizei *numParams)
3994{
3995 if (!ValidateRobustEntryPoint(context, bufSize))
3996 {
3997 return false;
3998 }
3999
Jamie Madillbe849e42017-05-02 15:49:00 -04004000 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4001 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004002 {
4003 return false;
4004 }
4005
4006 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4007 {
4008 return false;
4009 }
4010
4011 return true;
4012}
4013
Geoff Langff5b2d52016-09-07 11:32:23 -04004014bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004015 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004016 GLenum pname,
4017 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004018 GLsizei *length,
4019 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004020{
4021 if (!ValidateRobustEntryPoint(context, bufSize))
4022 {
4023 return false;
4024 }
4025
Geoff Langebebe1c2016-10-14 12:01:31 -04004026 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004027 {
4028 return false;
4029 }
4030
Geoff Langebebe1c2016-10-14 12:01:31 -04004031 if (!ValidateRobustBufferSize(context, bufSize, *length))
4032 {
4033 return false;
4034 }
4035
4036 return true;
4037}
4038
Geoff Langebebe1c2016-10-14 12:01:31 -04004039bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004040 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004041 GLenum pname,
4042 GLsizei bufSize,
4043 GLsizei *length,
4044 GLint64 *params)
4045{
4046 if (!ValidateRobustEntryPoint(context, bufSize))
4047 {
4048 return false;
4049 }
4050
4051 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4052 {
4053 return false;
4054 }
4055
4056 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004057 {
4058 return false;
4059 }
4060
4061 return true;
4062}
4063
Jamie Madillbe849e42017-05-02 15:49:00 -04004064bool ValidateGetProgramivBase(ValidationContext *context,
4065 GLuint program,
4066 GLenum pname,
4067 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004068{
4069 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004070 if (numParams)
4071 {
4072 *numParams = 1;
4073 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004074
4075 Program *programObject = GetValidProgram(context, program);
4076 if (!programObject)
4077 {
4078 return false;
4079 }
4080
4081 switch (pname)
4082 {
4083 case GL_DELETE_STATUS:
4084 case GL_LINK_STATUS:
4085 case GL_VALIDATE_STATUS:
4086 case GL_INFO_LOG_LENGTH:
4087 case GL_ATTACHED_SHADERS:
4088 case GL_ACTIVE_ATTRIBUTES:
4089 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4090 case GL_ACTIVE_UNIFORMS:
4091 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4092 break;
4093
4094 case GL_PROGRAM_BINARY_LENGTH:
4095 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4096 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004097 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4098 "requires GL_OES_get_program_binary or "
4099 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004100 return false;
4101 }
4102 break;
4103
4104 case GL_ACTIVE_UNIFORM_BLOCKS:
4105 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4106 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4107 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4108 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4109 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4110 if (context->getClientMajorVersion() < 3)
4111 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004112 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004113 return false;
4114 }
4115 break;
4116
Yunchao He61afff12017-03-14 15:34:03 +08004117 case GL_PROGRAM_SEPARABLE:
Xinghua Cao971f8502017-10-17 13:01:24 +08004118 case GL_COMPUTE_WORK_GROUP_SIZE:
jchen1058f67be2017-10-27 08:59:27 +08004119 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004120 if (context->getClientVersion() < Version(3, 1))
4121 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004122 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004123 return false;
4124 }
4125 break;
4126
Geoff Langff5b2d52016-09-07 11:32:23 -04004127 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004128 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004129 return false;
4130 }
4131
4132 return true;
4133}
4134
4135bool ValidateGetProgramivRobustANGLE(Context *context,
4136 GLuint program,
4137 GLenum pname,
4138 GLsizei bufSize,
4139 GLsizei *numParams)
4140{
4141 if (!ValidateRobustEntryPoint(context, bufSize))
4142 {
4143 return false;
4144 }
4145
Jamie Madillbe849e42017-05-02 15:49:00 -04004146 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004147 {
4148 return false;
4149 }
4150
4151 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4152 {
4153 return false;
4154 }
4155
4156 return true;
4157}
4158
Geoff Lang740d9022016-10-07 11:20:52 -04004159bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4160 GLenum target,
4161 GLenum pname,
4162 GLsizei bufSize,
4163 GLsizei *length,
4164 GLint *params)
4165{
4166 if (!ValidateRobustEntryPoint(context, bufSize))
4167 {
4168 return false;
4169 }
4170
4171 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4172 {
4173 return false;
4174 }
4175
4176 if (!ValidateRobustBufferSize(context, bufSize, *length))
4177 {
4178 return false;
4179 }
4180
4181 return true;
4182}
4183
Geoff Langd7d0ed32016-10-07 11:33:51 -04004184bool ValidateGetShaderivRobustANGLE(Context *context,
4185 GLuint shader,
4186 GLenum pname,
4187 GLsizei bufSize,
4188 GLsizei *length,
4189 GLint *params)
4190{
4191 if (!ValidateRobustEntryPoint(context, bufSize))
4192 {
4193 return false;
4194 }
4195
4196 if (!ValidateGetShaderivBase(context, shader, pname, length))
4197 {
4198 return false;
4199 }
4200
4201 if (!ValidateRobustBufferSize(context, bufSize, *length))
4202 {
4203 return false;
4204 }
4205
4206 return true;
4207}
4208
Geoff Langc1984ed2016-10-07 12:41:00 -04004209bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4210 GLenum target,
4211 GLenum pname,
4212 GLsizei bufSize,
4213 GLsizei *length,
4214 GLfloat *params)
4215{
4216 if (!ValidateRobustEntryPoint(context, bufSize))
4217 {
4218 return false;
4219 }
4220
4221 if (!ValidateGetTexParameterBase(context, target, pname, length))
4222 {
4223 return false;
4224 }
4225
4226 if (!ValidateRobustBufferSize(context, bufSize, *length))
4227 {
4228 return false;
4229 }
4230
4231 return true;
4232}
4233
Geoff Langc1984ed2016-10-07 12:41:00 -04004234bool ValidateGetTexParameterivRobustANGLE(Context *context,
4235 GLenum target,
4236 GLenum pname,
4237 GLsizei bufSize,
4238 GLsizei *length,
4239 GLint *params)
4240{
4241 if (!ValidateRobustEntryPoint(context, bufSize))
4242 {
4243 return false;
4244 }
4245
4246 if (!ValidateGetTexParameterBase(context, target, pname, length))
4247 {
4248 return false;
4249 }
4250
4251 if (!ValidateRobustBufferSize(context, bufSize, *length))
4252 {
4253 return false;
4254 }
4255
4256 return true;
4257}
4258
Geoff Langc1984ed2016-10-07 12:41:00 -04004259bool ValidateTexParameterfvRobustANGLE(Context *context,
4260 GLenum target,
4261 GLenum pname,
4262 GLsizei bufSize,
4263 const GLfloat *params)
4264{
4265 if (!ValidateRobustEntryPoint(context, bufSize))
4266 {
4267 return false;
4268 }
4269
4270 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4271}
4272
Geoff Langc1984ed2016-10-07 12:41:00 -04004273bool ValidateTexParameterivRobustANGLE(Context *context,
4274 GLenum target,
4275 GLenum pname,
4276 GLsizei bufSize,
4277 const GLint *params)
4278{
4279 if (!ValidateRobustEntryPoint(context, bufSize))
4280 {
4281 return false;
4282 }
4283
4284 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4285}
4286
Geoff Langc1984ed2016-10-07 12:41:00 -04004287bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4288 GLuint sampler,
4289 GLenum pname,
4290 GLuint bufSize,
4291 GLsizei *length,
4292 GLfloat *params)
4293{
4294 if (!ValidateRobustEntryPoint(context, bufSize))
4295 {
4296 return false;
4297 }
4298
4299 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4300 {
4301 return false;
4302 }
4303
4304 if (!ValidateRobustBufferSize(context, bufSize, *length))
4305 {
4306 return false;
4307 }
4308
4309 return true;
4310}
4311
Geoff Langc1984ed2016-10-07 12:41:00 -04004312bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4313 GLuint sampler,
4314 GLenum pname,
4315 GLuint bufSize,
4316 GLsizei *length,
4317 GLint *params)
4318{
4319 if (!ValidateRobustEntryPoint(context, bufSize))
4320 {
4321 return false;
4322 }
4323
4324 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4325 {
4326 return false;
4327 }
4328
4329 if (!ValidateRobustBufferSize(context, bufSize, *length))
4330 {
4331 return false;
4332 }
4333
4334 return true;
4335}
4336
Geoff Langc1984ed2016-10-07 12:41:00 -04004337bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4338 GLuint sampler,
4339 GLenum pname,
4340 GLsizei bufSize,
4341 const GLfloat *params)
4342{
4343 if (!ValidateRobustEntryPoint(context, bufSize))
4344 {
4345 return false;
4346 }
4347
4348 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4349}
4350
Geoff Langc1984ed2016-10-07 12:41:00 -04004351bool ValidateSamplerParameterivRobustANGLE(Context *context,
4352 GLuint sampler,
4353 GLenum pname,
4354 GLsizei bufSize,
4355 const GLint *params)
4356{
4357 if (!ValidateRobustEntryPoint(context, bufSize))
4358 {
4359 return false;
4360 }
4361
4362 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4363}
4364
Geoff Lang0b031062016-10-13 14:30:04 -04004365bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4366 GLuint index,
4367 GLenum pname,
4368 GLsizei bufSize,
4369 GLsizei *length,
4370 GLfloat *params)
4371{
4372 if (!ValidateRobustEntryPoint(context, bufSize))
4373 {
4374 return false;
4375 }
4376
4377 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4378 {
4379 return false;
4380 }
4381
4382 if (!ValidateRobustBufferSize(context, bufSize, *length))
4383 {
4384 return false;
4385 }
4386
4387 return true;
4388}
4389
Geoff Lang0b031062016-10-13 14:30:04 -04004390bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4391 GLuint index,
4392 GLenum pname,
4393 GLsizei bufSize,
4394 GLsizei *length,
4395 GLint *params)
4396{
4397 if (!ValidateRobustEntryPoint(context, bufSize))
4398 {
4399 return false;
4400 }
4401
4402 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4403 {
4404 return false;
4405 }
4406
4407 if (!ValidateRobustBufferSize(context, bufSize, *length))
4408 {
4409 return false;
4410 }
4411
4412 return true;
4413}
4414
Geoff Lang0b031062016-10-13 14:30:04 -04004415bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4416 GLuint index,
4417 GLenum pname,
4418 GLsizei bufSize,
4419 GLsizei *length,
4420 void **pointer)
4421{
4422 if (!ValidateRobustEntryPoint(context, bufSize))
4423 {
4424 return false;
4425 }
4426
4427 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4428 {
4429 return false;
4430 }
4431
4432 if (!ValidateRobustBufferSize(context, bufSize, *length))
4433 {
4434 return false;
4435 }
4436
4437 return true;
4438}
4439
Geoff Lang0b031062016-10-13 14:30:04 -04004440bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4441 GLuint index,
4442 GLenum pname,
4443 GLsizei bufSize,
4444 GLsizei *length,
4445 GLint *params)
4446{
4447 if (!ValidateRobustEntryPoint(context, bufSize))
4448 {
4449 return false;
4450 }
4451
4452 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4453 {
4454 return false;
4455 }
4456
4457 if (!ValidateRobustBufferSize(context, bufSize, *length))
4458 {
4459 return false;
4460 }
4461
4462 return true;
4463}
4464
Geoff Lang0b031062016-10-13 14:30:04 -04004465bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4466 GLuint index,
4467 GLenum pname,
4468 GLsizei bufSize,
4469 GLsizei *length,
4470 GLuint *params)
4471{
4472 if (!ValidateRobustEntryPoint(context, bufSize))
4473 {
4474 return false;
4475 }
4476
4477 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4478 {
4479 return false;
4480 }
4481
4482 if (!ValidateRobustBufferSize(context, bufSize, *length))
4483 {
4484 return false;
4485 }
4486
4487 return true;
4488}
4489
Geoff Lang6899b872016-10-14 11:30:13 -04004490bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4491 GLuint program,
4492 GLuint uniformBlockIndex,
4493 GLenum pname,
4494 GLsizei bufSize,
4495 GLsizei *length,
4496 GLint *params)
4497{
4498 if (!ValidateRobustEntryPoint(context, bufSize))
4499 {
4500 return false;
4501 }
4502
4503 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4504 {
4505 return false;
4506 }
4507
4508 if (!ValidateRobustBufferSize(context, bufSize, *length))
4509 {
4510 return false;
4511 }
4512
4513 return true;
4514}
4515
Geoff Lang0a9661f2016-10-20 10:59:20 -07004516bool ValidateGetInternalFormativRobustANGLE(Context *context,
4517 GLenum target,
4518 GLenum internalformat,
4519 GLenum pname,
4520 GLsizei bufSize,
4521 GLsizei *length,
4522 GLint *params)
4523{
4524 if (!ValidateRobustEntryPoint(context, bufSize))
4525 {
4526 return false;
4527 }
4528
4529 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4530 {
4531 return false;
4532 }
4533
4534 if (!ValidateRobustBufferSize(context, bufSize, *length))
4535 {
4536 return false;
4537 }
4538
4539 return true;
4540}
4541
Shao80957d92017-02-20 21:25:59 +08004542bool ValidateVertexFormatBase(ValidationContext *context,
4543 GLuint attribIndex,
4544 GLint size,
4545 GLenum type,
4546 GLboolean pureInteger)
4547{
4548 const Caps &caps = context->getCaps();
4549 if (attribIndex >= caps.maxVertexAttributes)
4550 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004551 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004552 return false;
4553 }
4554
4555 if (size < 1 || size > 4)
4556 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004557 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004558 return false;
Shao80957d92017-02-20 21:25:59 +08004559 }
4560
4561 switch (type)
4562 {
4563 case GL_BYTE:
4564 case GL_UNSIGNED_BYTE:
4565 case GL_SHORT:
4566 case GL_UNSIGNED_SHORT:
4567 break;
4568
4569 case GL_INT:
4570 case GL_UNSIGNED_INT:
4571 if (context->getClientMajorVersion() < 3)
4572 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004573 context->handleError(InvalidEnum()
4574 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004575 return false;
4576 }
4577 break;
4578
4579 case GL_FIXED:
4580 case GL_FLOAT:
4581 if (pureInteger)
4582 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004583 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004584 return false;
4585 }
4586 break;
4587
4588 case GL_HALF_FLOAT:
4589 if (context->getClientMajorVersion() < 3)
4590 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004591 context->handleError(InvalidEnum()
4592 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004593 return false;
4594 }
4595 if (pureInteger)
4596 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004597 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004598 return false;
4599 }
4600 break;
4601
4602 case GL_INT_2_10_10_10_REV:
4603 case GL_UNSIGNED_INT_2_10_10_10_REV:
4604 if (context->getClientMajorVersion() < 3)
4605 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004606 context->handleError(InvalidEnum()
4607 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004608 return false;
4609 }
4610 if (pureInteger)
4611 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004612 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004613 return false;
4614 }
4615 if (size != 4)
4616 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004617 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4618 "UNSIGNED_INT_2_10_10_10_REV and "
4619 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004620 return false;
4621 }
4622 break;
4623
4624 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004625 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004626 return false;
4627 }
4628
4629 return true;
4630}
4631
Geoff Lang76e65652017-03-27 14:58:02 -04004632// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4633// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4634// specified clear value and the type of a buffer that is being cleared generates an
4635// INVALID_OPERATION error instead of producing undefined results
4636bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4637 GLint drawbuffer,
4638 const GLenum *validComponentTypes,
4639 size_t validComponentTypeCount)
4640{
4641 const FramebufferAttachment *attachment =
4642 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4643 if (attachment)
4644 {
4645 GLenum componentType = attachment->getFormat().info->componentType;
4646 const GLenum *end = validComponentTypes + validComponentTypeCount;
4647 if (std::find(validComponentTypes, end, componentType) == end)
4648 {
4649 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004650 InvalidOperation()
4651 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004652 return false;
4653 }
4654 }
4655
4656 return true;
4657}
4658
Corentin Wallezb2931602017-04-11 15:58:57 -04004659bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4660 GLsizei imageSize,
4661 GLsizei dataSize)
4662{
4663 if (!ValidateRobustEntryPoint(context, dataSize))
4664 {
4665 return false;
4666 }
4667
Corentin Wallez336129f2017-10-17 15:55:40 -04004668 gl::Buffer *pixelUnpackBuffer =
4669 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004670 if (pixelUnpackBuffer == nullptr)
4671 {
4672 if (dataSize < imageSize)
4673 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004674 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004675 }
4676 }
4677 return true;
4678}
4679
Jamie Madillbe849e42017-05-02 15:49:00 -04004680bool ValidateGetBufferParameterBase(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004681 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004682 GLenum pname,
4683 bool pointerVersion,
4684 GLsizei *numParams)
4685{
4686 if (numParams)
4687 {
4688 *numParams = 0;
4689 }
4690
Corentin Walleze4477002017-12-01 14:39:58 -05004691 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004692 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004693 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004694 return false;
4695 }
4696
4697 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4698 if (!buffer)
4699 {
4700 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004701 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004702 return false;
4703 }
4704
4705 const Extensions &extensions = context->getExtensions();
4706
4707 switch (pname)
4708 {
4709 case GL_BUFFER_USAGE:
4710 case GL_BUFFER_SIZE:
4711 break;
4712
4713 case GL_BUFFER_ACCESS_OES:
4714 if (!extensions.mapBuffer)
4715 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004716 context->handleError(InvalidEnum()
4717 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004718 return false;
4719 }
4720 break;
4721
4722 case GL_BUFFER_MAPPED:
4723 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4724 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4725 !extensions.mapBufferRange)
4726 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004727 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4728 "GL_OES_mapbuffer or "
4729 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004730 return false;
4731 }
4732 break;
4733
4734 case GL_BUFFER_MAP_POINTER:
4735 if (!pointerVersion)
4736 {
4737 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004738 InvalidEnum()
4739 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004740 return false;
4741 }
4742 break;
4743
4744 case GL_BUFFER_ACCESS_FLAGS:
4745 case GL_BUFFER_MAP_OFFSET:
4746 case GL_BUFFER_MAP_LENGTH:
4747 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4748 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004749 context->handleError(InvalidEnum()
4750 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004751 return false;
4752 }
4753 break;
4754
4755 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004756 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004757 return false;
4758 }
4759
4760 // All buffer parameter queries return one value.
4761 if (numParams)
4762 {
4763 *numParams = 1;
4764 }
4765
4766 return true;
4767}
4768
4769bool ValidateGetRenderbufferParameterivBase(Context *context,
4770 GLenum target,
4771 GLenum pname,
4772 GLsizei *length)
4773{
4774 if (length)
4775 {
4776 *length = 0;
4777 }
4778
4779 if (target != GL_RENDERBUFFER)
4780 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004781 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004782 return false;
4783 }
4784
4785 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4786 if (renderbuffer == nullptr)
4787 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004788 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004789 return false;
4790 }
4791
4792 switch (pname)
4793 {
4794 case GL_RENDERBUFFER_WIDTH:
4795 case GL_RENDERBUFFER_HEIGHT:
4796 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4797 case GL_RENDERBUFFER_RED_SIZE:
4798 case GL_RENDERBUFFER_GREEN_SIZE:
4799 case GL_RENDERBUFFER_BLUE_SIZE:
4800 case GL_RENDERBUFFER_ALPHA_SIZE:
4801 case GL_RENDERBUFFER_DEPTH_SIZE:
4802 case GL_RENDERBUFFER_STENCIL_SIZE:
4803 break;
4804
4805 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4806 if (!context->getExtensions().framebufferMultisample)
4807 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004808 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
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 if (length)
4819 {
4820 *length = 1;
4821 }
4822 return true;
4823}
4824
4825bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4826{
4827 if (length)
4828 {
4829 *length = 0;
4830 }
4831
4832 if (GetValidShader(context, shader) == nullptr)
4833 {
4834 return false;
4835 }
4836
4837 switch (pname)
4838 {
4839 case GL_SHADER_TYPE:
4840 case GL_DELETE_STATUS:
4841 case GL_COMPILE_STATUS:
4842 case GL_INFO_LOG_LENGTH:
4843 case GL_SHADER_SOURCE_LENGTH:
4844 break;
4845
4846 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4847 if (!context->getExtensions().translatedShaderSource)
4848 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004849 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004850 return false;
4851 }
4852 break;
4853
4854 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004855 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004856 return false;
4857 }
4858
4859 if (length)
4860 {
4861 *length = 1;
4862 }
4863 return true;
4864}
4865
4866bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4867{
4868 if (length)
4869 {
4870 *length = 0;
4871 }
4872
4873 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4874 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004875 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004876 return false;
4877 }
4878
4879 if (context->getTargetTexture(target) == nullptr)
4880 {
4881 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004882 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004883 return false;
4884 }
4885
4886 switch (pname)
4887 {
4888 case GL_TEXTURE_MAG_FILTER:
4889 case GL_TEXTURE_MIN_FILTER:
4890 case GL_TEXTURE_WRAP_S:
4891 case GL_TEXTURE_WRAP_T:
4892 break;
4893
4894 case GL_TEXTURE_USAGE_ANGLE:
4895 if (!context->getExtensions().textureUsage)
4896 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004897 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004898 return false;
4899 }
4900 break;
4901
4902 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4903 if (!context->getExtensions().textureFilterAnisotropic)
4904 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004905 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004906 return false;
4907 }
4908 break;
4909
4910 case GL_TEXTURE_IMMUTABLE_FORMAT:
4911 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4912 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004913 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004914 return false;
4915 }
4916 break;
4917
4918 case GL_TEXTURE_WRAP_R:
4919 case GL_TEXTURE_IMMUTABLE_LEVELS:
4920 case GL_TEXTURE_SWIZZLE_R:
4921 case GL_TEXTURE_SWIZZLE_G:
4922 case GL_TEXTURE_SWIZZLE_B:
4923 case GL_TEXTURE_SWIZZLE_A:
4924 case GL_TEXTURE_BASE_LEVEL:
4925 case GL_TEXTURE_MAX_LEVEL:
4926 case GL_TEXTURE_MIN_LOD:
4927 case GL_TEXTURE_MAX_LOD:
4928 case GL_TEXTURE_COMPARE_MODE:
4929 case GL_TEXTURE_COMPARE_FUNC:
4930 if (context->getClientMajorVersion() < 3)
4931 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004932 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004933 return false;
4934 }
4935 break;
4936
4937 case GL_TEXTURE_SRGB_DECODE_EXT:
4938 if (!context->getExtensions().textureSRGBDecode)
4939 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004940 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004941 return false;
4942 }
4943 break;
4944
4945 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004946 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004947 return false;
4948 }
4949
4950 if (length)
4951 {
4952 *length = 1;
4953 }
4954 return true;
4955}
4956
4957bool ValidateGetVertexAttribBase(Context *context,
4958 GLuint index,
4959 GLenum pname,
4960 GLsizei *length,
4961 bool pointer,
4962 bool pureIntegerEntryPoint)
4963{
4964 if (length)
4965 {
4966 *length = 0;
4967 }
4968
4969 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
4970 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004971 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004972 return false;
4973 }
4974
4975 if (index >= context->getCaps().maxVertexAttributes)
4976 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004977 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04004978 return false;
4979 }
4980
4981 if (pointer)
4982 {
4983 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
4984 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004985 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004986 return false;
4987 }
4988 }
4989 else
4990 {
4991 switch (pname)
4992 {
4993 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4994 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4995 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4996 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4997 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4998 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
4999 case GL_CURRENT_VERTEX_ATTRIB:
5000 break;
5001
5002 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5003 static_assert(
5004 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5005 "ANGLE extension enums not equal to GL enums.");
5006 if (context->getClientMajorVersion() < 3 &&
5007 !context->getExtensions().instancedArrays)
5008 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005009 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5010 "requires OpenGL ES 3.0 or "
5011 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005012 return false;
5013 }
5014 break;
5015
5016 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5017 if (context->getClientMajorVersion() < 3)
5018 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005019 context->handleError(
5020 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005021 return false;
5022 }
5023 break;
5024
5025 case GL_VERTEX_ATTRIB_BINDING:
5026 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5027 if (context->getClientVersion() < ES_3_1)
5028 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005029 context->handleError(InvalidEnum()
5030 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005031 return false;
5032 }
5033 break;
5034
5035 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005036 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005037 return false;
5038 }
5039 }
5040
5041 if (length)
5042 {
5043 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5044 {
5045 *length = 4;
5046 }
5047 else
5048 {
5049 *length = 1;
5050 }
5051 }
5052
5053 return true;
5054}
5055
Jamie Madill4928b7c2017-06-20 12:57:39 -04005056bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005057 GLint x,
5058 GLint y,
5059 GLsizei width,
5060 GLsizei height,
5061 GLenum format,
5062 GLenum type,
5063 GLsizei bufSize,
5064 GLsizei *length,
5065 GLsizei *columns,
5066 GLsizei *rows,
5067 void *pixels)
5068{
5069 if (length != nullptr)
5070 {
5071 *length = 0;
5072 }
5073 if (rows != nullptr)
5074 {
5075 *rows = 0;
5076 }
5077 if (columns != nullptr)
5078 {
5079 *columns = 0;
5080 }
5081
5082 if (width < 0 || height < 0)
5083 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005084 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005085 return false;
5086 }
5087
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005088 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005089
5090 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5091 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005092 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005093 return false;
5094 }
5095
5096 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5097 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005098 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005099 return false;
5100 }
5101
5102 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5103 ASSERT(framebuffer);
5104
5105 if (framebuffer->getReadBufferState() == GL_NONE)
5106 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005107 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005108 return false;
5109 }
5110
5111 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5112 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5113 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5114 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5115 // situation is an application error that would lead to a crash in ANGLE.
5116 if (readBuffer == nullptr)
5117 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005118 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005119 return false;
5120 }
5121
Martin Radev28031682017-07-28 14:47:56 +03005122 // ANGLE_multiview, Revision 1:
5123 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5124 // current read framebuffer is not NONE.
5125 if (readBuffer->getMultiviewLayout() != GL_NONE)
5126 {
5127 context->handleError(InvalidFramebufferOperation()
5128 << "Attempting to read from a multi-view framebuffer.");
5129 return false;
5130 }
5131
Geoff Lang280ba992017-04-18 16:30:58 -04005132 if (context->getExtensions().webglCompatibility)
5133 {
5134 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5135 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5136 // and type before validating the combination of format and type. However, the
5137 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5138 // verifies that GL_INVALID_OPERATION is generated.
5139 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5140 // dEQP/WebGL.
5141 if (!ValidReadPixelsFormatEnum(context, format))
5142 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005143 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005144 return false;
5145 }
5146
5147 if (!ValidReadPixelsTypeEnum(context, type))
5148 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005149 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005150 return false;
5151 }
5152 }
5153
Jamie Madill4928b7c2017-06-20 12:57:39 -04005154 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5155 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005156 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5157
5158 bool validFormatTypeCombination =
5159 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5160
5161 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5162 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005163 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005164 return false;
5165 }
5166
5167 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005168 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005169 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5170 {
5171 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005172 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005173 return false;
5174 }
5175
5176 // .. the data would be packed to the buffer object such that the memory writes required
5177 // would exceed the data store size.
5178 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5179 const gl::Extents size(width, height, 1);
5180 const auto &pack = context->getGLState().getPackState();
5181
5182 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5183 if (endByteOrErr.isError())
5184 {
5185 context->handleError(endByteOrErr.getError());
5186 return false;
5187 }
5188
5189 size_t endByte = endByteOrErr.getResult();
5190 if (bufSize >= 0)
5191 {
5192 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5193 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005194 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005195 return false;
5196 }
5197 }
5198
5199 if (pixelPackBuffer != nullptr)
5200 {
5201 CheckedNumeric<size_t> checkedEndByte(endByte);
5202 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5203 checkedEndByte += checkedOffset;
5204
5205 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5206 {
5207 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005208 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005209 return false;
5210 }
5211 }
5212
5213 if (pixelPackBuffer == nullptr && length != nullptr)
5214 {
5215 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5216 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005217 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005218 return false;
5219 }
5220
5221 *length = static_cast<GLsizei>(endByte);
5222 }
5223
5224 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5225 angle::CheckedNumeric<int> clippedExtent(length);
5226 if (start < 0)
5227 {
5228 // "subtract" the area that is less than 0
5229 clippedExtent += start;
5230 }
5231
5232 const int readExtent = start + length;
5233 if (readExtent > bufferSize)
5234 {
5235 // Subtract the region to the right of the read buffer
5236 clippedExtent -= (readExtent - bufferSize);
5237 }
5238
5239 if (!clippedExtent.IsValid())
5240 {
5241 return 0;
5242 }
5243
5244 return std::max(clippedExtent.ValueOrDie(), 0);
5245 };
5246
5247 if (columns != nullptr)
5248 {
5249 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5250 }
5251
5252 if (rows != nullptr)
5253 {
5254 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5255 }
5256
5257 return true;
5258}
5259
5260template <typename ParamType>
5261bool ValidateTexParameterBase(Context *context,
5262 GLenum target,
5263 GLenum pname,
5264 GLsizei bufSize,
5265 const ParamType *params)
5266{
5267 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5268 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005269 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005270 return false;
5271 }
5272
5273 if (context->getTargetTexture(target) == nullptr)
5274 {
5275 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005276 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005277 return false;
5278 }
5279
5280 const GLsizei minBufSize = 1;
5281 if (bufSize >= 0 && bufSize < minBufSize)
5282 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005283 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005284 return false;
5285 }
5286
5287 switch (pname)
5288 {
5289 case GL_TEXTURE_WRAP_R:
5290 case GL_TEXTURE_SWIZZLE_R:
5291 case GL_TEXTURE_SWIZZLE_G:
5292 case GL_TEXTURE_SWIZZLE_B:
5293 case GL_TEXTURE_SWIZZLE_A:
5294 case GL_TEXTURE_BASE_LEVEL:
5295 case GL_TEXTURE_MAX_LEVEL:
5296 case GL_TEXTURE_COMPARE_MODE:
5297 case GL_TEXTURE_COMPARE_FUNC:
5298 case GL_TEXTURE_MIN_LOD:
5299 case GL_TEXTURE_MAX_LOD:
5300 if (context->getClientMajorVersion() < 3)
5301 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005302 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005303 return false;
5304 }
5305 if (target == GL_TEXTURE_EXTERNAL_OES &&
5306 !context->getExtensions().eglImageExternalEssl3)
5307 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005308 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5309 "available without "
5310 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005311 return false;
5312 }
5313 break;
5314
5315 default:
5316 break;
5317 }
5318
JiangYizhou4cff8d62017-07-06 14:54:09 +08005319 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5320 {
5321 switch (pname)
5322 {
5323 case GL_TEXTURE_MIN_FILTER:
5324 case GL_TEXTURE_MAG_FILTER:
5325 case GL_TEXTURE_WRAP_S:
5326 case GL_TEXTURE_WRAP_T:
5327 case GL_TEXTURE_WRAP_R:
5328 case GL_TEXTURE_MIN_LOD:
5329 case GL_TEXTURE_MAX_LOD:
5330 case GL_TEXTURE_COMPARE_MODE:
5331 case GL_TEXTURE_COMPARE_FUNC:
5332 context->handleError(InvalidEnum()
5333 << "Invalid parameter for 2D multisampled textures.");
5334 return false;
5335 }
5336 }
5337
Jamie Madillbe849e42017-05-02 15:49:00 -04005338 switch (pname)
5339 {
5340 case GL_TEXTURE_WRAP_S:
5341 case GL_TEXTURE_WRAP_T:
5342 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005343 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005344 bool restrictedWrapModes =
5345 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5346 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5347 {
5348 return false;
5349 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005350 }
5351 break;
5352
5353 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005354 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005355 bool restrictedMinFilter =
5356 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5357 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5358 {
5359 return false;
5360 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005361 }
5362 break;
5363
5364 case GL_TEXTURE_MAG_FILTER:
5365 if (!ValidateTextureMagFilterValue(context, params))
5366 {
5367 return false;
5368 }
5369 break;
5370
5371 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005372 if (!context->getExtensions().textureUsage)
5373 {
5374 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5375 return false;
5376 }
5377
Jamie Madillbe849e42017-05-02 15:49:00 -04005378 switch (ConvertToGLenum(params[0]))
5379 {
5380 case GL_NONE:
5381 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5382 break;
5383
5384 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005385 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005386 return false;
5387 }
5388 break;
5389
5390 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5391 if (!context->getExtensions().textureFilterAnisotropic)
5392 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005393 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005394 return false;
5395 }
5396
5397 // we assume the parameter passed to this validation method is truncated, not rounded
5398 if (params[0] < 1)
5399 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005400 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005401 return false;
5402 }
5403 break;
5404
5405 case GL_TEXTURE_MIN_LOD:
5406 case GL_TEXTURE_MAX_LOD:
5407 // any value is permissible
5408 break;
5409
5410 case GL_TEXTURE_COMPARE_MODE:
5411 if (!ValidateTextureCompareModeValue(context, params))
5412 {
5413 return false;
5414 }
5415 break;
5416
5417 case GL_TEXTURE_COMPARE_FUNC:
5418 if (!ValidateTextureCompareFuncValue(context, params))
5419 {
5420 return false;
5421 }
5422 break;
5423
5424 case GL_TEXTURE_SWIZZLE_R:
5425 case GL_TEXTURE_SWIZZLE_G:
5426 case GL_TEXTURE_SWIZZLE_B:
5427 case GL_TEXTURE_SWIZZLE_A:
5428 switch (ConvertToGLenum(params[0]))
5429 {
5430 case GL_RED:
5431 case GL_GREEN:
5432 case GL_BLUE:
5433 case GL_ALPHA:
5434 case GL_ZERO:
5435 case GL_ONE:
5436 break;
5437
5438 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005439 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005440 return false;
5441 }
5442 break;
5443
5444 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005445 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005446 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005447 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005448 return false;
5449 }
5450 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5451 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005452 context->handleError(InvalidOperation()
5453 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005454 return false;
5455 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005456 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5457 {
5458 context->handleError(InvalidOperation()
5459 << "Base level must be 0 for multisampled textures.");
5460 return false;
5461 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005462 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5463 {
5464 context->handleError(InvalidOperation()
5465 << "Base level must be 0 for rectangle textures.");
5466 return false;
5467 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005468 break;
5469
5470 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005471 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005472 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005473 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005474 return false;
5475 }
5476 break;
5477
5478 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5479 if (context->getClientVersion() < Version(3, 1))
5480 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005481 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005482 return false;
5483 }
5484 switch (ConvertToGLenum(params[0]))
5485 {
5486 case GL_DEPTH_COMPONENT:
5487 case GL_STENCIL_INDEX:
5488 break;
5489
5490 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005491 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005492 return false;
5493 }
5494 break;
5495
5496 case GL_TEXTURE_SRGB_DECODE_EXT:
5497 if (!ValidateTextureSRGBDecodeValue(context, params))
5498 {
5499 return false;
5500 }
5501 break;
5502
5503 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005504 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005505 return false;
5506 }
5507
5508 return true;
5509}
5510
5511template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5512template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5513
Jamie Madill12e957f2017-08-26 21:42:26 -04005514bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5515{
5516 if (index >= MAX_VERTEX_ATTRIBS)
5517 {
5518 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5519 return false;
5520 }
5521
5522 return true;
5523}
5524
5525bool ValidateGetActiveUniformBlockivBase(Context *context,
5526 GLuint program,
5527 GLuint uniformBlockIndex,
5528 GLenum pname,
5529 GLsizei *length)
5530{
5531 if (length)
5532 {
5533 *length = 0;
5534 }
5535
5536 if (context->getClientMajorVersion() < 3)
5537 {
5538 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5539 return false;
5540 }
5541
5542 Program *programObject = GetValidProgram(context, program);
5543 if (!programObject)
5544 {
5545 return false;
5546 }
5547
5548 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5549 {
5550 context->handleError(InvalidValue()
5551 << "uniformBlockIndex exceeds active uniform block count.");
5552 return false;
5553 }
5554
5555 switch (pname)
5556 {
5557 case GL_UNIFORM_BLOCK_BINDING:
5558 case GL_UNIFORM_BLOCK_DATA_SIZE:
5559 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5560 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5561 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5562 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5563 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5564 break;
5565
5566 default:
5567 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5568 return false;
5569 }
5570
5571 if (length)
5572 {
5573 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5574 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005575 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005576 programObject->getUniformBlockByIndex(uniformBlockIndex);
5577 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5578 }
5579 else
5580 {
5581 *length = 1;
5582 }
5583 }
5584
5585 return true;
5586}
5587
Jamie Madill9696d072017-08-26 23:19:57 -04005588template <typename ParamType>
5589bool ValidateSamplerParameterBase(Context *context,
5590 GLuint sampler,
5591 GLenum pname,
5592 GLsizei bufSize,
5593 ParamType *params)
5594{
5595 if (context->getClientMajorVersion() < 3)
5596 {
5597 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5598 return false;
5599 }
5600
5601 if (!context->isSampler(sampler))
5602 {
5603 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5604 return false;
5605 }
5606
5607 const GLsizei minBufSize = 1;
5608 if (bufSize >= 0 && bufSize < minBufSize)
5609 {
5610 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5611 return false;
5612 }
5613
5614 switch (pname)
5615 {
5616 case GL_TEXTURE_WRAP_S:
5617 case GL_TEXTURE_WRAP_T:
5618 case GL_TEXTURE_WRAP_R:
5619 if (!ValidateTextureWrapModeValue(context, params, false))
5620 {
5621 return false;
5622 }
5623 break;
5624
5625 case GL_TEXTURE_MIN_FILTER:
5626 if (!ValidateTextureMinFilterValue(context, params, false))
5627 {
5628 return false;
5629 }
5630 break;
5631
5632 case GL_TEXTURE_MAG_FILTER:
5633 if (!ValidateTextureMagFilterValue(context, params))
5634 {
5635 return false;
5636 }
5637 break;
5638
5639 case GL_TEXTURE_MIN_LOD:
5640 case GL_TEXTURE_MAX_LOD:
5641 // any value is permissible
5642 break;
5643
5644 case GL_TEXTURE_COMPARE_MODE:
5645 if (!ValidateTextureCompareModeValue(context, params))
5646 {
5647 return false;
5648 }
5649 break;
5650
5651 case GL_TEXTURE_COMPARE_FUNC:
5652 if (!ValidateTextureCompareFuncValue(context, params))
5653 {
5654 return false;
5655 }
5656 break;
5657
5658 case GL_TEXTURE_SRGB_DECODE_EXT:
5659 if (!ValidateTextureSRGBDecodeValue(context, params))
5660 {
5661 return false;
5662 }
5663 break;
5664
5665 default:
5666 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5667 return false;
5668 }
5669
5670 return true;
5671}
5672
5673template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5674template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5675
5676bool ValidateGetSamplerParameterBase(Context *context,
5677 GLuint sampler,
5678 GLenum pname,
5679 GLsizei *length)
5680{
5681 if (length)
5682 {
5683 *length = 0;
5684 }
5685
5686 if (context->getClientMajorVersion() < 3)
5687 {
5688 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5689 return false;
5690 }
5691
5692 if (!context->isSampler(sampler))
5693 {
5694 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5695 return false;
5696 }
5697
5698 switch (pname)
5699 {
5700 case GL_TEXTURE_WRAP_S:
5701 case GL_TEXTURE_WRAP_T:
5702 case GL_TEXTURE_WRAP_R:
5703 case GL_TEXTURE_MIN_FILTER:
5704 case GL_TEXTURE_MAG_FILTER:
5705 case GL_TEXTURE_MIN_LOD:
5706 case GL_TEXTURE_MAX_LOD:
5707 case GL_TEXTURE_COMPARE_MODE:
5708 case GL_TEXTURE_COMPARE_FUNC:
5709 break;
5710
5711 case GL_TEXTURE_SRGB_DECODE_EXT:
5712 if (!context->getExtensions().textureSRGBDecode)
5713 {
5714 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5715 return false;
5716 }
5717 break;
5718
5719 default:
5720 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5721 return false;
5722 }
5723
5724 if (length)
5725 {
5726 *length = 1;
5727 }
5728 return true;
5729}
5730
5731bool ValidateGetInternalFormativBase(Context *context,
5732 GLenum target,
5733 GLenum internalformat,
5734 GLenum pname,
5735 GLsizei bufSize,
5736 GLsizei *numParams)
5737{
5738 if (numParams)
5739 {
5740 *numParams = 0;
5741 }
5742
5743 if (context->getClientMajorVersion() < 3)
5744 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005745 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005746 return false;
5747 }
5748
5749 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5750 if (!formatCaps.renderable)
5751 {
5752 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5753 return false;
5754 }
5755
5756 switch (target)
5757 {
5758 case GL_RENDERBUFFER:
5759 break;
5760
5761 case GL_TEXTURE_2D_MULTISAMPLE:
5762 if (context->getClientVersion() < ES_3_1)
5763 {
5764 context->handleError(InvalidOperation()
5765 << "Texture target requires at least OpenGL ES 3.1.");
5766 return false;
5767 }
5768 break;
5769
5770 default:
5771 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5772 return false;
5773 }
5774
5775 if (bufSize < 0)
5776 {
5777 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5778 return false;
5779 }
5780
5781 GLsizei maxWriteParams = 0;
5782 switch (pname)
5783 {
5784 case GL_NUM_SAMPLE_COUNTS:
5785 maxWriteParams = 1;
5786 break;
5787
5788 case GL_SAMPLES:
5789 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5790 break;
5791
5792 default:
5793 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5794 return false;
5795 }
5796
5797 if (numParams)
5798 {
5799 // glGetInternalFormativ will not overflow bufSize
5800 *numParams = std::min(bufSize, maxWriteParams);
5801 }
5802
5803 return true;
5804}
5805
Jamie Madillc29968b2016-01-20 11:17:23 -05005806} // namespace gl