blob: f4e64b752864b5821743b5b8d1bafca97f782f4c [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.
Yunchao Heece12532017-11-21 15:50:21 +08002508 if (!program->hasLinkedVertexShader() || !program->hasLinkedFragmentShader())
Yunchao Hecddcb592017-11-13 15:27:35 +08002509 {
2510 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2511 "vertex shader stage or fragment shader stage.");
2512 return false;
2513 }
2514
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002515 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002516 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002517 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002518 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002519 }
2520
Martin Radevffe754b2017-07-31 10:38:07 +03002521 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002522 {
Martin Radevda8e2572017-09-12 17:21:16 +03002523 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002524 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002525 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002526 {
2527 context->handleError(InvalidOperation() << "The number of views in the active program "
2528 "and draw framebuffer does not match.");
2529 return false;
2530 }
Martin Radev7e69f762017-07-27 14:54:13 +03002531
2532 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2533 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2534 framebufferNumViews > 1)
2535 {
2536 context->handleError(InvalidOperation()
2537 << "There is an active transform feedback object "
2538 "when the number of views in the active draw "
2539 "framebuffer is greater than 1.");
2540 return false;
2541 }
Martin Radevffe754b2017-07-31 10:38:07 +03002542
2543 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2544 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2545 {
2546 context->handleError(InvalidOperation() << "There is an active query for target "
2547 "GL_TIME_ELAPSED_EXT when the number of "
2548 "views in the active draw framebuffer is "
2549 "greater than 1.");
2550 return false;
2551 }
Martin Radev7cf61662017-07-26 17:10:53 +03002552 }
2553
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002554 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002555 for (unsigned int uniformBlockIndex = 0;
2556 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002557 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002558 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002559 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002560 const OffsetBindingPointer<Buffer> &uniformBuffer =
2561 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002562
Geoff Lang5d124a62015-09-15 13:03:27 -04002563 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002564 {
2565 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002566 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002567 InvalidOperation()
2568 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002569 return false;
2570 }
2571
Geoff Lang5d124a62015-09-15 13:03:27 -04002572 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002573 if (uniformBufferSize == 0)
2574 {
2575 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002576 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002577 }
2578
Jamie Madill62d31cb2015-09-11 13:25:51 -04002579 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002580 {
2581 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002582 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002583 InvalidOperation()
2584 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002585 return false;
2586 }
2587 }
2588
Geoff Lange0cff192017-05-30 13:04:56 -04002589 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002590 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002591 {
Geoff Lange0cff192017-05-30 13:04:56 -04002592 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002593 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2594 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002595 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002596 return false;
2597 }
Geoff Lange0cff192017-05-30 13:04:56 -04002598
Geoff Lang9ab5b822017-05-30 16:19:23 -04002599 // Detect that the vertex shader input types match the attribute types
2600 if (!ValidateVertexShaderAttributeTypeMatch(context))
2601 {
2602 return false;
2603 }
2604
Geoff Lange0cff192017-05-30 13:04:56 -04002605 // Detect that the color buffer types match the fragment shader output types
2606 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2607 {
2608 return false;
2609 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002610 }
2611
Jamie Madill250d33f2014-06-06 17:09:03 -04002612 // No-op if zero count
2613 return (count > 0);
2614}
2615
Jamie Madillc1d770e2017-04-13 17:31:24 -04002616bool ValidateDrawArraysCommon(ValidationContext *context,
2617 GLenum mode,
2618 GLint first,
2619 GLsizei count,
2620 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002621{
Jamie Madillfd716582014-06-06 17:09:04 -04002622 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002623 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002624 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002625 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002626 }
2627
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002628 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002629 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002630 if (curTransformFeedback && curTransformFeedback->isActive() &&
2631 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002632 {
2633 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002634 // that does not match the current transform feedback object's draw mode (if transform
2635 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002636 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002637 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002638 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002639 }
2640
Jiajia Qind9671222016-11-29 16:30:31 +08002641 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002642 {
2643 return false;
2644 }
2645
Corentin Wallez71168a02016-12-19 15:11:18 -08002646 // Check the computation of maxVertex doesn't overflow.
2647 // - first < 0 or count < 0 have been checked as an error condition
2648 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2649 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2650 ASSERT(count > 0 && first >= 0);
2651 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2652 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002653 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002654 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002655 return false;
2656 }
2657
Corentin Wallez71168a02016-12-19 15:11:18 -08002658 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002659 {
2660 return false;
2661 }
2662
2663 return true;
2664}
2665
He Yunchaoced53ae2016-11-29 15:00:51 +08002666bool ValidateDrawArraysInstancedANGLE(Context *context,
2667 GLenum mode,
2668 GLint first,
2669 GLsizei count,
2670 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002671{
Geoff Lang63c5a592017-09-27 14:08:16 -04002672 if (!context->getExtensions().instancedArrays)
2673 {
2674 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2675 return false;
2676 }
2677
Corentin Wallez170efbf2017-05-02 13:45:01 -04002678 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002679 {
2680 return false;
2681 }
2682
Corentin Wallez0dc97812017-06-22 14:38:44 -04002683 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002684}
2685
Jiajia Qind9671222016-11-29 16:30:31 +08002686bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002687{
Jamie Madill250d33f2014-06-06 17:09:03 -04002688 switch (type)
2689 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002690 case GL_UNSIGNED_BYTE:
2691 case GL_UNSIGNED_SHORT:
2692 break;
2693 case GL_UNSIGNED_INT:
2694 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2695 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002696 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002697 return false;
2698 }
2699 break;
2700 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002701 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002702 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002703 }
2704
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002705 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002706
2707 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002708 if (curTransformFeedback && curTransformFeedback->isActive() &&
2709 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002710 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002711 // It is an invalid operation to call DrawElements, DrawRangeElements or
2712 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002713 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002714 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002715 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002716 }
2717
Jiajia Qind9671222016-11-29 16:30:31 +08002718 return true;
2719}
2720
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002721bool ValidateDrawElementsCommon(ValidationContext *context,
2722 GLenum mode,
2723 GLsizei count,
2724 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002725 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002726 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002727{
2728 if (!ValidateDrawElementsBase(context, type))
2729 return false;
2730
2731 const State &state = context->getGLState();
2732
Corentin Wallez170efbf2017-05-02 13:45:01 -04002733 if (!ValidateDrawBase(context, mode, count))
2734 {
2735 return false;
2736 }
2737
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002738 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2739 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2740 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2741 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002742 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002743 // Check for mapped buffers
2744 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002745 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002746 {
2747 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2748 return false;
2749 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002750 }
2751
He Yunchaoced53ae2016-11-29 15:00:51 +08002752 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002753 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002754
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002755 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2756
2757 if (context->getExtensions().webglCompatibility)
2758 {
2759 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2760 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2761 {
2762 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2763 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2764 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002765 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002766 return false;
2767 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002768
2769 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2770 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2771 // error is generated.
2772 if (reinterpret_cast<intptr_t>(indices) < 0)
2773 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002774 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002775 return false;
2776 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002777 }
2778
2779 if (context->getExtensions().webglCompatibility ||
2780 !context->getGLState().areClientArraysEnabled())
2781 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002782 if (!elementArrayBuffer && count > 0)
2783 {
2784 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2785 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2786 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002787 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002788 return false;
2789 }
2790 }
2791
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002792 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002793 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002794 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002795 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002796 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2797 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2798 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2799 constexpr uint64_t kMaxTypeSize = 8;
2800 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2801 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2802 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002803
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002804 uint64_t typeSize = typeBytes;
2805 uint64_t elementCount = static_cast<uint64_t>(count);
2806 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2807
2808 // Doing the multiplication here is overflow-safe
2809 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2810
2811 // The offset can be any value, check for overflows
2812 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2813 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002814 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002815 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002816 return false;
2817 }
2818
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002819 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2820 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002821 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002822 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002823 return false;
2824 }
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002825
Corentin Wallez487653b2017-09-01 17:17:55 -04002826 ASSERT(isPow2(typeSize) && typeSize > 0);
2827 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002828 {
2829 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
2830 return false;
2831 }
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002832 }
2833 else if (!indices)
2834 {
2835 // This is an application error that would normally result in a crash,
2836 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002837 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04002838 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002839 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002840 }
2841
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002842 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002843 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002844 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2845 // access is enabled.
2846 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2847 {
2848 return false;
2849 }
2850 }
2851 else
2852 {
2853 // Use the parameter buffer to retrieve and cache the index range.
2854 const auto &params = context->getParams<HasIndexRange>();
2855 const auto &indexRangeOpt = params.getIndexRange();
2856 if (!indexRangeOpt.valid())
2857 {
2858 // Unexpected error.
2859 return false;
2860 }
2861
2862 // If we use an index greater than our maximum supported index range, return an error.
2863 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2864 // return an error if possible here.
2865 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2866 {
2867 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2868 return false;
2869 }
2870
2871 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2872 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2873 {
2874 return false;
2875 }
2876
2877 // No op if there are no real indices in the index data (all are primitive restart).
2878 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002879 }
2880
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002881 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002882}
2883
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002884bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2885 GLenum mode,
2886 GLsizei count,
2887 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002888 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002889 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002890{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002891 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002892}
2893
Geoff Lang3edfe032015-09-04 16:38:24 -04002894bool ValidateDrawElementsInstancedANGLE(Context *context,
2895 GLenum mode,
2896 GLsizei count,
2897 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002898 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002899 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002900{
Geoff Lang63c5a592017-09-27 14:08:16 -04002901 if (!context->getExtensions().instancedArrays)
2902 {
2903 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2904 return false;
2905 }
2906
Corentin Wallez170efbf2017-05-02 13:45:01 -04002907 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002908 {
2909 return false;
2910 }
2911
Corentin Wallez0dc97812017-06-22 14:38:44 -04002912 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002913}
2914
He Yunchaoced53ae2016-11-29 15:00:51 +08002915bool ValidateFramebufferTextureBase(Context *context,
2916 GLenum target,
2917 GLenum attachment,
2918 GLuint texture,
2919 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002920{
Geoff Lange8afa902017-09-27 15:00:43 -04002921 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002922 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002923 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002924 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002925 }
2926
2927 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002928 {
2929 return false;
2930 }
2931
Jamie Madill55ec3b12014-07-03 10:38:57 -04002932 if (texture != 0)
2933 {
2934 gl::Texture *tex = context->getTexture(texture);
2935
Jamie Madillbe849e42017-05-02 15:49:00 -04002936 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002937 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002938 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002939 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002940 }
2941
2942 if (level < 0)
2943 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002944 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002945 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002946 }
2947 }
2948
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002949 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002950 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002951
Jamie Madill84115c92015-04-23 15:00:07 -04002952 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002953 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002954 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002955 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002956 }
2957
2958 return true;
2959}
2960
Geoff Langb1196682014-07-23 13:47:29 -04002961bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04002962{
2963 if (program == 0)
2964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002965 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002966 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002967 }
2968
Dian Xiang769769a2015-09-09 15:20:08 -07002969 gl::Program *programObject = GetValidProgram(context, program);
2970 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05002971 {
2972 return false;
2973 }
2974
Jamie Madill0063c512014-08-25 15:47:53 -04002975 if (!programObject || !programObject->isLinked())
2976 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002977 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04002978 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002979 }
2980
Geoff Lang7dd2e102014-11-10 15:19:26 -05002981 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04002982 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002983 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002984 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04002985 }
2986
Jamie Madill0063c512014-08-25 15:47:53 -04002987 return true;
2988}
2989
Geoff Langf41d0ee2016-10-07 13:04:23 -04002990static bool ValidateSizedGetUniform(Context *context,
2991 GLuint program,
2992 GLint location,
2993 GLsizei bufSize,
2994 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04002995{
Geoff Langf41d0ee2016-10-07 13:04:23 -04002996 if (length)
2997 {
2998 *length = 0;
2999 }
3000
Jamie Madill78f41802014-08-25 15:47:55 -04003001 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003002 {
Jamie Madill78f41802014-08-25 15:47:55 -04003003 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003004 }
3005
Geoff Langf41d0ee2016-10-07 13:04:23 -04003006 if (bufSize < 0)
3007 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003008 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003009 return false;
3010 }
3011
Jamie Madilla502c742014-08-28 17:19:13 -04003012 gl::Program *programObject = context->getProgram(program);
3013 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003014
Jamie Madill78f41802014-08-25 15:47:55 -04003015 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003016 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003017 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003018 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003019 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003020 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003021 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003022 }
3023
Geoff Langf41d0ee2016-10-07 13:04:23 -04003024 if (length)
3025 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003026 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003027 }
3028
Jamie Madill0063c512014-08-25 15:47:53 -04003029 return true;
3030}
3031
He Yunchaoced53ae2016-11-29 15:00:51 +08003032bool ValidateGetnUniformfvEXT(Context *context,
3033 GLuint program,
3034 GLint location,
3035 GLsizei bufSize,
3036 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003037{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003038 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003039}
3040
He Yunchaoced53ae2016-11-29 15:00:51 +08003041bool ValidateGetnUniformivEXT(Context *context,
3042 GLuint program,
3043 GLint location,
3044 GLsizei bufSize,
3045 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003046{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003047 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3048}
3049
3050bool ValidateGetUniformfvRobustANGLE(Context *context,
3051 GLuint program,
3052 GLint location,
3053 GLsizei bufSize,
3054 GLsizei *length,
3055 GLfloat *params)
3056{
3057 if (!ValidateRobustEntryPoint(context, bufSize))
3058 {
3059 return false;
3060 }
3061
3062 // bufSize is validated in ValidateSizedGetUniform
3063 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3064}
3065
3066bool ValidateGetUniformivRobustANGLE(Context *context,
3067 GLuint program,
3068 GLint location,
3069 GLsizei bufSize,
3070 GLsizei *length,
3071 GLint *params)
3072{
3073 if (!ValidateRobustEntryPoint(context, bufSize))
3074 {
3075 return false;
3076 }
3077
3078 // bufSize is validated in ValidateSizedGetUniform
3079 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3080}
3081
3082bool ValidateGetUniformuivRobustANGLE(Context *context,
3083 GLuint program,
3084 GLint location,
3085 GLsizei bufSize,
3086 GLsizei *length,
3087 GLuint *params)
3088{
3089 if (!ValidateRobustEntryPoint(context, bufSize))
3090 {
3091 return false;
3092 }
3093
3094 if (context->getClientMajorVersion() < 3)
3095 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003096 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003097 return false;
3098 }
3099
3100 // bufSize is validated in ValidateSizedGetUniform
3101 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003102}
3103
He Yunchaoced53ae2016-11-29 15:00:51 +08003104bool ValidateDiscardFramebufferBase(Context *context,
3105 GLenum target,
3106 GLsizei numAttachments,
3107 const GLenum *attachments,
3108 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003109{
3110 if (numAttachments < 0)
3111 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003112 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003113 return false;
3114 }
3115
3116 for (GLsizei i = 0; i < numAttachments; ++i)
3117 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003118 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003119 {
3120 if (defaultFramebuffer)
3121 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003122 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003123 return false;
3124 }
3125
3126 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3127 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003128 context->handleError(InvalidOperation() << "Requested color attachment is "
3129 "greater than the maximum supported "
3130 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003131 return false;
3132 }
3133 }
3134 else
3135 {
3136 switch (attachments[i])
3137 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003138 case GL_DEPTH_ATTACHMENT:
3139 case GL_STENCIL_ATTACHMENT:
3140 case GL_DEPTH_STENCIL_ATTACHMENT:
3141 if (defaultFramebuffer)
3142 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003143 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3144 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003145 return false;
3146 }
3147 break;
3148 case GL_COLOR:
3149 case GL_DEPTH:
3150 case GL_STENCIL:
3151 if (!defaultFramebuffer)
3152 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003153 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3154 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003155 return false;
3156 }
3157 break;
3158 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003159 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003160 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003161 }
3162 }
3163 }
3164
3165 return true;
3166}
3167
Austin Kinross6ee1e782015-05-29 17:05:37 -07003168bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3169{
Jamie Madill007530e2017-12-28 14:27:04 -05003170 if (!context->getExtensions().debugMarker)
3171 {
3172 // The debug marker calls should not set error state
3173 // However, it seems reasonable to set an error state if the extension is not enabled
3174 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3175 return false;
3176 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003177
Jamie Madill007530e2017-12-28 14:27:04 -05003178 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003179 if (length < 0)
3180 {
3181 return false;
3182 }
3183
3184 if (marker == nullptr)
3185 {
3186 return false;
3187 }
3188
3189 return true;
3190}
3191
3192bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3193{
Jamie Madill007530e2017-12-28 14:27:04 -05003194 if (!context->getExtensions().debugMarker)
3195 {
3196 // The debug marker calls should not set error state
3197 // However, it seems reasonable to set an error state if the extension is not enabled
3198 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3199 return false;
3200 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003201
Jamie Madill007530e2017-12-28 14:27:04 -05003202 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003203 if (length < 0)
3204 {
3205 return false;
3206 }
3207
3208 if (length > 0 && marker == nullptr)
3209 {
3210 return false;
3211 }
3212
3213 return true;
3214}
3215
Jamie Madill007530e2017-12-28 14:27:04 -05003216bool ValidateEGLImageTargetTexture2DOES(Context *context, GLenum target, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003217{
Geoff Langa8406172015-07-21 16:53:39 -04003218 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3219 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003220 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003221 return false;
3222 }
3223
3224 switch (target)
3225 {
3226 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003227 if (!context->getExtensions().eglImage)
3228 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003229 context->handleError(InvalidEnum()
3230 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003231 }
3232 break;
3233
3234 case GL_TEXTURE_EXTERNAL_OES:
3235 if (!context->getExtensions().eglImageExternal)
3236 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003237 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3238 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003239 }
Geoff Langa8406172015-07-21 16:53:39 -04003240 break;
3241
3242 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003243 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003244 return false;
3245 }
3246
Jamie Madill007530e2017-12-28 14:27:04 -05003247 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3248
Jamie Madill61e16b42017-06-19 11:13:23 -04003249 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003250 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003251 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003252 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003253 return false;
3254 }
3255
Jamie Madill007530e2017-12-28 14:27:04 -05003256 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003257 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003258 context->handleError(InvalidOperation()
3259 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003260 return false;
3261 }
3262
Geoff Langca271392017-04-05 12:30:00 -04003263 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003264 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003265 if (!textureCaps.texturable)
3266 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003267 context->handleError(InvalidOperation()
3268 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003269 return false;
3270 }
3271
Geoff Langdcab33b2015-07-21 13:03:16 -04003272 return true;
3273}
3274
3275bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003276 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003277 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003278{
Geoff Langa8406172015-07-21 16:53:39 -04003279 if (!context->getExtensions().eglImage)
3280 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003281 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003282 return false;
3283 }
3284
3285 switch (target)
3286 {
3287 case GL_RENDERBUFFER:
3288 break;
3289
3290 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003291 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003292 return false;
3293 }
3294
Jamie Madill007530e2017-12-28 14:27:04 -05003295 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3296
Jamie Madill61e16b42017-06-19 11:13:23 -04003297 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003298 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003299 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003300 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003301 return false;
3302 }
3303
Geoff Langca271392017-04-05 12:30:00 -04003304 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003305 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003306 if (!textureCaps.renderable)
3307 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003308 context->handleError(InvalidOperation()
3309 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003310 return false;
3311 }
3312
Geoff Langdcab33b2015-07-21 13:03:16 -04003313 return true;
3314}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003315
3316bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3317{
Geoff Lang36167ab2015-12-07 10:27:14 -05003318 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003319 {
3320 // The default VAO should always exist
3321 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003322 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003323 return false;
3324 }
3325
3326 return true;
3327}
3328
Geoff Langc5629752015-12-07 16:29:04 -05003329bool ValidateProgramBinaryBase(Context *context,
3330 GLuint program,
3331 GLenum binaryFormat,
3332 const void *binary,
3333 GLint length)
3334{
3335 Program *programObject = GetValidProgram(context, program);
3336 if (programObject == nullptr)
3337 {
3338 return false;
3339 }
3340
3341 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3342 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3343 programBinaryFormats.end())
3344 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003345 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003346 return false;
3347 }
3348
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003349 if (context->hasActiveTransformFeedback(program))
3350 {
3351 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003352 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3353 "is associated with an active transform "
3354 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003355 return false;
3356 }
3357
Geoff Langc5629752015-12-07 16:29:04 -05003358 return true;
3359}
3360
3361bool ValidateGetProgramBinaryBase(Context *context,
3362 GLuint program,
3363 GLsizei bufSize,
3364 GLsizei *length,
3365 GLenum *binaryFormat,
3366 void *binary)
3367{
3368 Program *programObject = GetValidProgram(context, program);
3369 if (programObject == nullptr)
3370 {
3371 return false;
3372 }
3373
3374 if (!programObject->isLinked())
3375 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003376 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003377 return false;
3378 }
3379
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003380 if (context->getCaps().programBinaryFormats.empty())
3381 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003382 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003383 return false;
3384 }
3385
Geoff Langc5629752015-12-07 16:29:04 -05003386 return true;
3387}
Jamie Madillc29968b2016-01-20 11:17:23 -05003388
Jamie Madillc29968b2016-01-20 11:17:23 -05003389bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3390{
3391 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003392 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003393 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003394 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3395 return false;
3396 }
3397 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3398 {
3399 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003400 return false;
3401 }
3402
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003403 ASSERT(context->getGLState().getDrawFramebuffer());
3404 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003405 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3406
3407 // This should come first before the check for the default frame buffer
3408 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3409 // rather than INVALID_OPERATION
3410 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3411 {
3412 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3413
3414 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003415 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3416 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003417 {
3418 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003419 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3420 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3421 // 3.1 is still a bit ambiguous about the error, but future specs are
3422 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003423 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003424 return false;
3425 }
3426 else if (bufs[colorAttachment] >= maxColorAttachment)
3427 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003428 context->handleError(InvalidOperation()
3429 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003430 return false;
3431 }
3432 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3433 frameBufferId != 0)
3434 {
3435 // INVALID_OPERATION-GL is bound to buffer and ith argument
3436 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003437 context->handleError(InvalidOperation()
3438 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003439 return false;
3440 }
3441 }
3442
3443 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3444 // and n is not 1 or bufs is bound to value other than BACK and NONE
3445 if (frameBufferId == 0)
3446 {
3447 if (n != 1)
3448 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003449 context->handleError(InvalidOperation()
3450 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003451 return false;
3452 }
3453
3454 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3455 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003456 context->handleError(
3457 InvalidOperation()
3458 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003459 return false;
3460 }
3461 }
3462
3463 return true;
3464}
3465
Geoff Lang496c02d2016-10-20 11:38:11 -07003466bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003467 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003468 GLenum pname,
3469 GLsizei *length,
3470 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003471{
Geoff Lang496c02d2016-10-20 11:38:11 -07003472 if (length)
3473 {
3474 *length = 0;
3475 }
3476
3477 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3478 {
3479 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003480 InvalidOperation()
3481 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003482 return false;
3483 }
3484
Corentin Walleze4477002017-12-01 14:39:58 -05003485 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003486 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003487 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003488 return false;
3489 }
3490
Geoff Lang496c02d2016-10-20 11:38:11 -07003491 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003492 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003493 case GL_BUFFER_MAP_POINTER:
3494 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003495
Geoff Lang496c02d2016-10-20 11:38:11 -07003496 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003497 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003498 return false;
3499 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003500
3501 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3502 // target bound to zero generate an INVALID_OPERATION error."
3503 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003504 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003505 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003506 context->handleError(InvalidOperation()
3507 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003508 return false;
3509 }
3510
Geoff Lang496c02d2016-10-20 11:38:11 -07003511 if (length)
3512 {
3513 *length = 1;
3514 }
3515
Olli Etuaho4f667482016-03-30 15:56:35 +03003516 return true;
3517}
3518
Corentin Wallez336129f2017-10-17 15:55:40 -04003519bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003520{
Corentin Walleze4477002017-12-01 14:39:58 -05003521 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003522 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003523 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003524 return false;
3525 }
3526
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003527 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003528
3529 if (buffer == nullptr || !buffer->isMapped())
3530 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003531 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003532 return false;
3533 }
3534
3535 return true;
3536}
3537
3538bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003539 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003540 GLintptr offset,
3541 GLsizeiptr length,
3542 GLbitfield access)
3543{
Corentin Walleze4477002017-12-01 14:39:58 -05003544 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003545 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003546 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003547 return false;
3548 }
3549
Brandon Jones6cad5662017-06-14 13:25:13 -07003550 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003551 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003552 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3553 return false;
3554 }
3555
3556 if (length < 0)
3557 {
3558 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003559 return false;
3560 }
3561
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003562 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003563
3564 if (!buffer)
3565 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003566 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003567 return false;
3568 }
3569
3570 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003571 CheckedNumeric<size_t> checkedOffset(offset);
3572 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003573
Jamie Madille2e406c2016-06-02 13:04:10 -04003574 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003575 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003576 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003577 return false;
3578 }
3579
3580 // Check for invalid bits in the mask
3581 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3582 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3583 GL_MAP_UNSYNCHRONIZED_BIT;
3584
3585 if (access & ~(allAccessBits))
3586 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003587 context->handleError(InvalidValue()
3588 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003589 return false;
3590 }
3591
3592 if (length == 0)
3593 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003594 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003595 return false;
3596 }
3597
3598 if (buffer->isMapped())
3599 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003600 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003601 return false;
3602 }
3603
3604 // Check for invalid bit combinations
3605 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3606 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003607 context->handleError(InvalidOperation()
3608 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003609 return false;
3610 }
3611
3612 GLbitfield writeOnlyBits =
3613 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3614
3615 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3616 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003617 context->handleError(InvalidOperation()
3618 << "Invalid access bits when mapping buffer for reading: 0x"
3619 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003620 return false;
3621 }
3622
3623 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003625 context->handleError(
3626 InvalidOperation()
3627 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003628 return false;
3629 }
Geoff Lang79f71042017-08-14 16:43:43 -04003630
3631 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003632}
3633
3634bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003635 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003636 GLintptr offset,
3637 GLsizeiptr length)
3638{
Brandon Jones6cad5662017-06-14 13:25:13 -07003639 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003640 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003641 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3642 return false;
3643 }
3644
3645 if (length < 0)
3646 {
3647 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003648 return false;
3649 }
3650
Corentin Walleze4477002017-12-01 14:39:58 -05003651 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003652 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003653 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003654 return false;
3655 }
3656
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003657 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003658
3659 if (buffer == nullptr)
3660 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003661 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003662 return false;
3663 }
3664
3665 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3666 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003667 context->handleError(InvalidOperation()
3668 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003669 return false;
3670 }
3671
3672 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003673 CheckedNumeric<size_t> checkedOffset(offset);
3674 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003675
Jamie Madille2e406c2016-06-02 13:04:10 -04003676 if (!checkedSize.IsValid() ||
3677 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003678 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003679 context->handleError(InvalidValue()
3680 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003681 return false;
3682 }
3683
3684 return true;
3685}
3686
Olli Etuaho41997e72016-03-10 13:38:39 +02003687bool ValidateGenOrDelete(Context *context, GLint n)
3688{
3689 if (n < 0)
3690 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003691 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003692 return false;
3693 }
3694 return true;
3695}
3696
Geoff Langff5b2d52016-09-07 11:32:23 -04003697bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3698{
3699 if (!context->getExtensions().robustClientMemory)
3700 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003701 context->handleError(InvalidOperation()
3702 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003703 return false;
3704 }
3705
3706 if (bufSize < 0)
3707 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003708 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003709 return false;
3710 }
3711
3712 return true;
3713}
3714
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003715bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3716{
3717 if (bufSize < numParams)
3718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003719 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3720 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003721 return false;
3722 }
3723
3724 return true;
3725}
3726
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003727bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003728 GLenum target,
3729 GLenum attachment,
3730 GLenum pname,
3731 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003732{
Geoff Lange8afa902017-09-27 15:00:43 -04003733 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003734 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003735 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003736 return false;
3737 }
3738
3739 int clientVersion = context->getClientMajorVersion();
3740
3741 switch (pname)
3742 {
3743 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3744 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3745 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3746 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3747 break;
3748
Martin Radeve5285d22017-07-14 16:23:53 +03003749 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3750 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3751 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3752 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3753 if (clientVersion < 3 || !context->getExtensions().multiview)
3754 {
3755 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3756 return false;
3757 }
3758 break;
3759
Geoff Langff5b2d52016-09-07 11:32:23 -04003760 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3761 if (clientVersion < 3 && !context->getExtensions().sRGB)
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 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3769 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3770 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3771 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3772 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3773 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3774 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3775 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3776 if (clientVersion < 3)
3777 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003778 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003779 return false;
3780 }
3781 break;
3782
3783 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003784 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003785 return false;
3786 }
3787
3788 // Determine if the attachment is a valid enum
3789 switch (attachment)
3790 {
3791 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04003792 case GL_DEPTH:
3793 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04003794 if (clientVersion < 3)
3795 {
Geoff Langfa125c92017-10-24 13:01:46 -04003796 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003797 return false;
3798 }
3799 break;
3800
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003801 case GL_DEPTH_STENCIL_ATTACHMENT:
3802 if (clientVersion < 3 && !context->isWebGL1())
3803 {
3804 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3805 return false;
3806 }
3807 break;
3808
Geoff Langfa125c92017-10-24 13:01:46 -04003809 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003810 case GL_DEPTH_ATTACHMENT:
3811 case GL_STENCIL_ATTACHMENT:
3812 break;
3813
3814 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003815 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3816 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003817 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3818 {
Geoff Langfa125c92017-10-24 13:01:46 -04003819 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003820 return false;
3821 }
3822 break;
3823 }
3824
3825 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3826 ASSERT(framebuffer);
3827
3828 if (framebuffer->id() == 0)
3829 {
3830 if (clientVersion < 3)
3831 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003832 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003833 return false;
3834 }
3835
3836 switch (attachment)
3837 {
3838 case GL_BACK:
3839 case GL_DEPTH:
3840 case GL_STENCIL:
3841 break;
3842
3843 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003844 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003845 return false;
3846 }
3847 }
3848 else
3849 {
3850 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3851 {
3852 // Valid attachment query
3853 }
3854 else
3855 {
3856 switch (attachment)
3857 {
3858 case GL_DEPTH_ATTACHMENT:
3859 case GL_STENCIL_ATTACHMENT:
3860 break;
3861
3862 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003863 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04003864 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003865 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003866 return false;
3867 }
3868 break;
3869
3870 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003871 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003872 return false;
3873 }
3874 }
3875 }
3876
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003877 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003878 if (attachmentObject)
3879 {
3880 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3881 attachmentObject->type() == GL_TEXTURE ||
3882 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3883
3884 switch (pname)
3885 {
3886 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3887 if (attachmentObject->type() != GL_RENDERBUFFER &&
3888 attachmentObject->type() != GL_TEXTURE)
3889 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003890 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003891 return false;
3892 }
3893 break;
3894
3895 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3896 if (attachmentObject->type() != GL_TEXTURE)
3897 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003898 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003899 return false;
3900 }
3901 break;
3902
3903 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3904 if (attachmentObject->type() != GL_TEXTURE)
3905 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003906 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003907 return false;
3908 }
3909 break;
3910
3911 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3912 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3913 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003914 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003915 return false;
3916 }
3917 break;
3918
3919 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3920 if (attachmentObject->type() != GL_TEXTURE)
3921 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003922 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003923 return false;
3924 }
3925 break;
3926
3927 default:
3928 break;
3929 }
3930 }
3931 else
3932 {
3933 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3934 // is NONE, then querying any other pname will generate INVALID_ENUM.
3935
3936 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3937 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3938 // INVALID_OPERATION for all other pnames
3939
3940 switch (pname)
3941 {
3942 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3943 break;
3944
3945 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3946 if (clientVersion < 3)
3947 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003948 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
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 break;
3953
3954 default:
3955 if (clientVersion < 3)
3956 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003957 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003958 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003959 return false;
3960 }
3961 else
3962 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003963 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003964 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003965 return false;
3966 }
3967 }
3968 }
3969
Martin Radeve5285d22017-07-14 16:23:53 +03003970 if (numParams)
3971 {
3972 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
3973 {
3974 // Only when the viewport offsets are queried we can have a varying number of output
3975 // parameters.
3976 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
3977 *numParams = numViews * 2;
3978 }
3979 else
3980 {
3981 // For all other queries we can have only one output parameter.
3982 *numParams = 1;
3983 }
3984 }
3985
Geoff Langff5b2d52016-09-07 11:32:23 -04003986 return true;
3987}
3988
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003989bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04003990 GLenum target,
3991 GLenum attachment,
3992 GLenum pname,
3993 GLsizei bufSize,
3994 GLsizei *numParams)
3995{
3996 if (!ValidateRobustEntryPoint(context, bufSize))
3997 {
3998 return false;
3999 }
4000
Jamie Madillbe849e42017-05-02 15:49:00 -04004001 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4002 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004003 {
4004 return false;
4005 }
4006
4007 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4008 {
4009 return false;
4010 }
4011
4012 return true;
4013}
4014
Geoff Langff5b2d52016-09-07 11:32:23 -04004015bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004016 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004017 GLenum pname,
4018 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004019 GLsizei *length,
4020 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004021{
4022 if (!ValidateRobustEntryPoint(context, bufSize))
4023 {
4024 return false;
4025 }
4026
Geoff Langebebe1c2016-10-14 12:01:31 -04004027 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004028 {
4029 return false;
4030 }
4031
Geoff Langebebe1c2016-10-14 12:01:31 -04004032 if (!ValidateRobustBufferSize(context, bufSize, *length))
4033 {
4034 return false;
4035 }
4036
4037 return true;
4038}
4039
Geoff Langebebe1c2016-10-14 12:01:31 -04004040bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004041 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004042 GLenum pname,
4043 GLsizei bufSize,
4044 GLsizei *length,
4045 GLint64 *params)
4046{
4047 if (!ValidateRobustEntryPoint(context, bufSize))
4048 {
4049 return false;
4050 }
4051
4052 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4053 {
4054 return false;
4055 }
4056
4057 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004058 {
4059 return false;
4060 }
4061
4062 return true;
4063}
4064
Jamie Madillbe849e42017-05-02 15:49:00 -04004065bool ValidateGetProgramivBase(ValidationContext *context,
4066 GLuint program,
4067 GLenum pname,
4068 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004069{
4070 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004071 if (numParams)
4072 {
4073 *numParams = 1;
4074 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004075
4076 Program *programObject = GetValidProgram(context, program);
4077 if (!programObject)
4078 {
4079 return false;
4080 }
4081
4082 switch (pname)
4083 {
4084 case GL_DELETE_STATUS:
4085 case GL_LINK_STATUS:
4086 case GL_VALIDATE_STATUS:
4087 case GL_INFO_LOG_LENGTH:
4088 case GL_ATTACHED_SHADERS:
4089 case GL_ACTIVE_ATTRIBUTES:
4090 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4091 case GL_ACTIVE_UNIFORMS:
4092 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4093 break;
4094
4095 case GL_PROGRAM_BINARY_LENGTH:
4096 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4097 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004098 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4099 "requires GL_OES_get_program_binary or "
4100 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004101 return false;
4102 }
4103 break;
4104
4105 case GL_ACTIVE_UNIFORM_BLOCKS:
4106 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4107 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4108 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4109 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4110 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4111 if (context->getClientMajorVersion() < 3)
4112 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004113 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004114 return false;
4115 }
4116 break;
4117
Yunchao He61afff12017-03-14 15:34:03 +08004118 case GL_PROGRAM_SEPARABLE:
Xinghua Cao971f8502017-10-17 13:01:24 +08004119 case GL_COMPUTE_WORK_GROUP_SIZE:
jchen1058f67be2017-10-27 08:59:27 +08004120 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004121 if (context->getClientVersion() < Version(3, 1))
4122 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004123 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004124 return false;
4125 }
4126 break;
4127
Geoff Langff5b2d52016-09-07 11:32:23 -04004128 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004129 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004130 return false;
4131 }
4132
4133 return true;
4134}
4135
4136bool ValidateGetProgramivRobustANGLE(Context *context,
4137 GLuint program,
4138 GLenum pname,
4139 GLsizei bufSize,
4140 GLsizei *numParams)
4141{
4142 if (!ValidateRobustEntryPoint(context, bufSize))
4143 {
4144 return false;
4145 }
4146
Jamie Madillbe849e42017-05-02 15:49:00 -04004147 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004148 {
4149 return false;
4150 }
4151
4152 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4153 {
4154 return false;
4155 }
4156
4157 return true;
4158}
4159
Geoff Lang740d9022016-10-07 11:20:52 -04004160bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4161 GLenum target,
4162 GLenum pname,
4163 GLsizei bufSize,
4164 GLsizei *length,
4165 GLint *params)
4166{
4167 if (!ValidateRobustEntryPoint(context, bufSize))
4168 {
4169 return false;
4170 }
4171
4172 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4173 {
4174 return false;
4175 }
4176
4177 if (!ValidateRobustBufferSize(context, bufSize, *length))
4178 {
4179 return false;
4180 }
4181
4182 return true;
4183}
4184
Geoff Langd7d0ed32016-10-07 11:33:51 -04004185bool ValidateGetShaderivRobustANGLE(Context *context,
4186 GLuint shader,
4187 GLenum pname,
4188 GLsizei bufSize,
4189 GLsizei *length,
4190 GLint *params)
4191{
4192 if (!ValidateRobustEntryPoint(context, bufSize))
4193 {
4194 return false;
4195 }
4196
4197 if (!ValidateGetShaderivBase(context, shader, pname, length))
4198 {
4199 return false;
4200 }
4201
4202 if (!ValidateRobustBufferSize(context, bufSize, *length))
4203 {
4204 return false;
4205 }
4206
4207 return true;
4208}
4209
Geoff Langc1984ed2016-10-07 12:41:00 -04004210bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4211 GLenum target,
4212 GLenum pname,
4213 GLsizei bufSize,
4214 GLsizei *length,
4215 GLfloat *params)
4216{
4217 if (!ValidateRobustEntryPoint(context, bufSize))
4218 {
4219 return false;
4220 }
4221
4222 if (!ValidateGetTexParameterBase(context, target, pname, length))
4223 {
4224 return false;
4225 }
4226
4227 if (!ValidateRobustBufferSize(context, bufSize, *length))
4228 {
4229 return false;
4230 }
4231
4232 return true;
4233}
4234
Geoff Langc1984ed2016-10-07 12:41:00 -04004235bool ValidateGetTexParameterivRobustANGLE(Context *context,
4236 GLenum target,
4237 GLenum pname,
4238 GLsizei bufSize,
4239 GLsizei *length,
4240 GLint *params)
4241{
4242 if (!ValidateRobustEntryPoint(context, bufSize))
4243 {
4244 return false;
4245 }
4246
4247 if (!ValidateGetTexParameterBase(context, target, pname, length))
4248 {
4249 return false;
4250 }
4251
4252 if (!ValidateRobustBufferSize(context, bufSize, *length))
4253 {
4254 return false;
4255 }
4256
4257 return true;
4258}
4259
Geoff Langc1984ed2016-10-07 12:41:00 -04004260bool ValidateTexParameterfvRobustANGLE(Context *context,
4261 GLenum target,
4262 GLenum pname,
4263 GLsizei bufSize,
4264 const GLfloat *params)
4265{
4266 if (!ValidateRobustEntryPoint(context, bufSize))
4267 {
4268 return false;
4269 }
4270
4271 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4272}
4273
Geoff Langc1984ed2016-10-07 12:41:00 -04004274bool ValidateTexParameterivRobustANGLE(Context *context,
4275 GLenum target,
4276 GLenum pname,
4277 GLsizei bufSize,
4278 const GLint *params)
4279{
4280 if (!ValidateRobustEntryPoint(context, bufSize))
4281 {
4282 return false;
4283 }
4284
4285 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4286}
4287
Geoff Langc1984ed2016-10-07 12:41:00 -04004288bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4289 GLuint sampler,
4290 GLenum pname,
4291 GLuint bufSize,
4292 GLsizei *length,
4293 GLfloat *params)
4294{
4295 if (!ValidateRobustEntryPoint(context, bufSize))
4296 {
4297 return false;
4298 }
4299
4300 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4301 {
4302 return false;
4303 }
4304
4305 if (!ValidateRobustBufferSize(context, bufSize, *length))
4306 {
4307 return false;
4308 }
4309
4310 return true;
4311}
4312
Geoff Langc1984ed2016-10-07 12:41:00 -04004313bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4314 GLuint sampler,
4315 GLenum pname,
4316 GLuint bufSize,
4317 GLsizei *length,
4318 GLint *params)
4319{
4320 if (!ValidateRobustEntryPoint(context, bufSize))
4321 {
4322 return false;
4323 }
4324
4325 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4326 {
4327 return false;
4328 }
4329
4330 if (!ValidateRobustBufferSize(context, bufSize, *length))
4331 {
4332 return false;
4333 }
4334
4335 return true;
4336}
4337
Geoff Langc1984ed2016-10-07 12:41:00 -04004338bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4339 GLuint sampler,
4340 GLenum pname,
4341 GLsizei bufSize,
4342 const GLfloat *params)
4343{
4344 if (!ValidateRobustEntryPoint(context, bufSize))
4345 {
4346 return false;
4347 }
4348
4349 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4350}
4351
Geoff Langc1984ed2016-10-07 12:41:00 -04004352bool ValidateSamplerParameterivRobustANGLE(Context *context,
4353 GLuint sampler,
4354 GLenum pname,
4355 GLsizei bufSize,
4356 const GLint *params)
4357{
4358 if (!ValidateRobustEntryPoint(context, bufSize))
4359 {
4360 return false;
4361 }
4362
4363 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4364}
4365
Geoff Lang0b031062016-10-13 14:30:04 -04004366bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4367 GLuint index,
4368 GLenum pname,
4369 GLsizei bufSize,
4370 GLsizei *length,
4371 GLfloat *params)
4372{
4373 if (!ValidateRobustEntryPoint(context, bufSize))
4374 {
4375 return false;
4376 }
4377
4378 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4379 {
4380 return false;
4381 }
4382
4383 if (!ValidateRobustBufferSize(context, bufSize, *length))
4384 {
4385 return false;
4386 }
4387
4388 return true;
4389}
4390
Geoff Lang0b031062016-10-13 14:30:04 -04004391bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4392 GLuint index,
4393 GLenum pname,
4394 GLsizei bufSize,
4395 GLsizei *length,
4396 GLint *params)
4397{
4398 if (!ValidateRobustEntryPoint(context, bufSize))
4399 {
4400 return false;
4401 }
4402
4403 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4404 {
4405 return false;
4406 }
4407
4408 if (!ValidateRobustBufferSize(context, bufSize, *length))
4409 {
4410 return false;
4411 }
4412
4413 return true;
4414}
4415
Geoff Lang0b031062016-10-13 14:30:04 -04004416bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4417 GLuint index,
4418 GLenum pname,
4419 GLsizei bufSize,
4420 GLsizei *length,
4421 void **pointer)
4422{
4423 if (!ValidateRobustEntryPoint(context, bufSize))
4424 {
4425 return false;
4426 }
4427
4428 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4429 {
4430 return false;
4431 }
4432
4433 if (!ValidateRobustBufferSize(context, bufSize, *length))
4434 {
4435 return false;
4436 }
4437
4438 return true;
4439}
4440
Geoff Lang0b031062016-10-13 14:30:04 -04004441bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4442 GLuint index,
4443 GLenum pname,
4444 GLsizei bufSize,
4445 GLsizei *length,
4446 GLint *params)
4447{
4448 if (!ValidateRobustEntryPoint(context, bufSize))
4449 {
4450 return false;
4451 }
4452
4453 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4454 {
4455 return false;
4456 }
4457
4458 if (!ValidateRobustBufferSize(context, bufSize, *length))
4459 {
4460 return false;
4461 }
4462
4463 return true;
4464}
4465
Geoff Lang0b031062016-10-13 14:30:04 -04004466bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4467 GLuint index,
4468 GLenum pname,
4469 GLsizei bufSize,
4470 GLsizei *length,
4471 GLuint *params)
4472{
4473 if (!ValidateRobustEntryPoint(context, bufSize))
4474 {
4475 return false;
4476 }
4477
4478 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4479 {
4480 return false;
4481 }
4482
4483 if (!ValidateRobustBufferSize(context, bufSize, *length))
4484 {
4485 return false;
4486 }
4487
4488 return true;
4489}
4490
Geoff Lang6899b872016-10-14 11:30:13 -04004491bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4492 GLuint program,
4493 GLuint uniformBlockIndex,
4494 GLenum pname,
4495 GLsizei bufSize,
4496 GLsizei *length,
4497 GLint *params)
4498{
4499 if (!ValidateRobustEntryPoint(context, bufSize))
4500 {
4501 return false;
4502 }
4503
4504 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4505 {
4506 return false;
4507 }
4508
4509 if (!ValidateRobustBufferSize(context, bufSize, *length))
4510 {
4511 return false;
4512 }
4513
4514 return true;
4515}
4516
Geoff Lang0a9661f2016-10-20 10:59:20 -07004517bool ValidateGetInternalFormativRobustANGLE(Context *context,
4518 GLenum target,
4519 GLenum internalformat,
4520 GLenum pname,
4521 GLsizei bufSize,
4522 GLsizei *length,
4523 GLint *params)
4524{
4525 if (!ValidateRobustEntryPoint(context, bufSize))
4526 {
4527 return false;
4528 }
4529
4530 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4531 {
4532 return false;
4533 }
4534
4535 if (!ValidateRobustBufferSize(context, bufSize, *length))
4536 {
4537 return false;
4538 }
4539
4540 return true;
4541}
4542
Shao80957d92017-02-20 21:25:59 +08004543bool ValidateVertexFormatBase(ValidationContext *context,
4544 GLuint attribIndex,
4545 GLint size,
4546 GLenum type,
4547 GLboolean pureInteger)
4548{
4549 const Caps &caps = context->getCaps();
4550 if (attribIndex >= caps.maxVertexAttributes)
4551 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004552 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004553 return false;
4554 }
4555
4556 if (size < 1 || size > 4)
4557 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004558 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004559 return false;
Shao80957d92017-02-20 21:25:59 +08004560 }
4561
4562 switch (type)
4563 {
4564 case GL_BYTE:
4565 case GL_UNSIGNED_BYTE:
4566 case GL_SHORT:
4567 case GL_UNSIGNED_SHORT:
4568 break;
4569
4570 case GL_INT:
4571 case GL_UNSIGNED_INT:
4572 if (context->getClientMajorVersion() < 3)
4573 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004574 context->handleError(InvalidEnum()
4575 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004576 return false;
4577 }
4578 break;
4579
4580 case GL_FIXED:
4581 case GL_FLOAT:
4582 if (pureInteger)
4583 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004584 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004585 return false;
4586 }
4587 break;
4588
4589 case GL_HALF_FLOAT:
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 break;
4602
4603 case GL_INT_2_10_10_10_REV:
4604 case GL_UNSIGNED_INT_2_10_10_10_REV:
4605 if (context->getClientMajorVersion() < 3)
4606 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004607 context->handleError(InvalidEnum()
4608 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004609 return false;
4610 }
4611 if (pureInteger)
4612 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004613 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004614 return false;
4615 }
4616 if (size != 4)
4617 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004618 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4619 "UNSIGNED_INT_2_10_10_10_REV and "
4620 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004621 return false;
4622 }
4623 break;
4624
4625 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004626 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004627 return false;
4628 }
4629
4630 return true;
4631}
4632
Geoff Lang76e65652017-03-27 14:58:02 -04004633// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4634// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4635// specified clear value and the type of a buffer that is being cleared generates an
4636// INVALID_OPERATION error instead of producing undefined results
4637bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4638 GLint drawbuffer,
4639 const GLenum *validComponentTypes,
4640 size_t validComponentTypeCount)
4641{
4642 const FramebufferAttachment *attachment =
4643 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4644 if (attachment)
4645 {
4646 GLenum componentType = attachment->getFormat().info->componentType;
4647 const GLenum *end = validComponentTypes + validComponentTypeCount;
4648 if (std::find(validComponentTypes, end, componentType) == end)
4649 {
4650 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004651 InvalidOperation()
4652 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004653 return false;
4654 }
4655 }
4656
4657 return true;
4658}
4659
Corentin Wallezb2931602017-04-11 15:58:57 -04004660bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4661 GLsizei imageSize,
4662 GLsizei dataSize)
4663{
4664 if (!ValidateRobustEntryPoint(context, dataSize))
4665 {
4666 return false;
4667 }
4668
Corentin Wallez336129f2017-10-17 15:55:40 -04004669 gl::Buffer *pixelUnpackBuffer =
4670 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004671 if (pixelUnpackBuffer == nullptr)
4672 {
4673 if (dataSize < imageSize)
4674 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004675 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004676 }
4677 }
4678 return true;
4679}
4680
Jamie Madillbe849e42017-05-02 15:49:00 -04004681bool ValidateGetBufferParameterBase(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004682 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004683 GLenum pname,
4684 bool pointerVersion,
4685 GLsizei *numParams)
4686{
4687 if (numParams)
4688 {
4689 *numParams = 0;
4690 }
4691
Corentin Walleze4477002017-12-01 14:39:58 -05004692 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004693 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004694 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004695 return false;
4696 }
4697
4698 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4699 if (!buffer)
4700 {
4701 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004702 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004703 return false;
4704 }
4705
4706 const Extensions &extensions = context->getExtensions();
4707
4708 switch (pname)
4709 {
4710 case GL_BUFFER_USAGE:
4711 case GL_BUFFER_SIZE:
4712 break;
4713
4714 case GL_BUFFER_ACCESS_OES:
4715 if (!extensions.mapBuffer)
4716 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004717 context->handleError(InvalidEnum()
4718 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004719 return false;
4720 }
4721 break;
4722
4723 case GL_BUFFER_MAPPED:
4724 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4725 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4726 !extensions.mapBufferRange)
4727 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004728 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4729 "GL_OES_mapbuffer or "
4730 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004731 return false;
4732 }
4733 break;
4734
4735 case GL_BUFFER_MAP_POINTER:
4736 if (!pointerVersion)
4737 {
4738 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004739 InvalidEnum()
4740 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004741 return false;
4742 }
4743 break;
4744
4745 case GL_BUFFER_ACCESS_FLAGS:
4746 case GL_BUFFER_MAP_OFFSET:
4747 case GL_BUFFER_MAP_LENGTH:
4748 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4749 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004750 context->handleError(InvalidEnum()
4751 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004752 return false;
4753 }
4754 break;
4755
4756 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004757 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004758 return false;
4759 }
4760
4761 // All buffer parameter queries return one value.
4762 if (numParams)
4763 {
4764 *numParams = 1;
4765 }
4766
4767 return true;
4768}
4769
4770bool ValidateGetRenderbufferParameterivBase(Context *context,
4771 GLenum target,
4772 GLenum pname,
4773 GLsizei *length)
4774{
4775 if (length)
4776 {
4777 *length = 0;
4778 }
4779
4780 if (target != GL_RENDERBUFFER)
4781 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004782 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004783 return false;
4784 }
4785
4786 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4787 if (renderbuffer == nullptr)
4788 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004789 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004790 return false;
4791 }
4792
4793 switch (pname)
4794 {
4795 case GL_RENDERBUFFER_WIDTH:
4796 case GL_RENDERBUFFER_HEIGHT:
4797 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4798 case GL_RENDERBUFFER_RED_SIZE:
4799 case GL_RENDERBUFFER_GREEN_SIZE:
4800 case GL_RENDERBUFFER_BLUE_SIZE:
4801 case GL_RENDERBUFFER_ALPHA_SIZE:
4802 case GL_RENDERBUFFER_DEPTH_SIZE:
4803 case GL_RENDERBUFFER_STENCIL_SIZE:
4804 break;
4805
4806 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4807 if (!context->getExtensions().framebufferMultisample)
4808 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004809 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004810 return false;
4811 }
4812 break;
4813
4814 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004815 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004816 return false;
4817 }
4818
4819 if (length)
4820 {
4821 *length = 1;
4822 }
4823 return true;
4824}
4825
4826bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4827{
4828 if (length)
4829 {
4830 *length = 0;
4831 }
4832
4833 if (GetValidShader(context, shader) == nullptr)
4834 {
4835 return false;
4836 }
4837
4838 switch (pname)
4839 {
4840 case GL_SHADER_TYPE:
4841 case GL_DELETE_STATUS:
4842 case GL_COMPILE_STATUS:
4843 case GL_INFO_LOG_LENGTH:
4844 case GL_SHADER_SOURCE_LENGTH:
4845 break;
4846
4847 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4848 if (!context->getExtensions().translatedShaderSource)
4849 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004850 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004851 return false;
4852 }
4853 break;
4854
4855 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004856 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004857 return false;
4858 }
4859
4860 if (length)
4861 {
4862 *length = 1;
4863 }
4864 return true;
4865}
4866
4867bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4868{
4869 if (length)
4870 {
4871 *length = 0;
4872 }
4873
4874 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4875 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004876 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004877 return false;
4878 }
4879
4880 if (context->getTargetTexture(target) == nullptr)
4881 {
4882 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004883 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004884 return false;
4885 }
4886
4887 switch (pname)
4888 {
4889 case GL_TEXTURE_MAG_FILTER:
4890 case GL_TEXTURE_MIN_FILTER:
4891 case GL_TEXTURE_WRAP_S:
4892 case GL_TEXTURE_WRAP_T:
4893 break;
4894
4895 case GL_TEXTURE_USAGE_ANGLE:
4896 if (!context->getExtensions().textureUsage)
4897 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004898 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004899 return false;
4900 }
4901 break;
4902
4903 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4904 if (!context->getExtensions().textureFilterAnisotropic)
4905 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004906 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004907 return false;
4908 }
4909 break;
4910
4911 case GL_TEXTURE_IMMUTABLE_FORMAT:
4912 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4913 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004914 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004915 return false;
4916 }
4917 break;
4918
4919 case GL_TEXTURE_WRAP_R:
4920 case GL_TEXTURE_IMMUTABLE_LEVELS:
4921 case GL_TEXTURE_SWIZZLE_R:
4922 case GL_TEXTURE_SWIZZLE_G:
4923 case GL_TEXTURE_SWIZZLE_B:
4924 case GL_TEXTURE_SWIZZLE_A:
4925 case GL_TEXTURE_BASE_LEVEL:
4926 case GL_TEXTURE_MAX_LEVEL:
4927 case GL_TEXTURE_MIN_LOD:
4928 case GL_TEXTURE_MAX_LOD:
4929 case GL_TEXTURE_COMPARE_MODE:
4930 case GL_TEXTURE_COMPARE_FUNC:
4931 if (context->getClientMajorVersion() < 3)
4932 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004933 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004934 return false;
4935 }
4936 break;
4937
4938 case GL_TEXTURE_SRGB_DECODE_EXT:
4939 if (!context->getExtensions().textureSRGBDecode)
4940 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004941 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004942 return false;
4943 }
4944 break;
4945
4946 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004947 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004948 return false;
4949 }
4950
4951 if (length)
4952 {
4953 *length = 1;
4954 }
4955 return true;
4956}
4957
4958bool ValidateGetVertexAttribBase(Context *context,
4959 GLuint index,
4960 GLenum pname,
4961 GLsizei *length,
4962 bool pointer,
4963 bool pureIntegerEntryPoint)
4964{
4965 if (length)
4966 {
4967 *length = 0;
4968 }
4969
4970 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
4971 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004972 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004973 return false;
4974 }
4975
4976 if (index >= context->getCaps().maxVertexAttributes)
4977 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004978 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04004979 return false;
4980 }
4981
4982 if (pointer)
4983 {
4984 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
4985 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004986 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004987 return false;
4988 }
4989 }
4990 else
4991 {
4992 switch (pname)
4993 {
4994 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4995 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4996 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4997 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4998 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4999 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5000 case GL_CURRENT_VERTEX_ATTRIB:
5001 break;
5002
5003 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5004 static_assert(
5005 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5006 "ANGLE extension enums not equal to GL enums.");
5007 if (context->getClientMajorVersion() < 3 &&
5008 !context->getExtensions().instancedArrays)
5009 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005010 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5011 "requires OpenGL ES 3.0 or "
5012 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005013 return false;
5014 }
5015 break;
5016
5017 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5018 if (context->getClientMajorVersion() < 3)
5019 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005020 context->handleError(
5021 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005022 return false;
5023 }
5024 break;
5025
5026 case GL_VERTEX_ATTRIB_BINDING:
5027 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5028 if (context->getClientVersion() < ES_3_1)
5029 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005030 context->handleError(InvalidEnum()
5031 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005032 return false;
5033 }
5034 break;
5035
5036 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005037 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005038 return false;
5039 }
5040 }
5041
5042 if (length)
5043 {
5044 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5045 {
5046 *length = 4;
5047 }
5048 else
5049 {
5050 *length = 1;
5051 }
5052 }
5053
5054 return true;
5055}
5056
Jamie Madill4928b7c2017-06-20 12:57:39 -04005057bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005058 GLint x,
5059 GLint y,
5060 GLsizei width,
5061 GLsizei height,
5062 GLenum format,
5063 GLenum type,
5064 GLsizei bufSize,
5065 GLsizei *length,
5066 GLsizei *columns,
5067 GLsizei *rows,
5068 void *pixels)
5069{
5070 if (length != nullptr)
5071 {
5072 *length = 0;
5073 }
5074 if (rows != nullptr)
5075 {
5076 *rows = 0;
5077 }
5078 if (columns != nullptr)
5079 {
5080 *columns = 0;
5081 }
5082
5083 if (width < 0 || height < 0)
5084 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005085 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005086 return false;
5087 }
5088
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005089 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005090
5091 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5092 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005093 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005094 return false;
5095 }
5096
5097 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5098 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005099 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005100 return false;
5101 }
5102
5103 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5104 ASSERT(framebuffer);
5105
5106 if (framebuffer->getReadBufferState() == GL_NONE)
5107 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005108 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005109 return false;
5110 }
5111
5112 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5113 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5114 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5115 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5116 // situation is an application error that would lead to a crash in ANGLE.
5117 if (readBuffer == nullptr)
5118 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005119 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005120 return false;
5121 }
5122
Martin Radev28031682017-07-28 14:47:56 +03005123 // ANGLE_multiview, Revision 1:
5124 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5125 // current read framebuffer is not NONE.
5126 if (readBuffer->getMultiviewLayout() != GL_NONE)
5127 {
5128 context->handleError(InvalidFramebufferOperation()
5129 << "Attempting to read from a multi-view framebuffer.");
5130 return false;
5131 }
5132
Geoff Lang280ba992017-04-18 16:30:58 -04005133 if (context->getExtensions().webglCompatibility)
5134 {
5135 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5136 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5137 // and type before validating the combination of format and type. However, the
5138 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5139 // verifies that GL_INVALID_OPERATION is generated.
5140 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5141 // dEQP/WebGL.
5142 if (!ValidReadPixelsFormatEnum(context, format))
5143 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005144 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005145 return false;
5146 }
5147
5148 if (!ValidReadPixelsTypeEnum(context, type))
5149 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005150 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005151 return false;
5152 }
5153 }
5154
Jamie Madill4928b7c2017-06-20 12:57:39 -04005155 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5156 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005157 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5158
5159 bool validFormatTypeCombination =
5160 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5161
5162 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5163 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005164 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005165 return false;
5166 }
5167
5168 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005169 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005170 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5171 {
5172 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005173 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005174 return false;
5175 }
5176
5177 // .. the data would be packed to the buffer object such that the memory writes required
5178 // would exceed the data store size.
5179 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5180 const gl::Extents size(width, height, 1);
5181 const auto &pack = context->getGLState().getPackState();
5182
5183 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5184 if (endByteOrErr.isError())
5185 {
5186 context->handleError(endByteOrErr.getError());
5187 return false;
5188 }
5189
5190 size_t endByte = endByteOrErr.getResult();
5191 if (bufSize >= 0)
5192 {
5193 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5194 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005195 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005196 return false;
5197 }
5198 }
5199
5200 if (pixelPackBuffer != nullptr)
5201 {
5202 CheckedNumeric<size_t> checkedEndByte(endByte);
5203 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5204 checkedEndByte += checkedOffset;
5205
5206 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5207 {
5208 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005209 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005210 return false;
5211 }
5212 }
5213
5214 if (pixelPackBuffer == nullptr && length != nullptr)
5215 {
5216 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5217 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005218 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005219 return false;
5220 }
5221
5222 *length = static_cast<GLsizei>(endByte);
5223 }
5224
5225 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5226 angle::CheckedNumeric<int> clippedExtent(length);
5227 if (start < 0)
5228 {
5229 // "subtract" the area that is less than 0
5230 clippedExtent += start;
5231 }
5232
5233 const int readExtent = start + length;
5234 if (readExtent > bufferSize)
5235 {
5236 // Subtract the region to the right of the read buffer
5237 clippedExtent -= (readExtent - bufferSize);
5238 }
5239
5240 if (!clippedExtent.IsValid())
5241 {
5242 return 0;
5243 }
5244
5245 return std::max(clippedExtent.ValueOrDie(), 0);
5246 };
5247
5248 if (columns != nullptr)
5249 {
5250 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5251 }
5252
5253 if (rows != nullptr)
5254 {
5255 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5256 }
5257
5258 return true;
5259}
5260
5261template <typename ParamType>
5262bool ValidateTexParameterBase(Context *context,
5263 GLenum target,
5264 GLenum pname,
5265 GLsizei bufSize,
5266 const ParamType *params)
5267{
5268 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5269 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005270 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005271 return false;
5272 }
5273
5274 if (context->getTargetTexture(target) == nullptr)
5275 {
5276 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005277 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005278 return false;
5279 }
5280
5281 const GLsizei minBufSize = 1;
5282 if (bufSize >= 0 && bufSize < minBufSize)
5283 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005284 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005285 return false;
5286 }
5287
5288 switch (pname)
5289 {
5290 case GL_TEXTURE_WRAP_R:
5291 case GL_TEXTURE_SWIZZLE_R:
5292 case GL_TEXTURE_SWIZZLE_G:
5293 case GL_TEXTURE_SWIZZLE_B:
5294 case GL_TEXTURE_SWIZZLE_A:
5295 case GL_TEXTURE_BASE_LEVEL:
5296 case GL_TEXTURE_MAX_LEVEL:
5297 case GL_TEXTURE_COMPARE_MODE:
5298 case GL_TEXTURE_COMPARE_FUNC:
5299 case GL_TEXTURE_MIN_LOD:
5300 case GL_TEXTURE_MAX_LOD:
5301 if (context->getClientMajorVersion() < 3)
5302 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005303 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005304 return false;
5305 }
5306 if (target == GL_TEXTURE_EXTERNAL_OES &&
5307 !context->getExtensions().eglImageExternalEssl3)
5308 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005309 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5310 "available without "
5311 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005312 return false;
5313 }
5314 break;
5315
5316 default:
5317 break;
5318 }
5319
JiangYizhou4cff8d62017-07-06 14:54:09 +08005320 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5321 {
5322 switch (pname)
5323 {
5324 case GL_TEXTURE_MIN_FILTER:
5325 case GL_TEXTURE_MAG_FILTER:
5326 case GL_TEXTURE_WRAP_S:
5327 case GL_TEXTURE_WRAP_T:
5328 case GL_TEXTURE_WRAP_R:
5329 case GL_TEXTURE_MIN_LOD:
5330 case GL_TEXTURE_MAX_LOD:
5331 case GL_TEXTURE_COMPARE_MODE:
5332 case GL_TEXTURE_COMPARE_FUNC:
5333 context->handleError(InvalidEnum()
5334 << "Invalid parameter for 2D multisampled textures.");
5335 return false;
5336 }
5337 }
5338
Jamie Madillbe849e42017-05-02 15:49:00 -04005339 switch (pname)
5340 {
5341 case GL_TEXTURE_WRAP_S:
5342 case GL_TEXTURE_WRAP_T:
5343 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005344 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005345 bool restrictedWrapModes =
5346 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5347 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5348 {
5349 return false;
5350 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005351 }
5352 break;
5353
5354 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005355 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005356 bool restrictedMinFilter =
5357 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5358 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5359 {
5360 return false;
5361 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005362 }
5363 break;
5364
5365 case GL_TEXTURE_MAG_FILTER:
5366 if (!ValidateTextureMagFilterValue(context, params))
5367 {
5368 return false;
5369 }
5370 break;
5371
5372 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005373 if (!context->getExtensions().textureUsage)
5374 {
5375 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5376 return false;
5377 }
5378
Jamie Madillbe849e42017-05-02 15:49:00 -04005379 switch (ConvertToGLenum(params[0]))
5380 {
5381 case GL_NONE:
5382 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5383 break;
5384
5385 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005386 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005387 return false;
5388 }
5389 break;
5390
5391 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5392 if (!context->getExtensions().textureFilterAnisotropic)
5393 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005394 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005395 return false;
5396 }
5397
5398 // we assume the parameter passed to this validation method is truncated, not rounded
5399 if (params[0] < 1)
5400 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005401 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005402 return false;
5403 }
5404 break;
5405
5406 case GL_TEXTURE_MIN_LOD:
5407 case GL_TEXTURE_MAX_LOD:
5408 // any value is permissible
5409 break;
5410
5411 case GL_TEXTURE_COMPARE_MODE:
5412 if (!ValidateTextureCompareModeValue(context, params))
5413 {
5414 return false;
5415 }
5416 break;
5417
5418 case GL_TEXTURE_COMPARE_FUNC:
5419 if (!ValidateTextureCompareFuncValue(context, params))
5420 {
5421 return false;
5422 }
5423 break;
5424
5425 case GL_TEXTURE_SWIZZLE_R:
5426 case GL_TEXTURE_SWIZZLE_G:
5427 case GL_TEXTURE_SWIZZLE_B:
5428 case GL_TEXTURE_SWIZZLE_A:
5429 switch (ConvertToGLenum(params[0]))
5430 {
5431 case GL_RED:
5432 case GL_GREEN:
5433 case GL_BLUE:
5434 case GL_ALPHA:
5435 case GL_ZERO:
5436 case GL_ONE:
5437 break;
5438
5439 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005440 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005441 return false;
5442 }
5443 break;
5444
5445 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005446 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005447 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005448 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005449 return false;
5450 }
5451 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5452 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005453 context->handleError(InvalidOperation()
5454 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005455 return false;
5456 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005457 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5458 {
5459 context->handleError(InvalidOperation()
5460 << "Base level must be 0 for multisampled textures.");
5461 return false;
5462 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005463 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5464 {
5465 context->handleError(InvalidOperation()
5466 << "Base level must be 0 for rectangle textures.");
5467 return false;
5468 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005469 break;
5470
5471 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005472 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005473 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005474 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005475 return false;
5476 }
5477 break;
5478
5479 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5480 if (context->getClientVersion() < Version(3, 1))
5481 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005482 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005483 return false;
5484 }
5485 switch (ConvertToGLenum(params[0]))
5486 {
5487 case GL_DEPTH_COMPONENT:
5488 case GL_STENCIL_INDEX:
5489 break;
5490
5491 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005492 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005493 return false;
5494 }
5495 break;
5496
5497 case GL_TEXTURE_SRGB_DECODE_EXT:
5498 if (!ValidateTextureSRGBDecodeValue(context, params))
5499 {
5500 return false;
5501 }
5502 break;
5503
5504 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005505 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005506 return false;
5507 }
5508
5509 return true;
5510}
5511
5512template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5513template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5514
Jamie Madill12e957f2017-08-26 21:42:26 -04005515bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5516{
5517 if (index >= MAX_VERTEX_ATTRIBS)
5518 {
5519 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5520 return false;
5521 }
5522
5523 return true;
5524}
5525
5526bool ValidateGetActiveUniformBlockivBase(Context *context,
5527 GLuint program,
5528 GLuint uniformBlockIndex,
5529 GLenum pname,
5530 GLsizei *length)
5531{
5532 if (length)
5533 {
5534 *length = 0;
5535 }
5536
5537 if (context->getClientMajorVersion() < 3)
5538 {
5539 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5540 return false;
5541 }
5542
5543 Program *programObject = GetValidProgram(context, program);
5544 if (!programObject)
5545 {
5546 return false;
5547 }
5548
5549 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5550 {
5551 context->handleError(InvalidValue()
5552 << "uniformBlockIndex exceeds active uniform block count.");
5553 return false;
5554 }
5555
5556 switch (pname)
5557 {
5558 case GL_UNIFORM_BLOCK_BINDING:
5559 case GL_UNIFORM_BLOCK_DATA_SIZE:
5560 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5561 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5562 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5563 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5564 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5565 break;
5566
5567 default:
5568 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5569 return false;
5570 }
5571
5572 if (length)
5573 {
5574 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5575 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005576 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005577 programObject->getUniformBlockByIndex(uniformBlockIndex);
5578 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5579 }
5580 else
5581 {
5582 *length = 1;
5583 }
5584 }
5585
5586 return true;
5587}
5588
Jamie Madill9696d072017-08-26 23:19:57 -04005589template <typename ParamType>
5590bool ValidateSamplerParameterBase(Context *context,
5591 GLuint sampler,
5592 GLenum pname,
5593 GLsizei bufSize,
5594 ParamType *params)
5595{
5596 if (context->getClientMajorVersion() < 3)
5597 {
5598 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5599 return false;
5600 }
5601
5602 if (!context->isSampler(sampler))
5603 {
5604 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5605 return false;
5606 }
5607
5608 const GLsizei minBufSize = 1;
5609 if (bufSize >= 0 && bufSize < minBufSize)
5610 {
5611 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5612 return false;
5613 }
5614
5615 switch (pname)
5616 {
5617 case GL_TEXTURE_WRAP_S:
5618 case GL_TEXTURE_WRAP_T:
5619 case GL_TEXTURE_WRAP_R:
5620 if (!ValidateTextureWrapModeValue(context, params, false))
5621 {
5622 return false;
5623 }
5624 break;
5625
5626 case GL_TEXTURE_MIN_FILTER:
5627 if (!ValidateTextureMinFilterValue(context, params, false))
5628 {
5629 return false;
5630 }
5631 break;
5632
5633 case GL_TEXTURE_MAG_FILTER:
5634 if (!ValidateTextureMagFilterValue(context, params))
5635 {
5636 return false;
5637 }
5638 break;
5639
5640 case GL_TEXTURE_MIN_LOD:
5641 case GL_TEXTURE_MAX_LOD:
5642 // any value is permissible
5643 break;
5644
5645 case GL_TEXTURE_COMPARE_MODE:
5646 if (!ValidateTextureCompareModeValue(context, params))
5647 {
5648 return false;
5649 }
5650 break;
5651
5652 case GL_TEXTURE_COMPARE_FUNC:
5653 if (!ValidateTextureCompareFuncValue(context, params))
5654 {
5655 return false;
5656 }
5657 break;
5658
5659 case GL_TEXTURE_SRGB_DECODE_EXT:
5660 if (!ValidateTextureSRGBDecodeValue(context, params))
5661 {
5662 return false;
5663 }
5664 break;
5665
5666 default:
5667 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5668 return false;
5669 }
5670
5671 return true;
5672}
5673
5674template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5675template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5676
5677bool ValidateGetSamplerParameterBase(Context *context,
5678 GLuint sampler,
5679 GLenum pname,
5680 GLsizei *length)
5681{
5682 if (length)
5683 {
5684 *length = 0;
5685 }
5686
5687 if (context->getClientMajorVersion() < 3)
5688 {
5689 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5690 return false;
5691 }
5692
5693 if (!context->isSampler(sampler))
5694 {
5695 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5696 return false;
5697 }
5698
5699 switch (pname)
5700 {
5701 case GL_TEXTURE_WRAP_S:
5702 case GL_TEXTURE_WRAP_T:
5703 case GL_TEXTURE_WRAP_R:
5704 case GL_TEXTURE_MIN_FILTER:
5705 case GL_TEXTURE_MAG_FILTER:
5706 case GL_TEXTURE_MIN_LOD:
5707 case GL_TEXTURE_MAX_LOD:
5708 case GL_TEXTURE_COMPARE_MODE:
5709 case GL_TEXTURE_COMPARE_FUNC:
5710 break;
5711
5712 case GL_TEXTURE_SRGB_DECODE_EXT:
5713 if (!context->getExtensions().textureSRGBDecode)
5714 {
5715 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5716 return false;
5717 }
5718 break;
5719
5720 default:
5721 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5722 return false;
5723 }
5724
5725 if (length)
5726 {
5727 *length = 1;
5728 }
5729 return true;
5730}
5731
5732bool ValidateGetInternalFormativBase(Context *context,
5733 GLenum target,
5734 GLenum internalformat,
5735 GLenum pname,
5736 GLsizei bufSize,
5737 GLsizei *numParams)
5738{
5739 if (numParams)
5740 {
5741 *numParams = 0;
5742 }
5743
5744 if (context->getClientMajorVersion() < 3)
5745 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005746 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005747 return false;
5748 }
5749
5750 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5751 if (!formatCaps.renderable)
5752 {
5753 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5754 return false;
5755 }
5756
5757 switch (target)
5758 {
5759 case GL_RENDERBUFFER:
5760 break;
5761
5762 case GL_TEXTURE_2D_MULTISAMPLE:
5763 if (context->getClientVersion() < ES_3_1)
5764 {
5765 context->handleError(InvalidOperation()
5766 << "Texture target requires at least OpenGL ES 3.1.");
5767 return false;
5768 }
5769 break;
5770
5771 default:
5772 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5773 return false;
5774 }
5775
5776 if (bufSize < 0)
5777 {
5778 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5779 return false;
5780 }
5781
5782 GLsizei maxWriteParams = 0;
5783 switch (pname)
5784 {
5785 case GL_NUM_SAMPLE_COUNTS:
5786 maxWriteParams = 1;
5787 break;
5788
5789 case GL_SAMPLES:
5790 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5791 break;
5792
5793 default:
5794 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5795 return false;
5796 }
5797
5798 if (numParams)
5799 {
5800 // glGetInternalFormativ will not overflow bufSize
5801 *numParams = std::min(bufSize, maxWriteParams);
5802 }
5803
5804 return true;
5805}
5806
Jamie Madillc29968b2016-01-20 11:17:23 -05005807} // namespace gl