blob: ae564b74122e0ad54b733acd4e21553e9894ba8e [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
400 const auto &programOutputTypes = program->getOutputVariableTypes();
401 for (size_t drawBufferIdx = 0; drawBufferIdx < programOutputTypes.size(); drawBufferIdx++)
402 {
403 GLenum outputType = programOutputTypes[drawBufferIdx];
404 GLenum inputType = framebuffer->getDrawbufferWriteType(drawBufferIdx);
405 if (outputType != GL_NONE && inputType != GL_NONE && inputType != outputType)
406 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500407 context->handleError(InvalidOperation() << "Fragment shader output type does not "
408 "match the bound framebuffer attachment "
409 "type.");
Geoff Lange0cff192017-05-30 13:04:56 -0400410 return false;
411 }
412 }
413
414 return true;
415}
416
Geoff Lang9ab5b822017-05-30 16:19:23 -0400417bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
418{
Jamie Madillcac94a92017-11-10 10:09:32 -0500419 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400420 const Program *program = context->getGLState().getProgram();
421 const VertexArray *vao = context->getGLState().getVertexArray();
Jamie Madillcac94a92017-11-10 10:09:32 -0500422 const auto &vertexAttribs = vao->getVertexAttributes();
423 const auto &currentValues = glState.getVertexAttribCurrentValues();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400424
Jamie Madillcac94a92017-11-10 10:09:32 -0500425 for (const sh::Attribute &shaderAttribute : program->getAttributes())
Geoff Lang9ab5b822017-05-30 16:19:23 -0400426 {
Geoff Lang69df2422017-07-05 12:42:31 -0400427 // gl_VertexID and gl_InstanceID are active attributes but don't have a bound attribute.
428 if (shaderAttribute.isBuiltIn())
429 {
430 continue;
431 }
432
Geoff Lang9ab5b822017-05-30 16:19:23 -0400433 GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
434
Jamie Madillcac94a92017-11-10 10:09:32 -0500435 const auto &attrib = vertexAttribs[shaderAttribute.location];
436 GLenum vertexType = attrib.enabled ? GetVertexAttributeBaseType(attrib)
437 : currentValues[shaderAttribute.location].Type;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400438
439 if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
440 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500441 context->handleError(InvalidOperation() << "Vertex shader input type does not "
442 "match the type of the bound vertex "
443 "attribute.");
Geoff Lang9ab5b822017-05-30 16:19:23 -0400444 return false;
445 }
446 }
447
448 return true;
449}
450
Geoff Langf41a7152016-09-19 15:11:17 -0400451} // anonymous namespace
452
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500453bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400454{
Jamie Madilld7460c72014-01-21 16:38:14 -0500455 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400456 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800457 case GL_TEXTURE_2D:
458 case GL_TEXTURE_CUBE_MAP:
459 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400460
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400461 case GL_TEXTURE_RECTANGLE_ANGLE:
462 return context->getExtensions().textureRectangle;
463
He Yunchaoced53ae2016-11-29 15:00:51 +0800464 case GL_TEXTURE_3D:
465 case GL_TEXTURE_2D_ARRAY:
466 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500467
He Yunchaoced53ae2016-11-29 15:00:51 +0800468 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800469 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400470
He Yunchaoced53ae2016-11-29 15:00:51 +0800471 default:
472 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500473 }
Jamie Madill35d15012013-10-07 10:46:37 -0400474}
475
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500476bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
477{
478 switch (target)
479 {
480 case GL_TEXTURE_2D:
481 case GL_TEXTURE_CUBE_MAP:
482 return true;
483
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400484 case GL_TEXTURE_RECTANGLE_ANGLE:
485 return context->getExtensions().textureRectangle;
486
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500487 default:
488 return false;
489 }
490}
491
492bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
493{
494 switch (target)
495 {
496 case GL_TEXTURE_3D:
497 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300498 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500499
500 default:
501 return false;
502 }
503}
504
Ian Ewellbda75592016-04-18 17:25:54 -0400505// Most texture GL calls are not compatible with external textures, so we have a separate validation
506// function for use in the GL calls that do
507bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
508{
509 return (target == GL_TEXTURE_EXTERNAL_OES) &&
510 (context->getExtensions().eglImageExternal ||
511 context->getExtensions().eglStreamConsumerExternal);
512}
513
Shannon Woods4dfed832014-03-17 20:03:39 -0400514// This function differs from ValidTextureTarget in that the target must be
515// usable as the destination of a 2D operation-- so a cube face is valid, but
516// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400517// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500518bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400519{
520 switch (target)
521 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800522 case GL_TEXTURE_2D:
523 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
524 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
525 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
526 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
527 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
528 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
529 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400530 case GL_TEXTURE_RECTANGLE_ANGLE:
531 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800532 default:
533 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500534 }
535}
536
Jamie Madillbe849e42017-05-02 15:49:00 -0400537bool ValidateDrawElementsInstancedBase(ValidationContext *context,
538 GLenum mode,
539 GLsizei count,
540 GLenum type,
541 const GLvoid *indices,
542 GLsizei primcount)
543{
544 if (primcount < 0)
545 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700546 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400547 return false;
548 }
549
550 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
551 {
552 return false;
553 }
554
555 // No-op zero primitive count
556 return (primcount > 0);
557}
558
559bool ValidateDrawArraysInstancedBase(Context *context,
560 GLenum mode,
561 GLint first,
562 GLsizei count,
563 GLsizei primcount)
564{
565 if (primcount < 0)
566 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700567 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400568 return false;
569 }
570
571 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
572 {
573 return false;
574 }
575
576 // No-op if zero primitive count
577 return (primcount > 0);
578}
579
Corentin Wallez0dc97812017-06-22 14:38:44 -0400580bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400581{
582 // Verify there is at least one active attribute with a divisor of zero
583 const State &state = context->getGLState();
584
585 Program *program = state.getProgram();
586
587 const auto &attribs = state.getVertexArray()->getVertexAttributes();
588 const auto &bindings = state.getVertexArray()->getVertexBindings();
589 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
590 {
591 const VertexAttribute &attrib = attribs[attributeIndex];
592 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300593 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400594 {
595 return true;
596 }
597 }
598
Brandon Jonesafa75152017-07-21 13:11:29 -0700599 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400600 return false;
601}
602
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500603bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
604{
605 switch (target)
606 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800607 case GL_TEXTURE_3D:
608 case GL_TEXTURE_2D_ARRAY:
609 return true;
610 default:
611 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400612 }
613}
614
He Yunchao11b038b2016-11-22 21:24:04 +0800615bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
616{
617 switch (target)
618 {
619 case GL_TEXTURE_2D:
620 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
621 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
622 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
623 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
624 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
625 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
626 case GL_TEXTURE_3D:
627 case GL_TEXTURE_2D_ARRAY:
628 case GL_TEXTURE_2D_MULTISAMPLE:
629 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400630 case GL_TEXTURE_RECTANGLE_ANGLE:
631 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800632 default:
633 return false;
634 }
635}
636
Geoff Lange8afa902017-09-27 15:00:43 -0400637bool ValidFramebufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500638{
He Yunchaoced53ae2016-11-29 15:00:51 +0800639 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
640 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400641 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500642
643 switch (target)
644 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800645 case GL_FRAMEBUFFER:
646 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400647
He Yunchaoced53ae2016-11-29 15:00:51 +0800648 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800649 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400650 return (context->getExtensions().framebufferBlit ||
651 context->getClientMajorVersion() >= 3);
652
He Yunchaoced53ae2016-11-29 15:00:51 +0800653 default:
654 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500655 }
656}
657
Corentin Wallez336129f2017-10-17 15:55:40 -0400658bool ValidBufferType(const ValidationContext *context, BufferBinding target)
Jamie Madill8c96d582014-03-05 15:01:23 -0500659{
660 switch (target)
661 {
Corentin Wallez336129f2017-10-17 15:55:40 -0400662 case BufferBinding::ElementArray:
663 case BufferBinding::Array:
He Yunchaoced53ae2016-11-29 15:00:51 +0800664 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -0500665
Corentin Wallez336129f2017-10-17 15:55:40 -0400666 case BufferBinding::PixelPack:
667 case BufferBinding::PixelUnpack:
He Yunchaoced53ae2016-11-29 15:00:51 +0800668 return (context->getExtensions().pixelBufferObject ||
669 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -0400670
Corentin Wallez336129f2017-10-17 15:55:40 -0400671 case BufferBinding::CopyRead:
672 case BufferBinding::CopyWrite:
673 case BufferBinding::TransformFeedback:
674 case BufferBinding::Uniform:
He Yunchaoced53ae2016-11-29 15:00:51 +0800675 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -0500676
Corentin Wallez336129f2017-10-17 15:55:40 -0400677 case BufferBinding::AtomicCounter:
678 case BufferBinding::ShaderStorage:
679 case BufferBinding::DrawIndirect:
680 case BufferBinding::DispatchIndirect:
He Yunchaoced53ae2016-11-29 15:00:51 +0800681 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -0400682
He Yunchaoced53ae2016-11-29 15:00:51 +0800683 default:
684 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -0500685 }
686}
687
Jamie Madillc29968b2016-01-20 11:17:23 -0500688bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400689{
Jamie Madillc29968b2016-01-20 11:17:23 -0500690 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400691 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400692 switch (target)
693 {
Jamie Madillc29968b2016-01-20 11:17:23 -0500694 case GL_TEXTURE_2D:
695 maxDimension = caps.max2DTextureSize;
696 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800697 case GL_TEXTURE_CUBE_MAP:
698 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
699 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
700 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
701 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
702 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
703 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
704 maxDimension = caps.maxCubeMapTextureSize;
705 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400706 case GL_TEXTURE_RECTANGLE_ANGLE:
707 return level == 0;
He Yunchaoced53ae2016-11-29 15:00:51 +0800708 case GL_TEXTURE_3D:
709 maxDimension = caps.max3DTextureSize;
710 break;
711 case GL_TEXTURE_2D_ARRAY:
712 maxDimension = caps.max2DTextureSize;
713 break;
He Yunchao11b038b2016-11-22 21:24:04 +0800714 case GL_TEXTURE_2D_MULTISAMPLE:
715 maxDimension = caps.max2DTextureSize;
716 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800717 default:
718 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400719 }
720
Brandon Jones6cad5662017-06-14 13:25:13 -0700721 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400722}
723
Brandon Jones6cad5662017-06-14 13:25:13 -0700724bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -0700725 GLenum target,
726 GLint level,
727 GLsizei width,
728 GLsizei height,
729 GLsizei depth,
730 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400731{
Brandon Jones6cad5662017-06-14 13:25:13 -0700732 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400733 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700734 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400735 return false;
736 }
Austin Kinross08528e12015-10-07 16:24:40 -0700737 // TexSubImage parameters can be NPOT without textureNPOT extension,
738 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500739 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500740 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500741 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400742 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400743 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700744 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400745 return false;
746 }
747
748 if (!ValidMipLevel(context, target, level))
749 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700750 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400751 return false;
752 }
753
754 return true;
755}
756
Geoff Lang0d8b7242015-09-09 14:56:53 -0400757bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
758{
759 // List of compressed format that require that the texture size is smaller than or a multiple of
760 // the compressed block size.
761 switch (internalFormat)
762 {
763 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
764 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
765 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
766 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -0400767 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
768 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
769 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
770 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -0800771 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800772 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
773 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
774 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
775 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
776 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
777 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -0400778 return true;
779
780 default:
781 return false;
782 }
783}
784
Geoff Lang966c9402017-04-18 12:38:27 -0400785bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
786{
787 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
788 (size % blockSize == 0);
789}
790
Jamie Madillc29968b2016-01-20 11:17:23 -0500791bool ValidCompressedImageSize(const ValidationContext *context,
792 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400793 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500794 GLsizei width,
795 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400796{
Geoff Langca271392017-04-05 12:30:00 -0400797 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400798 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400799 {
800 return false;
801 }
802
Geoff Lang966c9402017-04-18 12:38:27 -0400803 if (width < 0 || height < 0)
804 {
805 return false;
806 }
807
808 if (CompressedTextureFormatRequiresExactSize(internalFormat))
809 {
810 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
811 // block size for level 0 but WebGL disallows this.
812 bool smallerThanBlockSizeAllowed =
813 level > 0 || !context->getExtensions().webglCompatibility;
814
815 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
816 smallerThanBlockSizeAllowed) ||
817 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
818 smallerThanBlockSizeAllowed))
819 {
820 return false;
821 }
822 }
823
824 return true;
825}
826
827bool ValidCompressedSubImageSize(const ValidationContext *context,
828 GLenum internalFormat,
829 GLint xoffset,
830 GLint yoffset,
831 GLsizei width,
832 GLsizei height,
833 size_t textureWidth,
834 size_t textureHeight)
835{
836 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
837 if (!formatInfo.compressed)
838 {
839 return false;
840 }
841
Geoff Lang44ff5a72017-02-03 15:15:43 -0500842 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400843 {
844 return false;
845 }
846
Geoff Lang0d8b7242015-09-09 14:56:53 -0400847 if (CompressedTextureFormatRequiresExactSize(internalFormat))
848 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500849 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400850 yoffset % formatInfo.compressedBlockHeight != 0)
851 {
852 return false;
853 }
854
855 // Allowed to either have data that is a multiple of block size or is smaller than the block
856 // size but fills the entire mip
857 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
858 static_cast<size_t>(width) == textureWidth &&
859 static_cast<size_t>(height) == textureHeight;
860 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
861 (height % formatInfo.compressedBlockHeight) == 0;
862 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400863 {
864 return false;
865 }
866 }
867
Geoff Langd4f180b2013-09-24 13:57:44 -0400868 return true;
869}
870
Geoff Langff5b2d52016-09-07 11:32:23 -0400871bool ValidImageDataSize(ValidationContext *context,
872 GLenum textureTarget,
873 GLsizei width,
874 GLsizei height,
875 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400876 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400877 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400878 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400879 GLsizei imageSize)
880{
Corentin Wallez336129f2017-10-17 15:55:40 -0400881 gl::Buffer *pixelUnpackBuffer =
882 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400883 if (pixelUnpackBuffer == nullptr && imageSize < 0)
884 {
885 // Checks are not required
886 return true;
887 }
888
889 // ...the data would be unpacked from the buffer object such that the memory reads required
890 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400891 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
892 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400893 const gl::Extents size(width, height, depth);
894 const auto &unpack = context->getGLState().getUnpackState();
895
896 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
897 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
898 if (endByteOrErr.isError())
899 {
900 context->handleError(endByteOrErr.getError());
901 return false;
902 }
903
904 GLuint endByte = endByteOrErr.getResult();
905
906 if (pixelUnpackBuffer)
907 {
908 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
909 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
910 checkedEndByte += checkedOffset;
911
912 if (!checkedEndByte.IsValid() ||
913 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
914 {
915 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500916 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400917 return false;
918 }
919 }
920 else
921 {
922 ASSERT(imageSize >= 0);
923 if (pixels == nullptr && imageSize != 0)
924 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500925 context->handleError(InvalidOperation()
926 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400927 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400928 }
929
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400930 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400931 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500932 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400933 return false;
934 }
935 }
936
937 return true;
938}
939
Geoff Lang37dde692014-01-31 16:34:54 -0500940bool ValidQueryType(const Context *context, GLenum queryType)
941{
He Yunchaoced53ae2016-11-29 15:00:51 +0800942 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
943 "GL extension enums not equal.");
944 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
945 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -0500946
947 switch (queryType)
948 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800949 case GL_ANY_SAMPLES_PASSED:
950 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400951 return context->getClientMajorVersion() >= 3 ||
952 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +0800953 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
954 return (context->getClientMajorVersion() >= 3);
955 case GL_TIME_ELAPSED_EXT:
956 return context->getExtensions().disjointTimerQuery;
957 case GL_COMMANDS_COMPLETED_CHROMIUM:
958 return context->getExtensions().syncQuery;
959 default:
960 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500961 }
962}
963
Geoff Lang2d62ab72017-03-23 16:54:40 -0400964bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
965 GLenum type,
966 GLboolean normalized,
967 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400968 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400969 bool pureInteger)
970{
971 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400972 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
973 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
974 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
975 // parameter exceeds 255.
976 constexpr GLsizei kMaxWebGLStride = 255;
977 if (stride > kMaxWebGLStride)
978 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500979 context->handleError(InvalidValue()
980 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -0400981 return false;
982 }
983
984 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
985 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
986 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
987 // or an INVALID_OPERATION error is generated.
988 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
989 size_t typeSize = GetVertexFormatTypeSize(internalType);
990
991 ASSERT(isPow2(typeSize) && typeSize > 0);
992 size_t sizeMask = (typeSize - 1);
993 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
994 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700995 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400996 return false;
997 }
998
999 if ((stride & sizeMask) != 0)
1000 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001001 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001002 return false;
1003 }
1004
1005 return true;
1006}
1007
Jamie Madillef300b12016-10-07 15:12:09 -04001008Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001009{
He Yunchaoced53ae2016-11-29 15:00:51 +08001010 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1011 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1012 // or program object and INVALID_OPERATION if the provided name identifies an object
1013 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001014
Dian Xiang769769a2015-09-09 15:20:08 -07001015 Program *validProgram = context->getProgram(id);
1016
1017 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001018 {
Dian Xiang769769a2015-09-09 15:20:08 -07001019 if (context->getShader(id))
1020 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001021 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001022 }
1023 else
1024 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001025 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001026 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001027 }
Dian Xiang769769a2015-09-09 15:20:08 -07001028
1029 return validProgram;
1030}
1031
Jamie Madillef300b12016-10-07 15:12:09 -04001032Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001033{
1034 // See ValidProgram for spec details.
1035
1036 Shader *validShader = context->getShader(id);
1037
1038 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001039 {
Dian Xiang769769a2015-09-09 15:20:08 -07001040 if (context->getProgram(id))
1041 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001042 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001043 }
1044 else
1045 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001046 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001047 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001048 }
Dian Xiang769769a2015-09-09 15:20:08 -07001049
1050 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001051}
1052
Geoff Langb1196682014-07-23 13:47:29 -04001053bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001054{
Geoff Langfa125c92017-10-24 13:01:46 -04001055 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001056 {
Geoff Langfa125c92017-10-24 13:01:46 -04001057 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1058 {
1059 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1060 return false;
1061 }
Jamie Madillb4472272014-07-03 10:38:55 -04001062
Geoff Langfa125c92017-10-24 13:01:46 -04001063 // Color attachment 0 is validated below because it is always valid
1064 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001065 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001066 {
Geoff Langfa125c92017-10-24 13:01:46 -04001067 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001068 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001069 }
1070 }
1071 else
1072 {
1073 switch (attachment)
1074 {
Geoff Langfa125c92017-10-24 13:01:46 -04001075 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001076 case GL_DEPTH_ATTACHMENT:
1077 case GL_STENCIL_ATTACHMENT:
1078 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001079
He Yunchaoced53ae2016-11-29 15:00:51 +08001080 case GL_DEPTH_STENCIL_ATTACHMENT:
1081 if (!context->getExtensions().webglCompatibility &&
1082 context->getClientMajorVersion() < 3)
1083 {
Geoff Langfa125c92017-10-24 13:01:46 -04001084 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001085 return false;
1086 }
1087 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001088
He Yunchaoced53ae2016-11-29 15:00:51 +08001089 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001090 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001091 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001092 }
1093 }
1094
1095 return true;
1096}
1097
Jamie Madille8fb6402017-02-14 17:56:40 -05001098bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001099 GLenum target,
1100 GLsizei samples,
1101 GLenum internalformat,
1102 GLsizei width,
1103 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001104{
1105 switch (target)
1106 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001107 case GL_RENDERBUFFER:
1108 break;
1109 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001110 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001111 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001112 }
1113
1114 if (width < 0 || height < 0 || samples < 0)
1115 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001116 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001117 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001118 }
1119
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001120 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1121 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1122
1123 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001124 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001125 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001126 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001127 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001128 }
1129
1130 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1131 // 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 -08001132 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001133 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1134 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001135 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001136 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001137 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001138 }
1139
Geoff Langaae65a42014-05-26 12:43:44 -04001140 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001141 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001142 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001143 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001144 }
1145
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001146 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001147 if (handle == 0)
1148 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001149 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001150 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001151 }
1152
1153 return true;
1154}
1155
He Yunchaoced53ae2016-11-29 15:00:51 +08001156bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1157 GLenum target,
1158 GLenum attachment,
1159 GLenum renderbuffertarget,
1160 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001161{
Geoff Lange8afa902017-09-27 15:00:43 -04001162 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001163 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001164 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001165 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001166 }
1167
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001168 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001169
Jamie Madill84115c92015-04-23 15:00:07 -04001170 ASSERT(framebuffer);
1171 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001172 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001173 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001174 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001175 }
1176
Jamie Madillb4472272014-07-03 10:38:55 -04001177 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001178 {
Jamie Madillb4472272014-07-03 10:38:55 -04001179 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001180 }
1181
Jamie Madillab9d82c2014-01-21 16:38:14 -05001182 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1183 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1184 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1185 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1186 if (renderbuffer != 0)
1187 {
1188 if (!context->getRenderbuffer(renderbuffer))
1189 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001190 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001191 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001192 }
1193 }
1194
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001195 return true;
1196}
1197
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001198bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001199 GLint srcX0,
1200 GLint srcY0,
1201 GLint srcX1,
1202 GLint srcY1,
1203 GLint dstX0,
1204 GLint dstY0,
1205 GLint dstX1,
1206 GLint dstY1,
1207 GLbitfield mask,
1208 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001209{
1210 switch (filter)
1211 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001212 case GL_NEAREST:
1213 break;
1214 case GL_LINEAR:
1215 break;
1216 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001217 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001218 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001219 }
1220
1221 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1222 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001223 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001224 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001225 }
1226
1227 if (mask == 0)
1228 {
1229 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1230 // buffers are copied.
1231 return false;
1232 }
1233
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001234 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1235 // color buffer, leaving only nearest being unfiltered from above
1236 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1237 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001238 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001239 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001240 }
1241
Jamie Madill51f40ec2016-06-15 14:06:00 -04001242 const auto &glState = context->getGLState();
1243 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1244 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001245
1246 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001247 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001248 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001249 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001250 }
1251
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001252 if (readFramebuffer->id() == drawFramebuffer->id())
1253 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001254 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001255 return false;
1256 }
1257
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001258 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001259 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001260 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001261 return false;
1262 }
1263
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001264 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001265 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001266 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001267 return false;
1268 }
1269
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001270 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001271 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001272 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001273 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001274 }
1275
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001276 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1277
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001278 if (mask & GL_COLOR_BUFFER_BIT)
1279 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001280 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001281 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001282
He Yunchao66a41a22016-12-15 16:45:05 +08001283 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001284 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001285 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001286
Geoff Langa15472a2015-08-11 11:48:03 -04001287 for (size_t drawbufferIdx = 0;
1288 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001289 {
Geoff Langa15472a2015-08-11 11:48:03 -04001290 const FramebufferAttachment *attachment =
1291 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1292 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001293 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001294 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001295
Geoff Langb2f3d052013-08-13 12:49:27 -04001296 // The GL ES 3.0.2 spec (pg 193) states that:
1297 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001298 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1299 // as well
1300 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1301 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001302 // Changes with EXT_color_buffer_float:
1303 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001304 GLenum readComponentType = readFormat.info->componentType;
1305 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001306 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001307 readComponentType == GL_SIGNED_NORMALIZED);
1308 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1309 drawComponentType == GL_SIGNED_NORMALIZED);
1310
1311 if (extensions.colorBufferFloat)
1312 {
1313 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1314 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1315
1316 if (readFixedOrFloat != drawFixedOrFloat)
1317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001318 context->handleError(InvalidOperation()
1319 << "If the read buffer contains fixed-point or "
1320 "floating-point values, the draw buffer must "
1321 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001322 return false;
1323 }
1324 }
1325 else if (readFixedPoint != drawFixedPoint)
1326 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001327 context->handleError(InvalidOperation()
1328 << "If the read buffer contains fixed-point values, "
1329 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001330 return false;
1331 }
1332
1333 if (readComponentType == GL_UNSIGNED_INT &&
1334 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001335 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001336 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001337 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001338 }
1339
Jamie Madill6163c752015-12-07 16:32:59 -05001340 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001341 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001342 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001343 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001344 }
1345
Jamie Madilla3944d42016-07-22 22:13:26 -04001346 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001347 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001348 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001349 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001350 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001351 }
Geoff Lange4915782017-04-12 15:19:07 -04001352
1353 if (context->getExtensions().webglCompatibility &&
1354 *readColorBuffer == *attachment)
1355 {
1356 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001357 InvalidOperation()
1358 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001359 return false;
1360 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001361 }
1362 }
1363
Jamie Madilla3944d42016-07-22 22:13:26 -04001364 if ((readFormat.info->componentType == GL_INT ||
1365 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1366 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001367 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001368 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001369 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001370 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001371 }
He Yunchao66a41a22016-12-15 16:45:05 +08001372 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1373 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1374 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1375 // situation is an application error that would lead to a crash in ANGLE.
1376 else if (drawFramebuffer->hasEnabledDrawBuffer())
1377 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001378 context->handleError(
1379 InvalidOperation()
1380 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001381 return false;
1382 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001383 }
1384
He Yunchaoced53ae2016-11-29 15:00:51 +08001385 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001386 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1387 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001388 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001389 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001390 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001391 const gl::FramebufferAttachment *readBuffer =
1392 readFramebuffer->getAttachment(attachments[i]);
1393 const gl::FramebufferAttachment *drawBuffer =
1394 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001395
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001396 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001397 {
Kenneth Russell69382852017-07-21 16:38:44 -04001398 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001399 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001400 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001401 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001402 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001403
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001404 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001406 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001407 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001408 }
Geoff Lange4915782017-04-12 15:19:07 -04001409
1410 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1411 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001412 context->handleError(
1413 InvalidOperation()
1414 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001415 return false;
1416 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001417 }
He Yunchao66a41a22016-12-15 16:45:05 +08001418 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1419 else if (drawBuffer)
1420 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001421 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1422 "depth/stencil attachment of a "
1423 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001424 return false;
1425 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001426 }
1427 }
1428
Martin Radeva3ed4572017-07-27 18:29:37 +03001429 // ANGLE_multiview, Revision 1:
1430 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1431 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1432 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1433 {
1434 context->handleError(InvalidFramebufferOperation()
1435 << "Attempt to read from a multi-view framebuffer.");
1436 return false;
1437 }
1438 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1439 {
1440 context->handleError(InvalidFramebufferOperation()
1441 << "Attempt to write to a multi-view framebuffer.");
1442 return false;
1443 }
1444
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001445 return true;
1446}
1447
Jamie Madill4928b7c2017-06-20 12:57:39 -04001448bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001449 GLint x,
1450 GLint y,
1451 GLsizei width,
1452 GLsizei height,
1453 GLenum format,
1454 GLenum type,
1455 GLsizei bufSize,
1456 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001457 GLsizei *columns,
1458 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001459 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001460{
1461 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001462 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001463 return false;
1464 }
1465
Geoff Lang62fce5b2016-09-30 10:46:35 -04001466 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001467 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001468 {
Geoff Langb1196682014-07-23 13:47:29 -04001469 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001470 }
1471
Geoff Lang62fce5b2016-09-30 10:46:35 -04001472 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001473 {
Geoff Langb1196682014-07-23 13:47:29 -04001474 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001475 }
1476
Jamie Madillc29968b2016-01-20 11:17:23 -05001477 return true;
1478}
1479
1480bool ValidateReadnPixelsEXT(Context *context,
1481 GLint x,
1482 GLint y,
1483 GLsizei width,
1484 GLsizei height,
1485 GLenum format,
1486 GLenum type,
1487 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001488 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001489{
1490 if (bufSize < 0)
1491 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001492 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001493 return false;
1494 }
1495
Geoff Lang62fce5b2016-09-30 10:46:35 -04001496 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001497 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001498}
Jamie Madill26e91952014-03-05 15:01:27 -05001499
Jamie Madill4928b7c2017-06-20 12:57:39 -04001500bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001501 GLint x,
1502 GLint y,
1503 GLsizei width,
1504 GLsizei height,
1505 GLenum format,
1506 GLenum type,
1507 GLsizei bufSize,
1508 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001509 GLsizei *columns,
1510 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001511 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001512{
1513 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001514 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001515 return false;
1516 }
1517
Geoff Lange93daba2017-03-30 13:54:40 -04001518 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1519 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001520 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001521 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001522 }
1523
Geoff Lang62fce5b2016-09-30 10:46:35 -04001524 if (!ValidateRobustBufferSize(context, bufSize, *length))
1525 {
1526 return false;
1527 }
1528
1529 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001530}
1531
Jamie Madillf0e04492017-08-26 15:28:42 -04001532bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001533{
1534 if (!context->getExtensions().occlusionQueryBoolean &&
1535 !context->getExtensions().disjointTimerQuery)
1536 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001537 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001538 return false;
1539 }
1540
Olli Etuaho41997e72016-03-10 13:38:39 +02001541 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001542}
1543
Jamie Madillf0e04492017-08-26 15:28:42 -04001544bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001545{
1546 if (!context->getExtensions().occlusionQueryBoolean &&
1547 !context->getExtensions().disjointTimerQuery)
1548 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001549 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001550 return false;
1551 }
1552
Olli Etuaho41997e72016-03-10 13:38:39 +02001553 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001554}
1555
Jamie Madillf0e04492017-08-26 15:28:42 -04001556bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1557{
1558 if (!context->getExtensions().occlusionQueryBoolean &&
1559 !context->getExtensions().disjointTimerQuery)
1560 {
1561 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1562 return false;
1563 }
1564
1565 return true;
1566}
1567
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001568bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001569{
1570 if (!ValidQueryType(context, target))
1571 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001572 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001573 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001574 }
1575
1576 if (id == 0)
1577 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001578 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001579 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001580 }
1581
1582 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1583 // of zero, if the active query object name for <target> is non-zero (for the
1584 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1585 // the active query for either target is non-zero), if <id> is the name of an
1586 // existing query object whose type does not match <target>, or if <id> is the
1587 // active query object name for any query type, the error INVALID_OPERATION is
1588 // generated.
1589
1590 // Ensure no other queries are active
1591 // NOTE: If other queries than occlusion are supported, we will need to check
1592 // separately that:
1593 // a) The query ID passed is not the current active query for any target/type
1594 // b) There are no active queries for the requested target (and in the case
1595 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1596 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001597
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001598 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001599 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001600 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001601 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001602 }
1603
1604 Query *queryObject = context->getQuery(id, true, target);
1605
1606 // check that name was obtained with glGenQueries
1607 if (!queryObject)
1608 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001609 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001610 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001611 }
1612
1613 // check for type mismatch
1614 if (queryObject->getType() != target)
1615 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001616 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001617 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001618 }
1619
1620 return true;
1621}
1622
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001623bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1624{
1625 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001626 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001627 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001628 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001629 return false;
1630 }
1631
1632 return ValidateBeginQueryBase(context, target, id);
1633}
1634
1635bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001636{
1637 if (!ValidQueryType(context, target))
1638 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001639 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001640 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001641 }
1642
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001643 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001644
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001645 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001647 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001648 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001649 }
1650
Jamie Madill45c785d2014-05-13 14:09:34 -04001651 return true;
1652}
1653
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001654bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1655{
1656 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001657 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001658 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001659 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001660 return false;
1661 }
1662
1663 return ValidateEndQueryBase(context, target);
1664}
1665
1666bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1667{
1668 if (!context->getExtensions().disjointTimerQuery)
1669 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001670 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001671 return false;
1672 }
1673
1674 if (target != GL_TIMESTAMP_EXT)
1675 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001676 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001677 return false;
1678 }
1679
1680 Query *queryObject = context->getQuery(id, true, target);
1681 if (queryObject == nullptr)
1682 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001683 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001684 return false;
1685 }
1686
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001687 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001688 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001689 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001690 return false;
1691 }
1692
1693 return true;
1694}
1695
Geoff Lang2186c382016-10-14 10:54:54 -04001696bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001697{
Geoff Lang2186c382016-10-14 10:54:54 -04001698 if (numParams)
1699 {
1700 *numParams = 0;
1701 }
1702
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001703 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1704 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001705 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001706 return false;
1707 }
1708
1709 switch (pname)
1710 {
1711 case GL_CURRENT_QUERY_EXT:
1712 if (target == GL_TIMESTAMP_EXT)
1713 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001714 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001715 return false;
1716 }
1717 break;
1718 case GL_QUERY_COUNTER_BITS_EXT:
1719 if (!context->getExtensions().disjointTimerQuery ||
1720 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1721 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001722 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001723 return false;
1724 }
1725 break;
1726 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001727 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001728 return false;
1729 }
1730
Geoff Lang2186c382016-10-14 10:54:54 -04001731 if (numParams)
1732 {
1733 // All queries return only one value
1734 *numParams = 1;
1735 }
1736
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001737 return true;
1738}
1739
1740bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1741{
1742 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001743 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001744 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001745 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001746 return false;
1747 }
1748
Geoff Lang2186c382016-10-14 10:54:54 -04001749 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001750}
1751
Geoff Lang2186c382016-10-14 10:54:54 -04001752bool ValidateGetQueryivRobustANGLE(Context *context,
1753 GLenum target,
1754 GLenum pname,
1755 GLsizei bufSize,
1756 GLsizei *length,
1757 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001758{
Geoff Lang2186c382016-10-14 10:54:54 -04001759 if (!ValidateRobustEntryPoint(context, bufSize))
1760 {
1761 return false;
1762 }
1763
1764 if (!ValidateGetQueryivBase(context, target, pname, length))
1765 {
1766 return false;
1767 }
1768
1769 if (!ValidateRobustBufferSize(context, bufSize, *length))
1770 {
1771 return false;
1772 }
1773
1774 return true;
1775}
1776
1777bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1778{
1779 if (numParams)
1780 {
1781 *numParams = 0;
1782 }
1783
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001784 Query *queryObject = context->getQuery(id, false, GL_NONE);
1785
1786 if (!queryObject)
1787 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001788 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001789 return false;
1790 }
1791
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001792 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001793 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001794 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001795 return false;
1796 }
1797
1798 switch (pname)
1799 {
1800 case GL_QUERY_RESULT_EXT:
1801 case GL_QUERY_RESULT_AVAILABLE_EXT:
1802 break;
1803
1804 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001805 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001806 return false;
1807 }
1808
Geoff Lang2186c382016-10-14 10:54:54 -04001809 if (numParams)
1810 {
1811 *numParams = 1;
1812 }
1813
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001814 return true;
1815}
1816
1817bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1818{
1819 if (!context->getExtensions().disjointTimerQuery)
1820 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001821 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001822 return false;
1823 }
Geoff Lang2186c382016-10-14 10:54:54 -04001824 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1825}
1826
1827bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1828 GLuint id,
1829 GLenum pname,
1830 GLsizei bufSize,
1831 GLsizei *length,
1832 GLint *params)
1833{
1834 if (!context->getExtensions().disjointTimerQuery)
1835 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001836 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001837 return false;
1838 }
1839
1840 if (!ValidateRobustEntryPoint(context, bufSize))
1841 {
1842 return false;
1843 }
1844
1845 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1846 {
1847 return false;
1848 }
1849
1850 if (!ValidateRobustBufferSize(context, bufSize, *length))
1851 {
1852 return false;
1853 }
1854
1855 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001856}
1857
1858bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1859{
1860 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001861 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001862 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001863 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001864 return false;
1865 }
Geoff Lang2186c382016-10-14 10:54:54 -04001866 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1867}
1868
1869bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1870 GLuint id,
1871 GLenum pname,
1872 GLsizei bufSize,
1873 GLsizei *length,
1874 GLuint *params)
1875{
1876 if (!context->getExtensions().disjointTimerQuery &&
1877 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1878 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001879 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001880 return false;
1881 }
1882
1883 if (!ValidateRobustEntryPoint(context, bufSize))
1884 {
1885 return false;
1886 }
1887
1888 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1889 {
1890 return false;
1891 }
1892
1893 if (!ValidateRobustBufferSize(context, bufSize, *length))
1894 {
1895 return false;
1896 }
1897
1898 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001899}
1900
1901bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1902{
1903 if (!context->getExtensions().disjointTimerQuery)
1904 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001905 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001906 return false;
1907 }
Geoff Lang2186c382016-10-14 10:54:54 -04001908 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1909}
1910
1911bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1912 GLuint id,
1913 GLenum pname,
1914 GLsizei bufSize,
1915 GLsizei *length,
1916 GLint64 *params)
1917{
1918 if (!context->getExtensions().disjointTimerQuery)
1919 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001920 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001921 return false;
1922 }
1923
1924 if (!ValidateRobustEntryPoint(context, bufSize))
1925 {
1926 return false;
1927 }
1928
1929 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1930 {
1931 return false;
1932 }
1933
1934 if (!ValidateRobustBufferSize(context, bufSize, *length))
1935 {
1936 return false;
1937 }
1938
1939 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001940}
1941
1942bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1943{
1944 if (!context->getExtensions().disjointTimerQuery)
1945 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001946 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001947 return false;
1948 }
Geoff Lang2186c382016-10-14 10:54:54 -04001949 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1950}
1951
1952bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1953 GLuint id,
1954 GLenum pname,
1955 GLsizei bufSize,
1956 GLsizei *length,
1957 GLuint64 *params)
1958{
1959 if (!context->getExtensions().disjointTimerQuery)
1960 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001961 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001962 return false;
1963 }
1964
1965 if (!ValidateRobustEntryPoint(context, bufSize))
1966 {
1967 return false;
1968 }
1969
1970 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1971 {
1972 return false;
1973 }
1974
1975 if (!ValidateRobustBufferSize(context, bufSize, *length))
1976 {
1977 return false;
1978 }
1979
1980 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001981}
1982
Jiajia Qin5451d532017-11-16 17:16:34 +08001983bool ValidateUniformCommonBase(ValidationContext *context,
1984 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05001985 GLint location,
1986 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08001987 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05001988{
Jiajia Qin5451d532017-11-16 17:16:34 +08001989 // TODO(Jiajia): Add image uniform check in future.
1990 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05001991 {
Jiajia Qin5451d532017-11-16 17:16:34 +08001992 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05001993 return false;
1994 }
1995
Jiajia Qin5451d532017-11-16 17:16:34 +08001996 if (!program)
1997 {
1998 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
1999 return false;
2000 }
2001
2002 if (!program->isLinked())
2003 {
2004 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2005 return false;
2006 }
2007
2008 if (location == -1)
2009 {
2010 // Silently ignore the uniform command
2011 return false;
2012 }
2013
2014 const auto &uniformLocations = program->getUniformLocations();
2015 size_t castedLocation = static_cast<size_t>(location);
2016 if (castedLocation >= uniformLocations.size())
2017 {
2018 context->handleError(InvalidOperation() << "Invalid uniform location");
2019 return false;
2020 }
2021
2022 const auto &uniformLocation = uniformLocations[castedLocation];
2023 if (uniformLocation.ignored)
2024 {
2025 // Silently ignore the uniform command
2026 return false;
2027 }
2028
2029 if (!uniformLocation.used())
2030 {
2031 context->handleError(InvalidOperation());
2032 return false;
2033 }
2034
2035 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2036
2037 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2038 if (!uniform.isArray() && count > 1)
2039 {
2040 context->handleError(InvalidOperation());
2041 return false;
2042 }
2043
2044 *uniformOut = &uniform;
2045 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002046}
2047
Jiajia Qin5451d532017-11-16 17:16:34 +08002048bool ValidateUniform1ivValue(ValidationContext *context,
2049 GLenum uniformType,
2050 GLsizei count,
2051 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002052{
Jiajia Qin5451d532017-11-16 17:16:34 +08002053 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2054 // It is compatible with INT or BOOL.
2055 // Do these cheap tests first, for a little extra speed.
2056 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002057 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002058 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002059 }
2060
Jiajia Qin5451d532017-11-16 17:16:34 +08002061 if (IsSamplerType(uniformType))
2062 {
2063 // Check that the values are in range.
2064 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2065 for (GLsizei i = 0; i < count; ++i)
2066 {
2067 if (value[i] < 0 || value[i] >= max)
2068 {
2069 context->handleError(InvalidValue() << "sampler uniform value out of range");
2070 return false;
2071 }
2072 }
2073 return true;
2074 }
2075
2076 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2077 return false;
2078}
2079
2080bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2081{
2082 // Check that the value type is compatible with uniform type.
2083 // Do the cheaper test first, for a little extra speed.
2084 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2085 {
2086 return true;
2087 }
2088
2089 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2090 return false;
2091}
2092
2093bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2094{
2095 // Check that the value type is compatible with uniform type.
2096 if (valueType == uniformType)
2097 {
2098 return true;
2099 }
2100
2101 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2102 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002103}
2104
Jamie Madillc1d770e2017-04-13 17:31:24 -04002105bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002106{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002107 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002108 gl::Program *programObject = context->getGLState().getProgram();
2109 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2110 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002111}
2112
Jamie Madillbe849e42017-05-02 15:49:00 -04002113bool ValidateUniform1iv(ValidationContext *context,
2114 GLint location,
2115 GLsizei count,
2116 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002117{
2118 const LinkedUniform *uniform = nullptr;
2119 gl::Program *programObject = context->getGLState().getProgram();
2120 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2121 ValidateUniform1ivValue(context, uniform->type, count, value);
2122}
2123
Jamie Madillc1d770e2017-04-13 17:31:24 -04002124bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002125 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002126 GLint location,
2127 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002128 GLboolean transpose)
2129{
Geoff Lang92019432017-11-20 13:09:34 -05002130 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002131 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002132 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002133 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002134 }
2135
Jamie Madill62d31cb2015-09-11 13:25:51 -04002136 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002137 gl::Program *programObject = context->getGLState().getProgram();
2138 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2139 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002140}
2141
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002142bool ValidateStateQuery(ValidationContext *context,
2143 GLenum pname,
2144 GLenum *nativeType,
2145 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002146{
2147 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2148 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002149 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002150 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002151 }
2152
Jamie Madill0af26e12015-03-05 19:54:33 -05002153 const Caps &caps = context->getCaps();
2154
Jamie Madill893ab082014-05-16 16:56:10 -04002155 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2156 {
2157 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2158
Jamie Madill0af26e12015-03-05 19:54:33 -05002159 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002160 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002161 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002162 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002163 }
2164 }
2165
2166 switch (pname)
2167 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002168 case GL_TEXTURE_BINDING_2D:
2169 case GL_TEXTURE_BINDING_CUBE_MAP:
2170 case GL_TEXTURE_BINDING_3D:
2171 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002172 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002173 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002174 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2175 if (!context->getExtensions().textureRectangle)
2176 {
2177 context->handleError(InvalidEnum()
2178 << "ANGLE_texture_rectangle extension not present");
2179 return false;
2180 }
2181 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002182 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2183 if (!context->getExtensions().eglStreamConsumerExternal &&
2184 !context->getExtensions().eglImageExternal)
2185 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002186 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2187 "nor GL_OES_EGL_image_external "
2188 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002189 return false;
2190 }
2191 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002192
He Yunchaoced53ae2016-11-29 15:00:51 +08002193 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2194 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002195 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002196 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2197 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002198 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002199 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002200 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002201 }
2202
Jamie Madill51f40ec2016-06-15 14:06:00 -04002203 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2204 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002205
2206 if (framebuffer->getReadBufferState() == GL_NONE)
2207 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002208 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002209 return false;
2210 }
2211
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002212 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002213 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002214 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002215 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002216 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002217 }
2218 }
2219 break;
2220
He Yunchaoced53ae2016-11-29 15:00:51 +08002221 default:
2222 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002223 }
2224
2225 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002226 if (*numParams == 0)
2227 {
2228 return false;
2229 }
2230
2231 return true;
2232}
2233
2234bool ValidateRobustStateQuery(ValidationContext *context,
2235 GLenum pname,
2236 GLsizei bufSize,
2237 GLenum *nativeType,
2238 unsigned int *numParams)
2239{
2240 if (!ValidateRobustEntryPoint(context, bufSize))
2241 {
2242 return false;
2243 }
2244
2245 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2246 {
2247 return false;
2248 }
2249
2250 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002251 {
2252 return false;
2253 }
2254
2255 return true;
2256}
2257
Jamie Madillc29968b2016-01-20 11:17:23 -05002258bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2259 GLenum target,
2260 GLint level,
2261 GLenum internalformat,
2262 bool isSubImage,
2263 GLint xoffset,
2264 GLint yoffset,
2265 GLint zoffset,
2266 GLint x,
2267 GLint y,
2268 GLsizei width,
2269 GLsizei height,
2270 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002271 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002272{
Brandon Jones6cad5662017-06-14 13:25:13 -07002273 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002274 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002275 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2276 return false;
2277 }
2278
2279 if (width < 0 || height < 0)
2280 {
2281 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002282 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002283 }
2284
He Yunchaoced53ae2016-11-29 15:00:51 +08002285 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2286 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002287 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002288 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002289 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002290 }
2291
2292 if (border != 0)
2293 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002294 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002295 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002296 }
2297
2298 if (!ValidMipLevel(context, target, level))
2299 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002300 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002301 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002302 }
2303
Jamie Madill51f40ec2016-06-15 14:06:00 -04002304 const auto &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002305 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002306 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002307 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002308 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002309 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002310 }
2311
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002312 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002313 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002314 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002315 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002316 }
2317
Martin Radev138064f2016-07-15 12:03:41 +03002318 if (readFramebuffer->getReadBufferState() == GL_NONE)
2319 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002320 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002321 return false;
2322 }
2323
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002324 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2325 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002326 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002327 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002328 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2329 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002330 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002331 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002332 return false;
2333 }
2334
Martin Radev04e2c3b2017-07-27 16:54:35 +03002335 // ANGLE_multiview spec, Revision 1:
2336 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2337 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2338 // is not NONE.
2339 if (source->getMultiviewLayout() != GL_NONE)
2340 {
2341 context->handleError(InvalidFramebufferOperation()
2342 << "The active read framebuffer object has multiview attachments.");
2343 return false;
2344 }
2345
Geoff Langaae65a42014-05-26 12:43:44 -04002346 const gl::Caps &caps = context->getCaps();
2347
Geoff Langaae65a42014-05-26 12:43:44 -04002348 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002349 switch (target)
2350 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002351 case GL_TEXTURE_2D:
2352 maxDimension = caps.max2DTextureSize;
2353 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002354
He Yunchaoced53ae2016-11-29 15:00:51 +08002355 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2356 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2357 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2358 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2359 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2360 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2361 maxDimension = caps.maxCubeMapTextureSize;
2362 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002363
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002364 case GL_TEXTURE_RECTANGLE_ANGLE:
2365 maxDimension = caps.maxRectangleTextureSize;
2366 break;
2367
He Yunchaoced53ae2016-11-29 15:00:51 +08002368 case GL_TEXTURE_2D_ARRAY:
2369 maxDimension = caps.max2DTextureSize;
2370 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002371
He Yunchaoced53ae2016-11-29 15:00:51 +08002372 case GL_TEXTURE_3D:
2373 maxDimension = caps.max3DTextureSize;
2374 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002375
He Yunchaoced53ae2016-11-29 15:00:51 +08002376 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002377 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002378 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002379 }
2380
Jamie Madillc29968b2016-01-20 11:17:23 -05002381 gl::Texture *texture =
2382 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002383 if (!texture)
2384 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002385 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002386 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002387 }
2388
Geoff Lang69cce582015-09-17 13:20:36 -04002389 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002390 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002391 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002392 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002393 }
2394
Geoff Langca271392017-04-05 12:30:00 -04002395 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002396 isSubImage ? *texture->getFormat(target, level).info
2397 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002398
Geoff Lang966c9402017-04-18 12:38:27 -04002399 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002400 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002401 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002402 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002403 }
2404
2405 if (isSubImage)
2406 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002407 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2408 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2409 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002411 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002412 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002413 }
2414 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002415 else
2416 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002417 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002418 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002419 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002420 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002421 }
2422
Geoff Langeb66a6e2016-10-31 13:06:12 -04002423 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002424 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002425 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002426 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002427 }
2428
2429 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002430 if (static_cast<int>(width) > maxLevelDimension ||
2431 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002432 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002433 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002434 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002435 }
2436 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002437
Jamie Madill0c8abca2016-07-22 20:21:26 -04002438 if (textureFormatOut)
2439 {
2440 *textureFormatOut = texture->getFormat(target, level);
2441 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002442
2443 // Detect texture copying feedback loops for WebGL.
2444 if (context->getExtensions().webglCompatibility)
2445 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002446 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002447 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002448 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002449 return false;
2450 }
2451 }
2452
Jamie Madill560a8d82014-05-21 13:06:20 -04002453 return true;
2454}
2455
Jiajia Qind9671222016-11-29 16:30:31 +08002456bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002457{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002458 switch (mode)
2459 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002460 case GL_POINTS:
2461 case GL_LINES:
2462 case GL_LINE_LOOP:
2463 case GL_LINE_STRIP:
2464 case GL_TRIANGLES:
2465 case GL_TRIANGLE_STRIP:
2466 case GL_TRIANGLE_FAN:
2467 break;
2468 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002469 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002470 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002471 }
2472
Jamie Madill250d33f2014-06-06 17:09:03 -04002473 if (count < 0)
2474 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002475 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002476 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002477 }
2478
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002479 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002480
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002481 const Extensions &extensions = context->getExtensions();
2482
2483 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2484 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2485 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2486 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002487 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002488 // Check for mapped buffers
2489 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002490 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002491 {
2492 context->handleError(InvalidOperation());
2493 return false;
2494 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002495 }
2496
Jamie Madillcbcde722017-01-06 14:50:00 -05002497 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2498 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002499 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002500 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002501 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002502 const FramebufferAttachment *dsAttachment =
2503 framebuffer->getStencilOrDepthStencilAttachment();
2504 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002505 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002506 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002507
2508 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2509 bool differentWritemasks =
2510 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2511 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2512 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2513 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2514
2515 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002516 {
Martin Radevffe754b2017-07-31 10:38:07 +03002517 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002518 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002519 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2520 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002521 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002522 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002523 return false;
2524 }
Jamie Madillac528012014-06-20 13:21:23 -04002525 }
2526
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002527 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002528 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002529 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002530 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002531 }
2532
Geoff Lang7dd2e102014-11-10 15:19:26 -05002533 gl::Program *program = state.getProgram();
2534 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002535 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002536 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002537 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002538 }
2539
Yunchao Hecddcb592017-11-13 15:27:35 +08002540 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2541 // vertex shader stage or fragment shader stage is a undefined behaviour.
2542 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2543 // produce undefined result.
2544 if (program->isLinked() &&
2545 (!program->hasLinkedVertexShader() || !program->hasLinkedFragmentShader()))
2546 {
2547 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2548 "vertex shader stage or fragment shader stage.");
2549 return false;
2550 }
2551
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002552 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002553 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002554 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002555 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002556 }
2557
Martin Radevffe754b2017-07-31 10:38:07 +03002558 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002559 {
Martin Radevda8e2572017-09-12 17:21:16 +03002560 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002561 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002562 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002563 {
2564 context->handleError(InvalidOperation() << "The number of views in the active program "
2565 "and draw framebuffer does not match.");
2566 return false;
2567 }
Martin Radev7e69f762017-07-27 14:54:13 +03002568
2569 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2570 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2571 framebufferNumViews > 1)
2572 {
2573 context->handleError(InvalidOperation()
2574 << "There is an active transform feedback object "
2575 "when the number of views in the active draw "
2576 "framebuffer is greater than 1.");
2577 return false;
2578 }
Martin Radevffe754b2017-07-31 10:38:07 +03002579
2580 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2581 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2582 {
2583 context->handleError(InvalidOperation() << "There is an active query for target "
2584 "GL_TIME_ELAPSED_EXT when the number of "
2585 "views in the active draw framebuffer is "
2586 "greater than 1.");
2587 return false;
2588 }
Martin Radev7cf61662017-07-26 17:10:53 +03002589 }
2590
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002591 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002592 for (unsigned int uniformBlockIndex = 0;
2593 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002594 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002595 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002596 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002597 const OffsetBindingPointer<Buffer> &uniformBuffer =
2598 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002599
Geoff Lang5d124a62015-09-15 13:03:27 -04002600 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002601 {
2602 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002603 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002604 InvalidOperation()
2605 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002606 return false;
2607 }
2608
Geoff Lang5d124a62015-09-15 13:03:27 -04002609 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002610 if (uniformBufferSize == 0)
2611 {
2612 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002613 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002614 }
2615
Jamie Madill62d31cb2015-09-11 13:25:51 -04002616 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002617 {
2618 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002619 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002620 InvalidOperation()
2621 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002622 return false;
2623 }
2624 }
2625
Geoff Lange0cff192017-05-30 13:04:56 -04002626 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002627 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002628 {
Geoff Lange0cff192017-05-30 13:04:56 -04002629 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002630 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2631 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002632 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002633 return false;
2634 }
Geoff Lange0cff192017-05-30 13:04:56 -04002635
Geoff Lang9ab5b822017-05-30 16:19:23 -04002636 // Detect that the vertex shader input types match the attribute types
2637 if (!ValidateVertexShaderAttributeTypeMatch(context))
2638 {
2639 return false;
2640 }
2641
Geoff Lange0cff192017-05-30 13:04:56 -04002642 // Detect that the color buffer types match the fragment shader output types
2643 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2644 {
2645 return false;
2646 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002647 }
2648
Jamie Madill250d33f2014-06-06 17:09:03 -04002649 // No-op if zero count
2650 return (count > 0);
2651}
2652
Jamie Madillc1d770e2017-04-13 17:31:24 -04002653bool ValidateDrawArraysCommon(ValidationContext *context,
2654 GLenum mode,
2655 GLint first,
2656 GLsizei count,
2657 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002658{
Jamie Madillfd716582014-06-06 17:09:04 -04002659 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002660 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002661 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002662 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002663 }
2664
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002665 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002666 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002667 if (curTransformFeedback && curTransformFeedback->isActive() &&
2668 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002669 {
2670 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002671 // that does not match the current transform feedback object's draw mode (if transform
2672 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002673 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002674 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002675 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002676 }
2677
Jiajia Qind9671222016-11-29 16:30:31 +08002678 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002679 {
2680 return false;
2681 }
2682
Corentin Wallez71168a02016-12-19 15:11:18 -08002683 // Check the computation of maxVertex doesn't overflow.
2684 // - first < 0 or count < 0 have been checked as an error condition
2685 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2686 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2687 ASSERT(count > 0 && first >= 0);
2688 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2689 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002690 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002691 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002692 return false;
2693 }
2694
Corentin Wallez71168a02016-12-19 15:11:18 -08002695 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002696 {
2697 return false;
2698 }
2699
2700 return true;
2701}
2702
He Yunchaoced53ae2016-11-29 15:00:51 +08002703bool ValidateDrawArraysInstancedANGLE(Context *context,
2704 GLenum mode,
2705 GLint first,
2706 GLsizei count,
2707 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002708{
Geoff Lang63c5a592017-09-27 14:08:16 -04002709 if (!context->getExtensions().instancedArrays)
2710 {
2711 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2712 return false;
2713 }
2714
Corentin Wallez170efbf2017-05-02 13:45:01 -04002715 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002716 {
2717 return false;
2718 }
2719
Corentin Wallez0dc97812017-06-22 14:38:44 -04002720 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002721}
2722
Jiajia Qind9671222016-11-29 16:30:31 +08002723bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002724{
Jamie Madill250d33f2014-06-06 17:09:03 -04002725 switch (type)
2726 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002727 case GL_UNSIGNED_BYTE:
2728 case GL_UNSIGNED_SHORT:
2729 break;
2730 case GL_UNSIGNED_INT:
2731 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2732 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002733 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002734 return false;
2735 }
2736 break;
2737 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002738 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002739 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002740 }
2741
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002742 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002743
2744 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002745 if (curTransformFeedback && curTransformFeedback->isActive() &&
2746 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002747 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002748 // It is an invalid operation to call DrawElements, DrawRangeElements or
2749 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002750 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002751 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002752 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002753 }
2754
Jiajia Qind9671222016-11-29 16:30:31 +08002755 return true;
2756}
2757
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002758bool ValidateDrawElementsCommon(ValidationContext *context,
2759 GLenum mode,
2760 GLsizei count,
2761 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002762 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002763 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002764{
2765 if (!ValidateDrawElementsBase(context, type))
2766 return false;
2767
2768 const State &state = context->getGLState();
2769
Corentin Wallez170efbf2017-05-02 13:45:01 -04002770 if (!ValidateDrawBase(context, mode, count))
2771 {
2772 return false;
2773 }
2774
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002775 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2776 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2777 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2778 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002779 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002780 // Check for mapped buffers
2781 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002782 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002783 {
2784 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2785 return false;
2786 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002787 }
2788
He Yunchaoced53ae2016-11-29 15:00:51 +08002789 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002790 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002791
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002792 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2793
2794 if (context->getExtensions().webglCompatibility)
2795 {
2796 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2797 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2798 {
2799 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2800 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2801 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002802 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002803 return false;
2804 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002805
2806 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2807 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2808 // error is generated.
2809 if (reinterpret_cast<intptr_t>(indices) < 0)
2810 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002811 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002812 return false;
2813 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002814 }
2815
2816 if (context->getExtensions().webglCompatibility ||
2817 !context->getGLState().areClientArraysEnabled())
2818 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002819 if (!elementArrayBuffer && count > 0)
2820 {
2821 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2822 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2823 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002824 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002825 return false;
2826 }
2827 }
2828
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002829 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002830 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002831 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002832 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002833 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2834 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2835 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2836 constexpr uint64_t kMaxTypeSize = 8;
2837 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2838 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2839 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002840
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002841 uint64_t typeSize = typeBytes;
2842 uint64_t elementCount = static_cast<uint64_t>(count);
2843 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2844
2845 // Doing the multiplication here is overflow-safe
2846 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2847
2848 // The offset can be any value, check for overflows
2849 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2850 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002851 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002852 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002853 return false;
2854 }
2855
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002856 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2857 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002858 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002859 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002860 return false;
2861 }
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002862
Corentin Wallez487653b2017-09-01 17:17:55 -04002863 ASSERT(isPow2(typeSize) && typeSize > 0);
2864 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002865 {
2866 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
2867 return false;
2868 }
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002869 }
2870 else if (!indices)
2871 {
2872 // This is an application error that would normally result in a crash,
2873 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002874 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04002875 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002876 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002877 }
2878
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002879 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002880 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002881 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2882 // access is enabled.
2883 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2884 {
2885 return false;
2886 }
2887 }
2888 else
2889 {
2890 // Use the parameter buffer to retrieve and cache the index range.
2891 const auto &params = context->getParams<HasIndexRange>();
2892 const auto &indexRangeOpt = params.getIndexRange();
2893 if (!indexRangeOpt.valid())
2894 {
2895 // Unexpected error.
2896 return false;
2897 }
2898
2899 // If we use an index greater than our maximum supported index range, return an error.
2900 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2901 // return an error if possible here.
2902 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2903 {
2904 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2905 return false;
2906 }
2907
2908 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2909 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2910 {
2911 return false;
2912 }
2913
2914 // No op if there are no real indices in the index data (all are primitive restart).
2915 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002916 }
2917
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002918 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002919}
2920
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002921bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2922 GLenum mode,
2923 GLsizei count,
2924 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002925 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002926 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002927{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002928 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002929}
2930
Geoff Lang3edfe032015-09-04 16:38:24 -04002931bool ValidateDrawElementsInstancedANGLE(Context *context,
2932 GLenum mode,
2933 GLsizei count,
2934 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002935 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002936 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002937{
Geoff Lang63c5a592017-09-27 14:08:16 -04002938 if (!context->getExtensions().instancedArrays)
2939 {
2940 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2941 return false;
2942 }
2943
Corentin Wallez170efbf2017-05-02 13:45:01 -04002944 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002945 {
2946 return false;
2947 }
2948
Corentin Wallez0dc97812017-06-22 14:38:44 -04002949 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002950}
2951
He Yunchaoced53ae2016-11-29 15:00:51 +08002952bool ValidateFramebufferTextureBase(Context *context,
2953 GLenum target,
2954 GLenum attachment,
2955 GLuint texture,
2956 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002957{
Geoff Lange8afa902017-09-27 15:00:43 -04002958 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002959 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002960 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002961 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002962 }
2963
2964 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002965 {
2966 return false;
2967 }
2968
Jamie Madill55ec3b12014-07-03 10:38:57 -04002969 if (texture != 0)
2970 {
2971 gl::Texture *tex = context->getTexture(texture);
2972
Jamie Madillbe849e42017-05-02 15:49:00 -04002973 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002974 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002975 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002976 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002977 }
2978
2979 if (level < 0)
2980 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002981 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002982 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002983 }
2984 }
2985
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002986 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002987 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002988
Jamie Madill84115c92015-04-23 15:00:07 -04002989 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002990 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002991 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002992 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002993 }
2994
2995 return true;
2996}
2997
Geoff Langb1196682014-07-23 13:47:29 -04002998bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04002999{
3000 if (program == 0)
3001 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003002 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003003 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003004 }
3005
Dian Xiang769769a2015-09-09 15:20:08 -07003006 gl::Program *programObject = GetValidProgram(context, program);
3007 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003008 {
3009 return false;
3010 }
3011
Jamie Madill0063c512014-08-25 15:47:53 -04003012 if (!programObject || !programObject->isLinked())
3013 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003014 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003015 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003016 }
3017
Geoff Lang7dd2e102014-11-10 15:19:26 -05003018 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003019 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003020 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003021 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003022 }
3023
Jamie Madill0063c512014-08-25 15:47:53 -04003024 return true;
3025}
3026
Geoff Langf41d0ee2016-10-07 13:04:23 -04003027static bool ValidateSizedGetUniform(Context *context,
3028 GLuint program,
3029 GLint location,
3030 GLsizei bufSize,
3031 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003032{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003033 if (length)
3034 {
3035 *length = 0;
3036 }
3037
Jamie Madill78f41802014-08-25 15:47:55 -04003038 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003039 {
Jamie Madill78f41802014-08-25 15:47:55 -04003040 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003041 }
3042
Geoff Langf41d0ee2016-10-07 13:04:23 -04003043 if (bufSize < 0)
3044 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003045 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003046 return false;
3047 }
3048
Jamie Madilla502c742014-08-28 17:19:13 -04003049 gl::Program *programObject = context->getProgram(program);
3050 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003051
Jamie Madill78f41802014-08-25 15:47:55 -04003052 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003053 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003054 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003055 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003056 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003057 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003058 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003059 }
3060
Geoff Langf41d0ee2016-10-07 13:04:23 -04003061 if (length)
3062 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003063 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003064 }
3065
Jamie Madill0063c512014-08-25 15:47:53 -04003066 return true;
3067}
3068
He Yunchaoced53ae2016-11-29 15:00:51 +08003069bool ValidateGetnUniformfvEXT(Context *context,
3070 GLuint program,
3071 GLint location,
3072 GLsizei bufSize,
3073 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003074{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003075 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003076}
3077
He Yunchaoced53ae2016-11-29 15:00:51 +08003078bool ValidateGetnUniformivEXT(Context *context,
3079 GLuint program,
3080 GLint location,
3081 GLsizei bufSize,
3082 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003083{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003084 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3085}
3086
3087bool ValidateGetUniformfvRobustANGLE(Context *context,
3088 GLuint program,
3089 GLint location,
3090 GLsizei bufSize,
3091 GLsizei *length,
3092 GLfloat *params)
3093{
3094 if (!ValidateRobustEntryPoint(context, bufSize))
3095 {
3096 return false;
3097 }
3098
3099 // bufSize is validated in ValidateSizedGetUniform
3100 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3101}
3102
3103bool ValidateGetUniformivRobustANGLE(Context *context,
3104 GLuint program,
3105 GLint location,
3106 GLsizei bufSize,
3107 GLsizei *length,
3108 GLint *params)
3109{
3110 if (!ValidateRobustEntryPoint(context, bufSize))
3111 {
3112 return false;
3113 }
3114
3115 // bufSize is validated in ValidateSizedGetUniform
3116 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3117}
3118
3119bool ValidateGetUniformuivRobustANGLE(Context *context,
3120 GLuint program,
3121 GLint location,
3122 GLsizei bufSize,
3123 GLsizei *length,
3124 GLuint *params)
3125{
3126 if (!ValidateRobustEntryPoint(context, bufSize))
3127 {
3128 return false;
3129 }
3130
3131 if (context->getClientMajorVersion() < 3)
3132 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003133 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003134 return false;
3135 }
3136
3137 // bufSize is validated in ValidateSizedGetUniform
3138 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003139}
3140
He Yunchaoced53ae2016-11-29 15:00:51 +08003141bool ValidateDiscardFramebufferBase(Context *context,
3142 GLenum target,
3143 GLsizei numAttachments,
3144 const GLenum *attachments,
3145 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003146{
3147 if (numAttachments < 0)
3148 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003149 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003150 return false;
3151 }
3152
3153 for (GLsizei i = 0; i < numAttachments; ++i)
3154 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003155 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003156 {
3157 if (defaultFramebuffer)
3158 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003159 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003160 return false;
3161 }
3162
3163 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3164 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003165 context->handleError(InvalidOperation() << "Requested color attachment is "
3166 "greater than the maximum supported "
3167 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003168 return false;
3169 }
3170 }
3171 else
3172 {
3173 switch (attachments[i])
3174 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003175 case GL_DEPTH_ATTACHMENT:
3176 case GL_STENCIL_ATTACHMENT:
3177 case GL_DEPTH_STENCIL_ATTACHMENT:
3178 if (defaultFramebuffer)
3179 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003180 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3181 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003182 return false;
3183 }
3184 break;
3185 case GL_COLOR:
3186 case GL_DEPTH:
3187 case GL_STENCIL:
3188 if (!defaultFramebuffer)
3189 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003190 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3191 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003192 return false;
3193 }
3194 break;
3195 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003196 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003197 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003198 }
3199 }
3200 }
3201
3202 return true;
3203}
3204
Austin Kinross6ee1e782015-05-29 17:05:37 -07003205bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3206{
3207 // Note that debug marker calls must not set error state
3208
3209 if (length < 0)
3210 {
3211 return false;
3212 }
3213
3214 if (marker == nullptr)
3215 {
3216 return false;
3217 }
3218
3219 return true;
3220}
3221
3222bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3223{
3224 // Note that debug marker calls must not set error state
3225
3226 if (length < 0)
3227 {
3228 return false;
3229 }
3230
3231 if (length > 0 && marker == nullptr)
3232 {
3233 return false;
3234 }
3235
3236 return true;
3237}
3238
Geoff Langdcab33b2015-07-21 13:03:16 -04003239bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003240 GLenum target,
3241 egl::Image *image)
3242{
Geoff Langa8406172015-07-21 16:53:39 -04003243 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3244 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003245 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003246 return false;
3247 }
3248
3249 switch (target)
3250 {
3251 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003252 if (!context->getExtensions().eglImage)
3253 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003254 context->handleError(InvalidEnum()
3255 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003256 }
3257 break;
3258
3259 case GL_TEXTURE_EXTERNAL_OES:
3260 if (!context->getExtensions().eglImageExternal)
3261 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003262 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3263 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003264 }
Geoff Langa8406172015-07-21 16:53:39 -04003265 break;
3266
3267 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003268 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003269 return false;
3270 }
3271
Jamie Madill61e16b42017-06-19 11:13:23 -04003272 ASSERT(context->getCurrentDisplay());
3273 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003274 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003275 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003276 return false;
3277 }
3278
3279 if (image->getSamples() > 0)
3280 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003281 context->handleError(InvalidOperation()
3282 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003283 return false;
3284 }
3285
Geoff Langca271392017-04-05 12:30:00 -04003286 const TextureCaps &textureCaps =
3287 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003288 if (!textureCaps.texturable)
3289 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003290 context->handleError(InvalidOperation()
3291 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003292 return false;
3293 }
3294
Geoff Langdcab33b2015-07-21 13:03:16 -04003295 return true;
3296}
3297
3298bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003299 GLenum target,
3300 egl::Image *image)
3301{
Geoff Langa8406172015-07-21 16:53:39 -04003302 if (!context->getExtensions().eglImage)
3303 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003304 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003305 return false;
3306 }
3307
3308 switch (target)
3309 {
3310 case GL_RENDERBUFFER:
3311 break;
3312
3313 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003314 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003315 return false;
3316 }
3317
Jamie Madill61e16b42017-06-19 11:13:23 -04003318 ASSERT(context->getCurrentDisplay());
3319 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003320 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003321 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003322 return false;
3323 }
3324
Geoff Langca271392017-04-05 12:30:00 -04003325 const TextureCaps &textureCaps =
3326 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003327 if (!textureCaps.renderable)
3328 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003329 context->handleError(InvalidOperation()
3330 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003331 return false;
3332 }
3333
Geoff Langdcab33b2015-07-21 13:03:16 -04003334 return true;
3335}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003336
3337bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3338{
Geoff Lang36167ab2015-12-07 10:27:14 -05003339 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003340 {
3341 // The default VAO should always exist
3342 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003343 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003344 return false;
3345 }
3346
3347 return true;
3348}
3349
Geoff Langc5629752015-12-07 16:29:04 -05003350bool ValidateProgramBinaryBase(Context *context,
3351 GLuint program,
3352 GLenum binaryFormat,
3353 const void *binary,
3354 GLint length)
3355{
3356 Program *programObject = GetValidProgram(context, program);
3357 if (programObject == nullptr)
3358 {
3359 return false;
3360 }
3361
3362 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3363 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3364 programBinaryFormats.end())
3365 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003366 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003367 return false;
3368 }
3369
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003370 if (context->hasActiveTransformFeedback(program))
3371 {
3372 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003373 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3374 "is associated with an active transform "
3375 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003376 return false;
3377 }
3378
Geoff Langc5629752015-12-07 16:29:04 -05003379 return true;
3380}
3381
3382bool ValidateGetProgramBinaryBase(Context *context,
3383 GLuint program,
3384 GLsizei bufSize,
3385 GLsizei *length,
3386 GLenum *binaryFormat,
3387 void *binary)
3388{
3389 Program *programObject = GetValidProgram(context, program);
3390 if (programObject == nullptr)
3391 {
3392 return false;
3393 }
3394
3395 if (!programObject->isLinked())
3396 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003397 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003398 return false;
3399 }
3400
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003401 if (context->getCaps().programBinaryFormats.empty())
3402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003403 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003404 return false;
3405 }
3406
Geoff Langc5629752015-12-07 16:29:04 -05003407 return true;
3408}
Jamie Madillc29968b2016-01-20 11:17:23 -05003409
Jamie Madillc29968b2016-01-20 11:17:23 -05003410bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3411{
3412 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003413 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003414 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003415 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3416 return false;
3417 }
3418 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3419 {
3420 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003421 return false;
3422 }
3423
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003424 ASSERT(context->getGLState().getDrawFramebuffer());
3425 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003426 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3427
3428 // This should come first before the check for the default frame buffer
3429 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3430 // rather than INVALID_OPERATION
3431 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3432 {
3433 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3434
3435 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003436 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3437 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003438 {
3439 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003440 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3441 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3442 // 3.1 is still a bit ambiguous about the error, but future specs are
3443 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003444 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003445 return false;
3446 }
3447 else if (bufs[colorAttachment] >= maxColorAttachment)
3448 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003449 context->handleError(InvalidOperation()
3450 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003451 return false;
3452 }
3453 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3454 frameBufferId != 0)
3455 {
3456 // INVALID_OPERATION-GL is bound to buffer and ith argument
3457 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003458 context->handleError(InvalidOperation()
3459 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003460 return false;
3461 }
3462 }
3463
3464 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3465 // and n is not 1 or bufs is bound to value other than BACK and NONE
3466 if (frameBufferId == 0)
3467 {
3468 if (n != 1)
3469 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003470 context->handleError(InvalidOperation()
3471 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003472 return false;
3473 }
3474
3475 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3476 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003477 context->handleError(
3478 InvalidOperation()
3479 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003480 return false;
3481 }
3482 }
3483
3484 return true;
3485}
3486
Geoff Lang496c02d2016-10-20 11:38:11 -07003487bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003488 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003489 GLenum pname,
3490 GLsizei *length,
3491 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003492{
Geoff Lang496c02d2016-10-20 11:38:11 -07003493 if (length)
3494 {
3495 *length = 0;
3496 }
3497
3498 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3499 {
3500 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003501 InvalidOperation()
3502 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003503 return false;
3504 }
3505
Corentin Wallez336129f2017-10-17 15:55:40 -04003506 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003507 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003508 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003509 return false;
3510 }
3511
Geoff Lang496c02d2016-10-20 11:38:11 -07003512 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003513 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003514 case GL_BUFFER_MAP_POINTER:
3515 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003516
Geoff Lang496c02d2016-10-20 11:38:11 -07003517 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003518 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003519 return false;
3520 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003521
3522 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3523 // target bound to zero generate an INVALID_OPERATION error."
3524 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003525 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003527 context->handleError(InvalidOperation()
3528 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003529 return false;
3530 }
3531
Geoff Lang496c02d2016-10-20 11:38:11 -07003532 if (length)
3533 {
3534 *length = 1;
3535 }
3536
Olli Etuaho4f667482016-03-30 15:56:35 +03003537 return true;
3538}
3539
Corentin Wallez336129f2017-10-17 15:55:40 -04003540bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003541{
Corentin Wallez336129f2017-10-17 15:55:40 -04003542 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003543 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003544 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003545 return false;
3546 }
3547
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003548 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003549
3550 if (buffer == nullptr || !buffer->isMapped())
3551 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003552 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003553 return false;
3554 }
3555
3556 return true;
3557}
3558
3559bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003560 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003561 GLintptr offset,
3562 GLsizeiptr length,
3563 GLbitfield access)
3564{
Corentin Wallez336129f2017-10-17 15:55:40 -04003565 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003566 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003567 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003568 return false;
3569 }
3570
Brandon Jones6cad5662017-06-14 13:25:13 -07003571 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003572 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003573 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3574 return false;
3575 }
3576
3577 if (length < 0)
3578 {
3579 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003580 return false;
3581 }
3582
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003583 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003584
3585 if (!buffer)
3586 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003587 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003588 return false;
3589 }
3590
3591 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003592 CheckedNumeric<size_t> checkedOffset(offset);
3593 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003594
Jamie Madille2e406c2016-06-02 13:04:10 -04003595 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003596 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003597 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003598 return false;
3599 }
3600
3601 // Check for invalid bits in the mask
3602 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3603 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3604 GL_MAP_UNSYNCHRONIZED_BIT;
3605
3606 if (access & ~(allAccessBits))
3607 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003608 context->handleError(InvalidValue()
3609 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003610 return false;
3611 }
3612
3613 if (length == 0)
3614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003615 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003616 return false;
3617 }
3618
3619 if (buffer->isMapped())
3620 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003621 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003622 return false;
3623 }
3624
3625 // Check for invalid bit combinations
3626 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3627 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003628 context->handleError(InvalidOperation()
3629 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003630 return false;
3631 }
3632
3633 GLbitfield writeOnlyBits =
3634 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3635
3636 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3637 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003638 context->handleError(InvalidOperation()
3639 << "Invalid access bits when mapping buffer for reading: 0x"
3640 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003641 return false;
3642 }
3643
3644 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003646 context->handleError(
3647 InvalidOperation()
3648 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003649 return false;
3650 }
Geoff Lang79f71042017-08-14 16:43:43 -04003651
3652 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003653}
3654
3655bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003656 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003657 GLintptr offset,
3658 GLsizeiptr length)
3659{
Brandon Jones6cad5662017-06-14 13:25:13 -07003660 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003661 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003662 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3663 return false;
3664 }
3665
3666 if (length < 0)
3667 {
3668 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003669 return false;
3670 }
3671
Corentin Wallez336129f2017-10-17 15:55:40 -04003672 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003673 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003674 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003675 return false;
3676 }
3677
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003678 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003679
3680 if (buffer == nullptr)
3681 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003682 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003683 return false;
3684 }
3685
3686 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003688 context->handleError(InvalidOperation()
3689 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003690 return false;
3691 }
3692
3693 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003694 CheckedNumeric<size_t> checkedOffset(offset);
3695 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003696
Jamie Madille2e406c2016-06-02 13:04:10 -04003697 if (!checkedSize.IsValid() ||
3698 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003699 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003700 context->handleError(InvalidValue()
3701 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003702 return false;
3703 }
3704
3705 return true;
3706}
3707
Olli Etuaho41997e72016-03-10 13:38:39 +02003708bool ValidateGenOrDelete(Context *context, GLint n)
3709{
3710 if (n < 0)
3711 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003712 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003713 return false;
3714 }
3715 return true;
3716}
3717
Geoff Langff5b2d52016-09-07 11:32:23 -04003718bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3719{
3720 if (!context->getExtensions().robustClientMemory)
3721 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003722 context->handleError(InvalidOperation()
3723 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003724 return false;
3725 }
3726
3727 if (bufSize < 0)
3728 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003729 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003730 return false;
3731 }
3732
3733 return true;
3734}
3735
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003736bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3737{
3738 if (bufSize < numParams)
3739 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003740 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3741 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003742 return false;
3743 }
3744
3745 return true;
3746}
3747
Jamie Madillbe849e42017-05-02 15:49:00 -04003748bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3749 GLenum target,
3750 GLenum attachment,
3751 GLenum pname,
3752 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003753{
Geoff Lange8afa902017-09-27 15:00:43 -04003754 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003755 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003756 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003757 return false;
3758 }
3759
3760 int clientVersion = context->getClientMajorVersion();
3761
3762 switch (pname)
3763 {
3764 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3765 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3766 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3767 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3768 break;
3769
Martin Radeve5285d22017-07-14 16:23:53 +03003770 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3771 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3772 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3773 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3774 if (clientVersion < 3 || !context->getExtensions().multiview)
3775 {
3776 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3777 return false;
3778 }
3779 break;
3780
Geoff Langff5b2d52016-09-07 11:32:23 -04003781 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3782 if (clientVersion < 3 && !context->getExtensions().sRGB)
3783 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003784 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003785 return false;
3786 }
3787 break;
3788
3789 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3790 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3791 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3792 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3793 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3794 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3795 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3796 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3797 if (clientVersion < 3)
3798 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003799 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003800 return false;
3801 }
3802 break;
3803
3804 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003805 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003806 return false;
3807 }
3808
3809 // Determine if the attachment is a valid enum
3810 switch (attachment)
3811 {
3812 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04003813 case GL_DEPTH:
3814 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04003815 if (clientVersion < 3)
3816 {
Geoff Langfa125c92017-10-24 13:01:46 -04003817 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003818 return false;
3819 }
3820 break;
3821
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003822 case GL_DEPTH_STENCIL_ATTACHMENT:
3823 if (clientVersion < 3 && !context->isWebGL1())
3824 {
3825 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3826 return false;
3827 }
3828 break;
3829
Geoff Langfa125c92017-10-24 13:01:46 -04003830 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003831 case GL_DEPTH_ATTACHMENT:
3832 case GL_STENCIL_ATTACHMENT:
3833 break;
3834
3835 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003836 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3837 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003838 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3839 {
Geoff Langfa125c92017-10-24 13:01:46 -04003840 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003841 return false;
3842 }
3843 break;
3844 }
3845
3846 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3847 ASSERT(framebuffer);
3848
3849 if (framebuffer->id() == 0)
3850 {
3851 if (clientVersion < 3)
3852 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003853 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003854 return false;
3855 }
3856
3857 switch (attachment)
3858 {
3859 case GL_BACK:
3860 case GL_DEPTH:
3861 case GL_STENCIL:
3862 break;
3863
3864 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003865 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003866 return false;
3867 }
3868 }
3869 else
3870 {
3871 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3872 {
3873 // Valid attachment query
3874 }
3875 else
3876 {
3877 switch (attachment)
3878 {
3879 case GL_DEPTH_ATTACHMENT:
3880 case GL_STENCIL_ATTACHMENT:
3881 break;
3882
3883 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003884 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04003885 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003886 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003887 return false;
3888 }
3889 break;
3890
3891 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003892 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003893 return false;
3894 }
3895 }
3896 }
3897
3898 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3899 if (attachmentObject)
3900 {
3901 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3902 attachmentObject->type() == GL_TEXTURE ||
3903 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3904
3905 switch (pname)
3906 {
3907 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3908 if (attachmentObject->type() != GL_RENDERBUFFER &&
3909 attachmentObject->type() != GL_TEXTURE)
3910 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003911 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003912 return false;
3913 }
3914 break;
3915
3916 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3917 if (attachmentObject->type() != GL_TEXTURE)
3918 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003919 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003920 return false;
3921 }
3922 break;
3923
3924 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3925 if (attachmentObject->type() != GL_TEXTURE)
3926 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003927 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003928 return false;
3929 }
3930 break;
3931
3932 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3933 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3934 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003935 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003936 return false;
3937 }
3938 break;
3939
3940 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3941 if (attachmentObject->type() != GL_TEXTURE)
3942 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003943 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003944 return false;
3945 }
3946 break;
3947
3948 default:
3949 break;
3950 }
3951 }
3952 else
3953 {
3954 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3955 // is NONE, then querying any other pname will generate INVALID_ENUM.
3956
3957 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3958 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3959 // INVALID_OPERATION for all other pnames
3960
3961 switch (pname)
3962 {
3963 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3964 break;
3965
3966 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3967 if (clientVersion < 3)
3968 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003969 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003970 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003971 return false;
3972 }
3973 break;
3974
3975 default:
3976 if (clientVersion < 3)
3977 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003978 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003979 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003980 return false;
3981 }
3982 else
3983 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003984 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003985 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003986 return false;
3987 }
3988 }
3989 }
3990
Martin Radeve5285d22017-07-14 16:23:53 +03003991 if (numParams)
3992 {
3993 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
3994 {
3995 // Only when the viewport offsets are queried we can have a varying number of output
3996 // parameters.
3997 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
3998 *numParams = numViews * 2;
3999 }
4000 else
4001 {
4002 // For all other queries we can have only one output parameter.
4003 *numParams = 1;
4004 }
4005 }
4006
Geoff Langff5b2d52016-09-07 11:32:23 -04004007 return true;
4008}
4009
4010bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4011 GLenum target,
4012 GLenum attachment,
4013 GLenum pname,
4014 GLsizei bufSize,
4015 GLsizei *numParams)
4016{
4017 if (!ValidateRobustEntryPoint(context, bufSize))
4018 {
4019 return false;
4020 }
4021
Jamie Madillbe849e42017-05-02 15:49:00 -04004022 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4023 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004024 {
4025 return false;
4026 }
4027
4028 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4029 {
4030 return false;
4031 }
4032
4033 return true;
4034}
4035
Geoff Langff5b2d52016-09-07 11:32:23 -04004036bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004037 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004038 GLenum pname,
4039 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004040 GLsizei *length,
4041 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004042{
4043 if (!ValidateRobustEntryPoint(context, bufSize))
4044 {
4045 return false;
4046 }
4047
Geoff Langebebe1c2016-10-14 12:01:31 -04004048 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004049 {
4050 return false;
4051 }
4052
Geoff Langebebe1c2016-10-14 12:01:31 -04004053 if (!ValidateRobustBufferSize(context, bufSize, *length))
4054 {
4055 return false;
4056 }
4057
4058 return true;
4059}
4060
Geoff Langebebe1c2016-10-14 12:01:31 -04004061bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004062 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004063 GLenum pname,
4064 GLsizei bufSize,
4065 GLsizei *length,
4066 GLint64 *params)
4067{
4068 if (!ValidateRobustEntryPoint(context, bufSize))
4069 {
4070 return false;
4071 }
4072
4073 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4074 {
4075 return false;
4076 }
4077
4078 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004079 {
4080 return false;
4081 }
4082
4083 return true;
4084}
4085
Jamie Madillbe849e42017-05-02 15:49:00 -04004086bool ValidateGetProgramivBase(ValidationContext *context,
4087 GLuint program,
4088 GLenum pname,
4089 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004090{
4091 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004092 if (numParams)
4093 {
4094 *numParams = 1;
4095 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004096
4097 Program *programObject = GetValidProgram(context, program);
4098 if (!programObject)
4099 {
4100 return false;
4101 }
4102
4103 switch (pname)
4104 {
4105 case GL_DELETE_STATUS:
4106 case GL_LINK_STATUS:
4107 case GL_VALIDATE_STATUS:
4108 case GL_INFO_LOG_LENGTH:
4109 case GL_ATTACHED_SHADERS:
4110 case GL_ACTIVE_ATTRIBUTES:
4111 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4112 case GL_ACTIVE_UNIFORMS:
4113 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4114 break;
4115
4116 case GL_PROGRAM_BINARY_LENGTH:
4117 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4118 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004119 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4120 "requires GL_OES_get_program_binary or "
4121 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004122 return false;
4123 }
4124 break;
4125
4126 case GL_ACTIVE_UNIFORM_BLOCKS:
4127 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4128 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4129 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4130 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4131 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4132 if (context->getClientMajorVersion() < 3)
4133 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004134 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004135 return false;
4136 }
4137 break;
4138
Yunchao He61afff12017-03-14 15:34:03 +08004139 case GL_PROGRAM_SEPARABLE:
Xinghua Cao971f8502017-10-17 13:01:24 +08004140 case GL_COMPUTE_WORK_GROUP_SIZE:
jchen1058f67be2017-10-27 08:59:27 +08004141 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004142 if (context->getClientVersion() < Version(3, 1))
4143 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004144 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004145 return false;
4146 }
4147 break;
4148
Geoff Langff5b2d52016-09-07 11:32:23 -04004149 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004150 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004151 return false;
4152 }
4153
4154 return true;
4155}
4156
4157bool ValidateGetProgramivRobustANGLE(Context *context,
4158 GLuint program,
4159 GLenum pname,
4160 GLsizei bufSize,
4161 GLsizei *numParams)
4162{
4163 if (!ValidateRobustEntryPoint(context, bufSize))
4164 {
4165 return false;
4166 }
4167
Jamie Madillbe849e42017-05-02 15:49:00 -04004168 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004169 {
4170 return false;
4171 }
4172
4173 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4174 {
4175 return false;
4176 }
4177
4178 return true;
4179}
4180
Geoff Lang740d9022016-10-07 11:20:52 -04004181bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4182 GLenum target,
4183 GLenum pname,
4184 GLsizei bufSize,
4185 GLsizei *length,
4186 GLint *params)
4187{
4188 if (!ValidateRobustEntryPoint(context, bufSize))
4189 {
4190 return false;
4191 }
4192
4193 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4194 {
4195 return false;
4196 }
4197
4198 if (!ValidateRobustBufferSize(context, bufSize, *length))
4199 {
4200 return false;
4201 }
4202
4203 return true;
4204}
4205
Geoff Langd7d0ed32016-10-07 11:33:51 -04004206bool ValidateGetShaderivRobustANGLE(Context *context,
4207 GLuint shader,
4208 GLenum pname,
4209 GLsizei bufSize,
4210 GLsizei *length,
4211 GLint *params)
4212{
4213 if (!ValidateRobustEntryPoint(context, bufSize))
4214 {
4215 return false;
4216 }
4217
4218 if (!ValidateGetShaderivBase(context, shader, pname, length))
4219 {
4220 return false;
4221 }
4222
4223 if (!ValidateRobustBufferSize(context, bufSize, *length))
4224 {
4225 return false;
4226 }
4227
4228 return true;
4229}
4230
Geoff Langc1984ed2016-10-07 12:41:00 -04004231bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4232 GLenum target,
4233 GLenum pname,
4234 GLsizei bufSize,
4235 GLsizei *length,
4236 GLfloat *params)
4237{
4238 if (!ValidateRobustEntryPoint(context, bufSize))
4239 {
4240 return false;
4241 }
4242
4243 if (!ValidateGetTexParameterBase(context, target, pname, length))
4244 {
4245 return false;
4246 }
4247
4248 if (!ValidateRobustBufferSize(context, bufSize, *length))
4249 {
4250 return false;
4251 }
4252
4253 return true;
4254}
4255
Geoff Langc1984ed2016-10-07 12:41:00 -04004256bool ValidateGetTexParameterivRobustANGLE(Context *context,
4257 GLenum target,
4258 GLenum pname,
4259 GLsizei bufSize,
4260 GLsizei *length,
4261 GLint *params)
4262{
4263 if (!ValidateRobustEntryPoint(context, bufSize))
4264 {
4265 return false;
4266 }
4267
4268 if (!ValidateGetTexParameterBase(context, target, pname, length))
4269 {
4270 return false;
4271 }
4272
4273 if (!ValidateRobustBufferSize(context, bufSize, *length))
4274 {
4275 return false;
4276 }
4277
4278 return true;
4279}
4280
Geoff Langc1984ed2016-10-07 12:41:00 -04004281bool ValidateTexParameterfvRobustANGLE(Context *context,
4282 GLenum target,
4283 GLenum pname,
4284 GLsizei bufSize,
4285 const GLfloat *params)
4286{
4287 if (!ValidateRobustEntryPoint(context, bufSize))
4288 {
4289 return false;
4290 }
4291
4292 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4293}
4294
Geoff Langc1984ed2016-10-07 12:41:00 -04004295bool ValidateTexParameterivRobustANGLE(Context *context,
4296 GLenum target,
4297 GLenum pname,
4298 GLsizei bufSize,
4299 const GLint *params)
4300{
4301 if (!ValidateRobustEntryPoint(context, bufSize))
4302 {
4303 return false;
4304 }
4305
4306 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4307}
4308
Geoff Langc1984ed2016-10-07 12:41:00 -04004309bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4310 GLuint sampler,
4311 GLenum pname,
4312 GLuint bufSize,
4313 GLsizei *length,
4314 GLfloat *params)
4315{
4316 if (!ValidateRobustEntryPoint(context, bufSize))
4317 {
4318 return false;
4319 }
4320
4321 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4322 {
4323 return false;
4324 }
4325
4326 if (!ValidateRobustBufferSize(context, bufSize, *length))
4327 {
4328 return false;
4329 }
4330
4331 return true;
4332}
4333
Geoff Langc1984ed2016-10-07 12:41:00 -04004334bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4335 GLuint sampler,
4336 GLenum pname,
4337 GLuint bufSize,
4338 GLsizei *length,
4339 GLint *params)
4340{
4341 if (!ValidateRobustEntryPoint(context, bufSize))
4342 {
4343 return false;
4344 }
4345
4346 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4347 {
4348 return false;
4349 }
4350
4351 if (!ValidateRobustBufferSize(context, bufSize, *length))
4352 {
4353 return false;
4354 }
4355
4356 return true;
4357}
4358
Geoff Langc1984ed2016-10-07 12:41:00 -04004359bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4360 GLuint sampler,
4361 GLenum pname,
4362 GLsizei bufSize,
4363 const GLfloat *params)
4364{
4365 if (!ValidateRobustEntryPoint(context, bufSize))
4366 {
4367 return false;
4368 }
4369
4370 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4371}
4372
Geoff Langc1984ed2016-10-07 12:41:00 -04004373bool ValidateSamplerParameterivRobustANGLE(Context *context,
4374 GLuint sampler,
4375 GLenum pname,
4376 GLsizei bufSize,
4377 const GLint *params)
4378{
4379 if (!ValidateRobustEntryPoint(context, bufSize))
4380 {
4381 return false;
4382 }
4383
4384 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4385}
4386
Geoff Lang0b031062016-10-13 14:30:04 -04004387bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4388 GLuint index,
4389 GLenum pname,
4390 GLsizei bufSize,
4391 GLsizei *length,
4392 GLfloat *params)
4393{
4394 if (!ValidateRobustEntryPoint(context, bufSize))
4395 {
4396 return false;
4397 }
4398
4399 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4400 {
4401 return false;
4402 }
4403
4404 if (!ValidateRobustBufferSize(context, bufSize, *length))
4405 {
4406 return false;
4407 }
4408
4409 return true;
4410}
4411
Geoff Lang0b031062016-10-13 14:30:04 -04004412bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4413 GLuint index,
4414 GLenum pname,
4415 GLsizei bufSize,
4416 GLsizei *length,
4417 GLint *params)
4418{
4419 if (!ValidateRobustEntryPoint(context, bufSize))
4420 {
4421 return false;
4422 }
4423
4424 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4425 {
4426 return false;
4427 }
4428
4429 if (!ValidateRobustBufferSize(context, bufSize, *length))
4430 {
4431 return false;
4432 }
4433
4434 return true;
4435}
4436
Geoff Lang0b031062016-10-13 14:30:04 -04004437bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4438 GLuint index,
4439 GLenum pname,
4440 GLsizei bufSize,
4441 GLsizei *length,
4442 void **pointer)
4443{
4444 if (!ValidateRobustEntryPoint(context, bufSize))
4445 {
4446 return false;
4447 }
4448
4449 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4450 {
4451 return false;
4452 }
4453
4454 if (!ValidateRobustBufferSize(context, bufSize, *length))
4455 {
4456 return false;
4457 }
4458
4459 return true;
4460}
4461
Geoff Lang0b031062016-10-13 14:30:04 -04004462bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4463 GLuint index,
4464 GLenum pname,
4465 GLsizei bufSize,
4466 GLsizei *length,
4467 GLint *params)
4468{
4469 if (!ValidateRobustEntryPoint(context, bufSize))
4470 {
4471 return false;
4472 }
4473
4474 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4475 {
4476 return false;
4477 }
4478
4479 if (!ValidateRobustBufferSize(context, bufSize, *length))
4480 {
4481 return false;
4482 }
4483
4484 return true;
4485}
4486
Geoff Lang0b031062016-10-13 14:30:04 -04004487bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4488 GLuint index,
4489 GLenum pname,
4490 GLsizei bufSize,
4491 GLsizei *length,
4492 GLuint *params)
4493{
4494 if (!ValidateRobustEntryPoint(context, bufSize))
4495 {
4496 return false;
4497 }
4498
4499 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4500 {
4501 return false;
4502 }
4503
4504 if (!ValidateRobustBufferSize(context, bufSize, *length))
4505 {
4506 return false;
4507 }
4508
4509 return true;
4510}
4511
Geoff Lang6899b872016-10-14 11:30:13 -04004512bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4513 GLuint program,
4514 GLuint uniformBlockIndex,
4515 GLenum pname,
4516 GLsizei bufSize,
4517 GLsizei *length,
4518 GLint *params)
4519{
4520 if (!ValidateRobustEntryPoint(context, bufSize))
4521 {
4522 return false;
4523 }
4524
4525 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4526 {
4527 return false;
4528 }
4529
4530 if (!ValidateRobustBufferSize(context, bufSize, *length))
4531 {
4532 return false;
4533 }
4534
4535 return true;
4536}
4537
Geoff Lang0a9661f2016-10-20 10:59:20 -07004538bool ValidateGetInternalFormativRobustANGLE(Context *context,
4539 GLenum target,
4540 GLenum internalformat,
4541 GLenum pname,
4542 GLsizei bufSize,
4543 GLsizei *length,
4544 GLint *params)
4545{
4546 if (!ValidateRobustEntryPoint(context, bufSize))
4547 {
4548 return false;
4549 }
4550
4551 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4552 {
4553 return false;
4554 }
4555
4556 if (!ValidateRobustBufferSize(context, bufSize, *length))
4557 {
4558 return false;
4559 }
4560
4561 return true;
4562}
4563
Shao80957d92017-02-20 21:25:59 +08004564bool ValidateVertexFormatBase(ValidationContext *context,
4565 GLuint attribIndex,
4566 GLint size,
4567 GLenum type,
4568 GLboolean pureInteger)
4569{
4570 const Caps &caps = context->getCaps();
4571 if (attribIndex >= caps.maxVertexAttributes)
4572 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004573 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004574 return false;
4575 }
4576
4577 if (size < 1 || size > 4)
4578 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004579 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004580 return false;
Shao80957d92017-02-20 21:25:59 +08004581 }
4582
4583 switch (type)
4584 {
4585 case GL_BYTE:
4586 case GL_UNSIGNED_BYTE:
4587 case GL_SHORT:
4588 case GL_UNSIGNED_SHORT:
4589 break;
4590
4591 case GL_INT:
4592 case GL_UNSIGNED_INT:
4593 if (context->getClientMajorVersion() < 3)
4594 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004595 context->handleError(InvalidEnum()
4596 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004597 return false;
4598 }
4599 break;
4600
4601 case GL_FIXED:
4602 case GL_FLOAT:
4603 if (pureInteger)
4604 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004605 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004606 return false;
4607 }
4608 break;
4609
4610 case GL_HALF_FLOAT:
4611 if (context->getClientMajorVersion() < 3)
4612 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004613 context->handleError(InvalidEnum()
4614 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004615 return false;
4616 }
4617 if (pureInteger)
4618 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004619 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004620 return false;
4621 }
4622 break;
4623
4624 case GL_INT_2_10_10_10_REV:
4625 case GL_UNSIGNED_INT_2_10_10_10_REV:
4626 if (context->getClientMajorVersion() < 3)
4627 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004628 context->handleError(InvalidEnum()
4629 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004630 return false;
4631 }
4632 if (pureInteger)
4633 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004634 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004635 return false;
4636 }
4637 if (size != 4)
4638 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004639 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4640 "UNSIGNED_INT_2_10_10_10_REV and "
4641 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004642 return false;
4643 }
4644 break;
4645
4646 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004647 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004648 return false;
4649 }
4650
4651 return true;
4652}
4653
Geoff Lang76e65652017-03-27 14:58:02 -04004654// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4655// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4656// specified clear value and the type of a buffer that is being cleared generates an
4657// INVALID_OPERATION error instead of producing undefined results
4658bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4659 GLint drawbuffer,
4660 const GLenum *validComponentTypes,
4661 size_t validComponentTypeCount)
4662{
4663 const FramebufferAttachment *attachment =
4664 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4665 if (attachment)
4666 {
4667 GLenum componentType = attachment->getFormat().info->componentType;
4668 const GLenum *end = validComponentTypes + validComponentTypeCount;
4669 if (std::find(validComponentTypes, end, componentType) == end)
4670 {
4671 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004672 InvalidOperation()
4673 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004674 return false;
4675 }
4676 }
4677
4678 return true;
4679}
4680
Corentin Wallezb2931602017-04-11 15:58:57 -04004681bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4682 GLsizei imageSize,
4683 GLsizei dataSize)
4684{
4685 if (!ValidateRobustEntryPoint(context, dataSize))
4686 {
4687 return false;
4688 }
4689
Corentin Wallez336129f2017-10-17 15:55:40 -04004690 gl::Buffer *pixelUnpackBuffer =
4691 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004692 if (pixelUnpackBuffer == nullptr)
4693 {
4694 if (dataSize < imageSize)
4695 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004696 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004697 }
4698 }
4699 return true;
4700}
4701
Jamie Madillbe849e42017-05-02 15:49:00 -04004702bool ValidateGetBufferParameterBase(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004703 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004704 GLenum pname,
4705 bool pointerVersion,
4706 GLsizei *numParams)
4707{
4708 if (numParams)
4709 {
4710 *numParams = 0;
4711 }
4712
Corentin Wallez336129f2017-10-17 15:55:40 -04004713 if (!ValidBufferType(context, target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004714 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004715 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004716 return false;
4717 }
4718
4719 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4720 if (!buffer)
4721 {
4722 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004723 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004724 return false;
4725 }
4726
4727 const Extensions &extensions = context->getExtensions();
4728
4729 switch (pname)
4730 {
4731 case GL_BUFFER_USAGE:
4732 case GL_BUFFER_SIZE:
4733 break;
4734
4735 case GL_BUFFER_ACCESS_OES:
4736 if (!extensions.mapBuffer)
4737 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004738 context->handleError(InvalidEnum()
4739 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004740 return false;
4741 }
4742 break;
4743
4744 case GL_BUFFER_MAPPED:
4745 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4746 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4747 !extensions.mapBufferRange)
4748 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004749 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4750 "GL_OES_mapbuffer or "
4751 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004752 return false;
4753 }
4754 break;
4755
4756 case GL_BUFFER_MAP_POINTER:
4757 if (!pointerVersion)
4758 {
4759 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004760 InvalidEnum()
4761 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004762 return false;
4763 }
4764 break;
4765
4766 case GL_BUFFER_ACCESS_FLAGS:
4767 case GL_BUFFER_MAP_OFFSET:
4768 case GL_BUFFER_MAP_LENGTH:
4769 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4770 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004771 context->handleError(InvalidEnum()
4772 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004773 return false;
4774 }
4775 break;
4776
4777 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004778 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004779 return false;
4780 }
4781
4782 // All buffer parameter queries return one value.
4783 if (numParams)
4784 {
4785 *numParams = 1;
4786 }
4787
4788 return true;
4789}
4790
4791bool ValidateGetRenderbufferParameterivBase(Context *context,
4792 GLenum target,
4793 GLenum pname,
4794 GLsizei *length)
4795{
4796 if (length)
4797 {
4798 *length = 0;
4799 }
4800
4801 if (target != GL_RENDERBUFFER)
4802 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004803 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004804 return false;
4805 }
4806
4807 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4808 if (renderbuffer == nullptr)
4809 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004810 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004811 return false;
4812 }
4813
4814 switch (pname)
4815 {
4816 case GL_RENDERBUFFER_WIDTH:
4817 case GL_RENDERBUFFER_HEIGHT:
4818 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4819 case GL_RENDERBUFFER_RED_SIZE:
4820 case GL_RENDERBUFFER_GREEN_SIZE:
4821 case GL_RENDERBUFFER_BLUE_SIZE:
4822 case GL_RENDERBUFFER_ALPHA_SIZE:
4823 case GL_RENDERBUFFER_DEPTH_SIZE:
4824 case GL_RENDERBUFFER_STENCIL_SIZE:
4825 break;
4826
4827 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4828 if (!context->getExtensions().framebufferMultisample)
4829 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004830 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004831 return false;
4832 }
4833 break;
4834
4835 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004836 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004837 return false;
4838 }
4839
4840 if (length)
4841 {
4842 *length = 1;
4843 }
4844 return true;
4845}
4846
4847bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4848{
4849 if (length)
4850 {
4851 *length = 0;
4852 }
4853
4854 if (GetValidShader(context, shader) == nullptr)
4855 {
4856 return false;
4857 }
4858
4859 switch (pname)
4860 {
4861 case GL_SHADER_TYPE:
4862 case GL_DELETE_STATUS:
4863 case GL_COMPILE_STATUS:
4864 case GL_INFO_LOG_LENGTH:
4865 case GL_SHADER_SOURCE_LENGTH:
4866 break;
4867
4868 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4869 if (!context->getExtensions().translatedShaderSource)
4870 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004871 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004872 return false;
4873 }
4874 break;
4875
4876 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004877 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004878 return false;
4879 }
4880
4881 if (length)
4882 {
4883 *length = 1;
4884 }
4885 return true;
4886}
4887
4888bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4889{
4890 if (length)
4891 {
4892 *length = 0;
4893 }
4894
4895 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4896 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004897 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004898 return false;
4899 }
4900
4901 if (context->getTargetTexture(target) == nullptr)
4902 {
4903 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004904 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004905 return false;
4906 }
4907
4908 switch (pname)
4909 {
4910 case GL_TEXTURE_MAG_FILTER:
4911 case GL_TEXTURE_MIN_FILTER:
4912 case GL_TEXTURE_WRAP_S:
4913 case GL_TEXTURE_WRAP_T:
4914 break;
4915
4916 case GL_TEXTURE_USAGE_ANGLE:
4917 if (!context->getExtensions().textureUsage)
4918 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004919 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004920 return false;
4921 }
4922 break;
4923
4924 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4925 if (!context->getExtensions().textureFilterAnisotropic)
4926 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004927 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004928 return false;
4929 }
4930 break;
4931
4932 case GL_TEXTURE_IMMUTABLE_FORMAT:
4933 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4934 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004935 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004936 return false;
4937 }
4938 break;
4939
4940 case GL_TEXTURE_WRAP_R:
4941 case GL_TEXTURE_IMMUTABLE_LEVELS:
4942 case GL_TEXTURE_SWIZZLE_R:
4943 case GL_TEXTURE_SWIZZLE_G:
4944 case GL_TEXTURE_SWIZZLE_B:
4945 case GL_TEXTURE_SWIZZLE_A:
4946 case GL_TEXTURE_BASE_LEVEL:
4947 case GL_TEXTURE_MAX_LEVEL:
4948 case GL_TEXTURE_MIN_LOD:
4949 case GL_TEXTURE_MAX_LOD:
4950 case GL_TEXTURE_COMPARE_MODE:
4951 case GL_TEXTURE_COMPARE_FUNC:
4952 if (context->getClientMajorVersion() < 3)
4953 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004954 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004955 return false;
4956 }
4957 break;
4958
4959 case GL_TEXTURE_SRGB_DECODE_EXT:
4960 if (!context->getExtensions().textureSRGBDecode)
4961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004962 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004963 return false;
4964 }
4965 break;
4966
4967 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004968 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004969 return false;
4970 }
4971
4972 if (length)
4973 {
4974 *length = 1;
4975 }
4976 return true;
4977}
4978
4979bool ValidateGetVertexAttribBase(Context *context,
4980 GLuint index,
4981 GLenum pname,
4982 GLsizei *length,
4983 bool pointer,
4984 bool pureIntegerEntryPoint)
4985{
4986 if (length)
4987 {
4988 *length = 0;
4989 }
4990
4991 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
4992 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004993 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004994 return false;
4995 }
4996
4997 if (index >= context->getCaps().maxVertexAttributes)
4998 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004999 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005000 return false;
5001 }
5002
5003 if (pointer)
5004 {
5005 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5006 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005007 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005008 return false;
5009 }
5010 }
5011 else
5012 {
5013 switch (pname)
5014 {
5015 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5016 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5017 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5018 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5019 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5020 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5021 case GL_CURRENT_VERTEX_ATTRIB:
5022 break;
5023
5024 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5025 static_assert(
5026 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5027 "ANGLE extension enums not equal to GL enums.");
5028 if (context->getClientMajorVersion() < 3 &&
5029 !context->getExtensions().instancedArrays)
5030 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005031 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5032 "requires OpenGL ES 3.0 or "
5033 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005034 return false;
5035 }
5036 break;
5037
5038 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5039 if (context->getClientMajorVersion() < 3)
5040 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005041 context->handleError(
5042 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005043 return false;
5044 }
5045 break;
5046
5047 case GL_VERTEX_ATTRIB_BINDING:
5048 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5049 if (context->getClientVersion() < ES_3_1)
5050 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005051 context->handleError(InvalidEnum()
5052 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005053 return false;
5054 }
5055 break;
5056
5057 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005058 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005059 return false;
5060 }
5061 }
5062
5063 if (length)
5064 {
5065 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5066 {
5067 *length = 4;
5068 }
5069 else
5070 {
5071 *length = 1;
5072 }
5073 }
5074
5075 return true;
5076}
5077
Jamie Madill4928b7c2017-06-20 12:57:39 -04005078bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005079 GLint x,
5080 GLint y,
5081 GLsizei width,
5082 GLsizei height,
5083 GLenum format,
5084 GLenum type,
5085 GLsizei bufSize,
5086 GLsizei *length,
5087 GLsizei *columns,
5088 GLsizei *rows,
5089 void *pixels)
5090{
5091 if (length != nullptr)
5092 {
5093 *length = 0;
5094 }
5095 if (rows != nullptr)
5096 {
5097 *rows = 0;
5098 }
5099 if (columns != nullptr)
5100 {
5101 *columns = 0;
5102 }
5103
5104 if (width < 0 || height < 0)
5105 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005106 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005107 return false;
5108 }
5109
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005110 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005111
5112 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5113 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005114 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005115 return false;
5116 }
5117
5118 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5119 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005120 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005121 return false;
5122 }
5123
5124 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5125 ASSERT(framebuffer);
5126
5127 if (framebuffer->getReadBufferState() == GL_NONE)
5128 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005129 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005130 return false;
5131 }
5132
5133 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5134 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5135 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5136 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5137 // situation is an application error that would lead to a crash in ANGLE.
5138 if (readBuffer == nullptr)
5139 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005140 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005141 return false;
5142 }
5143
Martin Radev28031682017-07-28 14:47:56 +03005144 // ANGLE_multiview, Revision 1:
5145 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5146 // current read framebuffer is not NONE.
5147 if (readBuffer->getMultiviewLayout() != GL_NONE)
5148 {
5149 context->handleError(InvalidFramebufferOperation()
5150 << "Attempting to read from a multi-view framebuffer.");
5151 return false;
5152 }
5153
Geoff Lang280ba992017-04-18 16:30:58 -04005154 if (context->getExtensions().webglCompatibility)
5155 {
5156 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5157 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5158 // and type before validating the combination of format and type. However, the
5159 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5160 // verifies that GL_INVALID_OPERATION is generated.
5161 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5162 // dEQP/WebGL.
5163 if (!ValidReadPixelsFormatEnum(context, format))
5164 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005165 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005166 return false;
5167 }
5168
5169 if (!ValidReadPixelsTypeEnum(context, type))
5170 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005171 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005172 return false;
5173 }
5174 }
5175
Jamie Madill4928b7c2017-06-20 12:57:39 -04005176 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5177 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005178 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5179
5180 bool validFormatTypeCombination =
5181 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5182
5183 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5184 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005185 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005186 return false;
5187 }
5188
5189 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005190 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005191 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5192 {
5193 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005194 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005195 return false;
5196 }
5197
5198 // .. the data would be packed to the buffer object such that the memory writes required
5199 // would exceed the data store size.
5200 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5201 const gl::Extents size(width, height, 1);
5202 const auto &pack = context->getGLState().getPackState();
5203
5204 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5205 if (endByteOrErr.isError())
5206 {
5207 context->handleError(endByteOrErr.getError());
5208 return false;
5209 }
5210
5211 size_t endByte = endByteOrErr.getResult();
5212 if (bufSize >= 0)
5213 {
5214 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5215 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005216 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005217 return false;
5218 }
5219 }
5220
5221 if (pixelPackBuffer != nullptr)
5222 {
5223 CheckedNumeric<size_t> checkedEndByte(endByte);
5224 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5225 checkedEndByte += checkedOffset;
5226
5227 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5228 {
5229 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005230 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005231 return false;
5232 }
5233 }
5234
5235 if (pixelPackBuffer == nullptr && length != nullptr)
5236 {
5237 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5238 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005239 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005240 return false;
5241 }
5242
5243 *length = static_cast<GLsizei>(endByte);
5244 }
5245
5246 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5247 angle::CheckedNumeric<int> clippedExtent(length);
5248 if (start < 0)
5249 {
5250 // "subtract" the area that is less than 0
5251 clippedExtent += start;
5252 }
5253
5254 const int readExtent = start + length;
5255 if (readExtent > bufferSize)
5256 {
5257 // Subtract the region to the right of the read buffer
5258 clippedExtent -= (readExtent - bufferSize);
5259 }
5260
5261 if (!clippedExtent.IsValid())
5262 {
5263 return 0;
5264 }
5265
5266 return std::max(clippedExtent.ValueOrDie(), 0);
5267 };
5268
5269 if (columns != nullptr)
5270 {
5271 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5272 }
5273
5274 if (rows != nullptr)
5275 {
5276 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5277 }
5278
5279 return true;
5280}
5281
5282template <typename ParamType>
5283bool ValidateTexParameterBase(Context *context,
5284 GLenum target,
5285 GLenum pname,
5286 GLsizei bufSize,
5287 const ParamType *params)
5288{
5289 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5290 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005291 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005292 return false;
5293 }
5294
5295 if (context->getTargetTexture(target) == nullptr)
5296 {
5297 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005298 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005299 return false;
5300 }
5301
5302 const GLsizei minBufSize = 1;
5303 if (bufSize >= 0 && bufSize < minBufSize)
5304 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005305 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005306 return false;
5307 }
5308
5309 switch (pname)
5310 {
5311 case GL_TEXTURE_WRAP_R:
5312 case GL_TEXTURE_SWIZZLE_R:
5313 case GL_TEXTURE_SWIZZLE_G:
5314 case GL_TEXTURE_SWIZZLE_B:
5315 case GL_TEXTURE_SWIZZLE_A:
5316 case GL_TEXTURE_BASE_LEVEL:
5317 case GL_TEXTURE_MAX_LEVEL:
5318 case GL_TEXTURE_COMPARE_MODE:
5319 case GL_TEXTURE_COMPARE_FUNC:
5320 case GL_TEXTURE_MIN_LOD:
5321 case GL_TEXTURE_MAX_LOD:
5322 if (context->getClientMajorVersion() < 3)
5323 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005324 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005325 return false;
5326 }
5327 if (target == GL_TEXTURE_EXTERNAL_OES &&
5328 !context->getExtensions().eglImageExternalEssl3)
5329 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005330 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5331 "available without "
5332 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005333 return false;
5334 }
5335 break;
5336
5337 default:
5338 break;
5339 }
5340
JiangYizhou4cff8d62017-07-06 14:54:09 +08005341 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5342 {
5343 switch (pname)
5344 {
5345 case GL_TEXTURE_MIN_FILTER:
5346 case GL_TEXTURE_MAG_FILTER:
5347 case GL_TEXTURE_WRAP_S:
5348 case GL_TEXTURE_WRAP_T:
5349 case GL_TEXTURE_WRAP_R:
5350 case GL_TEXTURE_MIN_LOD:
5351 case GL_TEXTURE_MAX_LOD:
5352 case GL_TEXTURE_COMPARE_MODE:
5353 case GL_TEXTURE_COMPARE_FUNC:
5354 context->handleError(InvalidEnum()
5355 << "Invalid parameter for 2D multisampled textures.");
5356 return false;
5357 }
5358 }
5359
Jamie Madillbe849e42017-05-02 15:49:00 -04005360 switch (pname)
5361 {
5362 case GL_TEXTURE_WRAP_S:
5363 case GL_TEXTURE_WRAP_T:
5364 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005365 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005366 bool restrictedWrapModes =
5367 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5368 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5369 {
5370 return false;
5371 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005372 }
5373 break;
5374
5375 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005376 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005377 bool restrictedMinFilter =
5378 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5379 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5380 {
5381 return false;
5382 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005383 }
5384 break;
5385
5386 case GL_TEXTURE_MAG_FILTER:
5387 if (!ValidateTextureMagFilterValue(context, params))
5388 {
5389 return false;
5390 }
5391 break;
5392
5393 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005394 if (!context->getExtensions().textureUsage)
5395 {
5396 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5397 return false;
5398 }
5399
Jamie Madillbe849e42017-05-02 15:49:00 -04005400 switch (ConvertToGLenum(params[0]))
5401 {
5402 case GL_NONE:
5403 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5404 break;
5405
5406 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005407 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005408 return false;
5409 }
5410 break;
5411
5412 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5413 if (!context->getExtensions().textureFilterAnisotropic)
5414 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005415 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005416 return false;
5417 }
5418
5419 // we assume the parameter passed to this validation method is truncated, not rounded
5420 if (params[0] < 1)
5421 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005422 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005423 return false;
5424 }
5425 break;
5426
5427 case GL_TEXTURE_MIN_LOD:
5428 case GL_TEXTURE_MAX_LOD:
5429 // any value is permissible
5430 break;
5431
5432 case GL_TEXTURE_COMPARE_MODE:
5433 if (!ValidateTextureCompareModeValue(context, params))
5434 {
5435 return false;
5436 }
5437 break;
5438
5439 case GL_TEXTURE_COMPARE_FUNC:
5440 if (!ValidateTextureCompareFuncValue(context, params))
5441 {
5442 return false;
5443 }
5444 break;
5445
5446 case GL_TEXTURE_SWIZZLE_R:
5447 case GL_TEXTURE_SWIZZLE_G:
5448 case GL_TEXTURE_SWIZZLE_B:
5449 case GL_TEXTURE_SWIZZLE_A:
5450 switch (ConvertToGLenum(params[0]))
5451 {
5452 case GL_RED:
5453 case GL_GREEN:
5454 case GL_BLUE:
5455 case GL_ALPHA:
5456 case GL_ZERO:
5457 case GL_ONE:
5458 break;
5459
5460 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005461 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005462 return false;
5463 }
5464 break;
5465
5466 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005467 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005468 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005469 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005470 return false;
5471 }
5472 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5473 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005474 context->handleError(InvalidOperation()
5475 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005476 return false;
5477 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005478 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5479 {
5480 context->handleError(InvalidOperation()
5481 << "Base level must be 0 for multisampled textures.");
5482 return false;
5483 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005484 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5485 {
5486 context->handleError(InvalidOperation()
5487 << "Base level must be 0 for rectangle textures.");
5488 return false;
5489 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005490 break;
5491
5492 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005493 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005494 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005495 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005496 return false;
5497 }
5498 break;
5499
5500 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5501 if (context->getClientVersion() < Version(3, 1))
5502 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005503 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005504 return false;
5505 }
5506 switch (ConvertToGLenum(params[0]))
5507 {
5508 case GL_DEPTH_COMPONENT:
5509 case GL_STENCIL_INDEX:
5510 break;
5511
5512 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005513 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005514 return false;
5515 }
5516 break;
5517
5518 case GL_TEXTURE_SRGB_DECODE_EXT:
5519 if (!ValidateTextureSRGBDecodeValue(context, params))
5520 {
5521 return false;
5522 }
5523 break;
5524
5525 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005526 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005527 return false;
5528 }
5529
5530 return true;
5531}
5532
5533template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5534template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5535
Jamie Madill12e957f2017-08-26 21:42:26 -04005536bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5537{
5538 if (index >= MAX_VERTEX_ATTRIBS)
5539 {
5540 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5541 return false;
5542 }
5543
5544 return true;
5545}
5546
5547bool ValidateGetActiveUniformBlockivBase(Context *context,
5548 GLuint program,
5549 GLuint uniformBlockIndex,
5550 GLenum pname,
5551 GLsizei *length)
5552{
5553 if (length)
5554 {
5555 *length = 0;
5556 }
5557
5558 if (context->getClientMajorVersion() < 3)
5559 {
5560 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5561 return false;
5562 }
5563
5564 Program *programObject = GetValidProgram(context, program);
5565 if (!programObject)
5566 {
5567 return false;
5568 }
5569
5570 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5571 {
5572 context->handleError(InvalidValue()
5573 << "uniformBlockIndex exceeds active uniform block count.");
5574 return false;
5575 }
5576
5577 switch (pname)
5578 {
5579 case GL_UNIFORM_BLOCK_BINDING:
5580 case GL_UNIFORM_BLOCK_DATA_SIZE:
5581 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5582 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5583 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5584 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5585 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5586 break;
5587
5588 default:
5589 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5590 return false;
5591 }
5592
5593 if (length)
5594 {
5595 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5596 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005597 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005598 programObject->getUniformBlockByIndex(uniformBlockIndex);
5599 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5600 }
5601 else
5602 {
5603 *length = 1;
5604 }
5605 }
5606
5607 return true;
5608}
5609
Jamie Madill9696d072017-08-26 23:19:57 -04005610template <typename ParamType>
5611bool ValidateSamplerParameterBase(Context *context,
5612 GLuint sampler,
5613 GLenum pname,
5614 GLsizei bufSize,
5615 ParamType *params)
5616{
5617 if (context->getClientMajorVersion() < 3)
5618 {
5619 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5620 return false;
5621 }
5622
5623 if (!context->isSampler(sampler))
5624 {
5625 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5626 return false;
5627 }
5628
5629 const GLsizei minBufSize = 1;
5630 if (bufSize >= 0 && bufSize < minBufSize)
5631 {
5632 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5633 return false;
5634 }
5635
5636 switch (pname)
5637 {
5638 case GL_TEXTURE_WRAP_S:
5639 case GL_TEXTURE_WRAP_T:
5640 case GL_TEXTURE_WRAP_R:
5641 if (!ValidateTextureWrapModeValue(context, params, false))
5642 {
5643 return false;
5644 }
5645 break;
5646
5647 case GL_TEXTURE_MIN_FILTER:
5648 if (!ValidateTextureMinFilterValue(context, params, false))
5649 {
5650 return false;
5651 }
5652 break;
5653
5654 case GL_TEXTURE_MAG_FILTER:
5655 if (!ValidateTextureMagFilterValue(context, params))
5656 {
5657 return false;
5658 }
5659 break;
5660
5661 case GL_TEXTURE_MIN_LOD:
5662 case GL_TEXTURE_MAX_LOD:
5663 // any value is permissible
5664 break;
5665
5666 case GL_TEXTURE_COMPARE_MODE:
5667 if (!ValidateTextureCompareModeValue(context, params))
5668 {
5669 return false;
5670 }
5671 break;
5672
5673 case GL_TEXTURE_COMPARE_FUNC:
5674 if (!ValidateTextureCompareFuncValue(context, params))
5675 {
5676 return false;
5677 }
5678 break;
5679
5680 case GL_TEXTURE_SRGB_DECODE_EXT:
5681 if (!ValidateTextureSRGBDecodeValue(context, params))
5682 {
5683 return false;
5684 }
5685 break;
5686
5687 default:
5688 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5689 return false;
5690 }
5691
5692 return true;
5693}
5694
5695template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5696template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5697
5698bool ValidateGetSamplerParameterBase(Context *context,
5699 GLuint sampler,
5700 GLenum pname,
5701 GLsizei *length)
5702{
5703 if (length)
5704 {
5705 *length = 0;
5706 }
5707
5708 if (context->getClientMajorVersion() < 3)
5709 {
5710 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5711 return false;
5712 }
5713
5714 if (!context->isSampler(sampler))
5715 {
5716 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5717 return false;
5718 }
5719
5720 switch (pname)
5721 {
5722 case GL_TEXTURE_WRAP_S:
5723 case GL_TEXTURE_WRAP_T:
5724 case GL_TEXTURE_WRAP_R:
5725 case GL_TEXTURE_MIN_FILTER:
5726 case GL_TEXTURE_MAG_FILTER:
5727 case GL_TEXTURE_MIN_LOD:
5728 case GL_TEXTURE_MAX_LOD:
5729 case GL_TEXTURE_COMPARE_MODE:
5730 case GL_TEXTURE_COMPARE_FUNC:
5731 break;
5732
5733 case GL_TEXTURE_SRGB_DECODE_EXT:
5734 if (!context->getExtensions().textureSRGBDecode)
5735 {
5736 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5737 return false;
5738 }
5739 break;
5740
5741 default:
5742 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5743 return false;
5744 }
5745
5746 if (length)
5747 {
5748 *length = 1;
5749 }
5750 return true;
5751}
5752
5753bool ValidateGetInternalFormativBase(Context *context,
5754 GLenum target,
5755 GLenum internalformat,
5756 GLenum pname,
5757 GLsizei bufSize,
5758 GLsizei *numParams)
5759{
5760 if (numParams)
5761 {
5762 *numParams = 0;
5763 }
5764
5765 if (context->getClientMajorVersion() < 3)
5766 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005767 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005768 return false;
5769 }
5770
5771 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5772 if (!formatCaps.renderable)
5773 {
5774 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5775 return false;
5776 }
5777
5778 switch (target)
5779 {
5780 case GL_RENDERBUFFER:
5781 break;
5782
5783 case GL_TEXTURE_2D_MULTISAMPLE:
5784 if (context->getClientVersion() < ES_3_1)
5785 {
5786 context->handleError(InvalidOperation()
5787 << "Texture target requires at least OpenGL ES 3.1.");
5788 return false;
5789 }
5790 break;
5791
5792 default:
5793 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5794 return false;
5795 }
5796
5797 if (bufSize < 0)
5798 {
5799 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5800 return false;
5801 }
5802
5803 GLsizei maxWriteParams = 0;
5804 switch (pname)
5805 {
5806 case GL_NUM_SAMPLE_COUNTS:
5807 maxWriteParams = 1;
5808 break;
5809
5810 case GL_SAMPLES:
5811 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5812 break;
5813
5814 default:
5815 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5816 return false;
5817 }
5818
5819 if (numParams)
5820 {
5821 // glGetInternalFormativ will not overflow bufSize
5822 *numParams = std::min(bufSize, maxWriteParams);
5823 }
5824
5825 return true;
5826}
5827
Jamie Madillc29968b2016-01-20 11:17:23 -05005828} // namespace gl