blob: 3a29a33a64f7892889ba74a61264f82a10e89af2 [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 Madill231c7f52017-04-26 13:45:37 -040050 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040051 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
52 {
53 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallez672f7f32017-06-15 17:42:17 -040054
55 // No need to range check for disabled attribs.
56 if (!attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040057 {
Corentin Wallezfd456442016-12-21 17:57:00 -050058 continue;
59 }
Jamie Madill1ca74672015-07-21 15:14:11 -040060
Jamie Madill231c7f52017-04-26 13:45:37 -040061 // If we have no buffer, then we either get an error, or there are no more checks to be
62 // done.
Corentin Wallez672f7f32017-06-15 17:42:17 -040063 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
64 gl::Buffer *buffer = binding.getBuffer().get();
Corentin Wallezfd456442016-12-21 17:57:00 -050065 if (!buffer)
66 {
Geoff Langfeb8c682017-02-13 16:07:35 -050067 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050068 {
69 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050070 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
71 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
72 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
73 // error.
Brandon Jonesafa75152017-07-21 13:11:29 -070074 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
Corentin Wallezfd456442016-12-21 17:57:00 -050075 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050076 }
Corentin Wallezfd456442016-12-21 17:57:00 -050077 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040078 {
79 // This is an application error that would normally result in a crash,
80 // but we catch it and return an error
Brandon Jonesafa75152017-07-21 13:11:29 -070081 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
Jamie Madill1ca74672015-07-21 15:14:11 -040082 return false;
83 }
Corentin Wallezfd456442016-12-21 17:57:00 -050084 continue;
85 }
86
Corentin Wallez672f7f32017-06-15 17:42:17 -040087 // This needs to come after the check for client arrays as even unused attributes cannot use
88 // client-side arrays
89 if (!program->isAttribLocationActive(attributeIndex))
90 {
91 continue;
92 }
93
Corentin Wallezfd456442016-12-21 17:57:00 -050094 // If we're drawing zero vertices, we have enough data.
95 if (vertexCount <= 0 || primcount <= 0)
96 {
97 continue;
98 }
99
100 GLint maxVertexElement = 0;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300101 GLuint divisor = binding.getDivisor();
102 if (divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500103 {
104 maxVertexElement = maxVertex;
105 }
106 else
107 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300108 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500109 }
110
111 // We do manual overflow checks here instead of using safe_math.h because it was
112 // a bottleneck. Thanks to some properties of GL we know inequalities that can
113 // help us make the overflow checks faster.
114
115 // The max possible attribSize is 16 for a vector of 4 32 bit values.
116 constexpr uint64_t kMaxAttribSize = 16;
117 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
118 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
119
120 // We know attribStride is given as a GLsizei which is typedefed to int.
121 // We also know an upper bound for attribSize.
122 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800123 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500124 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
125 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
126
127 // Computing the max offset using uint64_t without attrib.offset is overflow
128 // safe. Note: Last vertex element does not take the full stride!
129 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
130 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
131
132 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800133 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
134 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500135 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700136 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500137 return false;
138 }
139 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
140
141 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
142 // We can return INVALID_OPERATION if our vertex attribute does not have
143 // enough backing data.
144 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
145 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700146 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500147 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400148 }
149 }
150
151 return true;
152}
153
Geoff Lang280ba992017-04-18 16:30:58 -0400154bool ValidReadPixelsTypeEnum(ValidationContext *context, GLenum type)
155{
156 switch (type)
157 {
158 // Types referenced in Table 3.4 of the ES 2.0.25 spec
159 case GL_UNSIGNED_BYTE:
160 case GL_UNSIGNED_SHORT_4_4_4_4:
161 case GL_UNSIGNED_SHORT_5_5_5_1:
162 case GL_UNSIGNED_SHORT_5_6_5:
163 return context->getClientVersion() >= ES_2_0;
164
165 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
166 case GL_BYTE:
167 case GL_INT:
168 case GL_SHORT:
169 case GL_UNSIGNED_INT:
170 case GL_UNSIGNED_INT_10F_11F_11F_REV:
171 case GL_UNSIGNED_INT_24_8:
172 case GL_UNSIGNED_INT_2_10_10_10_REV:
173 case GL_UNSIGNED_INT_5_9_9_9_REV:
174 case GL_UNSIGNED_SHORT:
175 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
176 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
177 return context->getClientVersion() >= ES_3_0;
178
179 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400180 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
181 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400182
183 case GL_HALF_FLOAT:
184 return context->getClientVersion() >= ES_3_0 ||
185 context->getExtensions().textureHalfFloat;
186
187 case GL_HALF_FLOAT_OES:
188 return context->getExtensions().colorBufferHalfFloat;
189
190 default:
191 return false;
192 }
193}
194
195bool ValidReadPixelsFormatEnum(ValidationContext *context, GLenum format)
196{
197 switch (format)
198 {
199 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
200 case GL_RGBA:
201 case GL_RGB:
202 case GL_ALPHA:
203 return context->getClientVersion() >= ES_2_0;
204
205 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
206 case GL_RG:
207 case GL_RED:
208 case GL_RGBA_INTEGER:
209 case GL_RGB_INTEGER:
210 case GL_RG_INTEGER:
211 case GL_RED_INTEGER:
212 return context->getClientVersion() >= ES_3_0;
213
214 case GL_SRGB_ALPHA_EXT:
215 case GL_SRGB_EXT:
216 return context->getExtensions().sRGB;
217
218 case GL_BGRA_EXT:
219 return context->getExtensions().readFormatBGRA;
220
221 default:
222 return false;
223 }
224}
225
Geoff Langf607c602016-09-21 11:46:48 -0400226bool ValidReadPixelsFormatType(ValidationContext *context,
227 GLenum framebufferComponentType,
228 GLenum format,
229 GLenum type)
230{
231 switch (framebufferComponentType)
232 {
233 case GL_UNSIGNED_NORMALIZED:
234 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
235 // ReadPixels with BGRA even if the extension is not present
236 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
237 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
238 type == GL_UNSIGNED_BYTE);
239
240 case GL_SIGNED_NORMALIZED:
241 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
242
243 case GL_INT:
244 return (format == GL_RGBA_INTEGER && type == GL_INT);
245
246 case GL_UNSIGNED_INT:
247 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
248
249 case GL_FLOAT:
250 return (format == GL_RGBA && type == GL_FLOAT);
251
252 default:
253 UNREACHABLE();
254 return false;
255 }
256}
257
Geoff Langc1984ed2016-10-07 12:41:00 -0400258template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400259bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400260{
261 switch (ConvertToGLenum(params[0]))
262 {
263 case GL_CLAMP_TO_EDGE:
264 break;
265
266 case GL_REPEAT:
267 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400268 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400269 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400270 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700271 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400272 return false;
273 }
274 break;
275
276 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700277 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400278 return false;
279 }
280
281 return true;
282}
283
284template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400285bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400286{
287 switch (ConvertToGLenum(params[0]))
288 {
289 case GL_NEAREST:
290 case GL_LINEAR:
291 break;
292
293 case GL_NEAREST_MIPMAP_NEAREST:
294 case GL_LINEAR_MIPMAP_NEAREST:
295 case GL_NEAREST_MIPMAP_LINEAR:
296 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400297 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400298 {
299 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700300 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400301 return false;
302 }
303 break;
304
305 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700306 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400307 return false;
308 }
309
310 return true;
311}
312
313template <typename ParamType>
314bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
315{
316 switch (ConvertToGLenum(params[0]))
317 {
318 case GL_NEAREST:
319 case GL_LINEAR:
320 break;
321
322 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700323 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400324 return false;
325 }
326
327 return true;
328}
329
330template <typename ParamType>
331bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
332{
333 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
334 switch (ConvertToGLenum(params[0]))
335 {
336 case GL_NONE:
337 case GL_COMPARE_REF_TO_TEXTURE:
338 break;
339
340 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700341 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400342 return false;
343 }
344
345 return true;
346}
347
348template <typename ParamType>
349bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
350{
351 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
352 switch (ConvertToGLenum(params[0]))
353 {
354 case GL_LEQUAL:
355 case GL_GEQUAL:
356 case GL_LESS:
357 case GL_GREATER:
358 case GL_EQUAL:
359 case GL_NOTEQUAL:
360 case GL_ALWAYS:
361 case GL_NEVER:
362 break;
363
364 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700365 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400366 return false;
367 }
368
369 return true;
370}
371
372template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700373bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
374{
375 if (!context->getExtensions().textureSRGBDecode)
376 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700377 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700378 return false;
379 }
380
381 switch (ConvertToGLenum(params[0]))
382 {
383 case GL_DECODE_EXT:
384 case GL_SKIP_DECODE_EXT:
385 break;
386
387 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700388 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700389 return false;
390 }
391
392 return true;
393}
394
Geoff Lange0cff192017-05-30 13:04:56 -0400395bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
396{
397 const Program *program = context->getGLState().getProgram();
398 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
399
Brandon Jones76746f92017-11-22 11:44:41 -0800400 if (!DrawBufferTypeMask::ProgramOutputsMatchFramebuffer(
401 program->getDrawBufferTypeMask(), framebuffer->getDrawBufferTypeMask(),
402 program->getActiveOutputVariables(), framebuffer->getDrawBufferMask()))
Geoff Lange0cff192017-05-30 13:04:56 -0400403 {
Brandon Jones76746f92017-11-22 11:44:41 -0800404 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
405 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400406 }
407
408 return true;
409}
410
Geoff Lang9ab5b822017-05-30 16:19:23 -0400411bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
412{
Jamie Madillcac94a92017-11-10 10:09:32 -0500413 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400414 const Program *program = context->getGLState().getProgram();
415 const VertexArray *vao = context->getGLState().getVertexArray();
Jamie Madillcac94a92017-11-10 10:09:32 -0500416 const auto &vertexAttribs = vao->getVertexAttributes();
417 const auto &currentValues = glState.getVertexAttribCurrentValues();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400418
Jamie Madillcac94a92017-11-10 10:09:32 -0500419 for (const sh::Attribute &shaderAttribute : program->getAttributes())
Geoff Lang9ab5b822017-05-30 16:19:23 -0400420 {
Geoff Lang69df2422017-07-05 12:42:31 -0400421 // gl_VertexID and gl_InstanceID are active attributes but don't have a bound attribute.
422 if (shaderAttribute.isBuiltIn())
423 {
424 continue;
425 }
426
Geoff Lang9ab5b822017-05-30 16:19:23 -0400427 GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
428
Jamie Madillcac94a92017-11-10 10:09:32 -0500429 const auto &attrib = vertexAttribs[shaderAttribute.location];
430 GLenum vertexType = attrib.enabled ? GetVertexAttributeBaseType(attrib)
431 : currentValues[shaderAttribute.location].Type;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400432
433 if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
434 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500435 context->handleError(InvalidOperation() << "Vertex shader input type does not "
436 "match the type of the bound vertex "
437 "attribute.");
Geoff Lang9ab5b822017-05-30 16:19:23 -0400438 return false;
439 }
440 }
441
442 return true;
443}
444
Geoff Langf41a7152016-09-19 15:11:17 -0400445} // anonymous namespace
446
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500447bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400448{
Jamie Madilld7460c72014-01-21 16:38:14 -0500449 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400450 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800451 case GL_TEXTURE_2D:
452 case GL_TEXTURE_CUBE_MAP:
453 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400454
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400455 case GL_TEXTURE_RECTANGLE_ANGLE:
456 return context->getExtensions().textureRectangle;
457
He Yunchaoced53ae2016-11-29 15:00:51 +0800458 case GL_TEXTURE_3D:
459 case GL_TEXTURE_2D_ARRAY:
460 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500461
He Yunchaoced53ae2016-11-29 15:00:51 +0800462 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800463 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400464
He Yunchaoced53ae2016-11-29 15:00:51 +0800465 default:
466 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500467 }
Jamie Madill35d15012013-10-07 10:46:37 -0400468}
469
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500470bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
471{
472 switch (target)
473 {
474 case GL_TEXTURE_2D:
475 case GL_TEXTURE_CUBE_MAP:
476 return true;
477
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400478 case GL_TEXTURE_RECTANGLE_ANGLE:
479 return context->getExtensions().textureRectangle;
480
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500481 default:
482 return false;
483 }
484}
485
486bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
487{
488 switch (target)
489 {
490 case GL_TEXTURE_3D:
491 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300492 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500493
494 default:
495 return false;
496 }
497}
498
Ian Ewellbda75592016-04-18 17:25:54 -0400499// Most texture GL calls are not compatible with external textures, so we have a separate validation
500// function for use in the GL calls that do
501bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
502{
503 return (target == GL_TEXTURE_EXTERNAL_OES) &&
504 (context->getExtensions().eglImageExternal ||
505 context->getExtensions().eglStreamConsumerExternal);
506}
507
Shannon Woods4dfed832014-03-17 20:03:39 -0400508// This function differs from ValidTextureTarget in that the target must be
509// usable as the destination of a 2D operation-- so a cube face is valid, but
510// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400511// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500512bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400513{
514 switch (target)
515 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800516 case GL_TEXTURE_2D:
517 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
518 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
519 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
520 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
521 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
522 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
523 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400524 case GL_TEXTURE_RECTANGLE_ANGLE:
525 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800526 default:
527 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500528 }
529}
530
Jamie Madillbe849e42017-05-02 15:49:00 -0400531bool ValidateDrawElementsInstancedBase(ValidationContext *context,
532 GLenum mode,
533 GLsizei count,
534 GLenum type,
535 const GLvoid *indices,
536 GLsizei primcount)
537{
538 if (primcount < 0)
539 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700540 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400541 return false;
542 }
543
544 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
545 {
546 return false;
547 }
548
549 // No-op zero primitive count
550 return (primcount > 0);
551}
552
553bool ValidateDrawArraysInstancedBase(Context *context,
554 GLenum mode,
555 GLint first,
556 GLsizei count,
557 GLsizei primcount)
558{
559 if (primcount < 0)
560 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700561 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400562 return false;
563 }
564
565 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
566 {
567 return false;
568 }
569
570 // No-op if zero primitive count
571 return (primcount > 0);
572}
573
Corentin Wallez0dc97812017-06-22 14:38:44 -0400574bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400575{
576 // Verify there is at least one active attribute with a divisor of zero
577 const State &state = context->getGLState();
578
579 Program *program = state.getProgram();
580
581 const auto &attribs = state.getVertexArray()->getVertexAttributes();
582 const auto &bindings = state.getVertexArray()->getVertexBindings();
583 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
584 {
585 const VertexAttribute &attrib = attribs[attributeIndex];
586 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300587 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400588 {
589 return true;
590 }
591 }
592
Brandon Jonesafa75152017-07-21 13:11:29 -0700593 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400594 return false;
595}
596
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500597bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
598{
599 switch (target)
600 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800601 case GL_TEXTURE_3D:
602 case GL_TEXTURE_2D_ARRAY:
603 return true;
604 default:
605 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400606 }
607}
608
He Yunchao11b038b2016-11-22 21:24:04 +0800609bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
610{
611 switch (target)
612 {
613 case GL_TEXTURE_2D:
614 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
615 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
616 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
617 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
618 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
619 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
620 case GL_TEXTURE_3D:
621 case GL_TEXTURE_2D_ARRAY:
622 case GL_TEXTURE_2D_MULTISAMPLE:
623 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400624 case GL_TEXTURE_RECTANGLE_ANGLE:
625 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800626 default:
627 return false;
628 }
629}
630
Geoff Lange8afa902017-09-27 15:00:43 -0400631bool ValidFramebufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500632{
He Yunchaoced53ae2016-11-29 15:00:51 +0800633 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
634 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400635 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500636
637 switch (target)
638 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800639 case GL_FRAMEBUFFER:
640 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400641
He Yunchaoced53ae2016-11-29 15:00:51 +0800642 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800643 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400644 return (context->getExtensions().framebufferBlit ||
645 context->getClientMajorVersion() >= 3);
646
He Yunchaoced53ae2016-11-29 15:00:51 +0800647 default:
648 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500649 }
650}
651
Jamie Madillc29968b2016-01-20 11:17:23 -0500652bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400653{
Jamie Madillc29968b2016-01-20 11:17:23 -0500654 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400655 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400656 switch (target)
657 {
Jamie Madillc29968b2016-01-20 11:17:23 -0500658 case GL_TEXTURE_2D:
659 maxDimension = caps.max2DTextureSize;
660 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800661 case GL_TEXTURE_CUBE_MAP:
662 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
663 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
664 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
665 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
666 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
667 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
668 maxDimension = caps.maxCubeMapTextureSize;
669 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400670 case GL_TEXTURE_RECTANGLE_ANGLE:
671 return level == 0;
He Yunchaoced53ae2016-11-29 15:00:51 +0800672 case GL_TEXTURE_3D:
673 maxDimension = caps.max3DTextureSize;
674 break;
675 case GL_TEXTURE_2D_ARRAY:
676 maxDimension = caps.max2DTextureSize;
677 break;
He Yunchao11b038b2016-11-22 21:24:04 +0800678 case GL_TEXTURE_2D_MULTISAMPLE:
679 maxDimension = caps.max2DTextureSize;
680 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800681 default:
682 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400683 }
684
Brandon Jones6cad5662017-06-14 13:25:13 -0700685 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400686}
687
Brandon Jones6cad5662017-06-14 13:25:13 -0700688bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -0700689 GLenum target,
690 GLint level,
691 GLsizei width,
692 GLsizei height,
693 GLsizei depth,
694 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400695{
Brandon Jones6cad5662017-06-14 13:25:13 -0700696 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400697 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700698 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400699 return false;
700 }
Austin Kinross08528e12015-10-07 16:24:40 -0700701 // TexSubImage parameters can be NPOT without textureNPOT extension,
702 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500703 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500704 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500705 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400706 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400707 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700708 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400709 return false;
710 }
711
712 if (!ValidMipLevel(context, target, level))
713 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700714 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400715 return false;
716 }
717
718 return true;
719}
720
Geoff Lang0d8b7242015-09-09 14:56:53 -0400721bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
722{
723 // List of compressed format that require that the texture size is smaller than or a multiple of
724 // the compressed block size.
725 switch (internalFormat)
726 {
727 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
728 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
729 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
730 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -0400731 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
732 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
733 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
734 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -0800735 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800736 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
737 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
738 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
739 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
740 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
741 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -0400742 return true;
743
744 default:
745 return false;
746 }
747}
748
Geoff Lang966c9402017-04-18 12:38:27 -0400749bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
750{
751 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
752 (size % blockSize == 0);
753}
754
Jamie Madillc29968b2016-01-20 11:17:23 -0500755bool ValidCompressedImageSize(const ValidationContext *context,
756 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400757 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500758 GLsizei width,
759 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400760{
Geoff Langca271392017-04-05 12:30:00 -0400761 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400762 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400763 {
764 return false;
765 }
766
Geoff Lang966c9402017-04-18 12:38:27 -0400767 if (width < 0 || height < 0)
768 {
769 return false;
770 }
771
772 if (CompressedTextureFormatRequiresExactSize(internalFormat))
773 {
774 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
775 // block size for level 0 but WebGL disallows this.
776 bool smallerThanBlockSizeAllowed =
777 level > 0 || !context->getExtensions().webglCompatibility;
778
779 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
780 smallerThanBlockSizeAllowed) ||
781 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
782 smallerThanBlockSizeAllowed))
783 {
784 return false;
785 }
786 }
787
788 return true;
789}
790
791bool ValidCompressedSubImageSize(const ValidationContext *context,
792 GLenum internalFormat,
793 GLint xoffset,
794 GLint yoffset,
795 GLsizei width,
796 GLsizei height,
797 size_t textureWidth,
798 size_t textureHeight)
799{
800 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
801 if (!formatInfo.compressed)
802 {
803 return false;
804 }
805
Geoff Lang44ff5a72017-02-03 15:15:43 -0500806 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400807 {
808 return false;
809 }
810
Geoff Lang0d8b7242015-09-09 14:56:53 -0400811 if (CompressedTextureFormatRequiresExactSize(internalFormat))
812 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500813 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400814 yoffset % formatInfo.compressedBlockHeight != 0)
815 {
816 return false;
817 }
818
819 // Allowed to either have data that is a multiple of block size or is smaller than the block
820 // size but fills the entire mip
821 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
822 static_cast<size_t>(width) == textureWidth &&
823 static_cast<size_t>(height) == textureHeight;
824 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
825 (height % formatInfo.compressedBlockHeight) == 0;
826 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400827 {
828 return false;
829 }
830 }
831
Geoff Langd4f180b2013-09-24 13:57:44 -0400832 return true;
833}
834
Geoff Langff5b2d52016-09-07 11:32:23 -0400835bool ValidImageDataSize(ValidationContext *context,
836 GLenum textureTarget,
837 GLsizei width,
838 GLsizei height,
839 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400840 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400841 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400842 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400843 GLsizei imageSize)
844{
Corentin Wallez336129f2017-10-17 15:55:40 -0400845 gl::Buffer *pixelUnpackBuffer =
846 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400847 if (pixelUnpackBuffer == nullptr && imageSize < 0)
848 {
849 // Checks are not required
850 return true;
851 }
852
853 // ...the data would be unpacked from the buffer object such that the memory reads required
854 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400855 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
856 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400857 const gl::Extents size(width, height, depth);
858 const auto &unpack = context->getGLState().getUnpackState();
859
860 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
861 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
862 if (endByteOrErr.isError())
863 {
864 context->handleError(endByteOrErr.getError());
865 return false;
866 }
867
868 GLuint endByte = endByteOrErr.getResult();
869
870 if (pixelUnpackBuffer)
871 {
872 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
873 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
874 checkedEndByte += checkedOffset;
875
876 if (!checkedEndByte.IsValid() ||
877 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
878 {
879 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500880 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400881 return false;
882 }
883 }
884 else
885 {
886 ASSERT(imageSize >= 0);
887 if (pixels == nullptr && imageSize != 0)
888 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500889 context->handleError(InvalidOperation()
890 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400891 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400892 }
893
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400894 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400895 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500896 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400897 return false;
898 }
899 }
900
901 return true;
902}
903
Geoff Lang37dde692014-01-31 16:34:54 -0500904bool ValidQueryType(const Context *context, GLenum queryType)
905{
He Yunchaoced53ae2016-11-29 15:00:51 +0800906 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
907 "GL extension enums not equal.");
908 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
909 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -0500910
911 switch (queryType)
912 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800913 case GL_ANY_SAMPLES_PASSED:
914 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400915 return context->getClientMajorVersion() >= 3 ||
916 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +0800917 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
918 return (context->getClientMajorVersion() >= 3);
919 case GL_TIME_ELAPSED_EXT:
920 return context->getExtensions().disjointTimerQuery;
921 case GL_COMMANDS_COMPLETED_CHROMIUM:
922 return context->getExtensions().syncQuery;
923 default:
924 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500925 }
926}
927
Geoff Lang2d62ab72017-03-23 16:54:40 -0400928bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
929 GLenum type,
930 GLboolean normalized,
931 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400932 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400933 bool pureInteger)
934{
935 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400936 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
937 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
938 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
939 // parameter exceeds 255.
940 constexpr GLsizei kMaxWebGLStride = 255;
941 if (stride > kMaxWebGLStride)
942 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500943 context->handleError(InvalidValue()
944 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -0400945 return false;
946 }
947
948 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
949 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
950 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
951 // or an INVALID_OPERATION error is generated.
952 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
953 size_t typeSize = GetVertexFormatTypeSize(internalType);
954
955 ASSERT(isPow2(typeSize) && typeSize > 0);
956 size_t sizeMask = (typeSize - 1);
957 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
958 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700959 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400960 return false;
961 }
962
963 if ((stride & sizeMask) != 0)
964 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700965 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400966 return false;
967 }
968
969 return true;
970}
971
Jamie Madillef300b12016-10-07 15:12:09 -0400972Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -0500973{
He Yunchaoced53ae2016-11-29 15:00:51 +0800974 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
975 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
976 // or program object and INVALID_OPERATION if the provided name identifies an object
977 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -0500978
Dian Xiang769769a2015-09-09 15:20:08 -0700979 Program *validProgram = context->getProgram(id);
980
981 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -0500982 {
Dian Xiang769769a2015-09-09 15:20:08 -0700983 if (context->getShader(id))
984 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700985 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -0700986 }
987 else
988 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700989 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -0700990 }
Geoff Lang48dcae72014-02-05 16:28:24 -0500991 }
Dian Xiang769769a2015-09-09 15:20:08 -0700992
993 return validProgram;
994}
995
Jamie Madillef300b12016-10-07 15:12:09 -0400996Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -0700997{
998 // See ValidProgram for spec details.
999
1000 Shader *validShader = context->getShader(id);
1001
1002 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001003 {
Dian Xiang769769a2015-09-09 15:20:08 -07001004 if (context->getProgram(id))
1005 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001006 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001007 }
1008 else
1009 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001010 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001011 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001012 }
Dian Xiang769769a2015-09-09 15:20:08 -07001013
1014 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001015}
1016
Geoff Langb1196682014-07-23 13:47:29 -04001017bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001018{
Geoff Langfa125c92017-10-24 13:01:46 -04001019 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001020 {
Geoff Langfa125c92017-10-24 13:01:46 -04001021 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1022 {
1023 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1024 return false;
1025 }
Jamie Madillb4472272014-07-03 10:38:55 -04001026
Geoff Langfa125c92017-10-24 13:01:46 -04001027 // Color attachment 0 is validated below because it is always valid
1028 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001029 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001030 {
Geoff Langfa125c92017-10-24 13:01:46 -04001031 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001032 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001033 }
1034 }
1035 else
1036 {
1037 switch (attachment)
1038 {
Geoff Langfa125c92017-10-24 13:01:46 -04001039 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001040 case GL_DEPTH_ATTACHMENT:
1041 case GL_STENCIL_ATTACHMENT:
1042 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001043
He Yunchaoced53ae2016-11-29 15:00:51 +08001044 case GL_DEPTH_STENCIL_ATTACHMENT:
1045 if (!context->getExtensions().webglCompatibility &&
1046 context->getClientMajorVersion() < 3)
1047 {
Geoff Langfa125c92017-10-24 13:01:46 -04001048 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001049 return false;
1050 }
1051 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001052
He Yunchaoced53ae2016-11-29 15:00:51 +08001053 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001054 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001055 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001056 }
1057 }
1058
1059 return true;
1060}
1061
Jamie Madille8fb6402017-02-14 17:56:40 -05001062bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001063 GLenum target,
1064 GLsizei samples,
1065 GLenum internalformat,
1066 GLsizei width,
1067 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001068{
1069 switch (target)
1070 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001071 case GL_RENDERBUFFER:
1072 break;
1073 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001074 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001075 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001076 }
1077
1078 if (width < 0 || height < 0 || samples < 0)
1079 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001080 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001081 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001082 }
1083
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001084 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1085 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1086
1087 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001088 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001089 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001090 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001091 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001092 }
1093
1094 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1095 // 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 -08001096 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001097 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1098 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001099 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001100 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001101 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001102 }
1103
Geoff Langaae65a42014-05-26 12:43:44 -04001104 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001105 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001106 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001107 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001108 }
1109
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001110 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001111 if (handle == 0)
1112 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001113 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001114 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001115 }
1116
1117 return true;
1118}
1119
He Yunchaoced53ae2016-11-29 15:00:51 +08001120bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1121 GLenum target,
1122 GLenum attachment,
1123 GLenum renderbuffertarget,
1124 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001125{
Geoff Lange8afa902017-09-27 15:00:43 -04001126 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001127 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001128 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001129 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001130 }
1131
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001132 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001133
Jamie Madill84115c92015-04-23 15:00:07 -04001134 ASSERT(framebuffer);
1135 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001136 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001137 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001138 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001139 }
1140
Jamie Madillb4472272014-07-03 10:38:55 -04001141 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001142 {
Jamie Madillb4472272014-07-03 10:38:55 -04001143 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001144 }
1145
Jamie Madillab9d82c2014-01-21 16:38:14 -05001146 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1147 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1148 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1149 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1150 if (renderbuffer != 0)
1151 {
1152 if (!context->getRenderbuffer(renderbuffer))
1153 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001154 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001155 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001156 }
1157 }
1158
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001159 return true;
1160}
1161
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001162bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001163 GLint srcX0,
1164 GLint srcY0,
1165 GLint srcX1,
1166 GLint srcY1,
1167 GLint dstX0,
1168 GLint dstY0,
1169 GLint dstX1,
1170 GLint dstY1,
1171 GLbitfield mask,
1172 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001173{
1174 switch (filter)
1175 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001176 case GL_NEAREST:
1177 break;
1178 case GL_LINEAR:
1179 break;
1180 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001181 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001182 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001183 }
1184
1185 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1186 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001187 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001188 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001189 }
1190
1191 if (mask == 0)
1192 {
1193 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1194 // buffers are copied.
1195 return false;
1196 }
1197
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001198 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1199 // color buffer, leaving only nearest being unfiltered from above
1200 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1201 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001202 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001203 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001204 }
1205
Jamie Madill51f40ec2016-06-15 14:06:00 -04001206 const auto &glState = context->getGLState();
1207 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1208 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001209
1210 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001211 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001212 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001213 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001214 }
1215
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001216 if (readFramebuffer->id() == drawFramebuffer->id())
1217 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001218 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001219 return false;
1220 }
1221
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001222 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001223 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001224 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001225 return false;
1226 }
1227
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001228 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001229 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001230 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001231 return false;
1232 }
1233
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001234 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001235 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001236 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001237 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001238 }
1239
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001240 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1241
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001242 if (mask & GL_COLOR_BUFFER_BIT)
1243 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001244 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001245 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001246
He Yunchao66a41a22016-12-15 16:45:05 +08001247 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001248 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001249 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001250
Geoff Langa15472a2015-08-11 11:48:03 -04001251 for (size_t drawbufferIdx = 0;
1252 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001253 {
Geoff Langa15472a2015-08-11 11:48:03 -04001254 const FramebufferAttachment *attachment =
1255 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1256 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001257 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001258 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001259
Geoff Langb2f3d052013-08-13 12:49:27 -04001260 // The GL ES 3.0.2 spec (pg 193) states that:
1261 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001262 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1263 // as well
1264 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1265 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001266 // Changes with EXT_color_buffer_float:
1267 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001268 GLenum readComponentType = readFormat.info->componentType;
1269 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001270 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001271 readComponentType == GL_SIGNED_NORMALIZED);
1272 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1273 drawComponentType == GL_SIGNED_NORMALIZED);
1274
1275 if (extensions.colorBufferFloat)
1276 {
1277 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1278 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1279
1280 if (readFixedOrFloat != drawFixedOrFloat)
1281 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001282 context->handleError(InvalidOperation()
1283 << "If the read buffer contains fixed-point or "
1284 "floating-point values, the draw buffer must "
1285 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001286 return false;
1287 }
1288 }
1289 else if (readFixedPoint != drawFixedPoint)
1290 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001291 context->handleError(InvalidOperation()
1292 << "If the read buffer contains fixed-point values, "
1293 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001294 return false;
1295 }
1296
1297 if (readComponentType == GL_UNSIGNED_INT &&
1298 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001299 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001300 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001301 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001302 }
1303
Jamie Madill6163c752015-12-07 16:32:59 -05001304 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001305 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001306 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001307 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001308 }
1309
Jamie Madilla3944d42016-07-22 22:13:26 -04001310 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001311 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001312 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001313 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001314 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001315 }
Geoff Lange4915782017-04-12 15:19:07 -04001316
1317 if (context->getExtensions().webglCompatibility &&
1318 *readColorBuffer == *attachment)
1319 {
1320 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001321 InvalidOperation()
1322 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001323 return false;
1324 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001325 }
1326 }
1327
Jamie Madilla3944d42016-07-22 22:13:26 -04001328 if ((readFormat.info->componentType == GL_INT ||
1329 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1330 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001331 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001332 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001333 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001334 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001335 }
He Yunchao66a41a22016-12-15 16:45:05 +08001336 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1337 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1338 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1339 // situation is an application error that would lead to a crash in ANGLE.
1340 else if (drawFramebuffer->hasEnabledDrawBuffer())
1341 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001342 context->handleError(
1343 InvalidOperation()
1344 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001345 return false;
1346 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001347 }
1348
He Yunchaoced53ae2016-11-29 15:00:51 +08001349 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001350 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1351 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001352 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001353 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001354 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001355 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001356 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001357 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001358 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001359
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001360 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001361 {
Kenneth Russell69382852017-07-21 16:38:44 -04001362 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001363 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001364 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001365 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001366 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001367
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001368 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001369 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001370 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001371 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001372 }
Geoff Lange4915782017-04-12 15:19:07 -04001373
1374 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1375 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001376 context->handleError(
1377 InvalidOperation()
1378 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001379 return false;
1380 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001381 }
He Yunchao66a41a22016-12-15 16:45:05 +08001382 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1383 else if (drawBuffer)
1384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001385 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1386 "depth/stencil attachment of a "
1387 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001388 return false;
1389 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001390 }
1391 }
1392
Martin Radeva3ed4572017-07-27 18:29:37 +03001393 // ANGLE_multiview, Revision 1:
1394 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1395 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1396 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1397 {
1398 context->handleError(InvalidFramebufferOperation()
1399 << "Attempt to read from a multi-view framebuffer.");
1400 return false;
1401 }
1402 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1403 {
1404 context->handleError(InvalidFramebufferOperation()
1405 << "Attempt to write to a multi-view framebuffer.");
1406 return false;
1407 }
1408
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001409 return true;
1410}
1411
Jamie Madill4928b7c2017-06-20 12:57:39 -04001412bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001413 GLint x,
1414 GLint y,
1415 GLsizei width,
1416 GLsizei height,
1417 GLenum format,
1418 GLenum type,
1419 GLsizei bufSize,
1420 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001421 GLsizei *columns,
1422 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001423 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001424{
1425 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001426 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001427 return false;
1428 }
1429
Geoff Lang62fce5b2016-09-30 10:46:35 -04001430 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001431 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001432 {
Geoff Langb1196682014-07-23 13:47:29 -04001433 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001434 }
1435
Geoff Lang62fce5b2016-09-30 10:46:35 -04001436 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001437 {
Geoff Langb1196682014-07-23 13:47:29 -04001438 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001439 }
1440
Jamie Madillc29968b2016-01-20 11:17:23 -05001441 return true;
1442}
1443
1444bool ValidateReadnPixelsEXT(Context *context,
1445 GLint x,
1446 GLint y,
1447 GLsizei width,
1448 GLsizei height,
1449 GLenum format,
1450 GLenum type,
1451 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001452 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001453{
1454 if (bufSize < 0)
1455 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001456 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001457 return false;
1458 }
1459
Geoff Lang62fce5b2016-09-30 10:46:35 -04001460 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001461 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001462}
Jamie Madill26e91952014-03-05 15:01:27 -05001463
Jamie Madill4928b7c2017-06-20 12:57:39 -04001464bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001465 GLint x,
1466 GLint y,
1467 GLsizei width,
1468 GLsizei height,
1469 GLenum format,
1470 GLenum type,
1471 GLsizei bufSize,
1472 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001473 GLsizei *columns,
1474 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001475 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001476{
1477 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001478 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001479 return false;
1480 }
1481
Geoff Lange93daba2017-03-30 13:54:40 -04001482 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1483 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001484 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001485 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001486 }
1487
Geoff Lang62fce5b2016-09-30 10:46:35 -04001488 if (!ValidateRobustBufferSize(context, bufSize, *length))
1489 {
1490 return false;
1491 }
1492
1493 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001494}
1495
Jamie Madillf0e04492017-08-26 15:28:42 -04001496bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001497{
1498 if (!context->getExtensions().occlusionQueryBoolean &&
1499 !context->getExtensions().disjointTimerQuery)
1500 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001501 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001502 return false;
1503 }
1504
Olli Etuaho41997e72016-03-10 13:38:39 +02001505 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001506}
1507
Jamie Madillf0e04492017-08-26 15:28:42 -04001508bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001509{
1510 if (!context->getExtensions().occlusionQueryBoolean &&
1511 !context->getExtensions().disjointTimerQuery)
1512 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001513 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001514 return false;
1515 }
1516
Olli Etuaho41997e72016-03-10 13:38:39 +02001517 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001518}
1519
Jamie Madillf0e04492017-08-26 15:28:42 -04001520bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1521{
1522 if (!context->getExtensions().occlusionQueryBoolean &&
1523 !context->getExtensions().disjointTimerQuery)
1524 {
1525 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1526 return false;
1527 }
1528
1529 return true;
1530}
1531
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001532bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001533{
1534 if (!ValidQueryType(context, target))
1535 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001536 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001537 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001538 }
1539
1540 if (id == 0)
1541 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001542 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001543 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001544 }
1545
1546 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1547 // of zero, if the active query object name for <target> is non-zero (for the
1548 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1549 // the active query for either target is non-zero), if <id> is the name of an
1550 // existing query object whose type does not match <target>, or if <id> is the
1551 // active query object name for any query type, the error INVALID_OPERATION is
1552 // generated.
1553
1554 // Ensure no other queries are active
1555 // NOTE: If other queries than occlusion are supported, we will need to check
1556 // separately that:
1557 // a) The query ID passed is not the current active query for any target/type
1558 // b) There are no active queries for the requested target (and in the case
1559 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1560 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001561
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001562 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001563 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001564 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001565 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001566 }
1567
1568 Query *queryObject = context->getQuery(id, true, target);
1569
1570 // check that name was obtained with glGenQueries
1571 if (!queryObject)
1572 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001573 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001574 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001575 }
1576
1577 // check for type mismatch
1578 if (queryObject->getType() != target)
1579 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001580 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001581 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001582 }
1583
1584 return true;
1585}
1586
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001587bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1588{
1589 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001590 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001591 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001592 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001593 return false;
1594 }
1595
1596 return ValidateBeginQueryBase(context, target, id);
1597}
1598
1599bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001600{
1601 if (!ValidQueryType(context, target))
1602 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001603 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001604 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001605 }
1606
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001607 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001608
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001609 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001610 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001611 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001612 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001613 }
1614
Jamie Madill45c785d2014-05-13 14:09:34 -04001615 return true;
1616}
1617
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001618bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1619{
1620 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001621 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001622 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001623 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001624 return false;
1625 }
1626
1627 return ValidateEndQueryBase(context, target);
1628}
1629
1630bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1631{
1632 if (!context->getExtensions().disjointTimerQuery)
1633 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001634 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001635 return false;
1636 }
1637
1638 if (target != GL_TIMESTAMP_EXT)
1639 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001640 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001641 return false;
1642 }
1643
1644 Query *queryObject = context->getQuery(id, true, target);
1645 if (queryObject == nullptr)
1646 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001647 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001648 return false;
1649 }
1650
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001651 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001652 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001653 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001654 return false;
1655 }
1656
1657 return true;
1658}
1659
Geoff Lang2186c382016-10-14 10:54:54 -04001660bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001661{
Geoff Lang2186c382016-10-14 10:54:54 -04001662 if (numParams)
1663 {
1664 *numParams = 0;
1665 }
1666
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001667 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1668 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001669 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001670 return false;
1671 }
1672
1673 switch (pname)
1674 {
1675 case GL_CURRENT_QUERY_EXT:
1676 if (target == GL_TIMESTAMP_EXT)
1677 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001678 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001679 return false;
1680 }
1681 break;
1682 case GL_QUERY_COUNTER_BITS_EXT:
1683 if (!context->getExtensions().disjointTimerQuery ||
1684 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1685 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001686 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001687 return false;
1688 }
1689 break;
1690 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001691 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001692 return false;
1693 }
1694
Geoff Lang2186c382016-10-14 10:54:54 -04001695 if (numParams)
1696 {
1697 // All queries return only one value
1698 *numParams = 1;
1699 }
1700
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001701 return true;
1702}
1703
1704bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1705{
1706 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001707 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001708 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001709 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001710 return false;
1711 }
1712
Geoff Lang2186c382016-10-14 10:54:54 -04001713 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001714}
1715
Geoff Lang2186c382016-10-14 10:54:54 -04001716bool ValidateGetQueryivRobustANGLE(Context *context,
1717 GLenum target,
1718 GLenum pname,
1719 GLsizei bufSize,
1720 GLsizei *length,
1721 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001722{
Geoff Lang2186c382016-10-14 10:54:54 -04001723 if (!ValidateRobustEntryPoint(context, bufSize))
1724 {
1725 return false;
1726 }
1727
1728 if (!ValidateGetQueryivBase(context, target, pname, length))
1729 {
1730 return false;
1731 }
1732
1733 if (!ValidateRobustBufferSize(context, bufSize, *length))
1734 {
1735 return false;
1736 }
1737
1738 return true;
1739}
1740
1741bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1742{
1743 if (numParams)
1744 {
1745 *numParams = 0;
1746 }
1747
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001748 Query *queryObject = context->getQuery(id, false, GL_NONE);
1749
1750 if (!queryObject)
1751 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001752 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001753 return false;
1754 }
1755
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001756 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001757 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001758 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001759 return false;
1760 }
1761
1762 switch (pname)
1763 {
1764 case GL_QUERY_RESULT_EXT:
1765 case GL_QUERY_RESULT_AVAILABLE_EXT:
1766 break;
1767
1768 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001769 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001770 return false;
1771 }
1772
Geoff Lang2186c382016-10-14 10:54:54 -04001773 if (numParams)
1774 {
1775 *numParams = 1;
1776 }
1777
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001778 return true;
1779}
1780
1781bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1782{
1783 if (!context->getExtensions().disjointTimerQuery)
1784 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001785 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001786 return false;
1787 }
Geoff Lang2186c382016-10-14 10:54:54 -04001788 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1789}
1790
1791bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1792 GLuint id,
1793 GLenum pname,
1794 GLsizei bufSize,
1795 GLsizei *length,
1796 GLint *params)
1797{
1798 if (!context->getExtensions().disjointTimerQuery)
1799 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001800 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001801 return false;
1802 }
1803
1804 if (!ValidateRobustEntryPoint(context, bufSize))
1805 {
1806 return false;
1807 }
1808
1809 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1810 {
1811 return false;
1812 }
1813
1814 if (!ValidateRobustBufferSize(context, bufSize, *length))
1815 {
1816 return false;
1817 }
1818
1819 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001820}
1821
1822bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1823{
1824 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001825 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001826 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001827 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001828 return false;
1829 }
Geoff Lang2186c382016-10-14 10:54:54 -04001830 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1831}
1832
1833bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1834 GLuint id,
1835 GLenum pname,
1836 GLsizei bufSize,
1837 GLsizei *length,
1838 GLuint *params)
1839{
1840 if (!context->getExtensions().disjointTimerQuery &&
1841 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1842 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001843 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001844 return false;
1845 }
1846
1847 if (!ValidateRobustEntryPoint(context, bufSize))
1848 {
1849 return false;
1850 }
1851
1852 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1853 {
1854 return false;
1855 }
1856
1857 if (!ValidateRobustBufferSize(context, bufSize, *length))
1858 {
1859 return false;
1860 }
1861
1862 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001863}
1864
1865bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1866{
1867 if (!context->getExtensions().disjointTimerQuery)
1868 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001869 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001870 return false;
1871 }
Geoff Lang2186c382016-10-14 10:54:54 -04001872 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1873}
1874
1875bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1876 GLuint id,
1877 GLenum pname,
1878 GLsizei bufSize,
1879 GLsizei *length,
1880 GLint64 *params)
1881{
1882 if (!context->getExtensions().disjointTimerQuery)
1883 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001884 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001885 return false;
1886 }
1887
1888 if (!ValidateRobustEntryPoint(context, bufSize))
1889 {
1890 return false;
1891 }
1892
1893 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1894 {
1895 return false;
1896 }
1897
1898 if (!ValidateRobustBufferSize(context, bufSize, *length))
1899 {
1900 return false;
1901 }
1902
1903 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001904}
1905
1906bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1907{
1908 if (!context->getExtensions().disjointTimerQuery)
1909 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001910 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001911 return false;
1912 }
Geoff Lang2186c382016-10-14 10:54:54 -04001913 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1914}
1915
1916bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1917 GLuint id,
1918 GLenum pname,
1919 GLsizei bufSize,
1920 GLsizei *length,
1921 GLuint64 *params)
1922{
1923 if (!context->getExtensions().disjointTimerQuery)
1924 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001925 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001926 return false;
1927 }
1928
1929 if (!ValidateRobustEntryPoint(context, bufSize))
1930 {
1931 return false;
1932 }
1933
1934 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1935 {
1936 return false;
1937 }
1938
1939 if (!ValidateRobustBufferSize(context, bufSize, *length))
1940 {
1941 return false;
1942 }
1943
1944 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001945}
1946
Jiajia Qin5451d532017-11-16 17:16:34 +08001947bool ValidateUniformCommonBase(ValidationContext *context,
1948 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05001949 GLint location,
1950 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08001951 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05001952{
Jiajia Qin5451d532017-11-16 17:16:34 +08001953 // TODO(Jiajia): Add image uniform check in future.
1954 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05001955 {
Jiajia Qin5451d532017-11-16 17:16:34 +08001956 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05001957 return false;
1958 }
1959
Jiajia Qin5451d532017-11-16 17:16:34 +08001960 if (!program)
1961 {
1962 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
1963 return false;
1964 }
1965
1966 if (!program->isLinked())
1967 {
1968 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
1969 return false;
1970 }
1971
1972 if (location == -1)
1973 {
1974 // Silently ignore the uniform command
1975 return false;
1976 }
1977
1978 const auto &uniformLocations = program->getUniformLocations();
1979 size_t castedLocation = static_cast<size_t>(location);
1980 if (castedLocation >= uniformLocations.size())
1981 {
1982 context->handleError(InvalidOperation() << "Invalid uniform location");
1983 return false;
1984 }
1985
1986 const auto &uniformLocation = uniformLocations[castedLocation];
1987 if (uniformLocation.ignored)
1988 {
1989 // Silently ignore the uniform command
1990 return false;
1991 }
1992
1993 if (!uniformLocation.used())
1994 {
1995 context->handleError(InvalidOperation());
1996 return false;
1997 }
1998
1999 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2000
2001 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2002 if (!uniform.isArray() && count > 1)
2003 {
2004 context->handleError(InvalidOperation());
2005 return false;
2006 }
2007
2008 *uniformOut = &uniform;
2009 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002010}
2011
Jiajia Qin5451d532017-11-16 17:16:34 +08002012bool ValidateUniform1ivValue(ValidationContext *context,
2013 GLenum uniformType,
2014 GLsizei count,
2015 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002016{
Jiajia Qin5451d532017-11-16 17:16:34 +08002017 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2018 // It is compatible with INT or BOOL.
2019 // Do these cheap tests first, for a little extra speed.
2020 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002021 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002022 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002023 }
2024
Jiajia Qin5451d532017-11-16 17:16:34 +08002025 if (IsSamplerType(uniformType))
2026 {
2027 // Check that the values are in range.
2028 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2029 for (GLsizei i = 0; i < count; ++i)
2030 {
2031 if (value[i] < 0 || value[i] >= max)
2032 {
2033 context->handleError(InvalidValue() << "sampler uniform value out of range");
2034 return false;
2035 }
2036 }
2037 return true;
2038 }
2039
2040 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2041 return false;
2042}
2043
2044bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2045{
2046 // Check that the value type is compatible with uniform type.
2047 // Do the cheaper test first, for a little extra speed.
2048 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2049 {
2050 return true;
2051 }
2052
2053 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2054 return false;
2055}
2056
2057bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2058{
2059 // Check that the value type is compatible with uniform type.
2060 if (valueType == uniformType)
2061 {
2062 return true;
2063 }
2064
2065 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2066 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002067}
2068
Jamie Madillc1d770e2017-04-13 17:31:24 -04002069bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002070{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002071 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002072 gl::Program *programObject = context->getGLState().getProgram();
2073 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2074 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002075}
2076
Jamie Madillbe849e42017-05-02 15:49:00 -04002077bool ValidateUniform1iv(ValidationContext *context,
2078 GLint location,
2079 GLsizei count,
2080 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002081{
2082 const LinkedUniform *uniform = nullptr;
2083 gl::Program *programObject = context->getGLState().getProgram();
2084 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2085 ValidateUniform1ivValue(context, uniform->type, count, value);
2086}
2087
Jamie Madillc1d770e2017-04-13 17:31:24 -04002088bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002089 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002090 GLint location,
2091 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002092 GLboolean transpose)
2093{
Geoff Lang92019432017-11-20 13:09:34 -05002094 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002095 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002096 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002097 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002098 }
2099
Jamie Madill62d31cb2015-09-11 13:25:51 -04002100 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002101 gl::Program *programObject = context->getGLState().getProgram();
2102 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2103 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002104}
2105
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002106bool ValidateStateQuery(ValidationContext *context,
2107 GLenum pname,
2108 GLenum *nativeType,
2109 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002110{
2111 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2112 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002113 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002114 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002115 }
2116
Jamie Madill0af26e12015-03-05 19:54:33 -05002117 const Caps &caps = context->getCaps();
2118
Jamie Madill893ab082014-05-16 16:56:10 -04002119 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2120 {
2121 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2122
Jamie Madill0af26e12015-03-05 19:54:33 -05002123 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002124 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002125 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002126 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002127 }
2128 }
2129
2130 switch (pname)
2131 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002132 case GL_TEXTURE_BINDING_2D:
2133 case GL_TEXTURE_BINDING_CUBE_MAP:
2134 case GL_TEXTURE_BINDING_3D:
2135 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002136 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002137 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002138 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2139 if (!context->getExtensions().textureRectangle)
2140 {
2141 context->handleError(InvalidEnum()
2142 << "ANGLE_texture_rectangle extension not present");
2143 return false;
2144 }
2145 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002146 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2147 if (!context->getExtensions().eglStreamConsumerExternal &&
2148 !context->getExtensions().eglImageExternal)
2149 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002150 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2151 "nor GL_OES_EGL_image_external "
2152 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002153 return false;
2154 }
2155 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002156
He Yunchaoced53ae2016-11-29 15:00:51 +08002157 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2158 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002159 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002160 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2161 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002162 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002163 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002164 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002165 }
2166
Jamie Madill51f40ec2016-06-15 14:06:00 -04002167 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2168 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002169
2170 if (framebuffer->getReadBufferState() == GL_NONE)
2171 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002172 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002173 return false;
2174 }
2175
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002176 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002177 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002178 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002179 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002180 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002181 }
2182 }
2183 break;
2184
He Yunchaoced53ae2016-11-29 15:00:51 +08002185 default:
2186 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002187 }
2188
2189 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002190 if (*numParams == 0)
2191 {
2192 return false;
2193 }
2194
2195 return true;
2196}
2197
2198bool ValidateRobustStateQuery(ValidationContext *context,
2199 GLenum pname,
2200 GLsizei bufSize,
2201 GLenum *nativeType,
2202 unsigned int *numParams)
2203{
2204 if (!ValidateRobustEntryPoint(context, bufSize))
2205 {
2206 return false;
2207 }
2208
2209 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2210 {
2211 return false;
2212 }
2213
2214 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002215 {
2216 return false;
2217 }
2218
2219 return true;
2220}
2221
Jamie Madillc29968b2016-01-20 11:17:23 -05002222bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2223 GLenum target,
2224 GLint level,
2225 GLenum internalformat,
2226 bool isSubImage,
2227 GLint xoffset,
2228 GLint yoffset,
2229 GLint zoffset,
2230 GLint x,
2231 GLint y,
2232 GLsizei width,
2233 GLsizei height,
2234 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002235 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002236{
Brandon Jones6cad5662017-06-14 13:25:13 -07002237 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002238 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002239 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2240 return false;
2241 }
2242
2243 if (width < 0 || height < 0)
2244 {
2245 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002246 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002247 }
2248
He Yunchaoced53ae2016-11-29 15:00:51 +08002249 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2250 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002251 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002252 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002253 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002254 }
2255
2256 if (border != 0)
2257 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002258 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002259 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002260 }
2261
2262 if (!ValidMipLevel(context, target, level))
2263 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002264 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002265 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002266 }
2267
Jamie Madill51f40ec2016-06-15 14:06:00 -04002268 const auto &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002269 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002270 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002271 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002272 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002273 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002274 }
2275
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002276 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002277 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002278 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002279 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002280 }
2281
Martin Radev138064f2016-07-15 12:03:41 +03002282 if (readFramebuffer->getReadBufferState() == GL_NONE)
2283 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002284 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002285 return false;
2286 }
2287
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002288 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2289 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002290 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002291 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002292 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2293 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002294 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002295 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002296 return false;
2297 }
2298
Martin Radev04e2c3b2017-07-27 16:54:35 +03002299 // ANGLE_multiview spec, Revision 1:
2300 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2301 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2302 // is not NONE.
2303 if (source->getMultiviewLayout() != GL_NONE)
2304 {
2305 context->handleError(InvalidFramebufferOperation()
2306 << "The active read framebuffer object has multiview attachments.");
2307 return false;
2308 }
2309
Geoff Langaae65a42014-05-26 12:43:44 -04002310 const gl::Caps &caps = context->getCaps();
2311
Geoff Langaae65a42014-05-26 12:43:44 -04002312 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002313 switch (target)
2314 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002315 case GL_TEXTURE_2D:
2316 maxDimension = caps.max2DTextureSize;
2317 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002318
He Yunchaoced53ae2016-11-29 15:00:51 +08002319 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2320 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2321 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2322 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2323 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2324 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2325 maxDimension = caps.maxCubeMapTextureSize;
2326 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002327
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002328 case GL_TEXTURE_RECTANGLE_ANGLE:
2329 maxDimension = caps.maxRectangleTextureSize;
2330 break;
2331
He Yunchaoced53ae2016-11-29 15:00:51 +08002332 case GL_TEXTURE_2D_ARRAY:
2333 maxDimension = caps.max2DTextureSize;
2334 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002335
He Yunchaoced53ae2016-11-29 15:00:51 +08002336 case GL_TEXTURE_3D:
2337 maxDimension = caps.max3DTextureSize;
2338 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002339
He Yunchaoced53ae2016-11-29 15:00:51 +08002340 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002341 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002342 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002343 }
2344
Jamie Madillc29968b2016-01-20 11:17:23 -05002345 gl::Texture *texture =
2346 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002347 if (!texture)
2348 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002349 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002350 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002351 }
2352
Geoff Lang69cce582015-09-17 13:20:36 -04002353 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002354 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002355 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002356 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002357 }
2358
Geoff Langca271392017-04-05 12:30:00 -04002359 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002360 isSubImage ? *texture->getFormat(target, level).info
2361 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002362
Geoff Lang966c9402017-04-18 12:38:27 -04002363 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002364 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002365 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002366 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002367 }
2368
2369 if (isSubImage)
2370 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002371 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2372 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2373 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002374 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002375 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002376 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002377 }
2378 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002379 else
2380 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002381 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002382 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002383 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002384 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002385 }
2386
Geoff Langeb66a6e2016-10-31 13:06:12 -04002387 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002388 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002389 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002390 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002391 }
2392
2393 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002394 if (static_cast<int>(width) > maxLevelDimension ||
2395 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002396 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002397 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002398 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002399 }
2400 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002401
Jamie Madill0c8abca2016-07-22 20:21:26 -04002402 if (textureFormatOut)
2403 {
2404 *textureFormatOut = texture->getFormat(target, level);
2405 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002406
2407 // Detect texture copying feedback loops for WebGL.
2408 if (context->getExtensions().webglCompatibility)
2409 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002410 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002411 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002412 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002413 return false;
2414 }
2415 }
2416
Jamie Madill560a8d82014-05-21 13:06:20 -04002417 return true;
2418}
2419
Jiajia Qind9671222016-11-29 16:30:31 +08002420bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002421{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002422 switch (mode)
2423 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002424 case GL_POINTS:
2425 case GL_LINES:
2426 case GL_LINE_LOOP:
2427 case GL_LINE_STRIP:
2428 case GL_TRIANGLES:
2429 case GL_TRIANGLE_STRIP:
2430 case GL_TRIANGLE_FAN:
2431 break;
2432 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002433 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002434 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002435 }
2436
Jamie Madill250d33f2014-06-06 17:09:03 -04002437 if (count < 0)
2438 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002439 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002440 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002441 }
2442
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002443 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002444
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002445 const Extensions &extensions = context->getExtensions();
2446
2447 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2448 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2449 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2450 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002451 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002452 // Check for mapped buffers
2453 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002454 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002455 {
2456 context->handleError(InvalidOperation());
2457 return false;
2458 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002459 }
2460
Jamie Madillcbcde722017-01-06 14:50:00 -05002461 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2462 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002463 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002464 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002465 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002466 const FramebufferAttachment *dsAttachment =
2467 framebuffer->getStencilOrDepthStencilAttachment();
2468 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002469 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002470 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002471
2472 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2473 bool differentWritemasks =
2474 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2475 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2476 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2477 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2478
2479 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002480 {
Martin Radevffe754b2017-07-31 10:38:07 +03002481 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002482 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002483 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2484 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002485 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002486 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002487 return false;
2488 }
Jamie Madillac528012014-06-20 13:21:23 -04002489 }
2490
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002491 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002492 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002493 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002494 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002495 }
2496
Geoff Lang7dd2e102014-11-10 15:19:26 -05002497 gl::Program *program = state.getProgram();
2498 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002499 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002500 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002501 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002502 }
2503
Yunchao Hecddcb592017-11-13 15:27:35 +08002504 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2505 // vertex shader stage or fragment shader stage is a undefined behaviour.
2506 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2507 // produce undefined result.
2508 if (program->isLinked() &&
2509 (!program->hasLinkedVertexShader() || !program->hasLinkedFragmentShader()))
2510 {
2511 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2512 "vertex shader stage or fragment shader stage.");
2513 return false;
2514 }
2515
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002516 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002517 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002518 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002519 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002520 }
2521
Martin Radevffe754b2017-07-31 10:38:07 +03002522 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002523 {
Martin Radevda8e2572017-09-12 17:21:16 +03002524 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002525 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002526 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002527 {
2528 context->handleError(InvalidOperation() << "The number of views in the active program "
2529 "and draw framebuffer does not match.");
2530 return false;
2531 }
Martin Radev7e69f762017-07-27 14:54:13 +03002532
2533 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2534 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2535 framebufferNumViews > 1)
2536 {
2537 context->handleError(InvalidOperation()
2538 << "There is an active transform feedback object "
2539 "when the number of views in the active draw "
2540 "framebuffer is greater than 1.");
2541 return false;
2542 }
Martin Radevffe754b2017-07-31 10:38:07 +03002543
2544 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2545 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2546 {
2547 context->handleError(InvalidOperation() << "There is an active query for target "
2548 "GL_TIME_ELAPSED_EXT when the number of "
2549 "views in the active draw framebuffer is "
2550 "greater than 1.");
2551 return false;
2552 }
Martin Radev7cf61662017-07-26 17:10:53 +03002553 }
2554
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002555 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002556 for (unsigned int uniformBlockIndex = 0;
2557 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002558 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002559 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002560 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002561 const OffsetBindingPointer<Buffer> &uniformBuffer =
2562 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002563
Geoff Lang5d124a62015-09-15 13:03:27 -04002564 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002565 {
2566 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002567 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002568 InvalidOperation()
2569 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002570 return false;
2571 }
2572
Geoff Lang5d124a62015-09-15 13:03:27 -04002573 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002574 if (uniformBufferSize == 0)
2575 {
2576 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002577 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002578 }
2579
Jamie Madill62d31cb2015-09-11 13:25:51 -04002580 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002581 {
2582 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002583 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002584 InvalidOperation()
2585 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002586 return false;
2587 }
2588 }
2589
Geoff Lange0cff192017-05-30 13:04:56 -04002590 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002591 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002592 {
Geoff Lange0cff192017-05-30 13:04:56 -04002593 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002594 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2595 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002596 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002597 return false;
2598 }
Geoff Lange0cff192017-05-30 13:04:56 -04002599
Geoff Lang9ab5b822017-05-30 16:19:23 -04002600 // Detect that the vertex shader input types match the attribute types
2601 if (!ValidateVertexShaderAttributeTypeMatch(context))
2602 {
2603 return false;
2604 }
2605
Geoff Lange0cff192017-05-30 13:04:56 -04002606 // Detect that the color buffer types match the fragment shader output types
2607 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2608 {
2609 return false;
2610 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002611 }
2612
Jamie Madill250d33f2014-06-06 17:09:03 -04002613 // No-op if zero count
2614 return (count > 0);
2615}
2616
Jamie Madillc1d770e2017-04-13 17:31:24 -04002617bool ValidateDrawArraysCommon(ValidationContext *context,
2618 GLenum mode,
2619 GLint first,
2620 GLsizei count,
2621 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002622{
Jamie Madillfd716582014-06-06 17:09:04 -04002623 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002624 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002625 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002626 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002627 }
2628
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002629 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002630 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002631 if (curTransformFeedback && curTransformFeedback->isActive() &&
2632 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002633 {
2634 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002635 // that does not match the current transform feedback object's draw mode (if transform
2636 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002637 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002638 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002639 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002640 }
2641
Jiajia Qind9671222016-11-29 16:30:31 +08002642 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002643 {
2644 return false;
2645 }
2646
Corentin Wallez71168a02016-12-19 15:11:18 -08002647 // Check the computation of maxVertex doesn't overflow.
2648 // - first < 0 or count < 0 have been checked as an error condition
2649 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2650 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2651 ASSERT(count > 0 && first >= 0);
2652 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2653 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002654 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002655 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002656 return false;
2657 }
2658
Corentin Wallez71168a02016-12-19 15:11:18 -08002659 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002660 {
2661 return false;
2662 }
2663
2664 return true;
2665}
2666
He Yunchaoced53ae2016-11-29 15:00:51 +08002667bool ValidateDrawArraysInstancedANGLE(Context *context,
2668 GLenum mode,
2669 GLint first,
2670 GLsizei count,
2671 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002672{
Geoff Lang63c5a592017-09-27 14:08:16 -04002673 if (!context->getExtensions().instancedArrays)
2674 {
2675 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2676 return false;
2677 }
2678
Corentin Wallez170efbf2017-05-02 13:45:01 -04002679 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002680 {
2681 return false;
2682 }
2683
Corentin Wallez0dc97812017-06-22 14:38:44 -04002684 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002685}
2686
Jiajia Qind9671222016-11-29 16:30:31 +08002687bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002688{
Jamie Madill250d33f2014-06-06 17:09:03 -04002689 switch (type)
2690 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002691 case GL_UNSIGNED_BYTE:
2692 case GL_UNSIGNED_SHORT:
2693 break;
2694 case GL_UNSIGNED_INT:
2695 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2696 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002697 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002698 return false;
2699 }
2700 break;
2701 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002702 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002703 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002704 }
2705
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002706 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002707
2708 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002709 if (curTransformFeedback && curTransformFeedback->isActive() &&
2710 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002711 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002712 // It is an invalid operation to call DrawElements, DrawRangeElements or
2713 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002714 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002715 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002716 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002717 }
2718
Jiajia Qind9671222016-11-29 16:30:31 +08002719 return true;
2720}
2721
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002722bool ValidateDrawElementsCommon(ValidationContext *context,
2723 GLenum mode,
2724 GLsizei count,
2725 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002726 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002727 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002728{
2729 if (!ValidateDrawElementsBase(context, type))
2730 return false;
2731
2732 const State &state = context->getGLState();
2733
Corentin Wallez170efbf2017-05-02 13:45:01 -04002734 if (!ValidateDrawBase(context, mode, count))
2735 {
2736 return false;
2737 }
2738
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002739 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2740 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2741 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2742 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002743 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002744 // Check for mapped buffers
2745 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002746 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002747 {
2748 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2749 return false;
2750 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002751 }
2752
He Yunchaoced53ae2016-11-29 15:00:51 +08002753 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002754 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002755
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002756 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2757
2758 if (context->getExtensions().webglCompatibility)
2759 {
2760 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2761 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2762 {
2763 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2764 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2765 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002766 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002767 return false;
2768 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002769
2770 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2771 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2772 // error is generated.
2773 if (reinterpret_cast<intptr_t>(indices) < 0)
2774 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002775 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002776 return false;
2777 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002778 }
2779
2780 if (context->getExtensions().webglCompatibility ||
2781 !context->getGLState().areClientArraysEnabled())
2782 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002783 if (!elementArrayBuffer && count > 0)
2784 {
2785 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2786 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2787 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002788 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002789 return false;
2790 }
2791 }
2792
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002793 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002794 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002795 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002796 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002797 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2798 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2799 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2800 constexpr uint64_t kMaxTypeSize = 8;
2801 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2802 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2803 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002804
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002805 uint64_t typeSize = typeBytes;
2806 uint64_t elementCount = static_cast<uint64_t>(count);
2807 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2808
2809 // Doing the multiplication here is overflow-safe
2810 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2811
2812 // The offset can be any value, check for overflows
2813 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2814 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002815 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002816 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002817 return false;
2818 }
2819
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002820 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2821 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002822 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002823 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002824 return false;
2825 }
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002826
Corentin Wallez487653b2017-09-01 17:17:55 -04002827 ASSERT(isPow2(typeSize) && typeSize > 0);
2828 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002829 {
2830 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
2831 return false;
2832 }
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002833 }
2834 else if (!indices)
2835 {
2836 // This is an application error that would normally result in a crash,
2837 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002838 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04002839 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002840 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002841 }
2842
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002843 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002844 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002845 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2846 // access is enabled.
2847 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2848 {
2849 return false;
2850 }
2851 }
2852 else
2853 {
2854 // Use the parameter buffer to retrieve and cache the index range.
2855 const auto &params = context->getParams<HasIndexRange>();
2856 const auto &indexRangeOpt = params.getIndexRange();
2857 if (!indexRangeOpt.valid())
2858 {
2859 // Unexpected error.
2860 return false;
2861 }
2862
2863 // If we use an index greater than our maximum supported index range, return an error.
2864 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2865 // return an error if possible here.
2866 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2867 {
2868 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2869 return false;
2870 }
2871
2872 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2873 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2874 {
2875 return false;
2876 }
2877
2878 // No op if there are no real indices in the index data (all are primitive restart).
2879 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002880 }
2881
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002882 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002883}
2884
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002885bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2886 GLenum mode,
2887 GLsizei count,
2888 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002889 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002890 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002891{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002892 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002893}
2894
Geoff Lang3edfe032015-09-04 16:38:24 -04002895bool ValidateDrawElementsInstancedANGLE(Context *context,
2896 GLenum mode,
2897 GLsizei count,
2898 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002899 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002900 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002901{
Geoff Lang63c5a592017-09-27 14:08:16 -04002902 if (!context->getExtensions().instancedArrays)
2903 {
2904 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2905 return false;
2906 }
2907
Corentin Wallez170efbf2017-05-02 13:45:01 -04002908 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002909 {
2910 return false;
2911 }
2912
Corentin Wallez0dc97812017-06-22 14:38:44 -04002913 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002914}
2915
He Yunchaoced53ae2016-11-29 15:00:51 +08002916bool ValidateFramebufferTextureBase(Context *context,
2917 GLenum target,
2918 GLenum attachment,
2919 GLuint texture,
2920 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002921{
Geoff Lange8afa902017-09-27 15:00:43 -04002922 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002923 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002924 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002925 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002926 }
2927
2928 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002929 {
2930 return false;
2931 }
2932
Jamie Madill55ec3b12014-07-03 10:38:57 -04002933 if (texture != 0)
2934 {
2935 gl::Texture *tex = context->getTexture(texture);
2936
Jamie Madillbe849e42017-05-02 15:49:00 -04002937 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002938 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002939 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002940 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002941 }
2942
2943 if (level < 0)
2944 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002945 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002946 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002947 }
2948 }
2949
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002950 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002951 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002952
Jamie Madill84115c92015-04-23 15:00:07 -04002953 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002954 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002955 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002956 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002957 }
2958
2959 return true;
2960}
2961
Geoff Langb1196682014-07-23 13:47:29 -04002962bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04002963{
2964 if (program == 0)
2965 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002966 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002967 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002968 }
2969
Dian Xiang769769a2015-09-09 15:20:08 -07002970 gl::Program *programObject = GetValidProgram(context, program);
2971 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05002972 {
2973 return false;
2974 }
2975
Jamie Madill0063c512014-08-25 15:47:53 -04002976 if (!programObject || !programObject->isLinked())
2977 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002978 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04002979 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002980 }
2981
Geoff Lang7dd2e102014-11-10 15:19:26 -05002982 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04002983 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002984 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002985 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04002986 }
2987
Jamie Madill0063c512014-08-25 15:47:53 -04002988 return true;
2989}
2990
Geoff Langf41d0ee2016-10-07 13:04:23 -04002991static bool ValidateSizedGetUniform(Context *context,
2992 GLuint program,
2993 GLint location,
2994 GLsizei bufSize,
2995 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04002996{
Geoff Langf41d0ee2016-10-07 13:04:23 -04002997 if (length)
2998 {
2999 *length = 0;
3000 }
3001
Jamie Madill78f41802014-08-25 15:47:55 -04003002 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003003 {
Jamie Madill78f41802014-08-25 15:47:55 -04003004 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003005 }
3006
Geoff Langf41d0ee2016-10-07 13:04:23 -04003007 if (bufSize < 0)
3008 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003009 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003010 return false;
3011 }
3012
Jamie Madilla502c742014-08-28 17:19:13 -04003013 gl::Program *programObject = context->getProgram(program);
3014 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003015
Jamie Madill78f41802014-08-25 15:47:55 -04003016 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003017 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003018 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003019 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003020 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003021 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003022 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003023 }
3024
Geoff Langf41d0ee2016-10-07 13:04:23 -04003025 if (length)
3026 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003027 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003028 }
3029
Jamie Madill0063c512014-08-25 15:47:53 -04003030 return true;
3031}
3032
He Yunchaoced53ae2016-11-29 15:00:51 +08003033bool ValidateGetnUniformfvEXT(Context *context,
3034 GLuint program,
3035 GLint location,
3036 GLsizei bufSize,
3037 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003038{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003039 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003040}
3041
He Yunchaoced53ae2016-11-29 15:00:51 +08003042bool ValidateGetnUniformivEXT(Context *context,
3043 GLuint program,
3044 GLint location,
3045 GLsizei bufSize,
3046 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003047{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003048 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3049}
3050
3051bool ValidateGetUniformfvRobustANGLE(Context *context,
3052 GLuint program,
3053 GLint location,
3054 GLsizei bufSize,
3055 GLsizei *length,
3056 GLfloat *params)
3057{
3058 if (!ValidateRobustEntryPoint(context, bufSize))
3059 {
3060 return false;
3061 }
3062
3063 // bufSize is validated in ValidateSizedGetUniform
3064 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3065}
3066
3067bool ValidateGetUniformivRobustANGLE(Context *context,
3068 GLuint program,
3069 GLint location,
3070 GLsizei bufSize,
3071 GLsizei *length,
3072 GLint *params)
3073{
3074 if (!ValidateRobustEntryPoint(context, bufSize))
3075 {
3076 return false;
3077 }
3078
3079 // bufSize is validated in ValidateSizedGetUniform
3080 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3081}
3082
3083bool ValidateGetUniformuivRobustANGLE(Context *context,
3084 GLuint program,
3085 GLint location,
3086 GLsizei bufSize,
3087 GLsizei *length,
3088 GLuint *params)
3089{
3090 if (!ValidateRobustEntryPoint(context, bufSize))
3091 {
3092 return false;
3093 }
3094
3095 if (context->getClientMajorVersion() < 3)
3096 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003097 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003098 return false;
3099 }
3100
3101 // bufSize is validated in ValidateSizedGetUniform
3102 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003103}
3104
He Yunchaoced53ae2016-11-29 15:00:51 +08003105bool ValidateDiscardFramebufferBase(Context *context,
3106 GLenum target,
3107 GLsizei numAttachments,
3108 const GLenum *attachments,
3109 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003110{
3111 if (numAttachments < 0)
3112 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003113 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003114 return false;
3115 }
3116
3117 for (GLsizei i = 0; i < numAttachments; ++i)
3118 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003119 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003120 {
3121 if (defaultFramebuffer)
3122 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003123 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003124 return false;
3125 }
3126
3127 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3128 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003129 context->handleError(InvalidOperation() << "Requested color attachment is "
3130 "greater than the maximum supported "
3131 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003132 return false;
3133 }
3134 }
3135 else
3136 {
3137 switch (attachments[i])
3138 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003139 case GL_DEPTH_ATTACHMENT:
3140 case GL_STENCIL_ATTACHMENT:
3141 case GL_DEPTH_STENCIL_ATTACHMENT:
3142 if (defaultFramebuffer)
3143 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003144 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3145 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003146 return false;
3147 }
3148 break;
3149 case GL_COLOR:
3150 case GL_DEPTH:
3151 case GL_STENCIL:
3152 if (!defaultFramebuffer)
3153 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003154 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3155 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003156 return false;
3157 }
3158 break;
3159 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003160 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003161 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003162 }
3163 }
3164 }
3165
3166 return true;
3167}
3168
Austin Kinross6ee1e782015-05-29 17:05:37 -07003169bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3170{
3171 // Note that debug marker calls must not set error state
3172
3173 if (length < 0)
3174 {
3175 return false;
3176 }
3177
3178 if (marker == nullptr)
3179 {
3180 return false;
3181 }
3182
3183 return true;
3184}
3185
3186bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3187{
3188 // Note that debug marker calls must not set error state
3189
3190 if (length < 0)
3191 {
3192 return false;
3193 }
3194
3195 if (length > 0 && marker == nullptr)
3196 {
3197 return false;
3198 }
3199
3200 return true;
3201}
3202
Geoff Langdcab33b2015-07-21 13:03:16 -04003203bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003204 GLenum target,
3205 egl::Image *image)
3206{
Geoff Langa8406172015-07-21 16:53:39 -04003207 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3208 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003209 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003210 return false;
3211 }
3212
3213 switch (target)
3214 {
3215 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003216 if (!context->getExtensions().eglImage)
3217 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003218 context->handleError(InvalidEnum()
3219 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003220 }
3221 break;
3222
3223 case GL_TEXTURE_EXTERNAL_OES:
3224 if (!context->getExtensions().eglImageExternal)
3225 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003226 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3227 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003228 }
Geoff Langa8406172015-07-21 16:53:39 -04003229 break;
3230
3231 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003232 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003233 return false;
3234 }
3235
Jamie Madill61e16b42017-06-19 11:13:23 -04003236 ASSERT(context->getCurrentDisplay());
3237 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003238 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003239 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003240 return false;
3241 }
3242
3243 if (image->getSamples() > 0)
3244 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003245 context->handleError(InvalidOperation()
3246 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003247 return false;
3248 }
3249
Geoff Langca271392017-04-05 12:30:00 -04003250 const TextureCaps &textureCaps =
3251 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003252 if (!textureCaps.texturable)
3253 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003254 context->handleError(InvalidOperation()
3255 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003256 return false;
3257 }
3258
Geoff Langdcab33b2015-07-21 13:03:16 -04003259 return true;
3260}
3261
3262bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003263 GLenum target,
3264 egl::Image *image)
3265{
Geoff Langa8406172015-07-21 16:53:39 -04003266 if (!context->getExtensions().eglImage)
3267 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003268 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003269 return false;
3270 }
3271
3272 switch (target)
3273 {
3274 case GL_RENDERBUFFER:
3275 break;
3276
3277 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003278 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003279 return false;
3280 }
3281
Jamie Madill61e16b42017-06-19 11:13:23 -04003282 ASSERT(context->getCurrentDisplay());
3283 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003284 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003285 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003286 return false;
3287 }
3288
Geoff Langca271392017-04-05 12:30:00 -04003289 const TextureCaps &textureCaps =
3290 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003291 if (!textureCaps.renderable)
3292 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003293 context->handleError(InvalidOperation()
3294 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003295 return false;
3296 }
3297
Geoff Langdcab33b2015-07-21 13:03:16 -04003298 return true;
3299}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003300
3301bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3302{
Geoff Lang36167ab2015-12-07 10:27:14 -05003303 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003304 {
3305 // The default VAO should always exist
3306 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003307 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003308 return false;
3309 }
3310
3311 return true;
3312}
3313
Geoff Langc5629752015-12-07 16:29:04 -05003314bool ValidateProgramBinaryBase(Context *context,
3315 GLuint program,
3316 GLenum binaryFormat,
3317 const void *binary,
3318 GLint length)
3319{
3320 Program *programObject = GetValidProgram(context, program);
3321 if (programObject == nullptr)
3322 {
3323 return false;
3324 }
3325
3326 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3327 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3328 programBinaryFormats.end())
3329 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003330 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003331 return false;
3332 }
3333
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003334 if (context->hasActiveTransformFeedback(program))
3335 {
3336 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003337 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3338 "is associated with an active transform "
3339 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003340 return false;
3341 }
3342
Geoff Langc5629752015-12-07 16:29:04 -05003343 return true;
3344}
3345
3346bool ValidateGetProgramBinaryBase(Context *context,
3347 GLuint program,
3348 GLsizei bufSize,
3349 GLsizei *length,
3350 GLenum *binaryFormat,
3351 void *binary)
3352{
3353 Program *programObject = GetValidProgram(context, program);
3354 if (programObject == nullptr)
3355 {
3356 return false;
3357 }
3358
3359 if (!programObject->isLinked())
3360 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003361 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003362 return false;
3363 }
3364
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003365 if (context->getCaps().programBinaryFormats.empty())
3366 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003367 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003368 return false;
3369 }
3370
Geoff Langc5629752015-12-07 16:29:04 -05003371 return true;
3372}
Jamie Madillc29968b2016-01-20 11:17:23 -05003373
Jamie Madillc29968b2016-01-20 11:17:23 -05003374bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3375{
3376 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003377 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003378 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003379 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3380 return false;
3381 }
3382 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3383 {
3384 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003385 return false;
3386 }
3387
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003388 ASSERT(context->getGLState().getDrawFramebuffer());
3389 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003390 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3391
3392 // This should come first before the check for the default frame buffer
3393 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3394 // rather than INVALID_OPERATION
3395 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3396 {
3397 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3398
3399 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003400 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3401 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003402 {
3403 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003404 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3405 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3406 // 3.1 is still a bit ambiguous about the error, but future specs are
3407 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003408 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003409 return false;
3410 }
3411 else if (bufs[colorAttachment] >= maxColorAttachment)
3412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003413 context->handleError(InvalidOperation()
3414 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003415 return false;
3416 }
3417 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3418 frameBufferId != 0)
3419 {
3420 // INVALID_OPERATION-GL is bound to buffer and ith argument
3421 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003422 context->handleError(InvalidOperation()
3423 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003424 return false;
3425 }
3426 }
3427
3428 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3429 // and n is not 1 or bufs is bound to value other than BACK and NONE
3430 if (frameBufferId == 0)
3431 {
3432 if (n != 1)
3433 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003434 context->handleError(InvalidOperation()
3435 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003436 return false;
3437 }
3438
3439 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3440 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003441 context->handleError(
3442 InvalidOperation()
3443 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003444 return false;
3445 }
3446 }
3447
3448 return true;
3449}
3450
Geoff Lang496c02d2016-10-20 11:38:11 -07003451bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003452 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003453 GLenum pname,
3454 GLsizei *length,
3455 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003456{
Geoff Lang496c02d2016-10-20 11:38:11 -07003457 if (length)
3458 {
3459 *length = 0;
3460 }
3461
3462 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3463 {
3464 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003465 InvalidOperation()
3466 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003467 return false;
3468 }
3469
Corentin Walleze4477002017-12-01 14:39:58 -05003470 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003471 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003472 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003473 return false;
3474 }
3475
Geoff Lang496c02d2016-10-20 11:38:11 -07003476 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003477 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003478 case GL_BUFFER_MAP_POINTER:
3479 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003480
Geoff Lang496c02d2016-10-20 11:38:11 -07003481 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003482 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003483 return false;
3484 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003485
3486 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3487 // target bound to zero generate an INVALID_OPERATION error."
3488 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003489 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003490 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003491 context->handleError(InvalidOperation()
3492 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003493 return false;
3494 }
3495
Geoff Lang496c02d2016-10-20 11:38:11 -07003496 if (length)
3497 {
3498 *length = 1;
3499 }
3500
Olli Etuaho4f667482016-03-30 15:56:35 +03003501 return true;
3502}
3503
Corentin Wallez336129f2017-10-17 15:55:40 -04003504bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003505{
Corentin Walleze4477002017-12-01 14:39:58 -05003506 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003507 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003508 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003509 return false;
3510 }
3511
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003512 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003513
3514 if (buffer == nullptr || !buffer->isMapped())
3515 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003516 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003517 return false;
3518 }
3519
3520 return true;
3521}
3522
3523bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003524 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003525 GLintptr offset,
3526 GLsizeiptr length,
3527 GLbitfield access)
3528{
Corentin Walleze4477002017-12-01 14:39:58 -05003529 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003530 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003531 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003532 return false;
3533 }
3534
Brandon Jones6cad5662017-06-14 13:25:13 -07003535 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003536 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003537 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3538 return false;
3539 }
3540
3541 if (length < 0)
3542 {
3543 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003544 return false;
3545 }
3546
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003547 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003548
3549 if (!buffer)
3550 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003551 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003552 return false;
3553 }
3554
3555 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003556 CheckedNumeric<size_t> checkedOffset(offset);
3557 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003558
Jamie Madille2e406c2016-06-02 13:04:10 -04003559 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003560 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003561 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003562 return false;
3563 }
3564
3565 // Check for invalid bits in the mask
3566 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3567 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3568 GL_MAP_UNSYNCHRONIZED_BIT;
3569
3570 if (access & ~(allAccessBits))
3571 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003572 context->handleError(InvalidValue()
3573 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003574 return false;
3575 }
3576
3577 if (length == 0)
3578 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003579 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003580 return false;
3581 }
3582
3583 if (buffer->isMapped())
3584 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003585 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003586 return false;
3587 }
3588
3589 // Check for invalid bit combinations
3590 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3591 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003592 context->handleError(InvalidOperation()
3593 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003594 return false;
3595 }
3596
3597 GLbitfield writeOnlyBits =
3598 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3599
3600 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3601 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003602 context->handleError(InvalidOperation()
3603 << "Invalid access bits when mapping buffer for reading: 0x"
3604 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003605 return false;
3606 }
3607
3608 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003610 context->handleError(
3611 InvalidOperation()
3612 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003613 return false;
3614 }
Geoff Lang79f71042017-08-14 16:43:43 -04003615
3616 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003617}
3618
3619bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003620 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003621 GLintptr offset,
3622 GLsizeiptr length)
3623{
Brandon Jones6cad5662017-06-14 13:25:13 -07003624 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003625 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003626 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3627 return false;
3628 }
3629
3630 if (length < 0)
3631 {
3632 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003633 return false;
3634 }
3635
Corentin Walleze4477002017-12-01 14:39:58 -05003636 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003637 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003638 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003639 return false;
3640 }
3641
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003642 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003643
3644 if (buffer == nullptr)
3645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003646 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003647 return false;
3648 }
3649
3650 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3651 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003652 context->handleError(InvalidOperation()
3653 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003654 return false;
3655 }
3656
3657 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003658 CheckedNumeric<size_t> checkedOffset(offset);
3659 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003660
Jamie Madille2e406c2016-06-02 13:04:10 -04003661 if (!checkedSize.IsValid() ||
3662 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003663 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003664 context->handleError(InvalidValue()
3665 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003666 return false;
3667 }
3668
3669 return true;
3670}
3671
Olli Etuaho41997e72016-03-10 13:38:39 +02003672bool ValidateGenOrDelete(Context *context, GLint n)
3673{
3674 if (n < 0)
3675 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003676 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003677 return false;
3678 }
3679 return true;
3680}
3681
Geoff Langff5b2d52016-09-07 11:32:23 -04003682bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3683{
3684 if (!context->getExtensions().robustClientMemory)
3685 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003686 context->handleError(InvalidOperation()
3687 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003688 return false;
3689 }
3690
3691 if (bufSize < 0)
3692 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003693 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003694 return false;
3695 }
3696
3697 return true;
3698}
3699
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003700bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3701{
3702 if (bufSize < numParams)
3703 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003704 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3705 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003706 return false;
3707 }
3708
3709 return true;
3710}
3711
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003712bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003713 GLenum target,
3714 GLenum attachment,
3715 GLenum pname,
3716 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003717{
Geoff Lange8afa902017-09-27 15:00:43 -04003718 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003719 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003720 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003721 return false;
3722 }
3723
3724 int clientVersion = context->getClientMajorVersion();
3725
3726 switch (pname)
3727 {
3728 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3729 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3730 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3731 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3732 break;
3733
Martin Radeve5285d22017-07-14 16:23:53 +03003734 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3735 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3736 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3737 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3738 if (clientVersion < 3 || !context->getExtensions().multiview)
3739 {
3740 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3741 return false;
3742 }
3743 break;
3744
Geoff Langff5b2d52016-09-07 11:32:23 -04003745 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3746 if (clientVersion < 3 && !context->getExtensions().sRGB)
3747 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003748 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003749 return false;
3750 }
3751 break;
3752
3753 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3754 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3755 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3756 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3757 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3758 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3759 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3760 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3761 if (clientVersion < 3)
3762 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003763 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003764 return false;
3765 }
3766 break;
3767
3768 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003769 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003770 return false;
3771 }
3772
3773 // Determine if the attachment is a valid enum
3774 switch (attachment)
3775 {
3776 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04003777 case GL_DEPTH:
3778 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04003779 if (clientVersion < 3)
3780 {
Geoff Langfa125c92017-10-24 13:01:46 -04003781 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003782 return false;
3783 }
3784 break;
3785
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003786 case GL_DEPTH_STENCIL_ATTACHMENT:
3787 if (clientVersion < 3 && !context->isWebGL1())
3788 {
3789 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3790 return false;
3791 }
3792 break;
3793
Geoff Langfa125c92017-10-24 13:01:46 -04003794 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003795 case GL_DEPTH_ATTACHMENT:
3796 case GL_STENCIL_ATTACHMENT:
3797 break;
3798
3799 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003800 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3801 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003802 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3803 {
Geoff Langfa125c92017-10-24 13:01:46 -04003804 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003805 return false;
3806 }
3807 break;
3808 }
3809
3810 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3811 ASSERT(framebuffer);
3812
3813 if (framebuffer->id() == 0)
3814 {
3815 if (clientVersion < 3)
3816 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003817 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003818 return false;
3819 }
3820
3821 switch (attachment)
3822 {
3823 case GL_BACK:
3824 case GL_DEPTH:
3825 case GL_STENCIL:
3826 break;
3827
3828 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003829 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003830 return false;
3831 }
3832 }
3833 else
3834 {
3835 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3836 {
3837 // Valid attachment query
3838 }
3839 else
3840 {
3841 switch (attachment)
3842 {
3843 case GL_DEPTH_ATTACHMENT:
3844 case GL_STENCIL_ATTACHMENT:
3845 break;
3846
3847 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003848 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04003849 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003850 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003851 return false;
3852 }
3853 break;
3854
3855 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003856 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003857 return false;
3858 }
3859 }
3860 }
3861
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003862 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003863 if (attachmentObject)
3864 {
3865 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3866 attachmentObject->type() == GL_TEXTURE ||
3867 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3868
3869 switch (pname)
3870 {
3871 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3872 if (attachmentObject->type() != GL_RENDERBUFFER &&
3873 attachmentObject->type() != GL_TEXTURE)
3874 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003875 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003876 return false;
3877 }
3878 break;
3879
3880 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3881 if (attachmentObject->type() != GL_TEXTURE)
3882 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003883 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003884 return false;
3885 }
3886 break;
3887
3888 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3889 if (attachmentObject->type() != GL_TEXTURE)
3890 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003891 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003892 return false;
3893 }
3894 break;
3895
3896 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3897 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3898 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003899 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003900 return false;
3901 }
3902 break;
3903
3904 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3905 if (attachmentObject->type() != GL_TEXTURE)
3906 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003907 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003908 return false;
3909 }
3910 break;
3911
3912 default:
3913 break;
3914 }
3915 }
3916 else
3917 {
3918 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3919 // is NONE, then querying any other pname will generate INVALID_ENUM.
3920
3921 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3922 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3923 // INVALID_OPERATION for all other pnames
3924
3925 switch (pname)
3926 {
3927 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3928 break;
3929
3930 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3931 if (clientVersion < 3)
3932 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003933 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003934 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003935 return false;
3936 }
3937 break;
3938
3939 default:
3940 if (clientVersion < 3)
3941 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003942 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003943 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003944 return false;
3945 }
3946 else
3947 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003948 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003949 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003950 return false;
3951 }
3952 }
3953 }
3954
Martin Radeve5285d22017-07-14 16:23:53 +03003955 if (numParams)
3956 {
3957 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
3958 {
3959 // Only when the viewport offsets are queried we can have a varying number of output
3960 // parameters.
3961 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
3962 *numParams = numViews * 2;
3963 }
3964 else
3965 {
3966 // For all other queries we can have only one output parameter.
3967 *numParams = 1;
3968 }
3969 }
3970
Geoff Langff5b2d52016-09-07 11:32:23 -04003971 return true;
3972}
3973
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003974bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04003975 GLenum target,
3976 GLenum attachment,
3977 GLenum pname,
3978 GLsizei bufSize,
3979 GLsizei *numParams)
3980{
3981 if (!ValidateRobustEntryPoint(context, bufSize))
3982 {
3983 return false;
3984 }
3985
Jamie Madillbe849e42017-05-02 15:49:00 -04003986 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
3987 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04003988 {
3989 return false;
3990 }
3991
3992 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
3993 {
3994 return false;
3995 }
3996
3997 return true;
3998}
3999
Geoff Langff5b2d52016-09-07 11:32:23 -04004000bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004001 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004002 GLenum pname,
4003 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004004 GLsizei *length,
4005 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004006{
4007 if (!ValidateRobustEntryPoint(context, bufSize))
4008 {
4009 return false;
4010 }
4011
Geoff Langebebe1c2016-10-14 12:01:31 -04004012 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004013 {
4014 return false;
4015 }
4016
Geoff Langebebe1c2016-10-14 12:01:31 -04004017 if (!ValidateRobustBufferSize(context, bufSize, *length))
4018 {
4019 return false;
4020 }
4021
4022 return true;
4023}
4024
Geoff Langebebe1c2016-10-14 12:01:31 -04004025bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004026 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004027 GLenum pname,
4028 GLsizei bufSize,
4029 GLsizei *length,
4030 GLint64 *params)
4031{
4032 if (!ValidateRobustEntryPoint(context, bufSize))
4033 {
4034 return false;
4035 }
4036
4037 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4038 {
4039 return false;
4040 }
4041
4042 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004043 {
4044 return false;
4045 }
4046
4047 return true;
4048}
4049
Jamie Madillbe849e42017-05-02 15:49:00 -04004050bool ValidateGetProgramivBase(ValidationContext *context,
4051 GLuint program,
4052 GLenum pname,
4053 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004054{
4055 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004056 if (numParams)
4057 {
4058 *numParams = 1;
4059 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004060
4061 Program *programObject = GetValidProgram(context, program);
4062 if (!programObject)
4063 {
4064 return false;
4065 }
4066
4067 switch (pname)
4068 {
4069 case GL_DELETE_STATUS:
4070 case GL_LINK_STATUS:
4071 case GL_VALIDATE_STATUS:
4072 case GL_INFO_LOG_LENGTH:
4073 case GL_ATTACHED_SHADERS:
4074 case GL_ACTIVE_ATTRIBUTES:
4075 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4076 case GL_ACTIVE_UNIFORMS:
4077 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4078 break;
4079
4080 case GL_PROGRAM_BINARY_LENGTH:
4081 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4082 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004083 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4084 "requires GL_OES_get_program_binary or "
4085 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004086 return false;
4087 }
4088 break;
4089
4090 case GL_ACTIVE_UNIFORM_BLOCKS:
4091 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4092 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4093 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4094 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4095 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4096 if (context->getClientMajorVersion() < 3)
4097 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004098 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004099 return false;
4100 }
4101 break;
4102
Yunchao He61afff12017-03-14 15:34:03 +08004103 case GL_PROGRAM_SEPARABLE:
Xinghua Cao971f8502017-10-17 13:01:24 +08004104 case GL_COMPUTE_WORK_GROUP_SIZE:
jchen1058f67be2017-10-27 08:59:27 +08004105 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004106 if (context->getClientVersion() < Version(3, 1))
4107 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004108 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004109 return false;
4110 }
4111 break;
4112
Geoff Langff5b2d52016-09-07 11:32:23 -04004113 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004114 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004115 return false;
4116 }
4117
4118 return true;
4119}
4120
4121bool ValidateGetProgramivRobustANGLE(Context *context,
4122 GLuint program,
4123 GLenum pname,
4124 GLsizei bufSize,
4125 GLsizei *numParams)
4126{
4127 if (!ValidateRobustEntryPoint(context, bufSize))
4128 {
4129 return false;
4130 }
4131
Jamie Madillbe849e42017-05-02 15:49:00 -04004132 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004133 {
4134 return false;
4135 }
4136
4137 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4138 {
4139 return false;
4140 }
4141
4142 return true;
4143}
4144
Geoff Lang740d9022016-10-07 11:20:52 -04004145bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4146 GLenum target,
4147 GLenum pname,
4148 GLsizei bufSize,
4149 GLsizei *length,
4150 GLint *params)
4151{
4152 if (!ValidateRobustEntryPoint(context, bufSize))
4153 {
4154 return false;
4155 }
4156
4157 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4158 {
4159 return false;
4160 }
4161
4162 if (!ValidateRobustBufferSize(context, bufSize, *length))
4163 {
4164 return false;
4165 }
4166
4167 return true;
4168}
4169
Geoff Langd7d0ed32016-10-07 11:33:51 -04004170bool ValidateGetShaderivRobustANGLE(Context *context,
4171 GLuint shader,
4172 GLenum pname,
4173 GLsizei bufSize,
4174 GLsizei *length,
4175 GLint *params)
4176{
4177 if (!ValidateRobustEntryPoint(context, bufSize))
4178 {
4179 return false;
4180 }
4181
4182 if (!ValidateGetShaderivBase(context, shader, pname, length))
4183 {
4184 return false;
4185 }
4186
4187 if (!ValidateRobustBufferSize(context, bufSize, *length))
4188 {
4189 return false;
4190 }
4191
4192 return true;
4193}
4194
Geoff Langc1984ed2016-10-07 12:41:00 -04004195bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4196 GLenum target,
4197 GLenum pname,
4198 GLsizei bufSize,
4199 GLsizei *length,
4200 GLfloat *params)
4201{
4202 if (!ValidateRobustEntryPoint(context, bufSize))
4203 {
4204 return false;
4205 }
4206
4207 if (!ValidateGetTexParameterBase(context, target, pname, length))
4208 {
4209 return false;
4210 }
4211
4212 if (!ValidateRobustBufferSize(context, bufSize, *length))
4213 {
4214 return false;
4215 }
4216
4217 return true;
4218}
4219
Geoff Langc1984ed2016-10-07 12:41:00 -04004220bool ValidateGetTexParameterivRobustANGLE(Context *context,
4221 GLenum target,
4222 GLenum pname,
4223 GLsizei bufSize,
4224 GLsizei *length,
4225 GLint *params)
4226{
4227 if (!ValidateRobustEntryPoint(context, bufSize))
4228 {
4229 return false;
4230 }
4231
4232 if (!ValidateGetTexParameterBase(context, target, pname, length))
4233 {
4234 return false;
4235 }
4236
4237 if (!ValidateRobustBufferSize(context, bufSize, *length))
4238 {
4239 return false;
4240 }
4241
4242 return true;
4243}
4244
Geoff Langc1984ed2016-10-07 12:41:00 -04004245bool ValidateTexParameterfvRobustANGLE(Context *context,
4246 GLenum target,
4247 GLenum pname,
4248 GLsizei bufSize,
4249 const GLfloat *params)
4250{
4251 if (!ValidateRobustEntryPoint(context, bufSize))
4252 {
4253 return false;
4254 }
4255
4256 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4257}
4258
Geoff Langc1984ed2016-10-07 12:41:00 -04004259bool ValidateTexParameterivRobustANGLE(Context *context,
4260 GLenum target,
4261 GLenum pname,
4262 GLsizei bufSize,
4263 const GLint *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 ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4274 GLuint sampler,
4275 GLenum pname,
4276 GLuint bufSize,
4277 GLsizei *length,
4278 GLfloat *params)
4279{
4280 if (!ValidateRobustEntryPoint(context, bufSize))
4281 {
4282 return false;
4283 }
4284
4285 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4286 {
4287 return false;
4288 }
4289
4290 if (!ValidateRobustBufferSize(context, bufSize, *length))
4291 {
4292 return false;
4293 }
4294
4295 return true;
4296}
4297
Geoff Langc1984ed2016-10-07 12:41:00 -04004298bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4299 GLuint sampler,
4300 GLenum pname,
4301 GLuint bufSize,
4302 GLsizei *length,
4303 GLint *params)
4304{
4305 if (!ValidateRobustEntryPoint(context, bufSize))
4306 {
4307 return false;
4308 }
4309
4310 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4311 {
4312 return false;
4313 }
4314
4315 if (!ValidateRobustBufferSize(context, bufSize, *length))
4316 {
4317 return false;
4318 }
4319
4320 return true;
4321}
4322
Geoff Langc1984ed2016-10-07 12:41:00 -04004323bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4324 GLuint sampler,
4325 GLenum pname,
4326 GLsizei bufSize,
4327 const GLfloat *params)
4328{
4329 if (!ValidateRobustEntryPoint(context, bufSize))
4330 {
4331 return false;
4332 }
4333
4334 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4335}
4336
Geoff Langc1984ed2016-10-07 12:41:00 -04004337bool ValidateSamplerParameterivRobustANGLE(Context *context,
4338 GLuint sampler,
4339 GLenum pname,
4340 GLsizei bufSize,
4341 const GLint *params)
4342{
4343 if (!ValidateRobustEntryPoint(context, bufSize))
4344 {
4345 return false;
4346 }
4347
4348 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4349}
4350
Geoff Lang0b031062016-10-13 14:30:04 -04004351bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4352 GLuint index,
4353 GLenum pname,
4354 GLsizei bufSize,
4355 GLsizei *length,
4356 GLfloat *params)
4357{
4358 if (!ValidateRobustEntryPoint(context, bufSize))
4359 {
4360 return false;
4361 }
4362
4363 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4364 {
4365 return false;
4366 }
4367
4368 if (!ValidateRobustBufferSize(context, bufSize, *length))
4369 {
4370 return false;
4371 }
4372
4373 return true;
4374}
4375
Geoff Lang0b031062016-10-13 14:30:04 -04004376bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4377 GLuint index,
4378 GLenum pname,
4379 GLsizei bufSize,
4380 GLsizei *length,
4381 GLint *params)
4382{
4383 if (!ValidateRobustEntryPoint(context, bufSize))
4384 {
4385 return false;
4386 }
4387
4388 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4389 {
4390 return false;
4391 }
4392
4393 if (!ValidateRobustBufferSize(context, bufSize, *length))
4394 {
4395 return false;
4396 }
4397
4398 return true;
4399}
4400
Geoff Lang0b031062016-10-13 14:30:04 -04004401bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4402 GLuint index,
4403 GLenum pname,
4404 GLsizei bufSize,
4405 GLsizei *length,
4406 void **pointer)
4407{
4408 if (!ValidateRobustEntryPoint(context, bufSize))
4409 {
4410 return false;
4411 }
4412
4413 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4414 {
4415 return false;
4416 }
4417
4418 if (!ValidateRobustBufferSize(context, bufSize, *length))
4419 {
4420 return false;
4421 }
4422
4423 return true;
4424}
4425
Geoff Lang0b031062016-10-13 14:30:04 -04004426bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4427 GLuint index,
4428 GLenum pname,
4429 GLsizei bufSize,
4430 GLsizei *length,
4431 GLint *params)
4432{
4433 if (!ValidateRobustEntryPoint(context, bufSize))
4434 {
4435 return false;
4436 }
4437
4438 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4439 {
4440 return false;
4441 }
4442
4443 if (!ValidateRobustBufferSize(context, bufSize, *length))
4444 {
4445 return false;
4446 }
4447
4448 return true;
4449}
4450
Geoff Lang0b031062016-10-13 14:30:04 -04004451bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4452 GLuint index,
4453 GLenum pname,
4454 GLsizei bufSize,
4455 GLsizei *length,
4456 GLuint *params)
4457{
4458 if (!ValidateRobustEntryPoint(context, bufSize))
4459 {
4460 return false;
4461 }
4462
4463 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4464 {
4465 return false;
4466 }
4467
4468 if (!ValidateRobustBufferSize(context, bufSize, *length))
4469 {
4470 return false;
4471 }
4472
4473 return true;
4474}
4475
Geoff Lang6899b872016-10-14 11:30:13 -04004476bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4477 GLuint program,
4478 GLuint uniformBlockIndex,
4479 GLenum pname,
4480 GLsizei bufSize,
4481 GLsizei *length,
4482 GLint *params)
4483{
4484 if (!ValidateRobustEntryPoint(context, bufSize))
4485 {
4486 return false;
4487 }
4488
4489 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4490 {
4491 return false;
4492 }
4493
4494 if (!ValidateRobustBufferSize(context, bufSize, *length))
4495 {
4496 return false;
4497 }
4498
4499 return true;
4500}
4501
Geoff Lang0a9661f2016-10-20 10:59:20 -07004502bool ValidateGetInternalFormativRobustANGLE(Context *context,
4503 GLenum target,
4504 GLenum internalformat,
4505 GLenum pname,
4506 GLsizei bufSize,
4507 GLsizei *length,
4508 GLint *params)
4509{
4510 if (!ValidateRobustEntryPoint(context, bufSize))
4511 {
4512 return false;
4513 }
4514
4515 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4516 {
4517 return false;
4518 }
4519
4520 if (!ValidateRobustBufferSize(context, bufSize, *length))
4521 {
4522 return false;
4523 }
4524
4525 return true;
4526}
4527
Shao80957d92017-02-20 21:25:59 +08004528bool ValidateVertexFormatBase(ValidationContext *context,
4529 GLuint attribIndex,
4530 GLint size,
4531 GLenum type,
4532 GLboolean pureInteger)
4533{
4534 const Caps &caps = context->getCaps();
4535 if (attribIndex >= caps.maxVertexAttributes)
4536 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004537 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004538 return false;
4539 }
4540
4541 if (size < 1 || size > 4)
4542 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004543 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004544 return false;
Shao80957d92017-02-20 21:25:59 +08004545 }
4546
4547 switch (type)
4548 {
4549 case GL_BYTE:
4550 case GL_UNSIGNED_BYTE:
4551 case GL_SHORT:
4552 case GL_UNSIGNED_SHORT:
4553 break;
4554
4555 case GL_INT:
4556 case GL_UNSIGNED_INT:
4557 if (context->getClientMajorVersion() < 3)
4558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004559 context->handleError(InvalidEnum()
4560 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004561 return false;
4562 }
4563 break;
4564
4565 case GL_FIXED:
4566 case GL_FLOAT:
4567 if (pureInteger)
4568 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004569 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004570 return false;
4571 }
4572 break;
4573
4574 case GL_HALF_FLOAT:
4575 if (context->getClientMajorVersion() < 3)
4576 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004577 context->handleError(InvalidEnum()
4578 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004579 return false;
4580 }
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_INT_2_10_10_10_REV:
4589 case GL_UNSIGNED_INT_2_10_10_10_REV:
4590 if (context->getClientMajorVersion() < 3)
4591 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004592 context->handleError(InvalidEnum()
4593 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004594 return false;
4595 }
4596 if (pureInteger)
4597 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004598 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004599 return false;
4600 }
4601 if (size != 4)
4602 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004603 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4604 "UNSIGNED_INT_2_10_10_10_REV and "
4605 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004606 return false;
4607 }
4608 break;
4609
4610 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004611 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004612 return false;
4613 }
4614
4615 return true;
4616}
4617
Geoff Lang76e65652017-03-27 14:58:02 -04004618// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4619// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4620// specified clear value and the type of a buffer that is being cleared generates an
4621// INVALID_OPERATION error instead of producing undefined results
4622bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4623 GLint drawbuffer,
4624 const GLenum *validComponentTypes,
4625 size_t validComponentTypeCount)
4626{
4627 const FramebufferAttachment *attachment =
4628 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4629 if (attachment)
4630 {
4631 GLenum componentType = attachment->getFormat().info->componentType;
4632 const GLenum *end = validComponentTypes + validComponentTypeCount;
4633 if (std::find(validComponentTypes, end, componentType) == end)
4634 {
4635 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004636 InvalidOperation()
4637 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004638 return false;
4639 }
4640 }
4641
4642 return true;
4643}
4644
Corentin Wallezb2931602017-04-11 15:58:57 -04004645bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4646 GLsizei imageSize,
4647 GLsizei dataSize)
4648{
4649 if (!ValidateRobustEntryPoint(context, dataSize))
4650 {
4651 return false;
4652 }
4653
Corentin Wallez336129f2017-10-17 15:55:40 -04004654 gl::Buffer *pixelUnpackBuffer =
4655 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004656 if (pixelUnpackBuffer == nullptr)
4657 {
4658 if (dataSize < imageSize)
4659 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004660 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004661 }
4662 }
4663 return true;
4664}
4665
Jamie Madillbe849e42017-05-02 15:49:00 -04004666bool ValidateGetBufferParameterBase(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004667 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004668 GLenum pname,
4669 bool pointerVersion,
4670 GLsizei *numParams)
4671{
4672 if (numParams)
4673 {
4674 *numParams = 0;
4675 }
4676
Corentin Walleze4477002017-12-01 14:39:58 -05004677 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004678 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004679 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004680 return false;
4681 }
4682
4683 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4684 if (!buffer)
4685 {
4686 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004687 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004688 return false;
4689 }
4690
4691 const Extensions &extensions = context->getExtensions();
4692
4693 switch (pname)
4694 {
4695 case GL_BUFFER_USAGE:
4696 case GL_BUFFER_SIZE:
4697 break;
4698
4699 case GL_BUFFER_ACCESS_OES:
4700 if (!extensions.mapBuffer)
4701 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004702 context->handleError(InvalidEnum()
4703 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004704 return false;
4705 }
4706 break;
4707
4708 case GL_BUFFER_MAPPED:
4709 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4710 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4711 !extensions.mapBufferRange)
4712 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004713 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4714 "GL_OES_mapbuffer or "
4715 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004716 return false;
4717 }
4718 break;
4719
4720 case GL_BUFFER_MAP_POINTER:
4721 if (!pointerVersion)
4722 {
4723 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004724 InvalidEnum()
4725 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004726 return false;
4727 }
4728 break;
4729
4730 case GL_BUFFER_ACCESS_FLAGS:
4731 case GL_BUFFER_MAP_OFFSET:
4732 case GL_BUFFER_MAP_LENGTH:
4733 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4734 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004735 context->handleError(InvalidEnum()
4736 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004737 return false;
4738 }
4739 break;
4740
4741 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004742 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004743 return false;
4744 }
4745
4746 // All buffer parameter queries return one value.
4747 if (numParams)
4748 {
4749 *numParams = 1;
4750 }
4751
4752 return true;
4753}
4754
4755bool ValidateGetRenderbufferParameterivBase(Context *context,
4756 GLenum target,
4757 GLenum pname,
4758 GLsizei *length)
4759{
4760 if (length)
4761 {
4762 *length = 0;
4763 }
4764
4765 if (target != GL_RENDERBUFFER)
4766 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004767 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004768 return false;
4769 }
4770
4771 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4772 if (renderbuffer == nullptr)
4773 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004774 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004775 return false;
4776 }
4777
4778 switch (pname)
4779 {
4780 case GL_RENDERBUFFER_WIDTH:
4781 case GL_RENDERBUFFER_HEIGHT:
4782 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4783 case GL_RENDERBUFFER_RED_SIZE:
4784 case GL_RENDERBUFFER_GREEN_SIZE:
4785 case GL_RENDERBUFFER_BLUE_SIZE:
4786 case GL_RENDERBUFFER_ALPHA_SIZE:
4787 case GL_RENDERBUFFER_DEPTH_SIZE:
4788 case GL_RENDERBUFFER_STENCIL_SIZE:
4789 break;
4790
4791 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4792 if (!context->getExtensions().framebufferMultisample)
4793 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004794 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004795 return false;
4796 }
4797 break;
4798
4799 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004800 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004801 return false;
4802 }
4803
4804 if (length)
4805 {
4806 *length = 1;
4807 }
4808 return true;
4809}
4810
4811bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4812{
4813 if (length)
4814 {
4815 *length = 0;
4816 }
4817
4818 if (GetValidShader(context, shader) == nullptr)
4819 {
4820 return false;
4821 }
4822
4823 switch (pname)
4824 {
4825 case GL_SHADER_TYPE:
4826 case GL_DELETE_STATUS:
4827 case GL_COMPILE_STATUS:
4828 case GL_INFO_LOG_LENGTH:
4829 case GL_SHADER_SOURCE_LENGTH:
4830 break;
4831
4832 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4833 if (!context->getExtensions().translatedShaderSource)
4834 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004835 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004836 return false;
4837 }
4838 break;
4839
4840 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004841 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004842 return false;
4843 }
4844
4845 if (length)
4846 {
4847 *length = 1;
4848 }
4849 return true;
4850}
4851
4852bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4853{
4854 if (length)
4855 {
4856 *length = 0;
4857 }
4858
4859 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4860 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004861 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004862 return false;
4863 }
4864
4865 if (context->getTargetTexture(target) == nullptr)
4866 {
4867 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004868 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004869 return false;
4870 }
4871
4872 switch (pname)
4873 {
4874 case GL_TEXTURE_MAG_FILTER:
4875 case GL_TEXTURE_MIN_FILTER:
4876 case GL_TEXTURE_WRAP_S:
4877 case GL_TEXTURE_WRAP_T:
4878 break;
4879
4880 case GL_TEXTURE_USAGE_ANGLE:
4881 if (!context->getExtensions().textureUsage)
4882 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004883 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004884 return false;
4885 }
4886 break;
4887
4888 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4889 if (!context->getExtensions().textureFilterAnisotropic)
4890 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004891 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004892 return false;
4893 }
4894 break;
4895
4896 case GL_TEXTURE_IMMUTABLE_FORMAT:
4897 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4898 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004899 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004900 return false;
4901 }
4902 break;
4903
4904 case GL_TEXTURE_WRAP_R:
4905 case GL_TEXTURE_IMMUTABLE_LEVELS:
4906 case GL_TEXTURE_SWIZZLE_R:
4907 case GL_TEXTURE_SWIZZLE_G:
4908 case GL_TEXTURE_SWIZZLE_B:
4909 case GL_TEXTURE_SWIZZLE_A:
4910 case GL_TEXTURE_BASE_LEVEL:
4911 case GL_TEXTURE_MAX_LEVEL:
4912 case GL_TEXTURE_MIN_LOD:
4913 case GL_TEXTURE_MAX_LOD:
4914 case GL_TEXTURE_COMPARE_MODE:
4915 case GL_TEXTURE_COMPARE_FUNC:
4916 if (context->getClientMajorVersion() < 3)
4917 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004918 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004919 return false;
4920 }
4921 break;
4922
4923 case GL_TEXTURE_SRGB_DECODE_EXT:
4924 if (!context->getExtensions().textureSRGBDecode)
4925 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004926 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004927 return false;
4928 }
4929 break;
4930
4931 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004932 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004933 return false;
4934 }
4935
4936 if (length)
4937 {
4938 *length = 1;
4939 }
4940 return true;
4941}
4942
4943bool ValidateGetVertexAttribBase(Context *context,
4944 GLuint index,
4945 GLenum pname,
4946 GLsizei *length,
4947 bool pointer,
4948 bool pureIntegerEntryPoint)
4949{
4950 if (length)
4951 {
4952 *length = 0;
4953 }
4954
4955 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
4956 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004957 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004958 return false;
4959 }
4960
4961 if (index >= context->getCaps().maxVertexAttributes)
4962 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004963 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04004964 return false;
4965 }
4966
4967 if (pointer)
4968 {
4969 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
4970 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004971 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004972 return false;
4973 }
4974 }
4975 else
4976 {
4977 switch (pname)
4978 {
4979 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4980 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4981 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4982 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4983 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4984 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
4985 case GL_CURRENT_VERTEX_ATTRIB:
4986 break;
4987
4988 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
4989 static_assert(
4990 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
4991 "ANGLE extension enums not equal to GL enums.");
4992 if (context->getClientMajorVersion() < 3 &&
4993 !context->getExtensions().instancedArrays)
4994 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004995 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
4996 "requires OpenGL ES 3.0 or "
4997 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004998 return false;
4999 }
5000 break;
5001
5002 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5003 if (context->getClientMajorVersion() < 3)
5004 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005005 context->handleError(
5006 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005007 return false;
5008 }
5009 break;
5010
5011 case GL_VERTEX_ATTRIB_BINDING:
5012 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5013 if (context->getClientVersion() < ES_3_1)
5014 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005015 context->handleError(InvalidEnum()
5016 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005017 return false;
5018 }
5019 break;
5020
5021 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005022 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005023 return false;
5024 }
5025 }
5026
5027 if (length)
5028 {
5029 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5030 {
5031 *length = 4;
5032 }
5033 else
5034 {
5035 *length = 1;
5036 }
5037 }
5038
5039 return true;
5040}
5041
Jamie Madill4928b7c2017-06-20 12:57:39 -04005042bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005043 GLint x,
5044 GLint y,
5045 GLsizei width,
5046 GLsizei height,
5047 GLenum format,
5048 GLenum type,
5049 GLsizei bufSize,
5050 GLsizei *length,
5051 GLsizei *columns,
5052 GLsizei *rows,
5053 void *pixels)
5054{
5055 if (length != nullptr)
5056 {
5057 *length = 0;
5058 }
5059 if (rows != nullptr)
5060 {
5061 *rows = 0;
5062 }
5063 if (columns != nullptr)
5064 {
5065 *columns = 0;
5066 }
5067
5068 if (width < 0 || height < 0)
5069 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005070 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005071 return false;
5072 }
5073
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005074 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005075
5076 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5077 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005078 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005079 return false;
5080 }
5081
5082 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5083 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005084 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005085 return false;
5086 }
5087
5088 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5089 ASSERT(framebuffer);
5090
5091 if (framebuffer->getReadBufferState() == GL_NONE)
5092 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005093 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005094 return false;
5095 }
5096
5097 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5098 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5099 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5100 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5101 // situation is an application error that would lead to a crash in ANGLE.
5102 if (readBuffer == nullptr)
5103 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005104 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005105 return false;
5106 }
5107
Martin Radev28031682017-07-28 14:47:56 +03005108 // ANGLE_multiview, Revision 1:
5109 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5110 // current read framebuffer is not NONE.
5111 if (readBuffer->getMultiviewLayout() != GL_NONE)
5112 {
5113 context->handleError(InvalidFramebufferOperation()
5114 << "Attempting to read from a multi-view framebuffer.");
5115 return false;
5116 }
5117
Geoff Lang280ba992017-04-18 16:30:58 -04005118 if (context->getExtensions().webglCompatibility)
5119 {
5120 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5121 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5122 // and type before validating the combination of format and type. However, the
5123 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5124 // verifies that GL_INVALID_OPERATION is generated.
5125 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5126 // dEQP/WebGL.
5127 if (!ValidReadPixelsFormatEnum(context, format))
5128 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005129 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005130 return false;
5131 }
5132
5133 if (!ValidReadPixelsTypeEnum(context, type))
5134 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005135 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005136 return false;
5137 }
5138 }
5139
Jamie Madill4928b7c2017-06-20 12:57:39 -04005140 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5141 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005142 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5143
5144 bool validFormatTypeCombination =
5145 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5146
5147 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5148 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005149 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005150 return false;
5151 }
5152
5153 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005154 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005155 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5156 {
5157 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005158 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005159 return false;
5160 }
5161
5162 // .. the data would be packed to the buffer object such that the memory writes required
5163 // would exceed the data store size.
5164 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5165 const gl::Extents size(width, height, 1);
5166 const auto &pack = context->getGLState().getPackState();
5167
5168 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5169 if (endByteOrErr.isError())
5170 {
5171 context->handleError(endByteOrErr.getError());
5172 return false;
5173 }
5174
5175 size_t endByte = endByteOrErr.getResult();
5176 if (bufSize >= 0)
5177 {
5178 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5179 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005180 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005181 return false;
5182 }
5183 }
5184
5185 if (pixelPackBuffer != nullptr)
5186 {
5187 CheckedNumeric<size_t> checkedEndByte(endByte);
5188 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5189 checkedEndByte += checkedOffset;
5190
5191 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5192 {
5193 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005194 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005195 return false;
5196 }
5197 }
5198
5199 if (pixelPackBuffer == nullptr && length != nullptr)
5200 {
5201 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5202 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005203 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005204 return false;
5205 }
5206
5207 *length = static_cast<GLsizei>(endByte);
5208 }
5209
5210 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5211 angle::CheckedNumeric<int> clippedExtent(length);
5212 if (start < 0)
5213 {
5214 // "subtract" the area that is less than 0
5215 clippedExtent += start;
5216 }
5217
5218 const int readExtent = start + length;
5219 if (readExtent > bufferSize)
5220 {
5221 // Subtract the region to the right of the read buffer
5222 clippedExtent -= (readExtent - bufferSize);
5223 }
5224
5225 if (!clippedExtent.IsValid())
5226 {
5227 return 0;
5228 }
5229
5230 return std::max(clippedExtent.ValueOrDie(), 0);
5231 };
5232
5233 if (columns != nullptr)
5234 {
5235 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5236 }
5237
5238 if (rows != nullptr)
5239 {
5240 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5241 }
5242
5243 return true;
5244}
5245
5246template <typename ParamType>
5247bool ValidateTexParameterBase(Context *context,
5248 GLenum target,
5249 GLenum pname,
5250 GLsizei bufSize,
5251 const ParamType *params)
5252{
5253 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5254 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005255 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005256 return false;
5257 }
5258
5259 if (context->getTargetTexture(target) == nullptr)
5260 {
5261 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005262 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005263 return false;
5264 }
5265
5266 const GLsizei minBufSize = 1;
5267 if (bufSize >= 0 && bufSize < minBufSize)
5268 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005269 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005270 return false;
5271 }
5272
5273 switch (pname)
5274 {
5275 case GL_TEXTURE_WRAP_R:
5276 case GL_TEXTURE_SWIZZLE_R:
5277 case GL_TEXTURE_SWIZZLE_G:
5278 case GL_TEXTURE_SWIZZLE_B:
5279 case GL_TEXTURE_SWIZZLE_A:
5280 case GL_TEXTURE_BASE_LEVEL:
5281 case GL_TEXTURE_MAX_LEVEL:
5282 case GL_TEXTURE_COMPARE_MODE:
5283 case GL_TEXTURE_COMPARE_FUNC:
5284 case GL_TEXTURE_MIN_LOD:
5285 case GL_TEXTURE_MAX_LOD:
5286 if (context->getClientMajorVersion() < 3)
5287 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005288 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005289 return false;
5290 }
5291 if (target == GL_TEXTURE_EXTERNAL_OES &&
5292 !context->getExtensions().eglImageExternalEssl3)
5293 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005294 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5295 "available without "
5296 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005297 return false;
5298 }
5299 break;
5300
5301 default:
5302 break;
5303 }
5304
JiangYizhou4cff8d62017-07-06 14:54:09 +08005305 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5306 {
5307 switch (pname)
5308 {
5309 case GL_TEXTURE_MIN_FILTER:
5310 case GL_TEXTURE_MAG_FILTER:
5311 case GL_TEXTURE_WRAP_S:
5312 case GL_TEXTURE_WRAP_T:
5313 case GL_TEXTURE_WRAP_R:
5314 case GL_TEXTURE_MIN_LOD:
5315 case GL_TEXTURE_MAX_LOD:
5316 case GL_TEXTURE_COMPARE_MODE:
5317 case GL_TEXTURE_COMPARE_FUNC:
5318 context->handleError(InvalidEnum()
5319 << "Invalid parameter for 2D multisampled textures.");
5320 return false;
5321 }
5322 }
5323
Jamie Madillbe849e42017-05-02 15:49:00 -04005324 switch (pname)
5325 {
5326 case GL_TEXTURE_WRAP_S:
5327 case GL_TEXTURE_WRAP_T:
5328 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005329 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005330 bool restrictedWrapModes =
5331 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5332 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5333 {
5334 return false;
5335 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005336 }
5337 break;
5338
5339 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005340 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005341 bool restrictedMinFilter =
5342 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5343 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5344 {
5345 return false;
5346 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005347 }
5348 break;
5349
5350 case GL_TEXTURE_MAG_FILTER:
5351 if (!ValidateTextureMagFilterValue(context, params))
5352 {
5353 return false;
5354 }
5355 break;
5356
5357 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005358 if (!context->getExtensions().textureUsage)
5359 {
5360 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5361 return false;
5362 }
5363
Jamie Madillbe849e42017-05-02 15:49:00 -04005364 switch (ConvertToGLenum(params[0]))
5365 {
5366 case GL_NONE:
5367 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5368 break;
5369
5370 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005371 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005372 return false;
5373 }
5374 break;
5375
5376 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5377 if (!context->getExtensions().textureFilterAnisotropic)
5378 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005379 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005380 return false;
5381 }
5382
5383 // we assume the parameter passed to this validation method is truncated, not rounded
5384 if (params[0] < 1)
5385 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005386 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005387 return false;
5388 }
5389 break;
5390
5391 case GL_TEXTURE_MIN_LOD:
5392 case GL_TEXTURE_MAX_LOD:
5393 // any value is permissible
5394 break;
5395
5396 case GL_TEXTURE_COMPARE_MODE:
5397 if (!ValidateTextureCompareModeValue(context, params))
5398 {
5399 return false;
5400 }
5401 break;
5402
5403 case GL_TEXTURE_COMPARE_FUNC:
5404 if (!ValidateTextureCompareFuncValue(context, params))
5405 {
5406 return false;
5407 }
5408 break;
5409
5410 case GL_TEXTURE_SWIZZLE_R:
5411 case GL_TEXTURE_SWIZZLE_G:
5412 case GL_TEXTURE_SWIZZLE_B:
5413 case GL_TEXTURE_SWIZZLE_A:
5414 switch (ConvertToGLenum(params[0]))
5415 {
5416 case GL_RED:
5417 case GL_GREEN:
5418 case GL_BLUE:
5419 case GL_ALPHA:
5420 case GL_ZERO:
5421 case GL_ONE:
5422 break;
5423
5424 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005425 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005426 return false;
5427 }
5428 break;
5429
5430 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005431 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005432 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005433 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005434 return false;
5435 }
5436 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5437 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005438 context->handleError(InvalidOperation()
5439 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005440 return false;
5441 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005442 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5443 {
5444 context->handleError(InvalidOperation()
5445 << "Base level must be 0 for multisampled textures.");
5446 return false;
5447 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005448 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5449 {
5450 context->handleError(InvalidOperation()
5451 << "Base level must be 0 for rectangle textures.");
5452 return false;
5453 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005454 break;
5455
5456 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005457 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005458 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005459 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005460 return false;
5461 }
5462 break;
5463
5464 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5465 if (context->getClientVersion() < Version(3, 1))
5466 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005467 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005468 return false;
5469 }
5470 switch (ConvertToGLenum(params[0]))
5471 {
5472 case GL_DEPTH_COMPONENT:
5473 case GL_STENCIL_INDEX:
5474 break;
5475
5476 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005477 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005478 return false;
5479 }
5480 break;
5481
5482 case GL_TEXTURE_SRGB_DECODE_EXT:
5483 if (!ValidateTextureSRGBDecodeValue(context, params))
5484 {
5485 return false;
5486 }
5487 break;
5488
5489 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005490 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005491 return false;
5492 }
5493
5494 return true;
5495}
5496
5497template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5498template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5499
Jamie Madill12e957f2017-08-26 21:42:26 -04005500bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5501{
5502 if (index >= MAX_VERTEX_ATTRIBS)
5503 {
5504 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5505 return false;
5506 }
5507
5508 return true;
5509}
5510
5511bool ValidateGetActiveUniformBlockivBase(Context *context,
5512 GLuint program,
5513 GLuint uniformBlockIndex,
5514 GLenum pname,
5515 GLsizei *length)
5516{
5517 if (length)
5518 {
5519 *length = 0;
5520 }
5521
5522 if (context->getClientMajorVersion() < 3)
5523 {
5524 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5525 return false;
5526 }
5527
5528 Program *programObject = GetValidProgram(context, program);
5529 if (!programObject)
5530 {
5531 return false;
5532 }
5533
5534 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5535 {
5536 context->handleError(InvalidValue()
5537 << "uniformBlockIndex exceeds active uniform block count.");
5538 return false;
5539 }
5540
5541 switch (pname)
5542 {
5543 case GL_UNIFORM_BLOCK_BINDING:
5544 case GL_UNIFORM_BLOCK_DATA_SIZE:
5545 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5546 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5547 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5548 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5549 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5550 break;
5551
5552 default:
5553 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5554 return false;
5555 }
5556
5557 if (length)
5558 {
5559 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5560 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005561 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005562 programObject->getUniformBlockByIndex(uniformBlockIndex);
5563 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5564 }
5565 else
5566 {
5567 *length = 1;
5568 }
5569 }
5570
5571 return true;
5572}
5573
Jamie Madill9696d072017-08-26 23:19:57 -04005574template <typename ParamType>
5575bool ValidateSamplerParameterBase(Context *context,
5576 GLuint sampler,
5577 GLenum pname,
5578 GLsizei bufSize,
5579 ParamType *params)
5580{
5581 if (context->getClientMajorVersion() < 3)
5582 {
5583 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5584 return false;
5585 }
5586
5587 if (!context->isSampler(sampler))
5588 {
5589 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5590 return false;
5591 }
5592
5593 const GLsizei minBufSize = 1;
5594 if (bufSize >= 0 && bufSize < minBufSize)
5595 {
5596 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5597 return false;
5598 }
5599
5600 switch (pname)
5601 {
5602 case GL_TEXTURE_WRAP_S:
5603 case GL_TEXTURE_WRAP_T:
5604 case GL_TEXTURE_WRAP_R:
5605 if (!ValidateTextureWrapModeValue(context, params, false))
5606 {
5607 return false;
5608 }
5609 break;
5610
5611 case GL_TEXTURE_MIN_FILTER:
5612 if (!ValidateTextureMinFilterValue(context, params, false))
5613 {
5614 return false;
5615 }
5616 break;
5617
5618 case GL_TEXTURE_MAG_FILTER:
5619 if (!ValidateTextureMagFilterValue(context, params))
5620 {
5621 return false;
5622 }
5623 break;
5624
5625 case GL_TEXTURE_MIN_LOD:
5626 case GL_TEXTURE_MAX_LOD:
5627 // any value is permissible
5628 break;
5629
5630 case GL_TEXTURE_COMPARE_MODE:
5631 if (!ValidateTextureCompareModeValue(context, params))
5632 {
5633 return false;
5634 }
5635 break;
5636
5637 case GL_TEXTURE_COMPARE_FUNC:
5638 if (!ValidateTextureCompareFuncValue(context, params))
5639 {
5640 return false;
5641 }
5642 break;
5643
5644 case GL_TEXTURE_SRGB_DECODE_EXT:
5645 if (!ValidateTextureSRGBDecodeValue(context, params))
5646 {
5647 return false;
5648 }
5649 break;
5650
5651 default:
5652 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5653 return false;
5654 }
5655
5656 return true;
5657}
5658
5659template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5660template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5661
5662bool ValidateGetSamplerParameterBase(Context *context,
5663 GLuint sampler,
5664 GLenum pname,
5665 GLsizei *length)
5666{
5667 if (length)
5668 {
5669 *length = 0;
5670 }
5671
5672 if (context->getClientMajorVersion() < 3)
5673 {
5674 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5675 return false;
5676 }
5677
5678 if (!context->isSampler(sampler))
5679 {
5680 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5681 return false;
5682 }
5683
5684 switch (pname)
5685 {
5686 case GL_TEXTURE_WRAP_S:
5687 case GL_TEXTURE_WRAP_T:
5688 case GL_TEXTURE_WRAP_R:
5689 case GL_TEXTURE_MIN_FILTER:
5690 case GL_TEXTURE_MAG_FILTER:
5691 case GL_TEXTURE_MIN_LOD:
5692 case GL_TEXTURE_MAX_LOD:
5693 case GL_TEXTURE_COMPARE_MODE:
5694 case GL_TEXTURE_COMPARE_FUNC:
5695 break;
5696
5697 case GL_TEXTURE_SRGB_DECODE_EXT:
5698 if (!context->getExtensions().textureSRGBDecode)
5699 {
5700 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5701 return false;
5702 }
5703 break;
5704
5705 default:
5706 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5707 return false;
5708 }
5709
5710 if (length)
5711 {
5712 *length = 1;
5713 }
5714 return true;
5715}
5716
5717bool ValidateGetInternalFormativBase(Context *context,
5718 GLenum target,
5719 GLenum internalformat,
5720 GLenum pname,
5721 GLsizei bufSize,
5722 GLsizei *numParams)
5723{
5724 if (numParams)
5725 {
5726 *numParams = 0;
5727 }
5728
5729 if (context->getClientMajorVersion() < 3)
5730 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005731 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005732 return false;
5733 }
5734
5735 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5736 if (!formatCaps.renderable)
5737 {
5738 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5739 return false;
5740 }
5741
5742 switch (target)
5743 {
5744 case GL_RENDERBUFFER:
5745 break;
5746
5747 case GL_TEXTURE_2D_MULTISAMPLE:
5748 if (context->getClientVersion() < ES_3_1)
5749 {
5750 context->handleError(InvalidOperation()
5751 << "Texture target requires at least OpenGL ES 3.1.");
5752 return false;
5753 }
5754 break;
5755
5756 default:
5757 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5758 return false;
5759 }
5760
5761 if (bufSize < 0)
5762 {
5763 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5764 return false;
5765 }
5766
5767 GLsizei maxWriteParams = 0;
5768 switch (pname)
5769 {
5770 case GL_NUM_SAMPLE_COUNTS:
5771 maxWriteParams = 1;
5772 break;
5773
5774 case GL_SAMPLES:
5775 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5776 break;
5777
5778 default:
5779 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5780 return false;
5781 }
5782
5783 if (numParams)
5784 {
5785 // glGetInternalFormativ will not overflow bufSize
5786 *numParams = std::min(bufSize, maxWriteParams);
5787 }
5788
5789 return true;
5790}
5791
Jamie Madillc29968b2016-01-20 11:17:23 -05005792} // namespace gl