blob: 3e4e12af9f38c419ae2f9a71b2795a91c873ee55 [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 Hef81ce4a2017-04-24 10:49:17 +08002540 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002541 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002542 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002543 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002544 }
2545
Martin Radevffe754b2017-07-31 10:38:07 +03002546 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002547 {
Martin Radevda8e2572017-09-12 17:21:16 +03002548 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002549 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002550 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002551 {
2552 context->handleError(InvalidOperation() << "The number of views in the active program "
2553 "and draw framebuffer does not match.");
2554 return false;
2555 }
Martin Radev7e69f762017-07-27 14:54:13 +03002556
2557 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2558 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2559 framebufferNumViews > 1)
2560 {
2561 context->handleError(InvalidOperation()
2562 << "There is an active transform feedback object "
2563 "when the number of views in the active draw "
2564 "framebuffer is greater than 1.");
2565 return false;
2566 }
Martin Radevffe754b2017-07-31 10:38:07 +03002567
2568 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2569 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2570 {
2571 context->handleError(InvalidOperation() << "There is an active query for target "
2572 "GL_TIME_ELAPSED_EXT when the number of "
2573 "views in the active draw framebuffer is "
2574 "greater than 1.");
2575 return false;
2576 }
Martin Radev7cf61662017-07-26 17:10:53 +03002577 }
2578
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002579 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002580 for (unsigned int uniformBlockIndex = 0;
2581 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002582 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002583 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002584 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002585 const OffsetBindingPointer<Buffer> &uniformBuffer =
2586 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002587
Geoff Lang5d124a62015-09-15 13:03:27 -04002588 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002589 {
2590 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002591 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002592 InvalidOperation()
2593 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002594 return false;
2595 }
2596
Geoff Lang5d124a62015-09-15 13:03:27 -04002597 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002598 if (uniformBufferSize == 0)
2599 {
2600 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002601 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002602 }
2603
Jamie Madill62d31cb2015-09-11 13:25:51 -04002604 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002605 {
2606 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002607 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002608 InvalidOperation()
2609 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002610 return false;
2611 }
2612 }
2613
Geoff Lange0cff192017-05-30 13:04:56 -04002614 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002615 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002616 {
Geoff Lange0cff192017-05-30 13:04:56 -04002617 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002618 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2619 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002620 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002621 return false;
2622 }
Geoff Lange0cff192017-05-30 13:04:56 -04002623
Geoff Lang9ab5b822017-05-30 16:19:23 -04002624 // Detect that the vertex shader input types match the attribute types
2625 if (!ValidateVertexShaderAttributeTypeMatch(context))
2626 {
2627 return false;
2628 }
2629
Geoff Lange0cff192017-05-30 13:04:56 -04002630 // Detect that the color buffer types match the fragment shader output types
2631 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2632 {
2633 return false;
2634 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002635 }
2636
Jamie Madill250d33f2014-06-06 17:09:03 -04002637 // No-op if zero count
2638 return (count > 0);
2639}
2640
Jamie Madillc1d770e2017-04-13 17:31:24 -04002641bool ValidateDrawArraysCommon(ValidationContext *context,
2642 GLenum mode,
2643 GLint first,
2644 GLsizei count,
2645 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002646{
Jamie Madillfd716582014-06-06 17:09:04 -04002647 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002648 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002649 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002650 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002651 }
2652
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002653 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002654 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002655 if (curTransformFeedback && curTransformFeedback->isActive() &&
2656 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002657 {
2658 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002659 // that does not match the current transform feedback object's draw mode (if transform
2660 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002661 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002662 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002663 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002664 }
2665
Jiajia Qind9671222016-11-29 16:30:31 +08002666 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002667 {
2668 return false;
2669 }
2670
Corentin Wallez71168a02016-12-19 15:11:18 -08002671 // Check the computation of maxVertex doesn't overflow.
2672 // - first < 0 or count < 0 have been checked as an error condition
2673 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2674 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2675 ASSERT(count > 0 && first >= 0);
2676 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2677 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002678 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002679 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002680 return false;
2681 }
2682
Corentin Wallez71168a02016-12-19 15:11:18 -08002683 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002684 {
2685 return false;
2686 }
2687
2688 return true;
2689}
2690
He Yunchaoced53ae2016-11-29 15:00:51 +08002691bool ValidateDrawArraysInstancedANGLE(Context *context,
2692 GLenum mode,
2693 GLint first,
2694 GLsizei count,
2695 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002696{
Geoff Lang63c5a592017-09-27 14:08:16 -04002697 if (!context->getExtensions().instancedArrays)
2698 {
2699 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2700 return false;
2701 }
2702
Corentin Wallez170efbf2017-05-02 13:45:01 -04002703 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002704 {
2705 return false;
2706 }
2707
Corentin Wallez0dc97812017-06-22 14:38:44 -04002708 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002709}
2710
Jiajia Qind9671222016-11-29 16:30:31 +08002711bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002712{
Jamie Madill250d33f2014-06-06 17:09:03 -04002713 switch (type)
2714 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002715 case GL_UNSIGNED_BYTE:
2716 case GL_UNSIGNED_SHORT:
2717 break;
2718 case GL_UNSIGNED_INT:
2719 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2720 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002721 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002722 return false;
2723 }
2724 break;
2725 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002726 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002727 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002728 }
2729
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002730 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002731
2732 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002733 if (curTransformFeedback && curTransformFeedback->isActive() &&
2734 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002735 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002736 // It is an invalid operation to call DrawElements, DrawRangeElements or
2737 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002738 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002739 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002740 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002741 }
2742
Jiajia Qind9671222016-11-29 16:30:31 +08002743 return true;
2744}
2745
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002746bool ValidateDrawElementsCommon(ValidationContext *context,
2747 GLenum mode,
2748 GLsizei count,
2749 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002750 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002751 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002752{
2753 if (!ValidateDrawElementsBase(context, type))
2754 return false;
2755
2756 const State &state = context->getGLState();
2757
Corentin Wallez170efbf2017-05-02 13:45:01 -04002758 if (!ValidateDrawBase(context, mode, count))
2759 {
2760 return false;
2761 }
2762
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002763 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2764 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2765 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2766 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002767 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002768 // Check for mapped buffers
2769 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002770 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002771 {
2772 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2773 return false;
2774 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002775 }
2776
He Yunchaoced53ae2016-11-29 15:00:51 +08002777 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002778 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002779
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002780 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2781
2782 if (context->getExtensions().webglCompatibility)
2783 {
2784 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2785 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2786 {
2787 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2788 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2789 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002790 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002791 return false;
2792 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002793
2794 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2795 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2796 // error is generated.
2797 if (reinterpret_cast<intptr_t>(indices) < 0)
2798 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002799 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002800 return false;
2801 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002802 }
2803
2804 if (context->getExtensions().webglCompatibility ||
2805 !context->getGLState().areClientArraysEnabled())
2806 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002807 if (!elementArrayBuffer && count > 0)
2808 {
2809 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2810 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2811 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002812 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002813 return false;
2814 }
2815 }
2816
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002817 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002818 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002819 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002820 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002821 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2822 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2823 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2824 constexpr uint64_t kMaxTypeSize = 8;
2825 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2826 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2827 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002828
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002829 uint64_t typeSize = typeBytes;
2830 uint64_t elementCount = static_cast<uint64_t>(count);
2831 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2832
2833 // Doing the multiplication here is overflow-safe
2834 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2835
2836 // The offset can be any value, check for overflows
2837 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2838 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002839 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002840 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002841 return false;
2842 }
2843
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002844 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2845 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002846 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002847 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002848 return false;
2849 }
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002850
Corentin Wallez487653b2017-09-01 17:17:55 -04002851 ASSERT(isPow2(typeSize) && typeSize > 0);
2852 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002853 {
2854 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
2855 return false;
2856 }
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002857 }
2858 else if (!indices)
2859 {
2860 // This is an application error that would normally result in a crash,
2861 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002862 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04002863 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002864 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002865 }
2866
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002867 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002868 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002869 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2870 // access is enabled.
2871 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2872 {
2873 return false;
2874 }
2875 }
2876 else
2877 {
2878 // Use the parameter buffer to retrieve and cache the index range.
2879 const auto &params = context->getParams<HasIndexRange>();
2880 const auto &indexRangeOpt = params.getIndexRange();
2881 if (!indexRangeOpt.valid())
2882 {
2883 // Unexpected error.
2884 return false;
2885 }
2886
2887 // If we use an index greater than our maximum supported index range, return an error.
2888 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2889 // return an error if possible here.
2890 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2891 {
2892 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2893 return false;
2894 }
2895
2896 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2897 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2898 {
2899 return false;
2900 }
2901
2902 // No op if there are no real indices in the index data (all are primitive restart).
2903 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002904 }
2905
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002906 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002907}
2908
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002909bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2910 GLenum mode,
2911 GLsizei count,
2912 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002913 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002914 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002915{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002916 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002917}
2918
Geoff Lang3edfe032015-09-04 16:38:24 -04002919bool ValidateDrawElementsInstancedANGLE(Context *context,
2920 GLenum mode,
2921 GLsizei count,
2922 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002923 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002924 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002925{
Geoff Lang63c5a592017-09-27 14:08:16 -04002926 if (!context->getExtensions().instancedArrays)
2927 {
2928 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2929 return false;
2930 }
2931
Corentin Wallez170efbf2017-05-02 13:45:01 -04002932 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002933 {
2934 return false;
2935 }
2936
Corentin Wallez0dc97812017-06-22 14:38:44 -04002937 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002938}
2939
He Yunchaoced53ae2016-11-29 15:00:51 +08002940bool ValidateFramebufferTextureBase(Context *context,
2941 GLenum target,
2942 GLenum attachment,
2943 GLuint texture,
2944 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002945{
Geoff Lange8afa902017-09-27 15:00:43 -04002946 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002947 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002948 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002949 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002950 }
2951
2952 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002953 {
2954 return false;
2955 }
2956
Jamie Madill55ec3b12014-07-03 10:38:57 -04002957 if (texture != 0)
2958 {
2959 gl::Texture *tex = context->getTexture(texture);
2960
Jamie Madillbe849e42017-05-02 15:49:00 -04002961 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002962 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002963 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002964 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002965 }
2966
2967 if (level < 0)
2968 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002969 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002970 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002971 }
2972 }
2973
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002974 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002975 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002976
Jamie Madill84115c92015-04-23 15:00:07 -04002977 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002978 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002979 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002980 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002981 }
2982
2983 return true;
2984}
2985
Geoff Langb1196682014-07-23 13:47:29 -04002986bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04002987{
2988 if (program == 0)
2989 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002990 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002991 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002992 }
2993
Dian Xiang769769a2015-09-09 15:20:08 -07002994 gl::Program *programObject = GetValidProgram(context, program);
2995 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05002996 {
2997 return false;
2998 }
2999
Jamie Madill0063c512014-08-25 15:47:53 -04003000 if (!programObject || !programObject->isLinked())
3001 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003002 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003003 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003004 }
3005
Geoff Lang7dd2e102014-11-10 15:19:26 -05003006 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003007 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003008 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003009 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003010 }
3011
Jamie Madill0063c512014-08-25 15:47:53 -04003012 return true;
3013}
3014
Geoff Langf41d0ee2016-10-07 13:04:23 -04003015static bool ValidateSizedGetUniform(Context *context,
3016 GLuint program,
3017 GLint location,
3018 GLsizei bufSize,
3019 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003020{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003021 if (length)
3022 {
3023 *length = 0;
3024 }
3025
Jamie Madill78f41802014-08-25 15:47:55 -04003026 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003027 {
Jamie Madill78f41802014-08-25 15:47:55 -04003028 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003029 }
3030
Geoff Langf41d0ee2016-10-07 13:04:23 -04003031 if (bufSize < 0)
3032 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003033 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003034 return false;
3035 }
3036
Jamie Madilla502c742014-08-28 17:19:13 -04003037 gl::Program *programObject = context->getProgram(program);
3038 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003039
Jamie Madill78f41802014-08-25 15:47:55 -04003040 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003041 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003042 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003043 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003044 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003045 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003046 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003047 }
3048
Geoff Langf41d0ee2016-10-07 13:04:23 -04003049 if (length)
3050 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003051 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003052 }
3053
Jamie Madill0063c512014-08-25 15:47:53 -04003054 return true;
3055}
3056
He Yunchaoced53ae2016-11-29 15:00:51 +08003057bool ValidateGetnUniformfvEXT(Context *context,
3058 GLuint program,
3059 GLint location,
3060 GLsizei bufSize,
3061 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003062{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003063 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003064}
3065
He Yunchaoced53ae2016-11-29 15:00:51 +08003066bool ValidateGetnUniformivEXT(Context *context,
3067 GLuint program,
3068 GLint location,
3069 GLsizei bufSize,
3070 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003071{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003072 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3073}
3074
3075bool ValidateGetUniformfvRobustANGLE(Context *context,
3076 GLuint program,
3077 GLint location,
3078 GLsizei bufSize,
3079 GLsizei *length,
3080 GLfloat *params)
3081{
3082 if (!ValidateRobustEntryPoint(context, bufSize))
3083 {
3084 return false;
3085 }
3086
3087 // bufSize is validated in ValidateSizedGetUniform
3088 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3089}
3090
3091bool ValidateGetUniformivRobustANGLE(Context *context,
3092 GLuint program,
3093 GLint location,
3094 GLsizei bufSize,
3095 GLsizei *length,
3096 GLint *params)
3097{
3098 if (!ValidateRobustEntryPoint(context, bufSize))
3099 {
3100 return false;
3101 }
3102
3103 // bufSize is validated in ValidateSizedGetUniform
3104 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3105}
3106
3107bool ValidateGetUniformuivRobustANGLE(Context *context,
3108 GLuint program,
3109 GLint location,
3110 GLsizei bufSize,
3111 GLsizei *length,
3112 GLuint *params)
3113{
3114 if (!ValidateRobustEntryPoint(context, bufSize))
3115 {
3116 return false;
3117 }
3118
3119 if (context->getClientMajorVersion() < 3)
3120 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003121 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003122 return false;
3123 }
3124
3125 // bufSize is validated in ValidateSizedGetUniform
3126 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003127}
3128
He Yunchaoced53ae2016-11-29 15:00:51 +08003129bool ValidateDiscardFramebufferBase(Context *context,
3130 GLenum target,
3131 GLsizei numAttachments,
3132 const GLenum *attachments,
3133 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003134{
3135 if (numAttachments < 0)
3136 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003137 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003138 return false;
3139 }
3140
3141 for (GLsizei i = 0; i < numAttachments; ++i)
3142 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003143 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003144 {
3145 if (defaultFramebuffer)
3146 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003147 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003148 return false;
3149 }
3150
3151 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3152 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003153 context->handleError(InvalidOperation() << "Requested color attachment is "
3154 "greater than the maximum supported "
3155 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003156 return false;
3157 }
3158 }
3159 else
3160 {
3161 switch (attachments[i])
3162 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003163 case GL_DEPTH_ATTACHMENT:
3164 case GL_STENCIL_ATTACHMENT:
3165 case GL_DEPTH_STENCIL_ATTACHMENT:
3166 if (defaultFramebuffer)
3167 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003168 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3169 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003170 return false;
3171 }
3172 break;
3173 case GL_COLOR:
3174 case GL_DEPTH:
3175 case GL_STENCIL:
3176 if (!defaultFramebuffer)
3177 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003178 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3179 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003180 return false;
3181 }
3182 break;
3183 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003184 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003185 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003186 }
3187 }
3188 }
3189
3190 return true;
3191}
3192
Austin Kinross6ee1e782015-05-29 17:05:37 -07003193bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3194{
3195 // Note that debug marker calls must not set error state
3196
3197 if (length < 0)
3198 {
3199 return false;
3200 }
3201
3202 if (marker == nullptr)
3203 {
3204 return false;
3205 }
3206
3207 return true;
3208}
3209
3210bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3211{
3212 // Note that debug marker calls must not set error state
3213
3214 if (length < 0)
3215 {
3216 return false;
3217 }
3218
3219 if (length > 0 && marker == nullptr)
3220 {
3221 return false;
3222 }
3223
3224 return true;
3225}
3226
Geoff Langdcab33b2015-07-21 13:03:16 -04003227bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003228 GLenum target,
3229 egl::Image *image)
3230{
Geoff Langa8406172015-07-21 16:53:39 -04003231 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3232 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003233 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003234 return false;
3235 }
3236
3237 switch (target)
3238 {
3239 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003240 if (!context->getExtensions().eglImage)
3241 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003242 context->handleError(InvalidEnum()
3243 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003244 }
3245 break;
3246
3247 case GL_TEXTURE_EXTERNAL_OES:
3248 if (!context->getExtensions().eglImageExternal)
3249 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003250 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3251 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003252 }
Geoff Langa8406172015-07-21 16:53:39 -04003253 break;
3254
3255 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003256 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003257 return false;
3258 }
3259
Jamie Madill61e16b42017-06-19 11:13:23 -04003260 ASSERT(context->getCurrentDisplay());
3261 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003262 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003263 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003264 return false;
3265 }
3266
3267 if (image->getSamples() > 0)
3268 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003269 context->handleError(InvalidOperation()
3270 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003271 return false;
3272 }
3273
Geoff Langca271392017-04-05 12:30:00 -04003274 const TextureCaps &textureCaps =
3275 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003276 if (!textureCaps.texturable)
3277 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003278 context->handleError(InvalidOperation()
3279 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003280 return false;
3281 }
3282
Geoff Langdcab33b2015-07-21 13:03:16 -04003283 return true;
3284}
3285
3286bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003287 GLenum target,
3288 egl::Image *image)
3289{
Geoff Langa8406172015-07-21 16:53:39 -04003290 if (!context->getExtensions().eglImage)
3291 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003292 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003293 return false;
3294 }
3295
3296 switch (target)
3297 {
3298 case GL_RENDERBUFFER:
3299 break;
3300
3301 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003302 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003303 return false;
3304 }
3305
Jamie Madill61e16b42017-06-19 11:13:23 -04003306 ASSERT(context->getCurrentDisplay());
3307 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003308 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003309 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003310 return false;
3311 }
3312
Geoff Langca271392017-04-05 12:30:00 -04003313 const TextureCaps &textureCaps =
3314 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003315 if (!textureCaps.renderable)
3316 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003317 context->handleError(InvalidOperation()
3318 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003319 return false;
3320 }
3321
Geoff Langdcab33b2015-07-21 13:03:16 -04003322 return true;
3323}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003324
3325bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3326{
Geoff Lang36167ab2015-12-07 10:27:14 -05003327 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003328 {
3329 // The default VAO should always exist
3330 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003331 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003332 return false;
3333 }
3334
3335 return true;
3336}
3337
Geoff Langc5629752015-12-07 16:29:04 -05003338bool ValidateProgramBinaryBase(Context *context,
3339 GLuint program,
3340 GLenum binaryFormat,
3341 const void *binary,
3342 GLint length)
3343{
3344 Program *programObject = GetValidProgram(context, program);
3345 if (programObject == nullptr)
3346 {
3347 return false;
3348 }
3349
3350 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3351 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3352 programBinaryFormats.end())
3353 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003354 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003355 return false;
3356 }
3357
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003358 if (context->hasActiveTransformFeedback(program))
3359 {
3360 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003361 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3362 "is associated with an active transform "
3363 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003364 return false;
3365 }
3366
Geoff Langc5629752015-12-07 16:29:04 -05003367 return true;
3368}
3369
3370bool ValidateGetProgramBinaryBase(Context *context,
3371 GLuint program,
3372 GLsizei bufSize,
3373 GLsizei *length,
3374 GLenum *binaryFormat,
3375 void *binary)
3376{
3377 Program *programObject = GetValidProgram(context, program);
3378 if (programObject == nullptr)
3379 {
3380 return false;
3381 }
3382
3383 if (!programObject->isLinked())
3384 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003385 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003386 return false;
3387 }
3388
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003389 if (context->getCaps().programBinaryFormats.empty())
3390 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003391 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003392 return false;
3393 }
3394
Geoff Langc5629752015-12-07 16:29:04 -05003395 return true;
3396}
Jamie Madillc29968b2016-01-20 11:17:23 -05003397
Jamie Madillc29968b2016-01-20 11:17:23 -05003398bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3399{
3400 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003401 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003402 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003403 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3404 return false;
3405 }
3406 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3407 {
3408 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003409 return false;
3410 }
3411
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003412 ASSERT(context->getGLState().getDrawFramebuffer());
3413 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003414 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3415
3416 // This should come first before the check for the default frame buffer
3417 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3418 // rather than INVALID_OPERATION
3419 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3420 {
3421 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3422
3423 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003424 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3425 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003426 {
3427 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003428 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3429 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3430 // 3.1 is still a bit ambiguous about the error, but future specs are
3431 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003432 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003433 return false;
3434 }
3435 else if (bufs[colorAttachment] >= maxColorAttachment)
3436 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003437 context->handleError(InvalidOperation()
3438 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003439 return false;
3440 }
3441 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3442 frameBufferId != 0)
3443 {
3444 // INVALID_OPERATION-GL is bound to buffer and ith argument
3445 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003446 context->handleError(InvalidOperation()
3447 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003448 return false;
3449 }
3450 }
3451
3452 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3453 // and n is not 1 or bufs is bound to value other than BACK and NONE
3454 if (frameBufferId == 0)
3455 {
3456 if (n != 1)
3457 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003458 context->handleError(InvalidOperation()
3459 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003460 return false;
3461 }
3462
3463 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3464 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003465 context->handleError(
3466 InvalidOperation()
3467 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003468 return false;
3469 }
3470 }
3471
3472 return true;
3473}
3474
Geoff Lang496c02d2016-10-20 11:38:11 -07003475bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003476 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003477 GLenum pname,
3478 GLsizei *length,
3479 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003480{
Geoff Lang496c02d2016-10-20 11:38:11 -07003481 if (length)
3482 {
3483 *length = 0;
3484 }
3485
3486 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3487 {
3488 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003489 InvalidOperation()
3490 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003491 return false;
3492 }
3493
Corentin Wallez336129f2017-10-17 15:55:40 -04003494 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003495 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003496 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003497 return false;
3498 }
3499
Geoff Lang496c02d2016-10-20 11:38:11 -07003500 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003501 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003502 case GL_BUFFER_MAP_POINTER:
3503 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003504
Geoff Lang496c02d2016-10-20 11:38:11 -07003505 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003506 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003507 return false;
3508 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003509
3510 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3511 // target bound to zero generate an INVALID_OPERATION error."
3512 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003513 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003514 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003515 context->handleError(InvalidOperation()
3516 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003517 return false;
3518 }
3519
Geoff Lang496c02d2016-10-20 11:38:11 -07003520 if (length)
3521 {
3522 *length = 1;
3523 }
3524
Olli Etuaho4f667482016-03-30 15:56:35 +03003525 return true;
3526}
3527
Corentin Wallez336129f2017-10-17 15:55:40 -04003528bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003529{
Corentin Wallez336129f2017-10-17 15:55:40 -04003530 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003531 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003532 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003533 return false;
3534 }
3535
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003536 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003537
3538 if (buffer == nullptr || !buffer->isMapped())
3539 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003540 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003541 return false;
3542 }
3543
3544 return true;
3545}
3546
3547bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003548 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003549 GLintptr offset,
3550 GLsizeiptr length,
3551 GLbitfield access)
3552{
Corentin Wallez336129f2017-10-17 15:55:40 -04003553 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003554 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003555 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003556 return false;
3557 }
3558
Brandon Jones6cad5662017-06-14 13:25:13 -07003559 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003560 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003561 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3562 return false;
3563 }
3564
3565 if (length < 0)
3566 {
3567 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003568 return false;
3569 }
3570
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003571 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003572
3573 if (!buffer)
3574 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003575 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003576 return false;
3577 }
3578
3579 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003580 CheckedNumeric<size_t> checkedOffset(offset);
3581 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003582
Jamie Madille2e406c2016-06-02 13:04:10 -04003583 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003584 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003585 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003586 return false;
3587 }
3588
3589 // Check for invalid bits in the mask
3590 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3591 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3592 GL_MAP_UNSYNCHRONIZED_BIT;
3593
3594 if (access & ~(allAccessBits))
3595 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003596 context->handleError(InvalidValue()
3597 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003598 return false;
3599 }
3600
3601 if (length == 0)
3602 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003603 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003604 return false;
3605 }
3606
3607 if (buffer->isMapped())
3608 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003609 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003610 return false;
3611 }
3612
3613 // Check for invalid bit combinations
3614 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3615 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003616 context->handleError(InvalidOperation()
3617 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003618 return false;
3619 }
3620
3621 GLbitfield writeOnlyBits =
3622 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3623
3624 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3625 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003626 context->handleError(InvalidOperation()
3627 << "Invalid access bits when mapping buffer for reading: 0x"
3628 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003629 return false;
3630 }
3631
3632 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3633 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003634 context->handleError(
3635 InvalidOperation()
3636 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003637 return false;
3638 }
Geoff Lang79f71042017-08-14 16:43:43 -04003639
3640 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003641}
3642
3643bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003644 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003645 GLintptr offset,
3646 GLsizeiptr length)
3647{
Brandon Jones6cad5662017-06-14 13:25:13 -07003648 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003649 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003650 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3651 return false;
3652 }
3653
3654 if (length < 0)
3655 {
3656 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003657 return false;
3658 }
3659
Corentin Wallez336129f2017-10-17 15:55:40 -04003660 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003661 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003662 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003663 return false;
3664 }
3665
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003666 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003667
3668 if (buffer == nullptr)
3669 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003670 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003671 return false;
3672 }
3673
3674 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003676 context->handleError(InvalidOperation()
3677 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003678 return false;
3679 }
3680
3681 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003682 CheckedNumeric<size_t> checkedOffset(offset);
3683 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003684
Jamie Madille2e406c2016-06-02 13:04:10 -04003685 if (!checkedSize.IsValid() ||
3686 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003688 context->handleError(InvalidValue()
3689 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003690 return false;
3691 }
3692
3693 return true;
3694}
3695
Olli Etuaho41997e72016-03-10 13:38:39 +02003696bool ValidateGenOrDelete(Context *context, GLint n)
3697{
3698 if (n < 0)
3699 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003700 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003701 return false;
3702 }
3703 return true;
3704}
3705
Geoff Langff5b2d52016-09-07 11:32:23 -04003706bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3707{
3708 if (!context->getExtensions().robustClientMemory)
3709 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003710 context->handleError(InvalidOperation()
3711 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003712 return false;
3713 }
3714
3715 if (bufSize < 0)
3716 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003717 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003718 return false;
3719 }
3720
3721 return true;
3722}
3723
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003724bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3725{
3726 if (bufSize < numParams)
3727 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003728 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3729 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003730 return false;
3731 }
3732
3733 return true;
3734}
3735
Jamie Madillbe849e42017-05-02 15:49:00 -04003736bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3737 GLenum target,
3738 GLenum attachment,
3739 GLenum pname,
3740 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003741{
Geoff Lange8afa902017-09-27 15:00:43 -04003742 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003743 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003744 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003745 return false;
3746 }
3747
3748 int clientVersion = context->getClientMajorVersion();
3749
3750 switch (pname)
3751 {
3752 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3753 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3754 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3755 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3756 break;
3757
Martin Radeve5285d22017-07-14 16:23:53 +03003758 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3759 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3760 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3761 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3762 if (clientVersion < 3 || !context->getExtensions().multiview)
3763 {
3764 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3765 return false;
3766 }
3767 break;
3768
Geoff Langff5b2d52016-09-07 11:32:23 -04003769 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3770 if (clientVersion < 3 && !context->getExtensions().sRGB)
3771 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003772 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003773 return false;
3774 }
3775 break;
3776
3777 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3778 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3779 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3780 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3781 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3782 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3783 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3784 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3785 if (clientVersion < 3)
3786 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003787 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003788 return false;
3789 }
3790 break;
3791
3792 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003793 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003794 return false;
3795 }
3796
3797 // Determine if the attachment is a valid enum
3798 switch (attachment)
3799 {
3800 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04003801 case GL_DEPTH:
3802 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04003803 if (clientVersion < 3)
3804 {
Geoff Langfa125c92017-10-24 13:01:46 -04003805 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003806 return false;
3807 }
3808 break;
3809
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003810 case GL_DEPTH_STENCIL_ATTACHMENT:
3811 if (clientVersion < 3 && !context->isWebGL1())
3812 {
3813 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3814 return false;
3815 }
3816 break;
3817
Geoff Langfa125c92017-10-24 13:01:46 -04003818 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003819 case GL_DEPTH_ATTACHMENT:
3820 case GL_STENCIL_ATTACHMENT:
3821 break;
3822
3823 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003824 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3825 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003826 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3827 {
Geoff Langfa125c92017-10-24 13:01:46 -04003828 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003829 return false;
3830 }
3831 break;
3832 }
3833
3834 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3835 ASSERT(framebuffer);
3836
3837 if (framebuffer->id() == 0)
3838 {
3839 if (clientVersion < 3)
3840 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003841 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003842 return false;
3843 }
3844
3845 switch (attachment)
3846 {
3847 case GL_BACK:
3848 case GL_DEPTH:
3849 case GL_STENCIL:
3850 break;
3851
3852 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003853 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003854 return false;
3855 }
3856 }
3857 else
3858 {
3859 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3860 {
3861 // Valid attachment query
3862 }
3863 else
3864 {
3865 switch (attachment)
3866 {
3867 case GL_DEPTH_ATTACHMENT:
3868 case GL_STENCIL_ATTACHMENT:
3869 break;
3870
3871 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003872 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04003873 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003874 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003875 return false;
3876 }
3877 break;
3878
3879 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003880 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003881 return false;
3882 }
3883 }
3884 }
3885
3886 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3887 if (attachmentObject)
3888 {
3889 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3890 attachmentObject->type() == GL_TEXTURE ||
3891 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3892
3893 switch (pname)
3894 {
3895 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3896 if (attachmentObject->type() != GL_RENDERBUFFER &&
3897 attachmentObject->type() != GL_TEXTURE)
3898 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003899 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003900 return false;
3901 }
3902 break;
3903
3904 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3905 if (attachmentObject->type() != GL_TEXTURE)
3906 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003907 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003908 return false;
3909 }
3910 break;
3911
3912 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3913 if (attachmentObject->type() != GL_TEXTURE)
3914 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003915 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003916 return false;
3917 }
3918 break;
3919
3920 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3921 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3922 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003923 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003924 return false;
3925 }
3926 break;
3927
3928 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3929 if (attachmentObject->type() != GL_TEXTURE)
3930 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003931 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003932 return false;
3933 }
3934 break;
3935
3936 default:
3937 break;
3938 }
3939 }
3940 else
3941 {
3942 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3943 // is NONE, then querying any other pname will generate INVALID_ENUM.
3944
3945 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3946 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3947 // INVALID_OPERATION for all other pnames
3948
3949 switch (pname)
3950 {
3951 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3952 break;
3953
3954 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3955 if (clientVersion < 3)
3956 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003957 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003958 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003959 return false;
3960 }
3961 break;
3962
3963 default:
3964 if (clientVersion < 3)
3965 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003966 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003967 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003968 return false;
3969 }
3970 else
3971 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003972 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003973 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003974 return false;
3975 }
3976 }
3977 }
3978
Martin Radeve5285d22017-07-14 16:23:53 +03003979 if (numParams)
3980 {
3981 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
3982 {
3983 // Only when the viewport offsets are queried we can have a varying number of output
3984 // parameters.
3985 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
3986 *numParams = numViews * 2;
3987 }
3988 else
3989 {
3990 // For all other queries we can have only one output parameter.
3991 *numParams = 1;
3992 }
3993 }
3994
Geoff Langff5b2d52016-09-07 11:32:23 -04003995 return true;
3996}
3997
3998bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
3999 GLenum target,
4000 GLenum attachment,
4001 GLenum pname,
4002 GLsizei bufSize,
4003 GLsizei *numParams)
4004{
4005 if (!ValidateRobustEntryPoint(context, bufSize))
4006 {
4007 return false;
4008 }
4009
Jamie Madillbe849e42017-05-02 15:49:00 -04004010 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4011 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004012 {
4013 return false;
4014 }
4015
4016 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4017 {
4018 return false;
4019 }
4020
4021 return true;
4022}
4023
Geoff Langff5b2d52016-09-07 11:32:23 -04004024bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004025 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004026 GLenum pname,
4027 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004028 GLsizei *length,
4029 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004030{
4031 if (!ValidateRobustEntryPoint(context, bufSize))
4032 {
4033 return false;
4034 }
4035
Geoff Langebebe1c2016-10-14 12:01:31 -04004036 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004037 {
4038 return false;
4039 }
4040
Geoff Langebebe1c2016-10-14 12:01:31 -04004041 if (!ValidateRobustBufferSize(context, bufSize, *length))
4042 {
4043 return false;
4044 }
4045
4046 return true;
4047}
4048
Geoff Langebebe1c2016-10-14 12:01:31 -04004049bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004050 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004051 GLenum pname,
4052 GLsizei bufSize,
4053 GLsizei *length,
4054 GLint64 *params)
4055{
4056 if (!ValidateRobustEntryPoint(context, bufSize))
4057 {
4058 return false;
4059 }
4060
4061 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4062 {
4063 return false;
4064 }
4065
4066 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004067 {
4068 return false;
4069 }
4070
4071 return true;
4072}
4073
Jamie Madillbe849e42017-05-02 15:49:00 -04004074bool ValidateGetProgramivBase(ValidationContext *context,
4075 GLuint program,
4076 GLenum pname,
4077 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004078{
4079 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004080 if (numParams)
4081 {
4082 *numParams = 1;
4083 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004084
4085 Program *programObject = GetValidProgram(context, program);
4086 if (!programObject)
4087 {
4088 return false;
4089 }
4090
4091 switch (pname)
4092 {
4093 case GL_DELETE_STATUS:
4094 case GL_LINK_STATUS:
4095 case GL_VALIDATE_STATUS:
4096 case GL_INFO_LOG_LENGTH:
4097 case GL_ATTACHED_SHADERS:
4098 case GL_ACTIVE_ATTRIBUTES:
4099 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4100 case GL_ACTIVE_UNIFORMS:
4101 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4102 break;
4103
4104 case GL_PROGRAM_BINARY_LENGTH:
4105 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4106 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004107 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4108 "requires GL_OES_get_program_binary or "
4109 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004110 return false;
4111 }
4112 break;
4113
4114 case GL_ACTIVE_UNIFORM_BLOCKS:
4115 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4116 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4117 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4118 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4119 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4120 if (context->getClientMajorVersion() < 3)
4121 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004122 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004123 return false;
4124 }
4125 break;
4126
Yunchao He61afff12017-03-14 15:34:03 +08004127 case GL_PROGRAM_SEPARABLE:
Xinghua Cao971f8502017-10-17 13:01:24 +08004128 case GL_COMPUTE_WORK_GROUP_SIZE:
jchen1058f67be2017-10-27 08:59:27 +08004129 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004130 if (context->getClientVersion() < Version(3, 1))
4131 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004132 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004133 return false;
4134 }
4135 break;
4136
Geoff Langff5b2d52016-09-07 11:32:23 -04004137 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004138 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004139 return false;
4140 }
4141
4142 return true;
4143}
4144
4145bool ValidateGetProgramivRobustANGLE(Context *context,
4146 GLuint program,
4147 GLenum pname,
4148 GLsizei bufSize,
4149 GLsizei *numParams)
4150{
4151 if (!ValidateRobustEntryPoint(context, bufSize))
4152 {
4153 return false;
4154 }
4155
Jamie Madillbe849e42017-05-02 15:49:00 -04004156 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004157 {
4158 return false;
4159 }
4160
4161 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4162 {
4163 return false;
4164 }
4165
4166 return true;
4167}
4168
Geoff Lang740d9022016-10-07 11:20:52 -04004169bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4170 GLenum target,
4171 GLenum pname,
4172 GLsizei bufSize,
4173 GLsizei *length,
4174 GLint *params)
4175{
4176 if (!ValidateRobustEntryPoint(context, bufSize))
4177 {
4178 return false;
4179 }
4180
4181 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4182 {
4183 return false;
4184 }
4185
4186 if (!ValidateRobustBufferSize(context, bufSize, *length))
4187 {
4188 return false;
4189 }
4190
4191 return true;
4192}
4193
Geoff Langd7d0ed32016-10-07 11:33:51 -04004194bool ValidateGetShaderivRobustANGLE(Context *context,
4195 GLuint shader,
4196 GLenum pname,
4197 GLsizei bufSize,
4198 GLsizei *length,
4199 GLint *params)
4200{
4201 if (!ValidateRobustEntryPoint(context, bufSize))
4202 {
4203 return false;
4204 }
4205
4206 if (!ValidateGetShaderivBase(context, shader, pname, length))
4207 {
4208 return false;
4209 }
4210
4211 if (!ValidateRobustBufferSize(context, bufSize, *length))
4212 {
4213 return false;
4214 }
4215
4216 return true;
4217}
4218
Geoff Langc1984ed2016-10-07 12:41:00 -04004219bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4220 GLenum target,
4221 GLenum pname,
4222 GLsizei bufSize,
4223 GLsizei *length,
4224 GLfloat *params)
4225{
4226 if (!ValidateRobustEntryPoint(context, bufSize))
4227 {
4228 return false;
4229 }
4230
4231 if (!ValidateGetTexParameterBase(context, target, pname, length))
4232 {
4233 return false;
4234 }
4235
4236 if (!ValidateRobustBufferSize(context, bufSize, *length))
4237 {
4238 return false;
4239 }
4240
4241 return true;
4242}
4243
Geoff Langc1984ed2016-10-07 12:41:00 -04004244bool ValidateGetTexParameterivRobustANGLE(Context *context,
4245 GLenum target,
4246 GLenum pname,
4247 GLsizei bufSize,
4248 GLsizei *length,
4249 GLint *params)
4250{
4251 if (!ValidateRobustEntryPoint(context, bufSize))
4252 {
4253 return false;
4254 }
4255
4256 if (!ValidateGetTexParameterBase(context, target, pname, length))
4257 {
4258 return false;
4259 }
4260
4261 if (!ValidateRobustBufferSize(context, bufSize, *length))
4262 {
4263 return false;
4264 }
4265
4266 return true;
4267}
4268
Geoff Langc1984ed2016-10-07 12:41:00 -04004269bool ValidateTexParameterfvRobustANGLE(Context *context,
4270 GLenum target,
4271 GLenum pname,
4272 GLsizei bufSize,
4273 const GLfloat *params)
4274{
4275 if (!ValidateRobustEntryPoint(context, bufSize))
4276 {
4277 return false;
4278 }
4279
4280 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4281}
4282
Geoff Langc1984ed2016-10-07 12:41:00 -04004283bool ValidateTexParameterivRobustANGLE(Context *context,
4284 GLenum target,
4285 GLenum pname,
4286 GLsizei bufSize,
4287 const GLint *params)
4288{
4289 if (!ValidateRobustEntryPoint(context, bufSize))
4290 {
4291 return false;
4292 }
4293
4294 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4295}
4296
Geoff Langc1984ed2016-10-07 12:41:00 -04004297bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4298 GLuint sampler,
4299 GLenum pname,
4300 GLuint bufSize,
4301 GLsizei *length,
4302 GLfloat *params)
4303{
4304 if (!ValidateRobustEntryPoint(context, bufSize))
4305 {
4306 return false;
4307 }
4308
4309 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4310 {
4311 return false;
4312 }
4313
4314 if (!ValidateRobustBufferSize(context, bufSize, *length))
4315 {
4316 return false;
4317 }
4318
4319 return true;
4320}
4321
Geoff Langc1984ed2016-10-07 12:41:00 -04004322bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4323 GLuint sampler,
4324 GLenum pname,
4325 GLuint bufSize,
4326 GLsizei *length,
4327 GLint *params)
4328{
4329 if (!ValidateRobustEntryPoint(context, bufSize))
4330 {
4331 return false;
4332 }
4333
4334 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4335 {
4336 return false;
4337 }
4338
4339 if (!ValidateRobustBufferSize(context, bufSize, *length))
4340 {
4341 return false;
4342 }
4343
4344 return true;
4345}
4346
Geoff Langc1984ed2016-10-07 12:41:00 -04004347bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4348 GLuint sampler,
4349 GLenum pname,
4350 GLsizei bufSize,
4351 const GLfloat *params)
4352{
4353 if (!ValidateRobustEntryPoint(context, bufSize))
4354 {
4355 return false;
4356 }
4357
4358 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4359}
4360
Geoff Langc1984ed2016-10-07 12:41:00 -04004361bool ValidateSamplerParameterivRobustANGLE(Context *context,
4362 GLuint sampler,
4363 GLenum pname,
4364 GLsizei bufSize,
4365 const GLint *params)
4366{
4367 if (!ValidateRobustEntryPoint(context, bufSize))
4368 {
4369 return false;
4370 }
4371
4372 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4373}
4374
Geoff Lang0b031062016-10-13 14:30:04 -04004375bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4376 GLuint index,
4377 GLenum pname,
4378 GLsizei bufSize,
4379 GLsizei *length,
4380 GLfloat *params)
4381{
4382 if (!ValidateRobustEntryPoint(context, bufSize))
4383 {
4384 return false;
4385 }
4386
4387 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4388 {
4389 return false;
4390 }
4391
4392 if (!ValidateRobustBufferSize(context, bufSize, *length))
4393 {
4394 return false;
4395 }
4396
4397 return true;
4398}
4399
Geoff Lang0b031062016-10-13 14:30:04 -04004400bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4401 GLuint index,
4402 GLenum pname,
4403 GLsizei bufSize,
4404 GLsizei *length,
4405 GLint *params)
4406{
4407 if (!ValidateRobustEntryPoint(context, bufSize))
4408 {
4409 return false;
4410 }
4411
4412 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4413 {
4414 return false;
4415 }
4416
4417 if (!ValidateRobustBufferSize(context, bufSize, *length))
4418 {
4419 return false;
4420 }
4421
4422 return true;
4423}
4424
Geoff Lang0b031062016-10-13 14:30:04 -04004425bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4426 GLuint index,
4427 GLenum pname,
4428 GLsizei bufSize,
4429 GLsizei *length,
4430 void **pointer)
4431{
4432 if (!ValidateRobustEntryPoint(context, bufSize))
4433 {
4434 return false;
4435 }
4436
4437 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4438 {
4439 return false;
4440 }
4441
4442 if (!ValidateRobustBufferSize(context, bufSize, *length))
4443 {
4444 return false;
4445 }
4446
4447 return true;
4448}
4449
Geoff Lang0b031062016-10-13 14:30:04 -04004450bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4451 GLuint index,
4452 GLenum pname,
4453 GLsizei bufSize,
4454 GLsizei *length,
4455 GLint *params)
4456{
4457 if (!ValidateRobustEntryPoint(context, bufSize))
4458 {
4459 return false;
4460 }
4461
4462 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4463 {
4464 return false;
4465 }
4466
4467 if (!ValidateRobustBufferSize(context, bufSize, *length))
4468 {
4469 return false;
4470 }
4471
4472 return true;
4473}
4474
Geoff Lang0b031062016-10-13 14:30:04 -04004475bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4476 GLuint index,
4477 GLenum pname,
4478 GLsizei bufSize,
4479 GLsizei *length,
4480 GLuint *params)
4481{
4482 if (!ValidateRobustEntryPoint(context, bufSize))
4483 {
4484 return false;
4485 }
4486
4487 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4488 {
4489 return false;
4490 }
4491
4492 if (!ValidateRobustBufferSize(context, bufSize, *length))
4493 {
4494 return false;
4495 }
4496
4497 return true;
4498}
4499
Geoff Lang6899b872016-10-14 11:30:13 -04004500bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4501 GLuint program,
4502 GLuint uniformBlockIndex,
4503 GLenum pname,
4504 GLsizei bufSize,
4505 GLsizei *length,
4506 GLint *params)
4507{
4508 if (!ValidateRobustEntryPoint(context, bufSize))
4509 {
4510 return false;
4511 }
4512
4513 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4514 {
4515 return false;
4516 }
4517
4518 if (!ValidateRobustBufferSize(context, bufSize, *length))
4519 {
4520 return false;
4521 }
4522
4523 return true;
4524}
4525
Geoff Lang0a9661f2016-10-20 10:59:20 -07004526bool ValidateGetInternalFormativRobustANGLE(Context *context,
4527 GLenum target,
4528 GLenum internalformat,
4529 GLenum pname,
4530 GLsizei bufSize,
4531 GLsizei *length,
4532 GLint *params)
4533{
4534 if (!ValidateRobustEntryPoint(context, bufSize))
4535 {
4536 return false;
4537 }
4538
4539 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4540 {
4541 return false;
4542 }
4543
4544 if (!ValidateRobustBufferSize(context, bufSize, *length))
4545 {
4546 return false;
4547 }
4548
4549 return true;
4550}
4551
Shao80957d92017-02-20 21:25:59 +08004552bool ValidateVertexFormatBase(ValidationContext *context,
4553 GLuint attribIndex,
4554 GLint size,
4555 GLenum type,
4556 GLboolean pureInteger)
4557{
4558 const Caps &caps = context->getCaps();
4559 if (attribIndex >= caps.maxVertexAttributes)
4560 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004561 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004562 return false;
4563 }
4564
4565 if (size < 1 || size > 4)
4566 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004567 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004568 return false;
Shao80957d92017-02-20 21:25:59 +08004569 }
4570
4571 switch (type)
4572 {
4573 case GL_BYTE:
4574 case GL_UNSIGNED_BYTE:
4575 case GL_SHORT:
4576 case GL_UNSIGNED_SHORT:
4577 break;
4578
4579 case GL_INT:
4580 case GL_UNSIGNED_INT:
4581 if (context->getClientMajorVersion() < 3)
4582 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004583 context->handleError(InvalidEnum()
4584 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004585 return false;
4586 }
4587 break;
4588
4589 case GL_FIXED:
4590 case GL_FLOAT:
4591 if (pureInteger)
4592 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004593 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004594 return false;
4595 }
4596 break;
4597
4598 case GL_HALF_FLOAT:
4599 if (context->getClientMajorVersion() < 3)
4600 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004601 context->handleError(InvalidEnum()
4602 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004603 return false;
4604 }
4605 if (pureInteger)
4606 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004607 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004608 return false;
4609 }
4610 break;
4611
4612 case GL_INT_2_10_10_10_REV:
4613 case GL_UNSIGNED_INT_2_10_10_10_REV:
4614 if (context->getClientMajorVersion() < 3)
4615 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004616 context->handleError(InvalidEnum()
4617 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004618 return false;
4619 }
4620 if (pureInteger)
4621 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004622 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004623 return false;
4624 }
4625 if (size != 4)
4626 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004627 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4628 "UNSIGNED_INT_2_10_10_10_REV and "
4629 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004630 return false;
4631 }
4632 break;
4633
4634 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004635 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004636 return false;
4637 }
4638
4639 return true;
4640}
4641
Geoff Lang76e65652017-03-27 14:58:02 -04004642// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4643// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4644// specified clear value and the type of a buffer that is being cleared generates an
4645// INVALID_OPERATION error instead of producing undefined results
4646bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4647 GLint drawbuffer,
4648 const GLenum *validComponentTypes,
4649 size_t validComponentTypeCount)
4650{
4651 const FramebufferAttachment *attachment =
4652 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4653 if (attachment)
4654 {
4655 GLenum componentType = attachment->getFormat().info->componentType;
4656 const GLenum *end = validComponentTypes + validComponentTypeCount;
4657 if (std::find(validComponentTypes, end, componentType) == end)
4658 {
4659 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004660 InvalidOperation()
4661 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004662 return false;
4663 }
4664 }
4665
4666 return true;
4667}
4668
Corentin Wallezb2931602017-04-11 15:58:57 -04004669bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4670 GLsizei imageSize,
4671 GLsizei dataSize)
4672{
4673 if (!ValidateRobustEntryPoint(context, dataSize))
4674 {
4675 return false;
4676 }
4677
Corentin Wallez336129f2017-10-17 15:55:40 -04004678 gl::Buffer *pixelUnpackBuffer =
4679 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004680 if (pixelUnpackBuffer == nullptr)
4681 {
4682 if (dataSize < imageSize)
4683 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004684 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004685 }
4686 }
4687 return true;
4688}
4689
Jamie Madillbe849e42017-05-02 15:49:00 -04004690bool ValidateGetBufferParameterBase(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004691 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004692 GLenum pname,
4693 bool pointerVersion,
4694 GLsizei *numParams)
4695{
4696 if (numParams)
4697 {
4698 *numParams = 0;
4699 }
4700
Corentin Wallez336129f2017-10-17 15:55:40 -04004701 if (!ValidBufferType(context, target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004702 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004703 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004704 return false;
4705 }
4706
4707 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4708 if (!buffer)
4709 {
4710 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004711 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004712 return false;
4713 }
4714
4715 const Extensions &extensions = context->getExtensions();
4716
4717 switch (pname)
4718 {
4719 case GL_BUFFER_USAGE:
4720 case GL_BUFFER_SIZE:
4721 break;
4722
4723 case GL_BUFFER_ACCESS_OES:
4724 if (!extensions.mapBuffer)
4725 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004726 context->handleError(InvalidEnum()
4727 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004728 return false;
4729 }
4730 break;
4731
4732 case GL_BUFFER_MAPPED:
4733 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4734 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4735 !extensions.mapBufferRange)
4736 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004737 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4738 "GL_OES_mapbuffer or "
4739 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004740 return false;
4741 }
4742 break;
4743
4744 case GL_BUFFER_MAP_POINTER:
4745 if (!pointerVersion)
4746 {
4747 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004748 InvalidEnum()
4749 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004750 return false;
4751 }
4752 break;
4753
4754 case GL_BUFFER_ACCESS_FLAGS:
4755 case GL_BUFFER_MAP_OFFSET:
4756 case GL_BUFFER_MAP_LENGTH:
4757 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4758 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004759 context->handleError(InvalidEnum()
4760 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004761 return false;
4762 }
4763 break;
4764
4765 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004766 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004767 return false;
4768 }
4769
4770 // All buffer parameter queries return one value.
4771 if (numParams)
4772 {
4773 *numParams = 1;
4774 }
4775
4776 return true;
4777}
4778
4779bool ValidateGetRenderbufferParameterivBase(Context *context,
4780 GLenum target,
4781 GLenum pname,
4782 GLsizei *length)
4783{
4784 if (length)
4785 {
4786 *length = 0;
4787 }
4788
4789 if (target != GL_RENDERBUFFER)
4790 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004791 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004792 return false;
4793 }
4794
4795 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4796 if (renderbuffer == nullptr)
4797 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004798 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004799 return false;
4800 }
4801
4802 switch (pname)
4803 {
4804 case GL_RENDERBUFFER_WIDTH:
4805 case GL_RENDERBUFFER_HEIGHT:
4806 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4807 case GL_RENDERBUFFER_RED_SIZE:
4808 case GL_RENDERBUFFER_GREEN_SIZE:
4809 case GL_RENDERBUFFER_BLUE_SIZE:
4810 case GL_RENDERBUFFER_ALPHA_SIZE:
4811 case GL_RENDERBUFFER_DEPTH_SIZE:
4812 case GL_RENDERBUFFER_STENCIL_SIZE:
4813 break;
4814
4815 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4816 if (!context->getExtensions().framebufferMultisample)
4817 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004818 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004819 return false;
4820 }
4821 break;
4822
4823 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004824 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004825 return false;
4826 }
4827
4828 if (length)
4829 {
4830 *length = 1;
4831 }
4832 return true;
4833}
4834
4835bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4836{
4837 if (length)
4838 {
4839 *length = 0;
4840 }
4841
4842 if (GetValidShader(context, shader) == nullptr)
4843 {
4844 return false;
4845 }
4846
4847 switch (pname)
4848 {
4849 case GL_SHADER_TYPE:
4850 case GL_DELETE_STATUS:
4851 case GL_COMPILE_STATUS:
4852 case GL_INFO_LOG_LENGTH:
4853 case GL_SHADER_SOURCE_LENGTH:
4854 break;
4855
4856 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4857 if (!context->getExtensions().translatedShaderSource)
4858 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004859 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004860 return false;
4861 }
4862 break;
4863
4864 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004865 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004866 return false;
4867 }
4868
4869 if (length)
4870 {
4871 *length = 1;
4872 }
4873 return true;
4874}
4875
4876bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4877{
4878 if (length)
4879 {
4880 *length = 0;
4881 }
4882
4883 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4884 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004885 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004886 return false;
4887 }
4888
4889 if (context->getTargetTexture(target) == nullptr)
4890 {
4891 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004892 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004893 return false;
4894 }
4895
4896 switch (pname)
4897 {
4898 case GL_TEXTURE_MAG_FILTER:
4899 case GL_TEXTURE_MIN_FILTER:
4900 case GL_TEXTURE_WRAP_S:
4901 case GL_TEXTURE_WRAP_T:
4902 break;
4903
4904 case GL_TEXTURE_USAGE_ANGLE:
4905 if (!context->getExtensions().textureUsage)
4906 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004907 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004908 return false;
4909 }
4910 break;
4911
4912 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4913 if (!context->getExtensions().textureFilterAnisotropic)
4914 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004915 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004916 return false;
4917 }
4918 break;
4919
4920 case GL_TEXTURE_IMMUTABLE_FORMAT:
4921 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4922 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004923 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004924 return false;
4925 }
4926 break;
4927
4928 case GL_TEXTURE_WRAP_R:
4929 case GL_TEXTURE_IMMUTABLE_LEVELS:
4930 case GL_TEXTURE_SWIZZLE_R:
4931 case GL_TEXTURE_SWIZZLE_G:
4932 case GL_TEXTURE_SWIZZLE_B:
4933 case GL_TEXTURE_SWIZZLE_A:
4934 case GL_TEXTURE_BASE_LEVEL:
4935 case GL_TEXTURE_MAX_LEVEL:
4936 case GL_TEXTURE_MIN_LOD:
4937 case GL_TEXTURE_MAX_LOD:
4938 case GL_TEXTURE_COMPARE_MODE:
4939 case GL_TEXTURE_COMPARE_FUNC:
4940 if (context->getClientMajorVersion() < 3)
4941 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004942 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004943 return false;
4944 }
4945 break;
4946
4947 case GL_TEXTURE_SRGB_DECODE_EXT:
4948 if (!context->getExtensions().textureSRGBDecode)
4949 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004950 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004951 return false;
4952 }
4953 break;
4954
4955 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004956 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004957 return false;
4958 }
4959
4960 if (length)
4961 {
4962 *length = 1;
4963 }
4964 return true;
4965}
4966
4967bool ValidateGetVertexAttribBase(Context *context,
4968 GLuint index,
4969 GLenum pname,
4970 GLsizei *length,
4971 bool pointer,
4972 bool pureIntegerEntryPoint)
4973{
4974 if (length)
4975 {
4976 *length = 0;
4977 }
4978
4979 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
4980 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004981 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004982 return false;
4983 }
4984
4985 if (index >= context->getCaps().maxVertexAttributes)
4986 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004987 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04004988 return false;
4989 }
4990
4991 if (pointer)
4992 {
4993 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
4994 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004995 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004996 return false;
4997 }
4998 }
4999 else
5000 {
5001 switch (pname)
5002 {
5003 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5004 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5005 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5006 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5007 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5008 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5009 case GL_CURRENT_VERTEX_ATTRIB:
5010 break;
5011
5012 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5013 static_assert(
5014 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5015 "ANGLE extension enums not equal to GL enums.");
5016 if (context->getClientMajorVersion() < 3 &&
5017 !context->getExtensions().instancedArrays)
5018 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005019 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5020 "requires OpenGL ES 3.0 or "
5021 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005022 return false;
5023 }
5024 break;
5025
5026 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5027 if (context->getClientMajorVersion() < 3)
5028 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005029 context->handleError(
5030 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005031 return false;
5032 }
5033 break;
5034
5035 case GL_VERTEX_ATTRIB_BINDING:
5036 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5037 if (context->getClientVersion() < ES_3_1)
5038 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005039 context->handleError(InvalidEnum()
5040 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005041 return false;
5042 }
5043 break;
5044
5045 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005046 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005047 return false;
5048 }
5049 }
5050
5051 if (length)
5052 {
5053 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5054 {
5055 *length = 4;
5056 }
5057 else
5058 {
5059 *length = 1;
5060 }
5061 }
5062
5063 return true;
5064}
5065
Jamie Madill4928b7c2017-06-20 12:57:39 -04005066bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005067 GLint x,
5068 GLint y,
5069 GLsizei width,
5070 GLsizei height,
5071 GLenum format,
5072 GLenum type,
5073 GLsizei bufSize,
5074 GLsizei *length,
5075 GLsizei *columns,
5076 GLsizei *rows,
5077 void *pixels)
5078{
5079 if (length != nullptr)
5080 {
5081 *length = 0;
5082 }
5083 if (rows != nullptr)
5084 {
5085 *rows = 0;
5086 }
5087 if (columns != nullptr)
5088 {
5089 *columns = 0;
5090 }
5091
5092 if (width < 0 || height < 0)
5093 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005094 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005095 return false;
5096 }
5097
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005098 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005099
5100 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5101 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005102 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005103 return false;
5104 }
5105
5106 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5107 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005108 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005109 return false;
5110 }
5111
5112 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5113 ASSERT(framebuffer);
5114
5115 if (framebuffer->getReadBufferState() == GL_NONE)
5116 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005117 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005118 return false;
5119 }
5120
5121 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5122 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5123 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5124 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5125 // situation is an application error that would lead to a crash in ANGLE.
5126 if (readBuffer == nullptr)
5127 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005128 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005129 return false;
5130 }
5131
Martin Radev28031682017-07-28 14:47:56 +03005132 // ANGLE_multiview, Revision 1:
5133 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5134 // current read framebuffer is not NONE.
5135 if (readBuffer->getMultiviewLayout() != GL_NONE)
5136 {
5137 context->handleError(InvalidFramebufferOperation()
5138 << "Attempting to read from a multi-view framebuffer.");
5139 return false;
5140 }
5141
Geoff Lang280ba992017-04-18 16:30:58 -04005142 if (context->getExtensions().webglCompatibility)
5143 {
5144 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5145 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5146 // and type before validating the combination of format and type. However, the
5147 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5148 // verifies that GL_INVALID_OPERATION is generated.
5149 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5150 // dEQP/WebGL.
5151 if (!ValidReadPixelsFormatEnum(context, format))
5152 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005153 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005154 return false;
5155 }
5156
5157 if (!ValidReadPixelsTypeEnum(context, type))
5158 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005159 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005160 return false;
5161 }
5162 }
5163
Jamie Madill4928b7c2017-06-20 12:57:39 -04005164 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5165 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005166 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5167
5168 bool validFormatTypeCombination =
5169 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5170
5171 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5172 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005173 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005174 return false;
5175 }
5176
5177 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005178 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005179 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5180 {
5181 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005182 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005183 return false;
5184 }
5185
5186 // .. the data would be packed to the buffer object such that the memory writes required
5187 // would exceed the data store size.
5188 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5189 const gl::Extents size(width, height, 1);
5190 const auto &pack = context->getGLState().getPackState();
5191
5192 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5193 if (endByteOrErr.isError())
5194 {
5195 context->handleError(endByteOrErr.getError());
5196 return false;
5197 }
5198
5199 size_t endByte = endByteOrErr.getResult();
5200 if (bufSize >= 0)
5201 {
5202 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5203 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005204 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005205 return false;
5206 }
5207 }
5208
5209 if (pixelPackBuffer != nullptr)
5210 {
5211 CheckedNumeric<size_t> checkedEndByte(endByte);
5212 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5213 checkedEndByte += checkedOffset;
5214
5215 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5216 {
5217 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005218 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005219 return false;
5220 }
5221 }
5222
5223 if (pixelPackBuffer == nullptr && length != nullptr)
5224 {
5225 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5226 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005227 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005228 return false;
5229 }
5230
5231 *length = static_cast<GLsizei>(endByte);
5232 }
5233
5234 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5235 angle::CheckedNumeric<int> clippedExtent(length);
5236 if (start < 0)
5237 {
5238 // "subtract" the area that is less than 0
5239 clippedExtent += start;
5240 }
5241
5242 const int readExtent = start + length;
5243 if (readExtent > bufferSize)
5244 {
5245 // Subtract the region to the right of the read buffer
5246 clippedExtent -= (readExtent - bufferSize);
5247 }
5248
5249 if (!clippedExtent.IsValid())
5250 {
5251 return 0;
5252 }
5253
5254 return std::max(clippedExtent.ValueOrDie(), 0);
5255 };
5256
5257 if (columns != nullptr)
5258 {
5259 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5260 }
5261
5262 if (rows != nullptr)
5263 {
5264 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5265 }
5266
5267 return true;
5268}
5269
5270template <typename ParamType>
5271bool ValidateTexParameterBase(Context *context,
5272 GLenum target,
5273 GLenum pname,
5274 GLsizei bufSize,
5275 const ParamType *params)
5276{
5277 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5278 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005279 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005280 return false;
5281 }
5282
5283 if (context->getTargetTexture(target) == nullptr)
5284 {
5285 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005286 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005287 return false;
5288 }
5289
5290 const GLsizei minBufSize = 1;
5291 if (bufSize >= 0 && bufSize < minBufSize)
5292 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005293 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005294 return false;
5295 }
5296
5297 switch (pname)
5298 {
5299 case GL_TEXTURE_WRAP_R:
5300 case GL_TEXTURE_SWIZZLE_R:
5301 case GL_TEXTURE_SWIZZLE_G:
5302 case GL_TEXTURE_SWIZZLE_B:
5303 case GL_TEXTURE_SWIZZLE_A:
5304 case GL_TEXTURE_BASE_LEVEL:
5305 case GL_TEXTURE_MAX_LEVEL:
5306 case GL_TEXTURE_COMPARE_MODE:
5307 case GL_TEXTURE_COMPARE_FUNC:
5308 case GL_TEXTURE_MIN_LOD:
5309 case GL_TEXTURE_MAX_LOD:
5310 if (context->getClientMajorVersion() < 3)
5311 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005312 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005313 return false;
5314 }
5315 if (target == GL_TEXTURE_EXTERNAL_OES &&
5316 !context->getExtensions().eglImageExternalEssl3)
5317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005318 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5319 "available without "
5320 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005321 return false;
5322 }
5323 break;
5324
5325 default:
5326 break;
5327 }
5328
JiangYizhou4cff8d62017-07-06 14:54:09 +08005329 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5330 {
5331 switch (pname)
5332 {
5333 case GL_TEXTURE_MIN_FILTER:
5334 case GL_TEXTURE_MAG_FILTER:
5335 case GL_TEXTURE_WRAP_S:
5336 case GL_TEXTURE_WRAP_T:
5337 case GL_TEXTURE_WRAP_R:
5338 case GL_TEXTURE_MIN_LOD:
5339 case GL_TEXTURE_MAX_LOD:
5340 case GL_TEXTURE_COMPARE_MODE:
5341 case GL_TEXTURE_COMPARE_FUNC:
5342 context->handleError(InvalidEnum()
5343 << "Invalid parameter for 2D multisampled textures.");
5344 return false;
5345 }
5346 }
5347
Jamie Madillbe849e42017-05-02 15:49:00 -04005348 switch (pname)
5349 {
5350 case GL_TEXTURE_WRAP_S:
5351 case GL_TEXTURE_WRAP_T:
5352 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005353 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005354 bool restrictedWrapModes =
5355 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5356 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5357 {
5358 return false;
5359 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005360 }
5361 break;
5362
5363 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005364 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005365 bool restrictedMinFilter =
5366 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5367 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5368 {
5369 return false;
5370 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005371 }
5372 break;
5373
5374 case GL_TEXTURE_MAG_FILTER:
5375 if (!ValidateTextureMagFilterValue(context, params))
5376 {
5377 return false;
5378 }
5379 break;
5380
5381 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005382 if (!context->getExtensions().textureUsage)
5383 {
5384 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5385 return false;
5386 }
5387
Jamie Madillbe849e42017-05-02 15:49:00 -04005388 switch (ConvertToGLenum(params[0]))
5389 {
5390 case GL_NONE:
5391 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5392 break;
5393
5394 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005395 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005396 return false;
5397 }
5398 break;
5399
5400 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5401 if (!context->getExtensions().textureFilterAnisotropic)
5402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005403 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005404 return false;
5405 }
5406
5407 // we assume the parameter passed to this validation method is truncated, not rounded
5408 if (params[0] < 1)
5409 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005410 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005411 return false;
5412 }
5413 break;
5414
5415 case GL_TEXTURE_MIN_LOD:
5416 case GL_TEXTURE_MAX_LOD:
5417 // any value is permissible
5418 break;
5419
5420 case GL_TEXTURE_COMPARE_MODE:
5421 if (!ValidateTextureCompareModeValue(context, params))
5422 {
5423 return false;
5424 }
5425 break;
5426
5427 case GL_TEXTURE_COMPARE_FUNC:
5428 if (!ValidateTextureCompareFuncValue(context, params))
5429 {
5430 return false;
5431 }
5432 break;
5433
5434 case GL_TEXTURE_SWIZZLE_R:
5435 case GL_TEXTURE_SWIZZLE_G:
5436 case GL_TEXTURE_SWIZZLE_B:
5437 case GL_TEXTURE_SWIZZLE_A:
5438 switch (ConvertToGLenum(params[0]))
5439 {
5440 case GL_RED:
5441 case GL_GREEN:
5442 case GL_BLUE:
5443 case GL_ALPHA:
5444 case GL_ZERO:
5445 case GL_ONE:
5446 break;
5447
5448 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005449 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005450 return false;
5451 }
5452 break;
5453
5454 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005455 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005456 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005457 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005458 return false;
5459 }
5460 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5461 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005462 context->handleError(InvalidOperation()
5463 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005464 return false;
5465 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005466 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5467 {
5468 context->handleError(InvalidOperation()
5469 << "Base level must be 0 for multisampled textures.");
5470 return false;
5471 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005472 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5473 {
5474 context->handleError(InvalidOperation()
5475 << "Base level must be 0 for rectangle textures.");
5476 return false;
5477 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005478 break;
5479
5480 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005481 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005482 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005483 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005484 return false;
5485 }
5486 break;
5487
5488 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5489 if (context->getClientVersion() < Version(3, 1))
5490 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005491 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005492 return false;
5493 }
5494 switch (ConvertToGLenum(params[0]))
5495 {
5496 case GL_DEPTH_COMPONENT:
5497 case GL_STENCIL_INDEX:
5498 break;
5499
5500 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005501 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005502 return false;
5503 }
5504 break;
5505
5506 case GL_TEXTURE_SRGB_DECODE_EXT:
5507 if (!ValidateTextureSRGBDecodeValue(context, params))
5508 {
5509 return false;
5510 }
5511 break;
5512
5513 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005514 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005515 return false;
5516 }
5517
5518 return true;
5519}
5520
5521template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5522template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5523
Jamie Madill12e957f2017-08-26 21:42:26 -04005524bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5525{
5526 if (index >= MAX_VERTEX_ATTRIBS)
5527 {
5528 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5529 return false;
5530 }
5531
5532 return true;
5533}
5534
5535bool ValidateGetActiveUniformBlockivBase(Context *context,
5536 GLuint program,
5537 GLuint uniformBlockIndex,
5538 GLenum pname,
5539 GLsizei *length)
5540{
5541 if (length)
5542 {
5543 *length = 0;
5544 }
5545
5546 if (context->getClientMajorVersion() < 3)
5547 {
5548 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5549 return false;
5550 }
5551
5552 Program *programObject = GetValidProgram(context, program);
5553 if (!programObject)
5554 {
5555 return false;
5556 }
5557
5558 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5559 {
5560 context->handleError(InvalidValue()
5561 << "uniformBlockIndex exceeds active uniform block count.");
5562 return false;
5563 }
5564
5565 switch (pname)
5566 {
5567 case GL_UNIFORM_BLOCK_BINDING:
5568 case GL_UNIFORM_BLOCK_DATA_SIZE:
5569 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5570 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5571 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5572 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5573 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5574 break;
5575
5576 default:
5577 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5578 return false;
5579 }
5580
5581 if (length)
5582 {
5583 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5584 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005585 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005586 programObject->getUniformBlockByIndex(uniformBlockIndex);
5587 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5588 }
5589 else
5590 {
5591 *length = 1;
5592 }
5593 }
5594
5595 return true;
5596}
5597
Jamie Madill9696d072017-08-26 23:19:57 -04005598template <typename ParamType>
5599bool ValidateSamplerParameterBase(Context *context,
5600 GLuint sampler,
5601 GLenum pname,
5602 GLsizei bufSize,
5603 ParamType *params)
5604{
5605 if (context->getClientMajorVersion() < 3)
5606 {
5607 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5608 return false;
5609 }
5610
5611 if (!context->isSampler(sampler))
5612 {
5613 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5614 return false;
5615 }
5616
5617 const GLsizei minBufSize = 1;
5618 if (bufSize >= 0 && bufSize < minBufSize)
5619 {
5620 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5621 return false;
5622 }
5623
5624 switch (pname)
5625 {
5626 case GL_TEXTURE_WRAP_S:
5627 case GL_TEXTURE_WRAP_T:
5628 case GL_TEXTURE_WRAP_R:
5629 if (!ValidateTextureWrapModeValue(context, params, false))
5630 {
5631 return false;
5632 }
5633 break;
5634
5635 case GL_TEXTURE_MIN_FILTER:
5636 if (!ValidateTextureMinFilterValue(context, params, false))
5637 {
5638 return false;
5639 }
5640 break;
5641
5642 case GL_TEXTURE_MAG_FILTER:
5643 if (!ValidateTextureMagFilterValue(context, params))
5644 {
5645 return false;
5646 }
5647 break;
5648
5649 case GL_TEXTURE_MIN_LOD:
5650 case GL_TEXTURE_MAX_LOD:
5651 // any value is permissible
5652 break;
5653
5654 case GL_TEXTURE_COMPARE_MODE:
5655 if (!ValidateTextureCompareModeValue(context, params))
5656 {
5657 return false;
5658 }
5659 break;
5660
5661 case GL_TEXTURE_COMPARE_FUNC:
5662 if (!ValidateTextureCompareFuncValue(context, params))
5663 {
5664 return false;
5665 }
5666 break;
5667
5668 case GL_TEXTURE_SRGB_DECODE_EXT:
5669 if (!ValidateTextureSRGBDecodeValue(context, params))
5670 {
5671 return false;
5672 }
5673 break;
5674
5675 default:
5676 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5677 return false;
5678 }
5679
5680 return true;
5681}
5682
5683template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5684template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5685
5686bool ValidateGetSamplerParameterBase(Context *context,
5687 GLuint sampler,
5688 GLenum pname,
5689 GLsizei *length)
5690{
5691 if (length)
5692 {
5693 *length = 0;
5694 }
5695
5696 if (context->getClientMajorVersion() < 3)
5697 {
5698 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5699 return false;
5700 }
5701
5702 if (!context->isSampler(sampler))
5703 {
5704 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5705 return false;
5706 }
5707
5708 switch (pname)
5709 {
5710 case GL_TEXTURE_WRAP_S:
5711 case GL_TEXTURE_WRAP_T:
5712 case GL_TEXTURE_WRAP_R:
5713 case GL_TEXTURE_MIN_FILTER:
5714 case GL_TEXTURE_MAG_FILTER:
5715 case GL_TEXTURE_MIN_LOD:
5716 case GL_TEXTURE_MAX_LOD:
5717 case GL_TEXTURE_COMPARE_MODE:
5718 case GL_TEXTURE_COMPARE_FUNC:
5719 break;
5720
5721 case GL_TEXTURE_SRGB_DECODE_EXT:
5722 if (!context->getExtensions().textureSRGBDecode)
5723 {
5724 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5725 return false;
5726 }
5727 break;
5728
5729 default:
5730 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5731 return false;
5732 }
5733
5734 if (length)
5735 {
5736 *length = 1;
5737 }
5738 return true;
5739}
5740
5741bool ValidateGetInternalFormativBase(Context *context,
5742 GLenum target,
5743 GLenum internalformat,
5744 GLenum pname,
5745 GLsizei bufSize,
5746 GLsizei *numParams)
5747{
5748 if (numParams)
5749 {
5750 *numParams = 0;
5751 }
5752
5753 if (context->getClientMajorVersion() < 3)
5754 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005755 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005756 return false;
5757 }
5758
5759 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5760 if (!formatCaps.renderable)
5761 {
5762 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5763 return false;
5764 }
5765
5766 switch (target)
5767 {
5768 case GL_RENDERBUFFER:
5769 break;
5770
5771 case GL_TEXTURE_2D_MULTISAMPLE:
5772 if (context->getClientVersion() < ES_3_1)
5773 {
5774 context->handleError(InvalidOperation()
5775 << "Texture target requires at least OpenGL ES 3.1.");
5776 return false;
5777 }
5778 break;
5779
5780 default:
5781 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5782 return false;
5783 }
5784
5785 if (bufSize < 0)
5786 {
5787 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5788 return false;
5789 }
5790
5791 GLsizei maxWriteParams = 0;
5792 switch (pname)
5793 {
5794 case GL_NUM_SAMPLE_COUNTS:
5795 maxWriteParams = 1;
5796 break;
5797
5798 case GL_SAMPLES:
5799 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5800 break;
5801
5802 default:
5803 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5804 return false;
5805 }
5806
5807 if (numParams)
5808 {
5809 // glGetInternalFormativ will not overflow bufSize
5810 *numParams = std::min(bufSize, maxWriteParams);
5811 }
5812
5813 return true;
5814}
5815
Jamie Madillc29968b2016-01-20 11:17:23 -05005816} // namespace gl