blob: a0617c2d35e3382fe46e249e4ea42dc10b7a650a [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040012#include "libANGLE/Display.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070013#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040016#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050017#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Query.h"
19#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/TransformFeedback.h"
21#include "libANGLE/VertexArray.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040022#include "libANGLE/formatutils.h"
jchen10a99ed552017-09-22 08:10:32 +080023#include "libANGLE/queryconversions.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040024#include "libANGLE/validationES2.h"
25#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040026
27#include "common/mathutil.h"
28#include "common/utilities.h"
29
Jamie Madille2e406c2016-06-02 13:04:10 -040030using namespace angle;
31
Geoff Lange8ebe7f2013-08-05 15:03:13 -040032namespace gl
33{
Jamie Madill1ca74672015-07-21 15:14:11 -040034namespace
35{
jchen10a99ed552017-09-22 08:10:32 +080036
Corentin Wallez92db6942016-12-09 13:10:36 -050037bool ValidateDrawAttribs(ValidationContext *context,
38 GLint primcount,
39 GLint maxVertex,
40 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040041{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070042 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040043 const gl::Program *program = state.getProgram();
44
Corentin Wallez327411e2016-12-09 11:09:17 -050045 bool webglCompatibility = context->getExtensions().webglCompatibility;
46
Jamie Madill231c7f52017-04-26 13:45:37 -040047 const VertexArray *vao = state.getVertexArray();
48 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080049 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madill231c7f52017-04-26 13:45:37 -040050 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040051 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
52 {
53 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallez672f7f32017-06-15 17:42:17 -040054
55 // No need to range check for disabled attribs.
56 if (!attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040057 {
Corentin Wallezfd456442016-12-21 17:57:00 -050058 continue;
59 }
Jamie Madill1ca74672015-07-21 15:14:11 -040060
Jamie Madill231c7f52017-04-26 13:45:37 -040061 // If we have no buffer, then we either get an error, or there are no more checks to be
62 // done.
Corentin Wallez672f7f32017-06-15 17:42:17 -040063 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
64 gl::Buffer *buffer = binding.getBuffer().get();
Corentin Wallezfd456442016-12-21 17:57:00 -050065 if (!buffer)
66 {
Geoff Langfeb8c682017-02-13 16:07:35 -050067 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050068 {
69 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050070 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
71 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
72 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
73 // error.
Brandon Jonesafa75152017-07-21 13:11:29 -070074 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
Corentin Wallezfd456442016-12-21 17:57:00 -050075 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050076 }
Corentin Wallezfd456442016-12-21 17:57:00 -050077 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040078 {
79 // This is an application error that would normally result in a crash,
80 // but we catch it and return an error
Brandon Jonesafa75152017-07-21 13:11:29 -070081 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
Jamie Madill1ca74672015-07-21 15:14:11 -040082 return false;
83 }
Corentin Wallezfd456442016-12-21 17:57:00 -050084 continue;
85 }
86
Corentin Wallez672f7f32017-06-15 17:42:17 -040087 // This needs to come after the check for client arrays as even unused attributes cannot use
88 // client-side arrays
89 if (!program->isAttribLocationActive(attributeIndex))
90 {
91 continue;
92 }
93
Corentin Wallezfd456442016-12-21 17:57:00 -050094 // If we're drawing zero vertices, we have enough data.
95 if (vertexCount <= 0 || primcount <= 0)
96 {
97 continue;
98 }
99
100 GLint maxVertexElement = 0;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300101 GLuint divisor = binding.getDivisor();
102 if (divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500103 {
104 maxVertexElement = maxVertex;
105 }
106 else
107 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300108 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500109 }
110
111 // We do manual overflow checks here instead of using safe_math.h because it was
112 // a bottleneck. Thanks to some properties of GL we know inequalities that can
113 // help us make the overflow checks faster.
114
115 // The max possible attribSize is 16 for a vector of 4 32 bit values.
116 constexpr uint64_t kMaxAttribSize = 16;
117 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
118 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
119
120 // We know attribStride is given as a GLsizei which is typedefed to int.
121 // We also know an upper bound for attribSize.
122 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800123 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500124 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
125 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
126
127 // Computing the max offset using uint64_t without attrib.offset is overflow
128 // safe. Note: Last vertex element does not take the full stride!
129 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
130 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
131
132 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800133 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
134 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500135 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700136 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500137 return false;
138 }
139 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
140
141 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
142 // We can return INVALID_OPERATION if our vertex attribute does not have
143 // enough backing data.
144 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
145 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700146 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500147 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400148 }
149 }
150
151 return true;
152}
153
Geoff Lang280ba992017-04-18 16:30:58 -0400154bool ValidReadPixelsTypeEnum(ValidationContext *context, GLenum type)
155{
156 switch (type)
157 {
158 // Types referenced in Table 3.4 of the ES 2.0.25 spec
159 case GL_UNSIGNED_BYTE:
160 case GL_UNSIGNED_SHORT_4_4_4_4:
161 case GL_UNSIGNED_SHORT_5_5_5_1:
162 case GL_UNSIGNED_SHORT_5_6_5:
163 return context->getClientVersion() >= ES_2_0;
164
165 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
166 case GL_BYTE:
167 case GL_INT:
168 case GL_SHORT:
169 case GL_UNSIGNED_INT:
170 case GL_UNSIGNED_INT_10F_11F_11F_REV:
171 case GL_UNSIGNED_INT_24_8:
172 case GL_UNSIGNED_INT_2_10_10_10_REV:
173 case GL_UNSIGNED_INT_5_9_9_9_REV:
174 case GL_UNSIGNED_SHORT:
175 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
176 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
177 return context->getClientVersion() >= ES_3_0;
178
179 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400180 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
181 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400182
183 case GL_HALF_FLOAT:
184 return context->getClientVersion() >= ES_3_0 ||
185 context->getExtensions().textureHalfFloat;
186
187 case GL_HALF_FLOAT_OES:
188 return context->getExtensions().colorBufferHalfFloat;
189
190 default:
191 return false;
192 }
193}
194
195bool ValidReadPixelsFormatEnum(ValidationContext *context, GLenum format)
196{
197 switch (format)
198 {
199 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
200 case GL_RGBA:
201 case GL_RGB:
202 case GL_ALPHA:
203 return context->getClientVersion() >= ES_2_0;
204
205 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
206 case GL_RG:
207 case GL_RED:
208 case GL_RGBA_INTEGER:
209 case GL_RGB_INTEGER:
210 case GL_RG_INTEGER:
211 case GL_RED_INTEGER:
212 return context->getClientVersion() >= ES_3_0;
213
214 case GL_SRGB_ALPHA_EXT:
215 case GL_SRGB_EXT:
216 return context->getExtensions().sRGB;
217
218 case GL_BGRA_EXT:
219 return context->getExtensions().readFormatBGRA;
220
221 default:
222 return false;
223 }
224}
225
Geoff Langf607c602016-09-21 11:46:48 -0400226bool ValidReadPixelsFormatType(ValidationContext *context,
227 GLenum framebufferComponentType,
228 GLenum format,
229 GLenum type)
230{
231 switch (framebufferComponentType)
232 {
233 case GL_UNSIGNED_NORMALIZED:
234 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
235 // ReadPixels with BGRA even if the extension is not present
236 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
237 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
238 type == GL_UNSIGNED_BYTE);
239
240 case GL_SIGNED_NORMALIZED:
241 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
242
243 case GL_INT:
244 return (format == GL_RGBA_INTEGER && type == GL_INT);
245
246 case GL_UNSIGNED_INT:
247 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
248
249 case GL_FLOAT:
250 return (format == GL_RGBA && type == GL_FLOAT);
251
252 default:
253 UNREACHABLE();
254 return false;
255 }
256}
257
Geoff Langc1984ed2016-10-07 12:41:00 -0400258template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400259bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400260{
261 switch (ConvertToGLenum(params[0]))
262 {
263 case GL_CLAMP_TO_EDGE:
264 break;
265
266 case GL_REPEAT:
267 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400268 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400269 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400270 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700271 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400272 return false;
273 }
274 break;
275
276 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700277 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400278 return false;
279 }
280
281 return true;
282}
283
284template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400285bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400286{
287 switch (ConvertToGLenum(params[0]))
288 {
289 case GL_NEAREST:
290 case GL_LINEAR:
291 break;
292
293 case GL_NEAREST_MIPMAP_NEAREST:
294 case GL_LINEAR_MIPMAP_NEAREST:
295 case GL_NEAREST_MIPMAP_LINEAR:
296 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400297 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400298 {
299 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700300 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400301 return false;
302 }
303 break;
304
305 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700306 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400307 return false;
308 }
309
310 return true;
311}
312
313template <typename ParamType>
314bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
315{
316 switch (ConvertToGLenum(params[0]))
317 {
318 case GL_NEAREST:
319 case GL_LINEAR:
320 break;
321
322 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700323 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400324 return false;
325 }
326
327 return true;
328}
329
330template <typename ParamType>
331bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
332{
333 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
334 switch (ConvertToGLenum(params[0]))
335 {
336 case GL_NONE:
337 case GL_COMPARE_REF_TO_TEXTURE:
338 break;
339
340 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700341 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400342 return false;
343 }
344
345 return true;
346}
347
348template <typename ParamType>
349bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
350{
351 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
352 switch (ConvertToGLenum(params[0]))
353 {
354 case GL_LEQUAL:
355 case GL_GEQUAL:
356 case GL_LESS:
357 case GL_GREATER:
358 case GL_EQUAL:
359 case GL_NOTEQUAL:
360 case GL_ALWAYS:
361 case GL_NEVER:
362 break;
363
364 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700365 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400366 return false;
367 }
368
369 return true;
370}
371
372template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700373bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
374{
375 if (!context->getExtensions().textureSRGBDecode)
376 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700377 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700378 return false;
379 }
380
381 switch (ConvertToGLenum(params[0]))
382 {
383 case GL_DECODE_EXT:
384 case GL_SKIP_DECODE_EXT:
385 break;
386
387 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700388 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700389 return false;
390 }
391
392 return true;
393}
394
Geoff Lange0cff192017-05-30 13:04:56 -0400395bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
396{
397 const Program *program = context->getGLState().getProgram();
398 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
399
Brandon Jones76746f92017-11-22 11:44:41 -0800400 if (!DrawBufferTypeMask::ProgramOutputsMatchFramebuffer(
401 program->getDrawBufferTypeMask(), framebuffer->getDrawBufferTypeMask(),
402 program->getActiveOutputVariables(), framebuffer->getDrawBufferMask()))
Geoff Lange0cff192017-05-30 13:04:56 -0400403 {
Brandon Jones76746f92017-11-22 11:44:41 -0800404 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
405 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400406 }
407
408 return true;
409}
410
Geoff Lang9ab5b822017-05-30 16:19:23 -0400411bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
412{
Jamie Madillcac94a92017-11-10 10:09:32 -0500413 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400414 const Program *program = context->getGLState().getProgram();
415 const VertexArray *vao = context->getGLState().getVertexArray();
Jamie Madillcac94a92017-11-10 10:09:32 -0500416 const auto &vertexAttribs = vao->getVertexAttributes();
417 const auto &currentValues = glState.getVertexAttribCurrentValues();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400418
Jamie Madillcac94a92017-11-10 10:09:32 -0500419 for (const sh::Attribute &shaderAttribute : program->getAttributes())
Geoff Lang9ab5b822017-05-30 16:19:23 -0400420 {
Geoff Lang69df2422017-07-05 12:42:31 -0400421 // gl_VertexID and gl_InstanceID are active attributes but don't have a bound attribute.
422 if (shaderAttribute.isBuiltIn())
423 {
424 continue;
425 }
426
Geoff Lang9ab5b822017-05-30 16:19:23 -0400427 GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
428
Jamie Madillcac94a92017-11-10 10:09:32 -0500429 const auto &attrib = vertexAttribs[shaderAttribute.location];
430 GLenum vertexType = attrib.enabled ? GetVertexAttributeBaseType(attrib)
431 : currentValues[shaderAttribute.location].Type;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400432
433 if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
434 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500435 context->handleError(InvalidOperation() << "Vertex shader input type does not "
436 "match the type of the bound vertex "
437 "attribute.");
Geoff Lang9ab5b822017-05-30 16:19:23 -0400438 return false;
439 }
440 }
441
442 return true;
443}
444
Geoff Langf41a7152016-09-19 15:11:17 -0400445} // anonymous namespace
446
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500447bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400448{
Jamie Madilld7460c72014-01-21 16:38:14 -0500449 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400450 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800451 case GL_TEXTURE_2D:
452 case GL_TEXTURE_CUBE_MAP:
453 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400454
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400455 case GL_TEXTURE_RECTANGLE_ANGLE:
456 return context->getExtensions().textureRectangle;
457
He Yunchaoced53ae2016-11-29 15:00:51 +0800458 case GL_TEXTURE_3D:
459 case GL_TEXTURE_2D_ARRAY:
460 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500461
He Yunchaoced53ae2016-11-29 15:00:51 +0800462 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800463 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400464
He Yunchaoced53ae2016-11-29 15:00:51 +0800465 default:
466 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500467 }
Jamie Madill35d15012013-10-07 10:46:37 -0400468}
469
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500470bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
471{
472 switch (target)
473 {
474 case GL_TEXTURE_2D:
475 case GL_TEXTURE_CUBE_MAP:
476 return true;
477
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400478 case GL_TEXTURE_RECTANGLE_ANGLE:
479 return context->getExtensions().textureRectangle;
480
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500481 default:
482 return false;
483 }
484}
485
486bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
487{
488 switch (target)
489 {
490 case GL_TEXTURE_3D:
491 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300492 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500493
494 default:
495 return false;
496 }
497}
498
Ian Ewellbda75592016-04-18 17:25:54 -0400499// Most texture GL calls are not compatible with external textures, so we have a separate validation
500// function for use in the GL calls that do
501bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
502{
503 return (target == GL_TEXTURE_EXTERNAL_OES) &&
504 (context->getExtensions().eglImageExternal ||
505 context->getExtensions().eglStreamConsumerExternal);
506}
507
Shannon Woods4dfed832014-03-17 20:03:39 -0400508// This function differs from ValidTextureTarget in that the target must be
509// usable as the destination of a 2D operation-- so a cube face is valid, but
510// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400511// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500512bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400513{
514 switch (target)
515 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800516 case GL_TEXTURE_2D:
517 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
518 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
519 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
520 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
521 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
522 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
523 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400524 case GL_TEXTURE_RECTANGLE_ANGLE:
525 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800526 default:
527 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500528 }
529}
530
Jamie Madillbe849e42017-05-02 15:49:00 -0400531bool ValidateDrawElementsInstancedBase(ValidationContext *context,
532 GLenum mode,
533 GLsizei count,
534 GLenum type,
535 const GLvoid *indices,
536 GLsizei primcount)
537{
538 if (primcount < 0)
539 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700540 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400541 return false;
542 }
543
544 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
545 {
546 return false;
547 }
548
549 // No-op zero primitive count
550 return (primcount > 0);
551}
552
553bool ValidateDrawArraysInstancedBase(Context *context,
554 GLenum mode,
555 GLint first,
556 GLsizei count,
557 GLsizei primcount)
558{
559 if (primcount < 0)
560 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700561 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400562 return false;
563 }
564
565 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
566 {
567 return false;
568 }
569
570 // No-op if zero primitive count
571 return (primcount > 0);
572}
573
Corentin Wallez0dc97812017-06-22 14:38:44 -0400574bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400575{
576 // Verify there is at least one active attribute with a divisor of zero
577 const State &state = context->getGLState();
578
579 Program *program = state.getProgram();
580
581 const auto &attribs = state.getVertexArray()->getVertexAttributes();
582 const auto &bindings = state.getVertexArray()->getVertexBindings();
583 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
584 {
585 const VertexAttribute &attrib = attribs[attributeIndex];
586 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300587 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400588 {
589 return true;
590 }
591 }
592
Brandon Jonesafa75152017-07-21 13:11:29 -0700593 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400594 return false;
595}
596
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500597bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
598{
599 switch (target)
600 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800601 case GL_TEXTURE_3D:
602 case GL_TEXTURE_2D_ARRAY:
603 return true;
604 default:
605 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400606 }
607}
608
He Yunchao11b038b2016-11-22 21:24:04 +0800609bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
610{
611 switch (target)
612 {
613 case GL_TEXTURE_2D:
614 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
615 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
616 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
617 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
618 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
619 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
620 case GL_TEXTURE_3D:
621 case GL_TEXTURE_2D_ARRAY:
622 case GL_TEXTURE_2D_MULTISAMPLE:
623 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400624 case GL_TEXTURE_RECTANGLE_ANGLE:
625 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800626 default:
627 return false;
628 }
629}
630
Geoff Lange8afa902017-09-27 15:00:43 -0400631bool ValidFramebufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500632{
He Yunchaoced53ae2016-11-29 15:00:51 +0800633 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
634 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400635 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500636
637 switch (target)
638 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800639 case GL_FRAMEBUFFER:
640 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400641
He Yunchaoced53ae2016-11-29 15:00:51 +0800642 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800643 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400644 return (context->getExtensions().framebufferBlit ||
645 context->getClientMajorVersion() >= 3);
646
He Yunchaoced53ae2016-11-29 15:00:51 +0800647 default:
648 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500649 }
650}
651
Corentin Wallez336129f2017-10-17 15:55:40 -0400652bool ValidBufferType(const ValidationContext *context, BufferBinding target)
Jamie Madill8c96d582014-03-05 15:01:23 -0500653{
654 switch (target)
655 {
Corentin Wallez336129f2017-10-17 15:55:40 -0400656 case BufferBinding::ElementArray:
657 case BufferBinding::Array:
He Yunchaoced53ae2016-11-29 15:00:51 +0800658 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -0500659
Corentin Wallez336129f2017-10-17 15:55:40 -0400660 case BufferBinding::PixelPack:
661 case BufferBinding::PixelUnpack:
He Yunchaoced53ae2016-11-29 15:00:51 +0800662 return (context->getExtensions().pixelBufferObject ||
663 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -0400664
Corentin Wallez336129f2017-10-17 15:55:40 -0400665 case BufferBinding::CopyRead:
666 case BufferBinding::CopyWrite:
667 case BufferBinding::TransformFeedback:
668 case BufferBinding::Uniform:
He Yunchaoced53ae2016-11-29 15:00:51 +0800669 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -0500670
Corentin Wallez336129f2017-10-17 15:55:40 -0400671 case BufferBinding::AtomicCounter:
672 case BufferBinding::ShaderStorage:
673 case BufferBinding::DrawIndirect:
674 case BufferBinding::DispatchIndirect:
He Yunchaoced53ae2016-11-29 15:00:51 +0800675 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -0400676
He Yunchaoced53ae2016-11-29 15:00:51 +0800677 default:
678 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -0500679 }
680}
681
Jamie Madillc29968b2016-01-20 11:17:23 -0500682bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400683{
Jamie Madillc29968b2016-01-20 11:17:23 -0500684 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400685 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400686 switch (target)
687 {
Jamie Madillc29968b2016-01-20 11:17:23 -0500688 case GL_TEXTURE_2D:
689 maxDimension = caps.max2DTextureSize;
690 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800691 case GL_TEXTURE_CUBE_MAP:
692 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
693 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
694 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
695 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
696 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
697 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
698 maxDimension = caps.maxCubeMapTextureSize;
699 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400700 case GL_TEXTURE_RECTANGLE_ANGLE:
701 return level == 0;
He Yunchaoced53ae2016-11-29 15:00:51 +0800702 case GL_TEXTURE_3D:
703 maxDimension = caps.max3DTextureSize;
704 break;
705 case GL_TEXTURE_2D_ARRAY:
706 maxDimension = caps.max2DTextureSize;
707 break;
He Yunchao11b038b2016-11-22 21:24:04 +0800708 case GL_TEXTURE_2D_MULTISAMPLE:
709 maxDimension = caps.max2DTextureSize;
710 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800711 default:
712 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400713 }
714
Brandon Jones6cad5662017-06-14 13:25:13 -0700715 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400716}
717
Brandon Jones6cad5662017-06-14 13:25:13 -0700718bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -0700719 GLenum target,
720 GLint level,
721 GLsizei width,
722 GLsizei height,
723 GLsizei depth,
724 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400725{
Brandon Jones6cad5662017-06-14 13:25:13 -0700726 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400727 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700728 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400729 return false;
730 }
Austin Kinross08528e12015-10-07 16:24:40 -0700731 // TexSubImage parameters can be NPOT without textureNPOT extension,
732 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500733 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500734 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500735 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400736 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400737 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700738 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400739 return false;
740 }
741
742 if (!ValidMipLevel(context, target, level))
743 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700744 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400745 return false;
746 }
747
748 return true;
749}
750
Geoff Lang0d8b7242015-09-09 14:56:53 -0400751bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
752{
753 // List of compressed format that require that the texture size is smaller than or a multiple of
754 // the compressed block size.
755 switch (internalFormat)
756 {
757 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
758 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
759 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
760 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -0400761 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
762 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
763 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
764 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -0800765 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800766 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
767 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
768 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
769 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
770 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
771 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -0400772 return true;
773
774 default:
775 return false;
776 }
777}
778
Geoff Lang966c9402017-04-18 12:38:27 -0400779bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
780{
781 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
782 (size % blockSize == 0);
783}
784
Jamie Madillc29968b2016-01-20 11:17:23 -0500785bool ValidCompressedImageSize(const ValidationContext *context,
786 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400787 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500788 GLsizei width,
789 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400790{
Geoff Langca271392017-04-05 12:30:00 -0400791 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400792 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400793 {
794 return false;
795 }
796
Geoff Lang966c9402017-04-18 12:38:27 -0400797 if (width < 0 || height < 0)
798 {
799 return false;
800 }
801
802 if (CompressedTextureFormatRequiresExactSize(internalFormat))
803 {
804 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
805 // block size for level 0 but WebGL disallows this.
806 bool smallerThanBlockSizeAllowed =
807 level > 0 || !context->getExtensions().webglCompatibility;
808
809 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
810 smallerThanBlockSizeAllowed) ||
811 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
812 smallerThanBlockSizeAllowed))
813 {
814 return false;
815 }
816 }
817
818 return true;
819}
820
821bool ValidCompressedSubImageSize(const ValidationContext *context,
822 GLenum internalFormat,
823 GLint xoffset,
824 GLint yoffset,
825 GLsizei width,
826 GLsizei height,
827 size_t textureWidth,
828 size_t textureHeight)
829{
830 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
831 if (!formatInfo.compressed)
832 {
833 return false;
834 }
835
Geoff Lang44ff5a72017-02-03 15:15:43 -0500836 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400837 {
838 return false;
839 }
840
Geoff Lang0d8b7242015-09-09 14:56:53 -0400841 if (CompressedTextureFormatRequiresExactSize(internalFormat))
842 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500843 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400844 yoffset % formatInfo.compressedBlockHeight != 0)
845 {
846 return false;
847 }
848
849 // Allowed to either have data that is a multiple of block size or is smaller than the block
850 // size but fills the entire mip
851 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
852 static_cast<size_t>(width) == textureWidth &&
853 static_cast<size_t>(height) == textureHeight;
854 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
855 (height % formatInfo.compressedBlockHeight) == 0;
856 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400857 {
858 return false;
859 }
860 }
861
Geoff Langd4f180b2013-09-24 13:57:44 -0400862 return true;
863}
864
Geoff Langff5b2d52016-09-07 11:32:23 -0400865bool ValidImageDataSize(ValidationContext *context,
866 GLenum textureTarget,
867 GLsizei width,
868 GLsizei height,
869 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400870 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400871 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400872 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400873 GLsizei imageSize)
874{
Corentin Wallez336129f2017-10-17 15:55:40 -0400875 gl::Buffer *pixelUnpackBuffer =
876 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400877 if (pixelUnpackBuffer == nullptr && imageSize < 0)
878 {
879 // Checks are not required
880 return true;
881 }
882
883 // ...the data would be unpacked from the buffer object such that the memory reads required
884 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400885 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
886 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400887 const gl::Extents size(width, height, depth);
888 const auto &unpack = context->getGLState().getUnpackState();
889
890 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
891 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
892 if (endByteOrErr.isError())
893 {
894 context->handleError(endByteOrErr.getError());
895 return false;
896 }
897
898 GLuint endByte = endByteOrErr.getResult();
899
900 if (pixelUnpackBuffer)
901 {
902 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
903 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
904 checkedEndByte += checkedOffset;
905
906 if (!checkedEndByte.IsValid() ||
907 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
908 {
909 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500910 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400911 return false;
912 }
913 }
914 else
915 {
916 ASSERT(imageSize >= 0);
917 if (pixels == nullptr && imageSize != 0)
918 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500919 context->handleError(InvalidOperation()
920 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400921 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400922 }
923
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400924 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400925 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500926 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400927 return false;
928 }
929 }
930
931 return true;
932}
933
Geoff Lang37dde692014-01-31 16:34:54 -0500934bool ValidQueryType(const Context *context, GLenum queryType)
935{
He Yunchaoced53ae2016-11-29 15:00:51 +0800936 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
937 "GL extension enums not equal.");
938 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
939 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -0500940
941 switch (queryType)
942 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800943 case GL_ANY_SAMPLES_PASSED:
944 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400945 return context->getClientMajorVersion() >= 3 ||
946 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +0800947 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
948 return (context->getClientMajorVersion() >= 3);
949 case GL_TIME_ELAPSED_EXT:
950 return context->getExtensions().disjointTimerQuery;
951 case GL_COMMANDS_COMPLETED_CHROMIUM:
952 return context->getExtensions().syncQuery;
953 default:
954 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500955 }
956}
957
Geoff Lang2d62ab72017-03-23 16:54:40 -0400958bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
959 GLenum type,
960 GLboolean normalized,
961 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400962 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400963 bool pureInteger)
964{
965 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400966 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
967 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
968 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
969 // parameter exceeds 255.
970 constexpr GLsizei kMaxWebGLStride = 255;
971 if (stride > kMaxWebGLStride)
972 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500973 context->handleError(InvalidValue()
974 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -0400975 return false;
976 }
977
978 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
979 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
980 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
981 // or an INVALID_OPERATION error is generated.
982 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
983 size_t typeSize = GetVertexFormatTypeSize(internalType);
984
985 ASSERT(isPow2(typeSize) && typeSize > 0);
986 size_t sizeMask = (typeSize - 1);
987 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
988 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700989 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400990 return false;
991 }
992
993 if ((stride & sizeMask) != 0)
994 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700995 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400996 return false;
997 }
998
999 return true;
1000}
1001
Jamie Madillef300b12016-10-07 15:12:09 -04001002Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001003{
He Yunchaoced53ae2016-11-29 15:00:51 +08001004 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1005 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1006 // or program object and INVALID_OPERATION if the provided name identifies an object
1007 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001008
Dian Xiang769769a2015-09-09 15:20:08 -07001009 Program *validProgram = context->getProgram(id);
1010
1011 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001012 {
Dian Xiang769769a2015-09-09 15:20:08 -07001013 if (context->getShader(id))
1014 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001015 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001016 }
1017 else
1018 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001019 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001020 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001021 }
Dian Xiang769769a2015-09-09 15:20:08 -07001022
1023 return validProgram;
1024}
1025
Jamie Madillef300b12016-10-07 15:12:09 -04001026Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001027{
1028 // See ValidProgram for spec details.
1029
1030 Shader *validShader = context->getShader(id);
1031
1032 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001033 {
Dian Xiang769769a2015-09-09 15:20:08 -07001034 if (context->getProgram(id))
1035 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001036 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001037 }
1038 else
1039 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001040 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001041 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001042 }
Dian Xiang769769a2015-09-09 15:20:08 -07001043
1044 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001045}
1046
Geoff Langb1196682014-07-23 13:47:29 -04001047bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001048{
Geoff Langfa125c92017-10-24 13:01:46 -04001049 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001050 {
Geoff Langfa125c92017-10-24 13:01:46 -04001051 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1052 {
1053 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1054 return false;
1055 }
Jamie Madillb4472272014-07-03 10:38:55 -04001056
Geoff Langfa125c92017-10-24 13:01:46 -04001057 // Color attachment 0 is validated below because it is always valid
1058 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001059 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001060 {
Geoff Langfa125c92017-10-24 13:01:46 -04001061 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001062 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001063 }
1064 }
1065 else
1066 {
1067 switch (attachment)
1068 {
Geoff Langfa125c92017-10-24 13:01:46 -04001069 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001070 case GL_DEPTH_ATTACHMENT:
1071 case GL_STENCIL_ATTACHMENT:
1072 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001073
He Yunchaoced53ae2016-11-29 15:00:51 +08001074 case GL_DEPTH_STENCIL_ATTACHMENT:
1075 if (!context->getExtensions().webglCompatibility &&
1076 context->getClientMajorVersion() < 3)
1077 {
Geoff Langfa125c92017-10-24 13:01:46 -04001078 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001079 return false;
1080 }
1081 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001082
He Yunchaoced53ae2016-11-29 15:00:51 +08001083 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001084 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001085 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001086 }
1087 }
1088
1089 return true;
1090}
1091
Jamie Madille8fb6402017-02-14 17:56:40 -05001092bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001093 GLenum target,
1094 GLsizei samples,
1095 GLenum internalformat,
1096 GLsizei width,
1097 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001098{
1099 switch (target)
1100 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001101 case GL_RENDERBUFFER:
1102 break;
1103 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001104 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001105 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001106 }
1107
1108 if (width < 0 || height < 0 || samples < 0)
1109 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001110 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001111 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001112 }
1113
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001114 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1115 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1116
1117 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001118 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001119 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001120 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001121 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001122 }
1123
1124 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1125 // 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 -08001126 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001127 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1128 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001129 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001130 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001131 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001132 }
1133
Geoff Langaae65a42014-05-26 12:43:44 -04001134 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001135 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001136 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001137 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001138 }
1139
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001140 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001141 if (handle == 0)
1142 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001143 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001144 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001145 }
1146
1147 return true;
1148}
1149
He Yunchaoced53ae2016-11-29 15:00:51 +08001150bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1151 GLenum target,
1152 GLenum attachment,
1153 GLenum renderbuffertarget,
1154 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001155{
Geoff Lange8afa902017-09-27 15:00:43 -04001156 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001157 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001158 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001159 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001160 }
1161
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001162 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001163
Jamie Madill84115c92015-04-23 15:00:07 -04001164 ASSERT(framebuffer);
1165 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001166 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001167 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001168 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001169 }
1170
Jamie Madillb4472272014-07-03 10:38:55 -04001171 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001172 {
Jamie Madillb4472272014-07-03 10:38:55 -04001173 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001174 }
1175
Jamie Madillab9d82c2014-01-21 16:38:14 -05001176 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1177 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1178 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1179 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1180 if (renderbuffer != 0)
1181 {
1182 if (!context->getRenderbuffer(renderbuffer))
1183 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001184 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001185 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001186 }
1187 }
1188
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001189 return true;
1190}
1191
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001192bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001193 GLint srcX0,
1194 GLint srcY0,
1195 GLint srcX1,
1196 GLint srcY1,
1197 GLint dstX0,
1198 GLint dstY0,
1199 GLint dstX1,
1200 GLint dstY1,
1201 GLbitfield mask,
1202 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001203{
1204 switch (filter)
1205 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001206 case GL_NEAREST:
1207 break;
1208 case GL_LINEAR:
1209 break;
1210 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001211 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001212 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001213 }
1214
1215 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1216 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001217 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001218 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001219 }
1220
1221 if (mask == 0)
1222 {
1223 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1224 // buffers are copied.
1225 return false;
1226 }
1227
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001228 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1229 // color buffer, leaving only nearest being unfiltered from above
1230 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1231 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001232 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001233 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001234 }
1235
Jamie Madill51f40ec2016-06-15 14:06:00 -04001236 const auto &glState = context->getGLState();
1237 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1238 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001239
1240 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001241 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001242 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001243 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001244 }
1245
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001246 if (readFramebuffer->id() == drawFramebuffer->id())
1247 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001248 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001249 return false;
1250 }
1251
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001252 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001253 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001254 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001255 return false;
1256 }
1257
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001258 if (drawFramebuffer->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->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001265 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001266 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001267 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001268 }
1269
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001270 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1271
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001272 if (mask & GL_COLOR_BUFFER_BIT)
1273 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001274 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001275 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001276
He Yunchao66a41a22016-12-15 16:45:05 +08001277 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001278 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001279 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001280
Geoff Langa15472a2015-08-11 11:48:03 -04001281 for (size_t drawbufferIdx = 0;
1282 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001283 {
Geoff Langa15472a2015-08-11 11:48:03 -04001284 const FramebufferAttachment *attachment =
1285 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1286 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001287 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001288 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001289
Geoff Langb2f3d052013-08-13 12:49:27 -04001290 // The GL ES 3.0.2 spec (pg 193) states that:
1291 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001292 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1293 // as well
1294 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1295 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001296 // Changes with EXT_color_buffer_float:
1297 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001298 GLenum readComponentType = readFormat.info->componentType;
1299 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001300 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001301 readComponentType == GL_SIGNED_NORMALIZED);
1302 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1303 drawComponentType == GL_SIGNED_NORMALIZED);
1304
1305 if (extensions.colorBufferFloat)
1306 {
1307 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1308 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1309
1310 if (readFixedOrFloat != drawFixedOrFloat)
1311 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001312 context->handleError(InvalidOperation()
1313 << "If the read buffer contains fixed-point or "
1314 "floating-point values, the draw buffer must "
1315 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001316 return false;
1317 }
1318 }
1319 else if (readFixedPoint != drawFixedPoint)
1320 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001321 context->handleError(InvalidOperation()
1322 << "If the read buffer contains fixed-point values, "
1323 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001324 return false;
1325 }
1326
1327 if (readComponentType == GL_UNSIGNED_INT &&
1328 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001329 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001330 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001331 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001332 }
1333
Jamie Madill6163c752015-12-07 16:32:59 -05001334 if (readComponentType == GL_INT && drawComponentType != GL_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 Madilla3944d42016-07-22 22:13:26 -04001340 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001341 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001342 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001343 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001344 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001345 }
Geoff Lange4915782017-04-12 15:19:07 -04001346
1347 if (context->getExtensions().webglCompatibility &&
1348 *readColorBuffer == *attachment)
1349 {
1350 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001351 InvalidOperation()
1352 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001353 return false;
1354 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001355 }
1356 }
1357
Jamie Madilla3944d42016-07-22 22:13:26 -04001358 if ((readFormat.info->componentType == GL_INT ||
1359 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1360 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001361 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001362 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001363 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001364 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001365 }
He Yunchao66a41a22016-12-15 16:45:05 +08001366 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1367 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1368 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1369 // situation is an application error that would lead to a crash in ANGLE.
1370 else if (drawFramebuffer->hasEnabledDrawBuffer())
1371 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001372 context->handleError(
1373 InvalidOperation()
1374 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001375 return false;
1376 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001377 }
1378
He Yunchaoced53ae2016-11-29 15:00:51 +08001379 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001380 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1381 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001382 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001383 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001384 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001385 const gl::FramebufferAttachment *readBuffer =
1386 readFramebuffer->getAttachment(attachments[i]);
1387 const gl::FramebufferAttachment *drawBuffer =
1388 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001389
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001390 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001391 {
Kenneth Russell69382852017-07-21 16:38:44 -04001392 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001393 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001394 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001395 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001396 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001397
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001398 if (readBuffer->getSamples() > 0 && !sameBounds)
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 Lange4915782017-04-12 15:19:07 -04001403
1404 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001406 context->handleError(
1407 InvalidOperation()
1408 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001409 return false;
1410 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001411 }
He Yunchao66a41a22016-12-15 16:45:05 +08001412 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1413 else if (drawBuffer)
1414 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001415 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1416 "depth/stencil attachment of a "
1417 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001418 return false;
1419 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001420 }
1421 }
1422
Martin Radeva3ed4572017-07-27 18:29:37 +03001423 // ANGLE_multiview, Revision 1:
1424 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1425 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1426 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1427 {
1428 context->handleError(InvalidFramebufferOperation()
1429 << "Attempt to read from a multi-view framebuffer.");
1430 return false;
1431 }
1432 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1433 {
1434 context->handleError(InvalidFramebufferOperation()
1435 << "Attempt to write to a multi-view framebuffer.");
1436 return false;
1437 }
1438
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001439 return true;
1440}
1441
Jamie Madill4928b7c2017-06-20 12:57:39 -04001442bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001443 GLint x,
1444 GLint y,
1445 GLsizei width,
1446 GLsizei height,
1447 GLenum format,
1448 GLenum type,
1449 GLsizei bufSize,
1450 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001451 GLsizei *columns,
1452 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001453 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001454{
1455 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001456 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001457 return false;
1458 }
1459
Geoff Lang62fce5b2016-09-30 10:46:35 -04001460 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001461 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001462 {
Geoff Langb1196682014-07-23 13:47:29 -04001463 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001464 }
1465
Geoff Lang62fce5b2016-09-30 10:46:35 -04001466 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001467 {
Geoff Langb1196682014-07-23 13:47:29 -04001468 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001469 }
1470
Jamie Madillc29968b2016-01-20 11:17:23 -05001471 return true;
1472}
1473
1474bool ValidateReadnPixelsEXT(Context *context,
1475 GLint x,
1476 GLint y,
1477 GLsizei width,
1478 GLsizei height,
1479 GLenum format,
1480 GLenum type,
1481 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001482 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001483{
1484 if (bufSize < 0)
1485 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001486 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001487 return false;
1488 }
1489
Geoff Lang62fce5b2016-09-30 10:46:35 -04001490 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001491 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001492}
Jamie Madill26e91952014-03-05 15:01:27 -05001493
Jamie Madill4928b7c2017-06-20 12:57:39 -04001494bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001495 GLint x,
1496 GLint y,
1497 GLsizei width,
1498 GLsizei height,
1499 GLenum format,
1500 GLenum type,
1501 GLsizei bufSize,
1502 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001503 GLsizei *columns,
1504 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001505 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001506{
1507 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001508 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001509 return false;
1510 }
1511
Geoff Lange93daba2017-03-30 13:54:40 -04001512 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1513 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001514 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001515 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001516 }
1517
Geoff Lang62fce5b2016-09-30 10:46:35 -04001518 if (!ValidateRobustBufferSize(context, bufSize, *length))
1519 {
1520 return false;
1521 }
1522
1523 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001524}
1525
Jamie Madillf0e04492017-08-26 15:28:42 -04001526bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001527{
1528 if (!context->getExtensions().occlusionQueryBoolean &&
1529 !context->getExtensions().disjointTimerQuery)
1530 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001531 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001532 return false;
1533 }
1534
Olli Etuaho41997e72016-03-10 13:38:39 +02001535 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001536}
1537
Jamie Madillf0e04492017-08-26 15:28:42 -04001538bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001539{
1540 if (!context->getExtensions().occlusionQueryBoolean &&
1541 !context->getExtensions().disjointTimerQuery)
1542 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001543 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001544 return false;
1545 }
1546
Olli Etuaho41997e72016-03-10 13:38:39 +02001547 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001548}
1549
Jamie Madillf0e04492017-08-26 15:28:42 -04001550bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1551{
1552 if (!context->getExtensions().occlusionQueryBoolean &&
1553 !context->getExtensions().disjointTimerQuery)
1554 {
1555 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1556 return false;
1557 }
1558
1559 return true;
1560}
1561
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001562bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001563{
1564 if (!ValidQueryType(context, target))
1565 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001566 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001567 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001568 }
1569
1570 if (id == 0)
1571 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001572 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001573 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001574 }
1575
1576 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1577 // of zero, if the active query object name for <target> is non-zero (for the
1578 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1579 // the active query for either target is non-zero), if <id> is the name of an
1580 // existing query object whose type does not match <target>, or if <id> is the
1581 // active query object name for any query type, the error INVALID_OPERATION is
1582 // generated.
1583
1584 // Ensure no other queries are active
1585 // NOTE: If other queries than occlusion are supported, we will need to check
1586 // separately that:
1587 // a) The query ID passed is not the current active query for any target/type
1588 // b) There are no active queries for the requested target (and in the case
1589 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1590 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001591
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001592 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001593 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001594 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001595 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001596 }
1597
1598 Query *queryObject = context->getQuery(id, true, target);
1599
1600 // check that name was obtained with glGenQueries
1601 if (!queryObject)
1602 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001603 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001604 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001605 }
1606
1607 // check for type mismatch
1608 if (queryObject->getType() != target)
1609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001610 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001611 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001612 }
1613
1614 return true;
1615}
1616
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001617bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1618{
1619 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001620 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001621 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001622 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001623 return false;
1624 }
1625
1626 return ValidateBeginQueryBase(context, target, id);
1627}
1628
1629bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001630{
1631 if (!ValidQueryType(context, target))
1632 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001633 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001634 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001635 }
1636
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001637 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001638
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001639 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001640 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001641 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001642 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001643 }
1644
Jamie Madill45c785d2014-05-13 14:09:34 -04001645 return true;
1646}
1647
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001648bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1649{
1650 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001651 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001652 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001653 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001654 return false;
1655 }
1656
1657 return ValidateEndQueryBase(context, target);
1658}
1659
1660bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1661{
1662 if (!context->getExtensions().disjointTimerQuery)
1663 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001664 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001665 return false;
1666 }
1667
1668 if (target != GL_TIMESTAMP_EXT)
1669 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001670 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001671 return false;
1672 }
1673
1674 Query *queryObject = context->getQuery(id, true, target);
1675 if (queryObject == nullptr)
1676 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001677 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001678 return false;
1679 }
1680
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001681 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001682 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001683 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001684 return false;
1685 }
1686
1687 return true;
1688}
1689
Geoff Lang2186c382016-10-14 10:54:54 -04001690bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001691{
Geoff Lang2186c382016-10-14 10:54:54 -04001692 if (numParams)
1693 {
1694 *numParams = 0;
1695 }
1696
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001697 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1698 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001699 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001700 return false;
1701 }
1702
1703 switch (pname)
1704 {
1705 case GL_CURRENT_QUERY_EXT:
1706 if (target == GL_TIMESTAMP_EXT)
1707 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001708 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001709 return false;
1710 }
1711 break;
1712 case GL_QUERY_COUNTER_BITS_EXT:
1713 if (!context->getExtensions().disjointTimerQuery ||
1714 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1715 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001716 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001717 return false;
1718 }
1719 break;
1720 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001721 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001722 return false;
1723 }
1724
Geoff Lang2186c382016-10-14 10:54:54 -04001725 if (numParams)
1726 {
1727 // All queries return only one value
1728 *numParams = 1;
1729 }
1730
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001731 return true;
1732}
1733
1734bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1735{
1736 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001737 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001738 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001739 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001740 return false;
1741 }
1742
Geoff Lang2186c382016-10-14 10:54:54 -04001743 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001744}
1745
Geoff Lang2186c382016-10-14 10:54:54 -04001746bool ValidateGetQueryivRobustANGLE(Context *context,
1747 GLenum target,
1748 GLenum pname,
1749 GLsizei bufSize,
1750 GLsizei *length,
1751 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001752{
Geoff Lang2186c382016-10-14 10:54:54 -04001753 if (!ValidateRobustEntryPoint(context, bufSize))
1754 {
1755 return false;
1756 }
1757
1758 if (!ValidateGetQueryivBase(context, target, pname, length))
1759 {
1760 return false;
1761 }
1762
1763 if (!ValidateRobustBufferSize(context, bufSize, *length))
1764 {
1765 return false;
1766 }
1767
1768 return true;
1769}
1770
1771bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1772{
1773 if (numParams)
1774 {
1775 *numParams = 0;
1776 }
1777
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001778 Query *queryObject = context->getQuery(id, false, GL_NONE);
1779
1780 if (!queryObject)
1781 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001782 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001783 return false;
1784 }
1785
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001786 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001787 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001788 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001789 return false;
1790 }
1791
1792 switch (pname)
1793 {
1794 case GL_QUERY_RESULT_EXT:
1795 case GL_QUERY_RESULT_AVAILABLE_EXT:
1796 break;
1797
1798 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001799 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001800 return false;
1801 }
1802
Geoff Lang2186c382016-10-14 10:54:54 -04001803 if (numParams)
1804 {
1805 *numParams = 1;
1806 }
1807
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001808 return true;
1809}
1810
1811bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1812{
1813 if (!context->getExtensions().disjointTimerQuery)
1814 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001815 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001816 return false;
1817 }
Geoff Lang2186c382016-10-14 10:54:54 -04001818 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1819}
1820
1821bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1822 GLuint id,
1823 GLenum pname,
1824 GLsizei bufSize,
1825 GLsizei *length,
1826 GLint *params)
1827{
1828 if (!context->getExtensions().disjointTimerQuery)
1829 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001830 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001831 return false;
1832 }
1833
1834 if (!ValidateRobustEntryPoint(context, bufSize))
1835 {
1836 return false;
1837 }
1838
1839 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1840 {
1841 return false;
1842 }
1843
1844 if (!ValidateRobustBufferSize(context, bufSize, *length))
1845 {
1846 return false;
1847 }
1848
1849 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001850}
1851
1852bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1853{
1854 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001855 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001856 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001857 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001858 return false;
1859 }
Geoff Lang2186c382016-10-14 10:54:54 -04001860 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1861}
1862
1863bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1864 GLuint id,
1865 GLenum pname,
1866 GLsizei bufSize,
1867 GLsizei *length,
1868 GLuint *params)
1869{
1870 if (!context->getExtensions().disjointTimerQuery &&
1871 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1872 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001873 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001874 return false;
1875 }
1876
1877 if (!ValidateRobustEntryPoint(context, bufSize))
1878 {
1879 return false;
1880 }
1881
1882 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1883 {
1884 return false;
1885 }
1886
1887 if (!ValidateRobustBufferSize(context, bufSize, *length))
1888 {
1889 return false;
1890 }
1891
1892 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001893}
1894
1895bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1896{
1897 if (!context->getExtensions().disjointTimerQuery)
1898 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001899 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001900 return false;
1901 }
Geoff Lang2186c382016-10-14 10:54:54 -04001902 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1903}
1904
1905bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1906 GLuint id,
1907 GLenum pname,
1908 GLsizei bufSize,
1909 GLsizei *length,
1910 GLint64 *params)
1911{
1912 if (!context->getExtensions().disjointTimerQuery)
1913 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001914 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001915 return false;
1916 }
1917
1918 if (!ValidateRobustEntryPoint(context, bufSize))
1919 {
1920 return false;
1921 }
1922
1923 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1924 {
1925 return false;
1926 }
1927
1928 if (!ValidateRobustBufferSize(context, bufSize, *length))
1929 {
1930 return false;
1931 }
1932
1933 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001934}
1935
1936bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1937{
1938 if (!context->getExtensions().disjointTimerQuery)
1939 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001940 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001941 return false;
1942 }
Geoff Lang2186c382016-10-14 10:54:54 -04001943 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1944}
1945
1946bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1947 GLuint id,
1948 GLenum pname,
1949 GLsizei bufSize,
1950 GLsizei *length,
1951 GLuint64 *params)
1952{
1953 if (!context->getExtensions().disjointTimerQuery)
1954 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001955 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001956 return false;
1957 }
1958
1959 if (!ValidateRobustEntryPoint(context, bufSize))
1960 {
1961 return false;
1962 }
1963
1964 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1965 {
1966 return false;
1967 }
1968
1969 if (!ValidateRobustBufferSize(context, bufSize, *length))
1970 {
1971 return false;
1972 }
1973
1974 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001975}
1976
Jiajia Qin5451d532017-11-16 17:16:34 +08001977bool ValidateUniformCommonBase(ValidationContext *context,
1978 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05001979 GLint location,
1980 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08001981 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05001982{
Jiajia Qin5451d532017-11-16 17:16:34 +08001983 // TODO(Jiajia): Add image uniform check in future.
1984 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05001985 {
Jiajia Qin5451d532017-11-16 17:16:34 +08001986 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05001987 return false;
1988 }
1989
Jiajia Qin5451d532017-11-16 17:16:34 +08001990 if (!program)
1991 {
1992 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
1993 return false;
1994 }
1995
1996 if (!program->isLinked())
1997 {
1998 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
1999 return false;
2000 }
2001
2002 if (location == -1)
2003 {
2004 // Silently ignore the uniform command
2005 return false;
2006 }
2007
2008 const auto &uniformLocations = program->getUniformLocations();
2009 size_t castedLocation = static_cast<size_t>(location);
2010 if (castedLocation >= uniformLocations.size())
2011 {
2012 context->handleError(InvalidOperation() << "Invalid uniform location");
2013 return false;
2014 }
2015
2016 const auto &uniformLocation = uniformLocations[castedLocation];
2017 if (uniformLocation.ignored)
2018 {
2019 // Silently ignore the uniform command
2020 return false;
2021 }
2022
2023 if (!uniformLocation.used())
2024 {
2025 context->handleError(InvalidOperation());
2026 return false;
2027 }
2028
2029 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2030
2031 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2032 if (!uniform.isArray() && count > 1)
2033 {
2034 context->handleError(InvalidOperation());
2035 return false;
2036 }
2037
2038 *uniformOut = &uniform;
2039 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002040}
2041
Jiajia Qin5451d532017-11-16 17:16:34 +08002042bool ValidateUniform1ivValue(ValidationContext *context,
2043 GLenum uniformType,
2044 GLsizei count,
2045 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002046{
Jiajia Qin5451d532017-11-16 17:16:34 +08002047 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2048 // It is compatible with INT or BOOL.
2049 // Do these cheap tests first, for a little extra speed.
2050 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002051 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002052 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002053 }
2054
Jiajia Qin5451d532017-11-16 17:16:34 +08002055 if (IsSamplerType(uniformType))
2056 {
2057 // Check that the values are in range.
2058 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2059 for (GLsizei i = 0; i < count; ++i)
2060 {
2061 if (value[i] < 0 || value[i] >= max)
2062 {
2063 context->handleError(InvalidValue() << "sampler uniform value out of range");
2064 return false;
2065 }
2066 }
2067 return true;
2068 }
2069
2070 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2071 return false;
2072}
2073
2074bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2075{
2076 // Check that the value type is compatible with uniform type.
2077 // Do the cheaper test first, for a little extra speed.
2078 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2079 {
2080 return true;
2081 }
2082
2083 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2084 return false;
2085}
2086
2087bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2088{
2089 // Check that the value type is compatible with uniform type.
2090 if (valueType == uniformType)
2091 {
2092 return true;
2093 }
2094
2095 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2096 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002097}
2098
Jamie Madillc1d770e2017-04-13 17:31:24 -04002099bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002100{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002101 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002102 gl::Program *programObject = context->getGLState().getProgram();
2103 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2104 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002105}
2106
Jamie Madillbe849e42017-05-02 15:49:00 -04002107bool ValidateUniform1iv(ValidationContext *context,
2108 GLint location,
2109 GLsizei count,
2110 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002111{
2112 const LinkedUniform *uniform = nullptr;
2113 gl::Program *programObject = context->getGLState().getProgram();
2114 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2115 ValidateUniform1ivValue(context, uniform->type, count, value);
2116}
2117
Jamie Madillc1d770e2017-04-13 17:31:24 -04002118bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002119 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002120 GLint location,
2121 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002122 GLboolean transpose)
2123{
Geoff Lang92019432017-11-20 13:09:34 -05002124 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002125 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002126 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002127 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002128 }
2129
Jamie Madill62d31cb2015-09-11 13:25:51 -04002130 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002131 gl::Program *programObject = context->getGLState().getProgram();
2132 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2133 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002134}
2135
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002136bool ValidateStateQuery(ValidationContext *context,
2137 GLenum pname,
2138 GLenum *nativeType,
2139 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002140{
2141 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2142 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002143 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002144 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002145 }
2146
Jamie Madill0af26e12015-03-05 19:54:33 -05002147 const Caps &caps = context->getCaps();
2148
Jamie Madill893ab082014-05-16 16:56:10 -04002149 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2150 {
2151 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2152
Jamie Madill0af26e12015-03-05 19:54:33 -05002153 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002154 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002155 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002156 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002157 }
2158 }
2159
2160 switch (pname)
2161 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002162 case GL_TEXTURE_BINDING_2D:
2163 case GL_TEXTURE_BINDING_CUBE_MAP:
2164 case GL_TEXTURE_BINDING_3D:
2165 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002166 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002167 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002168 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2169 if (!context->getExtensions().textureRectangle)
2170 {
2171 context->handleError(InvalidEnum()
2172 << "ANGLE_texture_rectangle extension not present");
2173 return false;
2174 }
2175 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002176 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2177 if (!context->getExtensions().eglStreamConsumerExternal &&
2178 !context->getExtensions().eglImageExternal)
2179 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002180 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2181 "nor GL_OES_EGL_image_external "
2182 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002183 return false;
2184 }
2185 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002186
He Yunchaoced53ae2016-11-29 15:00:51 +08002187 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2188 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002189 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002190 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2191 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002193 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002194 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002195 }
2196
Jamie Madill51f40ec2016-06-15 14:06:00 -04002197 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2198 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002199
2200 if (framebuffer->getReadBufferState() == GL_NONE)
2201 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002202 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002203 return false;
2204 }
2205
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002206 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002207 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002208 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002209 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002210 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002211 }
2212 }
2213 break;
2214
He Yunchaoced53ae2016-11-29 15:00:51 +08002215 default:
2216 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002217 }
2218
2219 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002220 if (*numParams == 0)
2221 {
2222 return false;
2223 }
2224
2225 return true;
2226}
2227
2228bool ValidateRobustStateQuery(ValidationContext *context,
2229 GLenum pname,
2230 GLsizei bufSize,
2231 GLenum *nativeType,
2232 unsigned int *numParams)
2233{
2234 if (!ValidateRobustEntryPoint(context, bufSize))
2235 {
2236 return false;
2237 }
2238
2239 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2240 {
2241 return false;
2242 }
2243
2244 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002245 {
2246 return false;
2247 }
2248
2249 return true;
2250}
2251
Jamie Madillc29968b2016-01-20 11:17:23 -05002252bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2253 GLenum target,
2254 GLint level,
2255 GLenum internalformat,
2256 bool isSubImage,
2257 GLint xoffset,
2258 GLint yoffset,
2259 GLint zoffset,
2260 GLint x,
2261 GLint y,
2262 GLsizei width,
2263 GLsizei height,
2264 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002265 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002266{
Brandon Jones6cad5662017-06-14 13:25:13 -07002267 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002268 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002269 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2270 return false;
2271 }
2272
2273 if (width < 0 || height < 0)
2274 {
2275 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002276 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002277 }
2278
He Yunchaoced53ae2016-11-29 15:00:51 +08002279 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2280 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002281 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002282 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002283 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002284 }
2285
2286 if (border != 0)
2287 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002288 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002289 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002290 }
2291
2292 if (!ValidMipLevel(context, target, level))
2293 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002294 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002295 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002296 }
2297
Jamie Madill51f40ec2016-06-15 14:06:00 -04002298 const auto &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002299 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002300 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002301 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002302 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002303 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002304 }
2305
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002306 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002307 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002308 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002309 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002310 }
2311
Martin Radev138064f2016-07-15 12:03:41 +03002312 if (readFramebuffer->getReadBufferState() == GL_NONE)
2313 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002314 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002315 return false;
2316 }
2317
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002318 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2319 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002320 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002321 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002322 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2323 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002324 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002325 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002326 return false;
2327 }
2328
Martin Radev04e2c3b2017-07-27 16:54:35 +03002329 // ANGLE_multiview spec, Revision 1:
2330 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2331 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2332 // is not NONE.
2333 if (source->getMultiviewLayout() != GL_NONE)
2334 {
2335 context->handleError(InvalidFramebufferOperation()
2336 << "The active read framebuffer object has multiview attachments.");
2337 return false;
2338 }
2339
Geoff Langaae65a42014-05-26 12:43:44 -04002340 const gl::Caps &caps = context->getCaps();
2341
Geoff Langaae65a42014-05-26 12:43:44 -04002342 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002343 switch (target)
2344 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002345 case GL_TEXTURE_2D:
2346 maxDimension = caps.max2DTextureSize;
2347 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002348
He Yunchaoced53ae2016-11-29 15:00:51 +08002349 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2350 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2351 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2352 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2353 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2354 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2355 maxDimension = caps.maxCubeMapTextureSize;
2356 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002357
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002358 case GL_TEXTURE_RECTANGLE_ANGLE:
2359 maxDimension = caps.maxRectangleTextureSize;
2360 break;
2361
He Yunchaoced53ae2016-11-29 15:00:51 +08002362 case GL_TEXTURE_2D_ARRAY:
2363 maxDimension = caps.max2DTextureSize;
2364 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002365
He Yunchaoced53ae2016-11-29 15:00:51 +08002366 case GL_TEXTURE_3D:
2367 maxDimension = caps.max3DTextureSize;
2368 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002369
He Yunchaoced53ae2016-11-29 15:00:51 +08002370 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002371 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002372 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002373 }
2374
Jamie Madillc29968b2016-01-20 11:17:23 -05002375 gl::Texture *texture =
2376 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002377 if (!texture)
2378 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002379 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002380 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002381 }
2382
Geoff Lang69cce582015-09-17 13:20:36 -04002383 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002385 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002386 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002387 }
2388
Geoff Langca271392017-04-05 12:30:00 -04002389 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002390 isSubImage ? *texture->getFormat(target, level).info
2391 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002392
Geoff Lang966c9402017-04-18 12:38:27 -04002393 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002394 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002395 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002396 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002397 }
2398
2399 if (isSubImage)
2400 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002401 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2402 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2403 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002404 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002405 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002406 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002407 }
2408 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002409 else
2410 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002411 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002412 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002413 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002414 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002415 }
2416
Geoff Langeb66a6e2016-10-31 13:06:12 -04002417 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002418 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002419 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002420 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002421 }
2422
2423 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002424 if (static_cast<int>(width) > maxLevelDimension ||
2425 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002426 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002427 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002428 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002429 }
2430 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002431
Jamie Madill0c8abca2016-07-22 20:21:26 -04002432 if (textureFormatOut)
2433 {
2434 *textureFormatOut = texture->getFormat(target, level);
2435 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002436
2437 // Detect texture copying feedback loops for WebGL.
2438 if (context->getExtensions().webglCompatibility)
2439 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002440 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002441 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002442 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002443 return false;
2444 }
2445 }
2446
Jamie Madill560a8d82014-05-21 13:06:20 -04002447 return true;
2448}
2449
Jiajia Qind9671222016-11-29 16:30:31 +08002450bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002451{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002452 switch (mode)
2453 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002454 case GL_POINTS:
2455 case GL_LINES:
2456 case GL_LINE_LOOP:
2457 case GL_LINE_STRIP:
2458 case GL_TRIANGLES:
2459 case GL_TRIANGLE_STRIP:
2460 case GL_TRIANGLE_FAN:
2461 break;
2462 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002463 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002464 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002465 }
2466
Jamie Madill250d33f2014-06-06 17:09:03 -04002467 if (count < 0)
2468 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002469 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002470 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002471 }
2472
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002473 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002474
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002475 const Extensions &extensions = context->getExtensions();
2476
2477 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2478 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2479 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2480 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002481 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002482 // Check for mapped buffers
2483 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002484 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002485 {
2486 context->handleError(InvalidOperation());
2487 return false;
2488 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002489 }
2490
Jamie Madillcbcde722017-01-06 14:50:00 -05002491 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2492 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002493 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002494 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002495 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002496 const FramebufferAttachment *dsAttachment =
2497 framebuffer->getStencilOrDepthStencilAttachment();
2498 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002499 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002500 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002501
2502 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2503 bool differentWritemasks =
2504 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2505 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2506 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2507 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2508
2509 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002510 {
Martin Radevffe754b2017-07-31 10:38:07 +03002511 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002512 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002513 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2514 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002515 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002516 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002517 return false;
2518 }
Jamie Madillac528012014-06-20 13:21:23 -04002519 }
2520
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002521 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002522 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002523 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002524 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002525 }
2526
Geoff Lang7dd2e102014-11-10 15:19:26 -05002527 gl::Program *program = state.getProgram();
2528 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002529 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002530 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002531 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002532 }
2533
Yunchao Hecddcb592017-11-13 15:27:35 +08002534 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2535 // vertex shader stage or fragment shader stage is a undefined behaviour.
2536 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2537 // produce undefined result.
2538 if (program->isLinked() &&
2539 (!program->hasLinkedVertexShader() || !program->hasLinkedFragmentShader()))
2540 {
2541 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2542 "vertex shader stage or fragment shader stage.");
2543 return false;
2544 }
2545
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002546 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002547 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002548 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002549 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002550 }
2551
Martin Radevffe754b2017-07-31 10:38:07 +03002552 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002553 {
Martin Radevda8e2572017-09-12 17:21:16 +03002554 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002555 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002556 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002557 {
2558 context->handleError(InvalidOperation() << "The number of views in the active program "
2559 "and draw framebuffer does not match.");
2560 return false;
2561 }
Martin Radev7e69f762017-07-27 14:54:13 +03002562
2563 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2564 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2565 framebufferNumViews > 1)
2566 {
2567 context->handleError(InvalidOperation()
2568 << "There is an active transform feedback object "
2569 "when the number of views in the active draw "
2570 "framebuffer is greater than 1.");
2571 return false;
2572 }
Martin Radevffe754b2017-07-31 10:38:07 +03002573
2574 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2575 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2576 {
2577 context->handleError(InvalidOperation() << "There is an active query for target "
2578 "GL_TIME_ELAPSED_EXT when the number of "
2579 "views in the active draw framebuffer is "
2580 "greater than 1.");
2581 return false;
2582 }
Martin Radev7cf61662017-07-26 17:10:53 +03002583 }
2584
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002585 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002586 for (unsigned int uniformBlockIndex = 0;
2587 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002588 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002589 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002590 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002591 const OffsetBindingPointer<Buffer> &uniformBuffer =
2592 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002593
Geoff Lang5d124a62015-09-15 13:03:27 -04002594 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002595 {
2596 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002597 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002598 InvalidOperation()
2599 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002600 return false;
2601 }
2602
Geoff Lang5d124a62015-09-15 13:03:27 -04002603 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002604 if (uniformBufferSize == 0)
2605 {
2606 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002607 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002608 }
2609
Jamie Madill62d31cb2015-09-11 13:25:51 -04002610 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002611 {
2612 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002613 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002614 InvalidOperation()
2615 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002616 return false;
2617 }
2618 }
2619
Geoff Lange0cff192017-05-30 13:04:56 -04002620 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002621 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002622 {
Geoff Lange0cff192017-05-30 13:04:56 -04002623 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002624 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2625 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002626 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002627 return false;
2628 }
Geoff Lange0cff192017-05-30 13:04:56 -04002629
Geoff Lang9ab5b822017-05-30 16:19:23 -04002630 // Detect that the vertex shader input types match the attribute types
2631 if (!ValidateVertexShaderAttributeTypeMatch(context))
2632 {
2633 return false;
2634 }
2635
Geoff Lange0cff192017-05-30 13:04:56 -04002636 // Detect that the color buffer types match the fragment shader output types
2637 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2638 {
2639 return false;
2640 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002641 }
2642
Jamie Madill250d33f2014-06-06 17:09:03 -04002643 // No-op if zero count
2644 return (count > 0);
2645}
2646
Jamie Madillc1d770e2017-04-13 17:31:24 -04002647bool ValidateDrawArraysCommon(ValidationContext *context,
2648 GLenum mode,
2649 GLint first,
2650 GLsizei count,
2651 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002652{
Jamie Madillfd716582014-06-06 17:09:04 -04002653 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002654 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002655 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002656 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002657 }
2658
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002659 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002660 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002661 if (curTransformFeedback && curTransformFeedback->isActive() &&
2662 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002663 {
2664 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002665 // that does not match the current transform feedback object's draw mode (if transform
2666 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002667 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002668 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002669 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002670 }
2671
Jiajia Qind9671222016-11-29 16:30:31 +08002672 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002673 {
2674 return false;
2675 }
2676
Corentin Wallez71168a02016-12-19 15:11:18 -08002677 // Check the computation of maxVertex doesn't overflow.
2678 // - first < 0 or count < 0 have been checked as an error condition
2679 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2680 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2681 ASSERT(count > 0 && first >= 0);
2682 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2683 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002684 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002685 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002686 return false;
2687 }
2688
Corentin Wallez71168a02016-12-19 15:11:18 -08002689 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002690 {
2691 return false;
2692 }
2693
2694 return true;
2695}
2696
He Yunchaoced53ae2016-11-29 15:00:51 +08002697bool ValidateDrawArraysInstancedANGLE(Context *context,
2698 GLenum mode,
2699 GLint first,
2700 GLsizei count,
2701 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002702{
Geoff Lang63c5a592017-09-27 14:08:16 -04002703 if (!context->getExtensions().instancedArrays)
2704 {
2705 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2706 return false;
2707 }
2708
Corentin Wallez170efbf2017-05-02 13:45:01 -04002709 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002710 {
2711 return false;
2712 }
2713
Corentin Wallez0dc97812017-06-22 14:38:44 -04002714 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002715}
2716
Jiajia Qind9671222016-11-29 16:30:31 +08002717bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002718{
Jamie Madill250d33f2014-06-06 17:09:03 -04002719 switch (type)
2720 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002721 case GL_UNSIGNED_BYTE:
2722 case GL_UNSIGNED_SHORT:
2723 break;
2724 case GL_UNSIGNED_INT:
2725 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2726 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002727 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002728 return false;
2729 }
2730 break;
2731 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002732 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002733 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002734 }
2735
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002736 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002737
2738 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002739 if (curTransformFeedback && curTransformFeedback->isActive() &&
2740 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002741 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002742 // It is an invalid operation to call DrawElements, DrawRangeElements or
2743 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002744 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002745 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002746 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002747 }
2748
Jiajia Qind9671222016-11-29 16:30:31 +08002749 return true;
2750}
2751
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002752bool ValidateDrawElementsCommon(ValidationContext *context,
2753 GLenum mode,
2754 GLsizei count,
2755 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002756 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002757 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002758{
2759 if (!ValidateDrawElementsBase(context, type))
2760 return false;
2761
2762 const State &state = context->getGLState();
2763
Corentin Wallez170efbf2017-05-02 13:45:01 -04002764 if (!ValidateDrawBase(context, mode, count))
2765 {
2766 return false;
2767 }
2768
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002769 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2770 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2771 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2772 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002773 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002774 // Check for mapped buffers
2775 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002776 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002777 {
2778 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2779 return false;
2780 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002781 }
2782
He Yunchaoced53ae2016-11-29 15:00:51 +08002783 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002784 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002785
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002786 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2787
2788 if (context->getExtensions().webglCompatibility)
2789 {
2790 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2791 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2792 {
2793 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2794 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2795 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002796 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002797 return false;
2798 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002799
2800 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2801 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2802 // error is generated.
2803 if (reinterpret_cast<intptr_t>(indices) < 0)
2804 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002805 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002806 return false;
2807 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002808 }
2809
2810 if (context->getExtensions().webglCompatibility ||
2811 !context->getGLState().areClientArraysEnabled())
2812 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002813 if (!elementArrayBuffer && count > 0)
2814 {
2815 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2816 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2817 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002818 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002819 return false;
2820 }
2821 }
2822
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002823 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002824 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002825 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002826 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002827 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2828 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2829 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2830 constexpr uint64_t kMaxTypeSize = 8;
2831 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2832 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2833 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002834
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002835 uint64_t typeSize = typeBytes;
2836 uint64_t elementCount = static_cast<uint64_t>(count);
2837 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2838
2839 // Doing the multiplication here is overflow-safe
2840 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2841
2842 // The offset can be any value, check for overflows
2843 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2844 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002845 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002846 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002847 return false;
2848 }
2849
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002850 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2851 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002852 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002853 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002854 return false;
2855 }
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002856
Corentin Wallez487653b2017-09-01 17:17:55 -04002857 ASSERT(isPow2(typeSize) && typeSize > 0);
2858 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002859 {
2860 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
2861 return false;
2862 }
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002863 }
2864 else if (!indices)
2865 {
2866 // This is an application error that would normally result in a crash,
2867 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002868 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04002869 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002870 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002871 }
2872
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002873 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002874 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002875 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2876 // access is enabled.
2877 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2878 {
2879 return false;
2880 }
2881 }
2882 else
2883 {
2884 // Use the parameter buffer to retrieve and cache the index range.
2885 const auto &params = context->getParams<HasIndexRange>();
2886 const auto &indexRangeOpt = params.getIndexRange();
2887 if (!indexRangeOpt.valid())
2888 {
2889 // Unexpected error.
2890 return false;
2891 }
2892
2893 // If we use an index greater than our maximum supported index range, return an error.
2894 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2895 // return an error if possible here.
2896 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2897 {
2898 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2899 return false;
2900 }
2901
2902 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2903 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2904 {
2905 return false;
2906 }
2907
2908 // No op if there are no real indices in the index data (all are primitive restart).
2909 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002910 }
2911
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002912 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002913}
2914
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002915bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2916 GLenum mode,
2917 GLsizei count,
2918 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002919 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002920 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002921{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002922 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002923}
2924
Geoff Lang3edfe032015-09-04 16:38:24 -04002925bool ValidateDrawElementsInstancedANGLE(Context *context,
2926 GLenum mode,
2927 GLsizei count,
2928 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002929 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002930 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002931{
Geoff Lang63c5a592017-09-27 14:08:16 -04002932 if (!context->getExtensions().instancedArrays)
2933 {
2934 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2935 return false;
2936 }
2937
Corentin Wallez170efbf2017-05-02 13:45:01 -04002938 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002939 {
2940 return false;
2941 }
2942
Corentin Wallez0dc97812017-06-22 14:38:44 -04002943 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002944}
2945
He Yunchaoced53ae2016-11-29 15:00:51 +08002946bool ValidateFramebufferTextureBase(Context *context,
2947 GLenum target,
2948 GLenum attachment,
2949 GLuint texture,
2950 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002951{
Geoff Lange8afa902017-09-27 15:00:43 -04002952 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002953 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002954 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002955 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002956 }
2957
2958 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002959 {
2960 return false;
2961 }
2962
Jamie Madill55ec3b12014-07-03 10:38:57 -04002963 if (texture != 0)
2964 {
2965 gl::Texture *tex = context->getTexture(texture);
2966
Jamie Madillbe849e42017-05-02 15:49:00 -04002967 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002968 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002969 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002970 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002971 }
2972
2973 if (level < 0)
2974 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002975 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002976 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002977 }
2978 }
2979
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002980 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002981 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002982
Jamie Madill84115c92015-04-23 15:00:07 -04002983 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002984 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002985 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002986 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002987 }
2988
2989 return true;
2990}
2991
Geoff Langb1196682014-07-23 13:47:29 -04002992bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04002993{
2994 if (program == 0)
2995 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002996 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002997 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002998 }
2999
Dian Xiang769769a2015-09-09 15:20:08 -07003000 gl::Program *programObject = GetValidProgram(context, program);
3001 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003002 {
3003 return false;
3004 }
3005
Jamie Madill0063c512014-08-25 15:47:53 -04003006 if (!programObject || !programObject->isLinked())
3007 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003008 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003009 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003010 }
3011
Geoff Lang7dd2e102014-11-10 15:19:26 -05003012 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003013 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003014 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003015 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003016 }
3017
Jamie Madill0063c512014-08-25 15:47:53 -04003018 return true;
3019}
3020
Geoff Langf41d0ee2016-10-07 13:04:23 -04003021static bool ValidateSizedGetUniform(Context *context,
3022 GLuint program,
3023 GLint location,
3024 GLsizei bufSize,
3025 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003026{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003027 if (length)
3028 {
3029 *length = 0;
3030 }
3031
Jamie Madill78f41802014-08-25 15:47:55 -04003032 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003033 {
Jamie Madill78f41802014-08-25 15:47:55 -04003034 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003035 }
3036
Geoff Langf41d0ee2016-10-07 13:04:23 -04003037 if (bufSize < 0)
3038 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003039 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003040 return false;
3041 }
3042
Jamie Madilla502c742014-08-28 17:19:13 -04003043 gl::Program *programObject = context->getProgram(program);
3044 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003045
Jamie Madill78f41802014-08-25 15:47:55 -04003046 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003047 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003048 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003049 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003050 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003051 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003052 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003053 }
3054
Geoff Langf41d0ee2016-10-07 13:04:23 -04003055 if (length)
3056 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003057 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003058 }
3059
Jamie Madill0063c512014-08-25 15:47:53 -04003060 return true;
3061}
3062
He Yunchaoced53ae2016-11-29 15:00:51 +08003063bool ValidateGetnUniformfvEXT(Context *context,
3064 GLuint program,
3065 GLint location,
3066 GLsizei bufSize,
3067 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003068{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003069 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003070}
3071
He Yunchaoced53ae2016-11-29 15:00:51 +08003072bool ValidateGetnUniformivEXT(Context *context,
3073 GLuint program,
3074 GLint location,
3075 GLsizei bufSize,
3076 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003077{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003078 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3079}
3080
3081bool ValidateGetUniformfvRobustANGLE(Context *context,
3082 GLuint program,
3083 GLint location,
3084 GLsizei bufSize,
3085 GLsizei *length,
3086 GLfloat *params)
3087{
3088 if (!ValidateRobustEntryPoint(context, bufSize))
3089 {
3090 return false;
3091 }
3092
3093 // bufSize is validated in ValidateSizedGetUniform
3094 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3095}
3096
3097bool ValidateGetUniformivRobustANGLE(Context *context,
3098 GLuint program,
3099 GLint location,
3100 GLsizei bufSize,
3101 GLsizei *length,
3102 GLint *params)
3103{
3104 if (!ValidateRobustEntryPoint(context, bufSize))
3105 {
3106 return false;
3107 }
3108
3109 // bufSize is validated in ValidateSizedGetUniform
3110 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3111}
3112
3113bool ValidateGetUniformuivRobustANGLE(Context *context,
3114 GLuint program,
3115 GLint location,
3116 GLsizei bufSize,
3117 GLsizei *length,
3118 GLuint *params)
3119{
3120 if (!ValidateRobustEntryPoint(context, bufSize))
3121 {
3122 return false;
3123 }
3124
3125 if (context->getClientMajorVersion() < 3)
3126 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003127 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003128 return false;
3129 }
3130
3131 // bufSize is validated in ValidateSizedGetUniform
3132 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003133}
3134
He Yunchaoced53ae2016-11-29 15:00:51 +08003135bool ValidateDiscardFramebufferBase(Context *context,
3136 GLenum target,
3137 GLsizei numAttachments,
3138 const GLenum *attachments,
3139 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003140{
3141 if (numAttachments < 0)
3142 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003143 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003144 return false;
3145 }
3146
3147 for (GLsizei i = 0; i < numAttachments; ++i)
3148 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003149 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003150 {
3151 if (defaultFramebuffer)
3152 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003153 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003154 return false;
3155 }
3156
3157 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3158 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003159 context->handleError(InvalidOperation() << "Requested color attachment is "
3160 "greater than the maximum supported "
3161 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003162 return false;
3163 }
3164 }
3165 else
3166 {
3167 switch (attachments[i])
3168 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003169 case GL_DEPTH_ATTACHMENT:
3170 case GL_STENCIL_ATTACHMENT:
3171 case GL_DEPTH_STENCIL_ATTACHMENT:
3172 if (defaultFramebuffer)
3173 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003174 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3175 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003176 return false;
3177 }
3178 break;
3179 case GL_COLOR:
3180 case GL_DEPTH:
3181 case GL_STENCIL:
3182 if (!defaultFramebuffer)
3183 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003184 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3185 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003186 return false;
3187 }
3188 break;
3189 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003190 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003191 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003192 }
3193 }
3194 }
3195
3196 return true;
3197}
3198
Austin Kinross6ee1e782015-05-29 17:05:37 -07003199bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3200{
3201 // Note that debug marker calls must not set error state
3202
3203 if (length < 0)
3204 {
3205 return false;
3206 }
3207
3208 if (marker == nullptr)
3209 {
3210 return false;
3211 }
3212
3213 return true;
3214}
3215
3216bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3217{
3218 // Note that debug marker calls must not set error state
3219
3220 if (length < 0)
3221 {
3222 return false;
3223 }
3224
3225 if (length > 0 && marker == nullptr)
3226 {
3227 return false;
3228 }
3229
3230 return true;
3231}
3232
Geoff Langdcab33b2015-07-21 13:03:16 -04003233bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003234 GLenum target,
3235 egl::Image *image)
3236{
Geoff Langa8406172015-07-21 16:53:39 -04003237 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3238 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003239 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003240 return false;
3241 }
3242
3243 switch (target)
3244 {
3245 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003246 if (!context->getExtensions().eglImage)
3247 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003248 context->handleError(InvalidEnum()
3249 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003250 }
3251 break;
3252
3253 case GL_TEXTURE_EXTERNAL_OES:
3254 if (!context->getExtensions().eglImageExternal)
3255 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003256 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3257 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003258 }
Geoff Langa8406172015-07-21 16:53:39 -04003259 break;
3260
3261 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003262 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003263 return false;
3264 }
3265
Jamie Madill61e16b42017-06-19 11:13:23 -04003266 ASSERT(context->getCurrentDisplay());
3267 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003268 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003269 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003270 return false;
3271 }
3272
3273 if (image->getSamples() > 0)
3274 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003275 context->handleError(InvalidOperation()
3276 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003277 return false;
3278 }
3279
Geoff Langca271392017-04-05 12:30:00 -04003280 const TextureCaps &textureCaps =
3281 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003282 if (!textureCaps.texturable)
3283 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003284 context->handleError(InvalidOperation()
3285 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003286 return false;
3287 }
3288
Geoff Langdcab33b2015-07-21 13:03:16 -04003289 return true;
3290}
3291
3292bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003293 GLenum target,
3294 egl::Image *image)
3295{
Geoff Langa8406172015-07-21 16:53:39 -04003296 if (!context->getExtensions().eglImage)
3297 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003298 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003299 return false;
3300 }
3301
3302 switch (target)
3303 {
3304 case GL_RENDERBUFFER:
3305 break;
3306
3307 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003308 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003309 return false;
3310 }
3311
Jamie Madill61e16b42017-06-19 11:13:23 -04003312 ASSERT(context->getCurrentDisplay());
3313 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003314 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003315 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003316 return false;
3317 }
3318
Geoff Langca271392017-04-05 12:30:00 -04003319 const TextureCaps &textureCaps =
3320 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003321 if (!textureCaps.renderable)
3322 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003323 context->handleError(InvalidOperation()
3324 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003325 return false;
3326 }
3327
Geoff Langdcab33b2015-07-21 13:03:16 -04003328 return true;
3329}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003330
3331bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3332{
Geoff Lang36167ab2015-12-07 10:27:14 -05003333 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003334 {
3335 // The default VAO should always exist
3336 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003337 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003338 return false;
3339 }
3340
3341 return true;
3342}
3343
Geoff Langc5629752015-12-07 16:29:04 -05003344bool ValidateProgramBinaryBase(Context *context,
3345 GLuint program,
3346 GLenum binaryFormat,
3347 const void *binary,
3348 GLint length)
3349{
3350 Program *programObject = GetValidProgram(context, program);
3351 if (programObject == nullptr)
3352 {
3353 return false;
3354 }
3355
3356 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3357 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3358 programBinaryFormats.end())
3359 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003360 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003361 return false;
3362 }
3363
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003364 if (context->hasActiveTransformFeedback(program))
3365 {
3366 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003367 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3368 "is associated with an active transform "
3369 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003370 return false;
3371 }
3372
Geoff Langc5629752015-12-07 16:29:04 -05003373 return true;
3374}
3375
3376bool ValidateGetProgramBinaryBase(Context *context,
3377 GLuint program,
3378 GLsizei bufSize,
3379 GLsizei *length,
3380 GLenum *binaryFormat,
3381 void *binary)
3382{
3383 Program *programObject = GetValidProgram(context, program);
3384 if (programObject == nullptr)
3385 {
3386 return false;
3387 }
3388
3389 if (!programObject->isLinked())
3390 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003391 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003392 return false;
3393 }
3394
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003395 if (context->getCaps().programBinaryFormats.empty())
3396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003397 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003398 return false;
3399 }
3400
Geoff Langc5629752015-12-07 16:29:04 -05003401 return true;
3402}
Jamie Madillc29968b2016-01-20 11:17:23 -05003403
Jamie Madillc29968b2016-01-20 11:17:23 -05003404bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3405{
3406 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003407 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003408 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003409 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3410 return false;
3411 }
3412 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3413 {
3414 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003415 return false;
3416 }
3417
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003418 ASSERT(context->getGLState().getDrawFramebuffer());
3419 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003420 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3421
3422 // This should come first before the check for the default frame buffer
3423 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3424 // rather than INVALID_OPERATION
3425 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3426 {
3427 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3428
3429 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003430 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3431 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003432 {
3433 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003434 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3435 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3436 // 3.1 is still a bit ambiguous about the error, but future specs are
3437 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003438 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003439 return false;
3440 }
3441 else if (bufs[colorAttachment] >= maxColorAttachment)
3442 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003443 context->handleError(InvalidOperation()
3444 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003445 return false;
3446 }
3447 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3448 frameBufferId != 0)
3449 {
3450 // INVALID_OPERATION-GL is bound to buffer and ith argument
3451 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003452 context->handleError(InvalidOperation()
3453 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003454 return false;
3455 }
3456 }
3457
3458 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3459 // and n is not 1 or bufs is bound to value other than BACK and NONE
3460 if (frameBufferId == 0)
3461 {
3462 if (n != 1)
3463 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003464 context->handleError(InvalidOperation()
3465 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003466 return false;
3467 }
3468
3469 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3470 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003471 context->handleError(
3472 InvalidOperation()
3473 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003474 return false;
3475 }
3476 }
3477
3478 return true;
3479}
3480
Geoff Lang496c02d2016-10-20 11:38:11 -07003481bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003482 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003483 GLenum pname,
3484 GLsizei *length,
3485 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003486{
Geoff Lang496c02d2016-10-20 11:38:11 -07003487 if (length)
3488 {
3489 *length = 0;
3490 }
3491
3492 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3493 {
3494 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003495 InvalidOperation()
3496 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003497 return false;
3498 }
3499
Corentin Wallez336129f2017-10-17 15:55:40 -04003500 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003501 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003502 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003503 return false;
3504 }
3505
Geoff Lang496c02d2016-10-20 11:38:11 -07003506 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003507 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003508 case GL_BUFFER_MAP_POINTER:
3509 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003510
Geoff Lang496c02d2016-10-20 11:38:11 -07003511 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003512 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003513 return false;
3514 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003515
3516 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3517 // target bound to zero generate an INVALID_OPERATION error."
3518 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003519 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003521 context->handleError(InvalidOperation()
3522 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003523 return false;
3524 }
3525
Geoff Lang496c02d2016-10-20 11:38:11 -07003526 if (length)
3527 {
3528 *length = 1;
3529 }
3530
Olli Etuaho4f667482016-03-30 15:56:35 +03003531 return true;
3532}
3533
Corentin Wallez336129f2017-10-17 15:55:40 -04003534bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003535{
Corentin Wallez336129f2017-10-17 15:55:40 -04003536 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003537 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003538 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003539 return false;
3540 }
3541
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003542 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003543
3544 if (buffer == nullptr || !buffer->isMapped())
3545 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003546 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003547 return false;
3548 }
3549
3550 return true;
3551}
3552
3553bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003554 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003555 GLintptr offset,
3556 GLsizeiptr length,
3557 GLbitfield access)
3558{
Corentin Wallez336129f2017-10-17 15:55:40 -04003559 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003560 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003561 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003562 return false;
3563 }
3564
Brandon Jones6cad5662017-06-14 13:25:13 -07003565 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003566 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003567 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3568 return false;
3569 }
3570
3571 if (length < 0)
3572 {
3573 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003574 return false;
3575 }
3576
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003577 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003578
3579 if (!buffer)
3580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003581 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003582 return false;
3583 }
3584
3585 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003586 CheckedNumeric<size_t> checkedOffset(offset);
3587 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003588
Jamie Madille2e406c2016-06-02 13:04:10 -04003589 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003590 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003591 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003592 return false;
3593 }
3594
3595 // Check for invalid bits in the mask
3596 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3597 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3598 GL_MAP_UNSYNCHRONIZED_BIT;
3599
3600 if (access & ~(allAccessBits))
3601 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003602 context->handleError(InvalidValue()
3603 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003604 return false;
3605 }
3606
3607 if (length == 0)
3608 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003609 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003610 return false;
3611 }
3612
3613 if (buffer->isMapped())
3614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003615 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003616 return false;
3617 }
3618
3619 // Check for invalid bit combinations
3620 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3621 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003622 context->handleError(InvalidOperation()
3623 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003624 return false;
3625 }
3626
3627 GLbitfield writeOnlyBits =
3628 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3629
3630 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3631 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003632 context->handleError(InvalidOperation()
3633 << "Invalid access bits when mapping buffer for reading: 0x"
3634 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003635 return false;
3636 }
3637
3638 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3639 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003640 context->handleError(
3641 InvalidOperation()
3642 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003643 return false;
3644 }
Geoff Lang79f71042017-08-14 16:43:43 -04003645
3646 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003647}
3648
3649bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003650 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003651 GLintptr offset,
3652 GLsizeiptr length)
3653{
Brandon Jones6cad5662017-06-14 13:25:13 -07003654 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003655 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003656 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3657 return false;
3658 }
3659
3660 if (length < 0)
3661 {
3662 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003663 return false;
3664 }
3665
Corentin Wallez336129f2017-10-17 15:55:40 -04003666 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003667 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003668 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003669 return false;
3670 }
3671
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003672 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003673
3674 if (buffer == nullptr)
3675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003676 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003677 return false;
3678 }
3679
3680 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3681 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003682 context->handleError(InvalidOperation()
3683 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003684 return false;
3685 }
3686
3687 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003688 CheckedNumeric<size_t> checkedOffset(offset);
3689 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003690
Jamie Madille2e406c2016-06-02 13:04:10 -04003691 if (!checkedSize.IsValid() ||
3692 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003693 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003694 context->handleError(InvalidValue()
3695 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003696 return false;
3697 }
3698
3699 return true;
3700}
3701
Olli Etuaho41997e72016-03-10 13:38:39 +02003702bool ValidateGenOrDelete(Context *context, GLint n)
3703{
3704 if (n < 0)
3705 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003706 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003707 return false;
3708 }
3709 return true;
3710}
3711
Geoff Langff5b2d52016-09-07 11:32:23 -04003712bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3713{
3714 if (!context->getExtensions().robustClientMemory)
3715 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003716 context->handleError(InvalidOperation()
3717 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003718 return false;
3719 }
3720
3721 if (bufSize < 0)
3722 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003723 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003724 return false;
3725 }
3726
3727 return true;
3728}
3729
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003730bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3731{
3732 if (bufSize < numParams)
3733 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003734 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3735 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003736 return false;
3737 }
3738
3739 return true;
3740}
3741
Jamie Madillbe849e42017-05-02 15:49:00 -04003742bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3743 GLenum target,
3744 GLenum attachment,
3745 GLenum pname,
3746 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003747{
Geoff Lange8afa902017-09-27 15:00:43 -04003748 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003749 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003750 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003751 return false;
3752 }
3753
3754 int clientVersion = context->getClientMajorVersion();
3755
3756 switch (pname)
3757 {
3758 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3759 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3760 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3761 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3762 break;
3763
Martin Radeve5285d22017-07-14 16:23:53 +03003764 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3765 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3766 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3767 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3768 if (clientVersion < 3 || !context->getExtensions().multiview)
3769 {
3770 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3771 return false;
3772 }
3773 break;
3774
Geoff Langff5b2d52016-09-07 11:32:23 -04003775 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3776 if (clientVersion < 3 && !context->getExtensions().sRGB)
3777 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003778 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003779 return false;
3780 }
3781 break;
3782
3783 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3784 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3785 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3786 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3787 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3788 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3789 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3790 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3791 if (clientVersion < 3)
3792 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003793 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003794 return false;
3795 }
3796 break;
3797
3798 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003799 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003800 return false;
3801 }
3802
3803 // Determine if the attachment is a valid enum
3804 switch (attachment)
3805 {
3806 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04003807 case GL_DEPTH:
3808 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04003809 if (clientVersion < 3)
3810 {
Geoff Langfa125c92017-10-24 13:01:46 -04003811 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003812 return false;
3813 }
3814 break;
3815
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003816 case GL_DEPTH_STENCIL_ATTACHMENT:
3817 if (clientVersion < 3 && !context->isWebGL1())
3818 {
3819 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3820 return false;
3821 }
3822 break;
3823
Geoff Langfa125c92017-10-24 13:01:46 -04003824 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003825 case GL_DEPTH_ATTACHMENT:
3826 case GL_STENCIL_ATTACHMENT:
3827 break;
3828
3829 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003830 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3831 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003832 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3833 {
Geoff Langfa125c92017-10-24 13:01:46 -04003834 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003835 return false;
3836 }
3837 break;
3838 }
3839
3840 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3841 ASSERT(framebuffer);
3842
3843 if (framebuffer->id() == 0)
3844 {
3845 if (clientVersion < 3)
3846 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003847 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003848 return false;
3849 }
3850
3851 switch (attachment)
3852 {
3853 case GL_BACK:
3854 case GL_DEPTH:
3855 case GL_STENCIL:
3856 break;
3857
3858 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003859 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003860 return false;
3861 }
3862 }
3863 else
3864 {
3865 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3866 {
3867 // Valid attachment query
3868 }
3869 else
3870 {
3871 switch (attachment)
3872 {
3873 case GL_DEPTH_ATTACHMENT:
3874 case GL_STENCIL_ATTACHMENT:
3875 break;
3876
3877 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003878 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04003879 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003880 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003881 return false;
3882 }
3883 break;
3884
3885 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003886 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003887 return false;
3888 }
3889 }
3890 }
3891
3892 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3893 if (attachmentObject)
3894 {
3895 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3896 attachmentObject->type() == GL_TEXTURE ||
3897 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3898
3899 switch (pname)
3900 {
3901 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3902 if (attachmentObject->type() != GL_RENDERBUFFER &&
3903 attachmentObject->type() != GL_TEXTURE)
3904 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003905 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003906 return false;
3907 }
3908 break;
3909
3910 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3911 if (attachmentObject->type() != GL_TEXTURE)
3912 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003913 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003914 return false;
3915 }
3916 break;
3917
3918 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3919 if (attachmentObject->type() != GL_TEXTURE)
3920 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003921 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003922 return false;
3923 }
3924 break;
3925
3926 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3927 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3928 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003929 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003930 return false;
3931 }
3932 break;
3933
3934 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3935 if (attachmentObject->type() != GL_TEXTURE)
3936 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003937 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003938 return false;
3939 }
3940 break;
3941
3942 default:
3943 break;
3944 }
3945 }
3946 else
3947 {
3948 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3949 // is NONE, then querying any other pname will generate INVALID_ENUM.
3950
3951 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3952 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3953 // INVALID_OPERATION for all other pnames
3954
3955 switch (pname)
3956 {
3957 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3958 break;
3959
3960 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3961 if (clientVersion < 3)
3962 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003963 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003964 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003965 return false;
3966 }
3967 break;
3968
3969 default:
3970 if (clientVersion < 3)
3971 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003972 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
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 else
3977 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003978 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003979 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003980 return false;
3981 }
3982 }
3983 }
3984
Martin Radeve5285d22017-07-14 16:23:53 +03003985 if (numParams)
3986 {
3987 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
3988 {
3989 // Only when the viewport offsets are queried we can have a varying number of output
3990 // parameters.
3991 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
3992 *numParams = numViews * 2;
3993 }
3994 else
3995 {
3996 // For all other queries we can have only one output parameter.
3997 *numParams = 1;
3998 }
3999 }
4000
Geoff Langff5b2d52016-09-07 11:32:23 -04004001 return true;
4002}
4003
4004bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4005 GLenum target,
4006 GLenum attachment,
4007 GLenum pname,
4008 GLsizei bufSize,
4009 GLsizei *numParams)
4010{
4011 if (!ValidateRobustEntryPoint(context, bufSize))
4012 {
4013 return false;
4014 }
4015
Jamie Madillbe849e42017-05-02 15:49:00 -04004016 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4017 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004018 {
4019 return false;
4020 }
4021
4022 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4023 {
4024 return false;
4025 }
4026
4027 return true;
4028}
4029
Geoff Langff5b2d52016-09-07 11:32:23 -04004030bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004031 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004032 GLenum pname,
4033 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004034 GLsizei *length,
4035 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004036{
4037 if (!ValidateRobustEntryPoint(context, bufSize))
4038 {
4039 return false;
4040 }
4041
Geoff Langebebe1c2016-10-14 12:01:31 -04004042 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004043 {
4044 return false;
4045 }
4046
Geoff Langebebe1c2016-10-14 12:01:31 -04004047 if (!ValidateRobustBufferSize(context, bufSize, *length))
4048 {
4049 return false;
4050 }
4051
4052 return true;
4053}
4054
Geoff Langebebe1c2016-10-14 12:01:31 -04004055bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004056 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004057 GLenum pname,
4058 GLsizei bufSize,
4059 GLsizei *length,
4060 GLint64 *params)
4061{
4062 if (!ValidateRobustEntryPoint(context, bufSize))
4063 {
4064 return false;
4065 }
4066
4067 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4068 {
4069 return false;
4070 }
4071
4072 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004073 {
4074 return false;
4075 }
4076
4077 return true;
4078}
4079
Jamie Madillbe849e42017-05-02 15:49:00 -04004080bool ValidateGetProgramivBase(ValidationContext *context,
4081 GLuint program,
4082 GLenum pname,
4083 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004084{
4085 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004086 if (numParams)
4087 {
4088 *numParams = 1;
4089 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004090
4091 Program *programObject = GetValidProgram(context, program);
4092 if (!programObject)
4093 {
4094 return false;
4095 }
4096
4097 switch (pname)
4098 {
4099 case GL_DELETE_STATUS:
4100 case GL_LINK_STATUS:
4101 case GL_VALIDATE_STATUS:
4102 case GL_INFO_LOG_LENGTH:
4103 case GL_ATTACHED_SHADERS:
4104 case GL_ACTIVE_ATTRIBUTES:
4105 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4106 case GL_ACTIVE_UNIFORMS:
4107 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4108 break;
4109
4110 case GL_PROGRAM_BINARY_LENGTH:
4111 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4112 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004113 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4114 "requires GL_OES_get_program_binary or "
4115 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004116 return false;
4117 }
4118 break;
4119
4120 case GL_ACTIVE_UNIFORM_BLOCKS:
4121 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4122 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4123 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4124 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4125 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4126 if (context->getClientMajorVersion() < 3)
4127 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004128 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004129 return false;
4130 }
4131 break;
4132
Yunchao He61afff12017-03-14 15:34:03 +08004133 case GL_PROGRAM_SEPARABLE:
Xinghua Cao971f8502017-10-17 13:01:24 +08004134 case GL_COMPUTE_WORK_GROUP_SIZE:
jchen1058f67be2017-10-27 08:59:27 +08004135 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004136 if (context->getClientVersion() < Version(3, 1))
4137 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004138 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004139 return false;
4140 }
4141 break;
4142
Geoff Langff5b2d52016-09-07 11:32:23 -04004143 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004144 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004145 return false;
4146 }
4147
4148 return true;
4149}
4150
4151bool ValidateGetProgramivRobustANGLE(Context *context,
4152 GLuint program,
4153 GLenum pname,
4154 GLsizei bufSize,
4155 GLsizei *numParams)
4156{
4157 if (!ValidateRobustEntryPoint(context, bufSize))
4158 {
4159 return false;
4160 }
4161
Jamie Madillbe849e42017-05-02 15:49:00 -04004162 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004163 {
4164 return false;
4165 }
4166
4167 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4168 {
4169 return false;
4170 }
4171
4172 return true;
4173}
4174
Geoff Lang740d9022016-10-07 11:20:52 -04004175bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4176 GLenum target,
4177 GLenum pname,
4178 GLsizei bufSize,
4179 GLsizei *length,
4180 GLint *params)
4181{
4182 if (!ValidateRobustEntryPoint(context, bufSize))
4183 {
4184 return false;
4185 }
4186
4187 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4188 {
4189 return false;
4190 }
4191
4192 if (!ValidateRobustBufferSize(context, bufSize, *length))
4193 {
4194 return false;
4195 }
4196
4197 return true;
4198}
4199
Geoff Langd7d0ed32016-10-07 11:33:51 -04004200bool ValidateGetShaderivRobustANGLE(Context *context,
4201 GLuint shader,
4202 GLenum pname,
4203 GLsizei bufSize,
4204 GLsizei *length,
4205 GLint *params)
4206{
4207 if (!ValidateRobustEntryPoint(context, bufSize))
4208 {
4209 return false;
4210 }
4211
4212 if (!ValidateGetShaderivBase(context, shader, pname, length))
4213 {
4214 return false;
4215 }
4216
4217 if (!ValidateRobustBufferSize(context, bufSize, *length))
4218 {
4219 return false;
4220 }
4221
4222 return true;
4223}
4224
Geoff Langc1984ed2016-10-07 12:41:00 -04004225bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4226 GLenum target,
4227 GLenum pname,
4228 GLsizei bufSize,
4229 GLsizei *length,
4230 GLfloat *params)
4231{
4232 if (!ValidateRobustEntryPoint(context, bufSize))
4233 {
4234 return false;
4235 }
4236
4237 if (!ValidateGetTexParameterBase(context, target, pname, length))
4238 {
4239 return false;
4240 }
4241
4242 if (!ValidateRobustBufferSize(context, bufSize, *length))
4243 {
4244 return false;
4245 }
4246
4247 return true;
4248}
4249
Geoff Langc1984ed2016-10-07 12:41:00 -04004250bool ValidateGetTexParameterivRobustANGLE(Context *context,
4251 GLenum target,
4252 GLenum pname,
4253 GLsizei bufSize,
4254 GLsizei *length,
4255 GLint *params)
4256{
4257 if (!ValidateRobustEntryPoint(context, bufSize))
4258 {
4259 return false;
4260 }
4261
4262 if (!ValidateGetTexParameterBase(context, target, pname, length))
4263 {
4264 return false;
4265 }
4266
4267 if (!ValidateRobustBufferSize(context, bufSize, *length))
4268 {
4269 return false;
4270 }
4271
4272 return true;
4273}
4274
Geoff Langc1984ed2016-10-07 12:41:00 -04004275bool ValidateTexParameterfvRobustANGLE(Context *context,
4276 GLenum target,
4277 GLenum pname,
4278 GLsizei bufSize,
4279 const GLfloat *params)
4280{
4281 if (!ValidateRobustEntryPoint(context, bufSize))
4282 {
4283 return false;
4284 }
4285
4286 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4287}
4288
Geoff Langc1984ed2016-10-07 12:41:00 -04004289bool ValidateTexParameterivRobustANGLE(Context *context,
4290 GLenum target,
4291 GLenum pname,
4292 GLsizei bufSize,
4293 const GLint *params)
4294{
4295 if (!ValidateRobustEntryPoint(context, bufSize))
4296 {
4297 return false;
4298 }
4299
4300 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4301}
4302
Geoff Langc1984ed2016-10-07 12:41:00 -04004303bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4304 GLuint sampler,
4305 GLenum pname,
4306 GLuint bufSize,
4307 GLsizei *length,
4308 GLfloat *params)
4309{
4310 if (!ValidateRobustEntryPoint(context, bufSize))
4311 {
4312 return false;
4313 }
4314
4315 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4316 {
4317 return false;
4318 }
4319
4320 if (!ValidateRobustBufferSize(context, bufSize, *length))
4321 {
4322 return false;
4323 }
4324
4325 return true;
4326}
4327
Geoff Langc1984ed2016-10-07 12:41:00 -04004328bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4329 GLuint sampler,
4330 GLenum pname,
4331 GLuint bufSize,
4332 GLsizei *length,
4333 GLint *params)
4334{
4335 if (!ValidateRobustEntryPoint(context, bufSize))
4336 {
4337 return false;
4338 }
4339
4340 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4341 {
4342 return false;
4343 }
4344
4345 if (!ValidateRobustBufferSize(context, bufSize, *length))
4346 {
4347 return false;
4348 }
4349
4350 return true;
4351}
4352
Geoff Langc1984ed2016-10-07 12:41:00 -04004353bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4354 GLuint sampler,
4355 GLenum pname,
4356 GLsizei bufSize,
4357 const GLfloat *params)
4358{
4359 if (!ValidateRobustEntryPoint(context, bufSize))
4360 {
4361 return false;
4362 }
4363
4364 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4365}
4366
Geoff Langc1984ed2016-10-07 12:41:00 -04004367bool ValidateSamplerParameterivRobustANGLE(Context *context,
4368 GLuint sampler,
4369 GLenum pname,
4370 GLsizei bufSize,
4371 const GLint *params)
4372{
4373 if (!ValidateRobustEntryPoint(context, bufSize))
4374 {
4375 return false;
4376 }
4377
4378 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4379}
4380
Geoff Lang0b031062016-10-13 14:30:04 -04004381bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4382 GLuint index,
4383 GLenum pname,
4384 GLsizei bufSize,
4385 GLsizei *length,
4386 GLfloat *params)
4387{
4388 if (!ValidateRobustEntryPoint(context, bufSize))
4389 {
4390 return false;
4391 }
4392
4393 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4394 {
4395 return false;
4396 }
4397
4398 if (!ValidateRobustBufferSize(context, bufSize, *length))
4399 {
4400 return false;
4401 }
4402
4403 return true;
4404}
4405
Geoff Lang0b031062016-10-13 14:30:04 -04004406bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4407 GLuint index,
4408 GLenum pname,
4409 GLsizei bufSize,
4410 GLsizei *length,
4411 GLint *params)
4412{
4413 if (!ValidateRobustEntryPoint(context, bufSize))
4414 {
4415 return false;
4416 }
4417
4418 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4419 {
4420 return false;
4421 }
4422
4423 if (!ValidateRobustBufferSize(context, bufSize, *length))
4424 {
4425 return false;
4426 }
4427
4428 return true;
4429}
4430
Geoff Lang0b031062016-10-13 14:30:04 -04004431bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4432 GLuint index,
4433 GLenum pname,
4434 GLsizei bufSize,
4435 GLsizei *length,
4436 void **pointer)
4437{
4438 if (!ValidateRobustEntryPoint(context, bufSize))
4439 {
4440 return false;
4441 }
4442
4443 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4444 {
4445 return false;
4446 }
4447
4448 if (!ValidateRobustBufferSize(context, bufSize, *length))
4449 {
4450 return false;
4451 }
4452
4453 return true;
4454}
4455
Geoff Lang0b031062016-10-13 14:30:04 -04004456bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4457 GLuint index,
4458 GLenum pname,
4459 GLsizei bufSize,
4460 GLsizei *length,
4461 GLint *params)
4462{
4463 if (!ValidateRobustEntryPoint(context, bufSize))
4464 {
4465 return false;
4466 }
4467
4468 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4469 {
4470 return false;
4471 }
4472
4473 if (!ValidateRobustBufferSize(context, bufSize, *length))
4474 {
4475 return false;
4476 }
4477
4478 return true;
4479}
4480
Geoff Lang0b031062016-10-13 14:30:04 -04004481bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4482 GLuint index,
4483 GLenum pname,
4484 GLsizei bufSize,
4485 GLsizei *length,
4486 GLuint *params)
4487{
4488 if (!ValidateRobustEntryPoint(context, bufSize))
4489 {
4490 return false;
4491 }
4492
4493 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4494 {
4495 return false;
4496 }
4497
4498 if (!ValidateRobustBufferSize(context, bufSize, *length))
4499 {
4500 return false;
4501 }
4502
4503 return true;
4504}
4505
Geoff Lang6899b872016-10-14 11:30:13 -04004506bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4507 GLuint program,
4508 GLuint uniformBlockIndex,
4509 GLenum pname,
4510 GLsizei bufSize,
4511 GLsizei *length,
4512 GLint *params)
4513{
4514 if (!ValidateRobustEntryPoint(context, bufSize))
4515 {
4516 return false;
4517 }
4518
4519 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4520 {
4521 return false;
4522 }
4523
4524 if (!ValidateRobustBufferSize(context, bufSize, *length))
4525 {
4526 return false;
4527 }
4528
4529 return true;
4530}
4531
Geoff Lang0a9661f2016-10-20 10:59:20 -07004532bool ValidateGetInternalFormativRobustANGLE(Context *context,
4533 GLenum target,
4534 GLenum internalformat,
4535 GLenum pname,
4536 GLsizei bufSize,
4537 GLsizei *length,
4538 GLint *params)
4539{
4540 if (!ValidateRobustEntryPoint(context, bufSize))
4541 {
4542 return false;
4543 }
4544
4545 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4546 {
4547 return false;
4548 }
4549
4550 if (!ValidateRobustBufferSize(context, bufSize, *length))
4551 {
4552 return false;
4553 }
4554
4555 return true;
4556}
4557
Shao80957d92017-02-20 21:25:59 +08004558bool ValidateVertexFormatBase(ValidationContext *context,
4559 GLuint attribIndex,
4560 GLint size,
4561 GLenum type,
4562 GLboolean pureInteger)
4563{
4564 const Caps &caps = context->getCaps();
4565 if (attribIndex >= caps.maxVertexAttributes)
4566 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004567 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004568 return false;
4569 }
4570
4571 if (size < 1 || size > 4)
4572 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004573 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004574 return false;
Shao80957d92017-02-20 21:25:59 +08004575 }
4576
4577 switch (type)
4578 {
4579 case GL_BYTE:
4580 case GL_UNSIGNED_BYTE:
4581 case GL_SHORT:
4582 case GL_UNSIGNED_SHORT:
4583 break;
4584
4585 case GL_INT:
4586 case GL_UNSIGNED_INT:
4587 if (context->getClientMajorVersion() < 3)
4588 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004589 context->handleError(InvalidEnum()
4590 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004591 return false;
4592 }
4593 break;
4594
4595 case GL_FIXED:
4596 case GL_FLOAT:
4597 if (pureInteger)
4598 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004599 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004600 return false;
4601 }
4602 break;
4603
4604 case GL_HALF_FLOAT:
4605 if (context->getClientMajorVersion() < 3)
4606 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004607 context->handleError(InvalidEnum()
4608 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004609 return false;
4610 }
4611 if (pureInteger)
4612 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004613 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004614 return false;
4615 }
4616 break;
4617
4618 case GL_INT_2_10_10_10_REV:
4619 case GL_UNSIGNED_INT_2_10_10_10_REV:
4620 if (context->getClientMajorVersion() < 3)
4621 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004622 context->handleError(InvalidEnum()
4623 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004624 return false;
4625 }
4626 if (pureInteger)
4627 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004628 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004629 return false;
4630 }
4631 if (size != 4)
4632 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004633 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4634 "UNSIGNED_INT_2_10_10_10_REV and "
4635 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004636 return false;
4637 }
4638 break;
4639
4640 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004641 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004642 return false;
4643 }
4644
4645 return true;
4646}
4647
Geoff Lang76e65652017-03-27 14:58:02 -04004648// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4649// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4650// specified clear value and the type of a buffer that is being cleared generates an
4651// INVALID_OPERATION error instead of producing undefined results
4652bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4653 GLint drawbuffer,
4654 const GLenum *validComponentTypes,
4655 size_t validComponentTypeCount)
4656{
4657 const FramebufferAttachment *attachment =
4658 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4659 if (attachment)
4660 {
4661 GLenum componentType = attachment->getFormat().info->componentType;
4662 const GLenum *end = validComponentTypes + validComponentTypeCount;
4663 if (std::find(validComponentTypes, end, componentType) == end)
4664 {
4665 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004666 InvalidOperation()
4667 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004668 return false;
4669 }
4670 }
4671
4672 return true;
4673}
4674
Corentin Wallezb2931602017-04-11 15:58:57 -04004675bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4676 GLsizei imageSize,
4677 GLsizei dataSize)
4678{
4679 if (!ValidateRobustEntryPoint(context, dataSize))
4680 {
4681 return false;
4682 }
4683
Corentin Wallez336129f2017-10-17 15:55:40 -04004684 gl::Buffer *pixelUnpackBuffer =
4685 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004686 if (pixelUnpackBuffer == nullptr)
4687 {
4688 if (dataSize < imageSize)
4689 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004690 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004691 }
4692 }
4693 return true;
4694}
4695
Jamie Madillbe849e42017-05-02 15:49:00 -04004696bool ValidateGetBufferParameterBase(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004697 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004698 GLenum pname,
4699 bool pointerVersion,
4700 GLsizei *numParams)
4701{
4702 if (numParams)
4703 {
4704 *numParams = 0;
4705 }
4706
Corentin Wallez336129f2017-10-17 15:55:40 -04004707 if (!ValidBufferType(context, target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004708 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004709 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004710 return false;
4711 }
4712
4713 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4714 if (!buffer)
4715 {
4716 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004717 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004718 return false;
4719 }
4720
4721 const Extensions &extensions = context->getExtensions();
4722
4723 switch (pname)
4724 {
4725 case GL_BUFFER_USAGE:
4726 case GL_BUFFER_SIZE:
4727 break;
4728
4729 case GL_BUFFER_ACCESS_OES:
4730 if (!extensions.mapBuffer)
4731 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004732 context->handleError(InvalidEnum()
4733 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004734 return false;
4735 }
4736 break;
4737
4738 case GL_BUFFER_MAPPED:
4739 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4740 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4741 !extensions.mapBufferRange)
4742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004743 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4744 "GL_OES_mapbuffer or "
4745 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004746 return false;
4747 }
4748 break;
4749
4750 case GL_BUFFER_MAP_POINTER:
4751 if (!pointerVersion)
4752 {
4753 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004754 InvalidEnum()
4755 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004756 return false;
4757 }
4758 break;
4759
4760 case GL_BUFFER_ACCESS_FLAGS:
4761 case GL_BUFFER_MAP_OFFSET:
4762 case GL_BUFFER_MAP_LENGTH:
4763 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004765 context->handleError(InvalidEnum()
4766 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004767 return false;
4768 }
4769 break;
4770
4771 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004772 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004773 return false;
4774 }
4775
4776 // All buffer parameter queries return one value.
4777 if (numParams)
4778 {
4779 *numParams = 1;
4780 }
4781
4782 return true;
4783}
4784
4785bool ValidateGetRenderbufferParameterivBase(Context *context,
4786 GLenum target,
4787 GLenum pname,
4788 GLsizei *length)
4789{
4790 if (length)
4791 {
4792 *length = 0;
4793 }
4794
4795 if (target != GL_RENDERBUFFER)
4796 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004797 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004798 return false;
4799 }
4800
4801 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4802 if (renderbuffer == nullptr)
4803 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004804 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004805 return false;
4806 }
4807
4808 switch (pname)
4809 {
4810 case GL_RENDERBUFFER_WIDTH:
4811 case GL_RENDERBUFFER_HEIGHT:
4812 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4813 case GL_RENDERBUFFER_RED_SIZE:
4814 case GL_RENDERBUFFER_GREEN_SIZE:
4815 case GL_RENDERBUFFER_BLUE_SIZE:
4816 case GL_RENDERBUFFER_ALPHA_SIZE:
4817 case GL_RENDERBUFFER_DEPTH_SIZE:
4818 case GL_RENDERBUFFER_STENCIL_SIZE:
4819 break;
4820
4821 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4822 if (!context->getExtensions().framebufferMultisample)
4823 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004824 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004825 return false;
4826 }
4827 break;
4828
4829 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004830 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004831 return false;
4832 }
4833
4834 if (length)
4835 {
4836 *length = 1;
4837 }
4838 return true;
4839}
4840
4841bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4842{
4843 if (length)
4844 {
4845 *length = 0;
4846 }
4847
4848 if (GetValidShader(context, shader) == nullptr)
4849 {
4850 return false;
4851 }
4852
4853 switch (pname)
4854 {
4855 case GL_SHADER_TYPE:
4856 case GL_DELETE_STATUS:
4857 case GL_COMPILE_STATUS:
4858 case GL_INFO_LOG_LENGTH:
4859 case GL_SHADER_SOURCE_LENGTH:
4860 break;
4861
4862 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4863 if (!context->getExtensions().translatedShaderSource)
4864 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004865 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004866 return false;
4867 }
4868 break;
4869
4870 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004871 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004872 return false;
4873 }
4874
4875 if (length)
4876 {
4877 *length = 1;
4878 }
4879 return true;
4880}
4881
4882bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4883{
4884 if (length)
4885 {
4886 *length = 0;
4887 }
4888
4889 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4890 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004891 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004892 return false;
4893 }
4894
4895 if (context->getTargetTexture(target) == nullptr)
4896 {
4897 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004898 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004899 return false;
4900 }
4901
4902 switch (pname)
4903 {
4904 case GL_TEXTURE_MAG_FILTER:
4905 case GL_TEXTURE_MIN_FILTER:
4906 case GL_TEXTURE_WRAP_S:
4907 case GL_TEXTURE_WRAP_T:
4908 break;
4909
4910 case GL_TEXTURE_USAGE_ANGLE:
4911 if (!context->getExtensions().textureUsage)
4912 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004913 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004914 return false;
4915 }
4916 break;
4917
4918 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4919 if (!context->getExtensions().textureFilterAnisotropic)
4920 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004921 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004922 return false;
4923 }
4924 break;
4925
4926 case GL_TEXTURE_IMMUTABLE_FORMAT:
4927 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4928 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004929 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004930 return false;
4931 }
4932 break;
4933
4934 case GL_TEXTURE_WRAP_R:
4935 case GL_TEXTURE_IMMUTABLE_LEVELS:
4936 case GL_TEXTURE_SWIZZLE_R:
4937 case GL_TEXTURE_SWIZZLE_G:
4938 case GL_TEXTURE_SWIZZLE_B:
4939 case GL_TEXTURE_SWIZZLE_A:
4940 case GL_TEXTURE_BASE_LEVEL:
4941 case GL_TEXTURE_MAX_LEVEL:
4942 case GL_TEXTURE_MIN_LOD:
4943 case GL_TEXTURE_MAX_LOD:
4944 case GL_TEXTURE_COMPARE_MODE:
4945 case GL_TEXTURE_COMPARE_FUNC:
4946 if (context->getClientMajorVersion() < 3)
4947 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004948 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004949 return false;
4950 }
4951 break;
4952
4953 case GL_TEXTURE_SRGB_DECODE_EXT:
4954 if (!context->getExtensions().textureSRGBDecode)
4955 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004956 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004957 return false;
4958 }
4959 break;
4960
4961 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004962 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004963 return false;
4964 }
4965
4966 if (length)
4967 {
4968 *length = 1;
4969 }
4970 return true;
4971}
4972
4973bool ValidateGetVertexAttribBase(Context *context,
4974 GLuint index,
4975 GLenum pname,
4976 GLsizei *length,
4977 bool pointer,
4978 bool pureIntegerEntryPoint)
4979{
4980 if (length)
4981 {
4982 *length = 0;
4983 }
4984
4985 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
4986 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004987 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004988 return false;
4989 }
4990
4991 if (index >= context->getCaps().maxVertexAttributes)
4992 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004993 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04004994 return false;
4995 }
4996
4997 if (pointer)
4998 {
4999 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5000 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005001 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005002 return false;
5003 }
5004 }
5005 else
5006 {
5007 switch (pname)
5008 {
5009 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5010 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5011 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5012 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5013 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5014 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5015 case GL_CURRENT_VERTEX_ATTRIB:
5016 break;
5017
5018 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5019 static_assert(
5020 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5021 "ANGLE extension enums not equal to GL enums.");
5022 if (context->getClientMajorVersion() < 3 &&
5023 !context->getExtensions().instancedArrays)
5024 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005025 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5026 "requires OpenGL ES 3.0 or "
5027 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005028 return false;
5029 }
5030 break;
5031
5032 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5033 if (context->getClientMajorVersion() < 3)
5034 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005035 context->handleError(
5036 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005037 return false;
5038 }
5039 break;
5040
5041 case GL_VERTEX_ATTRIB_BINDING:
5042 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5043 if (context->getClientVersion() < ES_3_1)
5044 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005045 context->handleError(InvalidEnum()
5046 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005047 return false;
5048 }
5049 break;
5050
5051 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005052 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005053 return false;
5054 }
5055 }
5056
5057 if (length)
5058 {
5059 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5060 {
5061 *length = 4;
5062 }
5063 else
5064 {
5065 *length = 1;
5066 }
5067 }
5068
5069 return true;
5070}
5071
Jamie Madill4928b7c2017-06-20 12:57:39 -04005072bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005073 GLint x,
5074 GLint y,
5075 GLsizei width,
5076 GLsizei height,
5077 GLenum format,
5078 GLenum type,
5079 GLsizei bufSize,
5080 GLsizei *length,
5081 GLsizei *columns,
5082 GLsizei *rows,
5083 void *pixels)
5084{
5085 if (length != nullptr)
5086 {
5087 *length = 0;
5088 }
5089 if (rows != nullptr)
5090 {
5091 *rows = 0;
5092 }
5093 if (columns != nullptr)
5094 {
5095 *columns = 0;
5096 }
5097
5098 if (width < 0 || height < 0)
5099 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005100 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005101 return false;
5102 }
5103
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005104 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005105
5106 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5107 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005108 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005109 return false;
5110 }
5111
5112 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5113 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005114 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005115 return false;
5116 }
5117
5118 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5119 ASSERT(framebuffer);
5120
5121 if (framebuffer->getReadBufferState() == GL_NONE)
5122 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005123 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005124 return false;
5125 }
5126
5127 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5128 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5129 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5130 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5131 // situation is an application error that would lead to a crash in ANGLE.
5132 if (readBuffer == nullptr)
5133 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005134 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005135 return false;
5136 }
5137
Martin Radev28031682017-07-28 14:47:56 +03005138 // ANGLE_multiview, Revision 1:
5139 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5140 // current read framebuffer is not NONE.
5141 if (readBuffer->getMultiviewLayout() != GL_NONE)
5142 {
5143 context->handleError(InvalidFramebufferOperation()
5144 << "Attempting to read from a multi-view framebuffer.");
5145 return false;
5146 }
5147
Geoff Lang280ba992017-04-18 16:30:58 -04005148 if (context->getExtensions().webglCompatibility)
5149 {
5150 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5151 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5152 // and type before validating the combination of format and type. However, the
5153 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5154 // verifies that GL_INVALID_OPERATION is generated.
5155 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5156 // dEQP/WebGL.
5157 if (!ValidReadPixelsFormatEnum(context, format))
5158 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005159 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005160 return false;
5161 }
5162
5163 if (!ValidReadPixelsTypeEnum(context, type))
5164 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005165 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005166 return false;
5167 }
5168 }
5169
Jamie Madill4928b7c2017-06-20 12:57:39 -04005170 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5171 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005172 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5173
5174 bool validFormatTypeCombination =
5175 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5176
5177 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5178 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005179 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005180 return false;
5181 }
5182
5183 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005184 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005185 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5186 {
5187 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005188 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005189 return false;
5190 }
5191
5192 // .. the data would be packed to the buffer object such that the memory writes required
5193 // would exceed the data store size.
5194 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5195 const gl::Extents size(width, height, 1);
5196 const auto &pack = context->getGLState().getPackState();
5197
5198 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5199 if (endByteOrErr.isError())
5200 {
5201 context->handleError(endByteOrErr.getError());
5202 return false;
5203 }
5204
5205 size_t endByte = endByteOrErr.getResult();
5206 if (bufSize >= 0)
5207 {
5208 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5209 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005210 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005211 return false;
5212 }
5213 }
5214
5215 if (pixelPackBuffer != nullptr)
5216 {
5217 CheckedNumeric<size_t> checkedEndByte(endByte);
5218 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5219 checkedEndByte += checkedOffset;
5220
5221 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5222 {
5223 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005224 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005225 return false;
5226 }
5227 }
5228
5229 if (pixelPackBuffer == nullptr && length != nullptr)
5230 {
5231 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5232 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005233 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005234 return false;
5235 }
5236
5237 *length = static_cast<GLsizei>(endByte);
5238 }
5239
5240 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5241 angle::CheckedNumeric<int> clippedExtent(length);
5242 if (start < 0)
5243 {
5244 // "subtract" the area that is less than 0
5245 clippedExtent += start;
5246 }
5247
5248 const int readExtent = start + length;
5249 if (readExtent > bufferSize)
5250 {
5251 // Subtract the region to the right of the read buffer
5252 clippedExtent -= (readExtent - bufferSize);
5253 }
5254
5255 if (!clippedExtent.IsValid())
5256 {
5257 return 0;
5258 }
5259
5260 return std::max(clippedExtent.ValueOrDie(), 0);
5261 };
5262
5263 if (columns != nullptr)
5264 {
5265 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5266 }
5267
5268 if (rows != nullptr)
5269 {
5270 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5271 }
5272
5273 return true;
5274}
5275
5276template <typename ParamType>
5277bool ValidateTexParameterBase(Context *context,
5278 GLenum target,
5279 GLenum pname,
5280 GLsizei bufSize,
5281 const ParamType *params)
5282{
5283 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5284 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005285 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005286 return false;
5287 }
5288
5289 if (context->getTargetTexture(target) == nullptr)
5290 {
5291 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005292 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005293 return false;
5294 }
5295
5296 const GLsizei minBufSize = 1;
5297 if (bufSize >= 0 && bufSize < minBufSize)
5298 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005299 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005300 return false;
5301 }
5302
5303 switch (pname)
5304 {
5305 case GL_TEXTURE_WRAP_R:
5306 case GL_TEXTURE_SWIZZLE_R:
5307 case GL_TEXTURE_SWIZZLE_G:
5308 case GL_TEXTURE_SWIZZLE_B:
5309 case GL_TEXTURE_SWIZZLE_A:
5310 case GL_TEXTURE_BASE_LEVEL:
5311 case GL_TEXTURE_MAX_LEVEL:
5312 case GL_TEXTURE_COMPARE_MODE:
5313 case GL_TEXTURE_COMPARE_FUNC:
5314 case GL_TEXTURE_MIN_LOD:
5315 case GL_TEXTURE_MAX_LOD:
5316 if (context->getClientMajorVersion() < 3)
5317 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005318 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005319 return false;
5320 }
5321 if (target == GL_TEXTURE_EXTERNAL_OES &&
5322 !context->getExtensions().eglImageExternalEssl3)
5323 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005324 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5325 "available without "
5326 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005327 return false;
5328 }
5329 break;
5330
5331 default:
5332 break;
5333 }
5334
JiangYizhou4cff8d62017-07-06 14:54:09 +08005335 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5336 {
5337 switch (pname)
5338 {
5339 case GL_TEXTURE_MIN_FILTER:
5340 case GL_TEXTURE_MAG_FILTER:
5341 case GL_TEXTURE_WRAP_S:
5342 case GL_TEXTURE_WRAP_T:
5343 case GL_TEXTURE_WRAP_R:
5344 case GL_TEXTURE_MIN_LOD:
5345 case GL_TEXTURE_MAX_LOD:
5346 case GL_TEXTURE_COMPARE_MODE:
5347 case GL_TEXTURE_COMPARE_FUNC:
5348 context->handleError(InvalidEnum()
5349 << "Invalid parameter for 2D multisampled textures.");
5350 return false;
5351 }
5352 }
5353
Jamie Madillbe849e42017-05-02 15:49:00 -04005354 switch (pname)
5355 {
5356 case GL_TEXTURE_WRAP_S:
5357 case GL_TEXTURE_WRAP_T:
5358 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005359 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005360 bool restrictedWrapModes =
5361 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5362 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5363 {
5364 return false;
5365 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005366 }
5367 break;
5368
5369 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005370 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005371 bool restrictedMinFilter =
5372 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5373 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5374 {
5375 return false;
5376 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005377 }
5378 break;
5379
5380 case GL_TEXTURE_MAG_FILTER:
5381 if (!ValidateTextureMagFilterValue(context, params))
5382 {
5383 return false;
5384 }
5385 break;
5386
5387 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005388 if (!context->getExtensions().textureUsage)
5389 {
5390 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5391 return false;
5392 }
5393
Jamie Madillbe849e42017-05-02 15:49:00 -04005394 switch (ConvertToGLenum(params[0]))
5395 {
5396 case GL_NONE:
5397 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5398 break;
5399
5400 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005401 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005402 return false;
5403 }
5404 break;
5405
5406 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5407 if (!context->getExtensions().textureFilterAnisotropic)
5408 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005409 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005410 return false;
5411 }
5412
5413 // we assume the parameter passed to this validation method is truncated, not rounded
5414 if (params[0] < 1)
5415 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005416 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005417 return false;
5418 }
5419 break;
5420
5421 case GL_TEXTURE_MIN_LOD:
5422 case GL_TEXTURE_MAX_LOD:
5423 // any value is permissible
5424 break;
5425
5426 case GL_TEXTURE_COMPARE_MODE:
5427 if (!ValidateTextureCompareModeValue(context, params))
5428 {
5429 return false;
5430 }
5431 break;
5432
5433 case GL_TEXTURE_COMPARE_FUNC:
5434 if (!ValidateTextureCompareFuncValue(context, params))
5435 {
5436 return false;
5437 }
5438 break;
5439
5440 case GL_TEXTURE_SWIZZLE_R:
5441 case GL_TEXTURE_SWIZZLE_G:
5442 case GL_TEXTURE_SWIZZLE_B:
5443 case GL_TEXTURE_SWIZZLE_A:
5444 switch (ConvertToGLenum(params[0]))
5445 {
5446 case GL_RED:
5447 case GL_GREEN:
5448 case GL_BLUE:
5449 case GL_ALPHA:
5450 case GL_ZERO:
5451 case GL_ONE:
5452 break;
5453
5454 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005455 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005456 return false;
5457 }
5458 break;
5459
5460 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005461 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005463 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005464 return false;
5465 }
5466 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5467 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005468 context->handleError(InvalidOperation()
5469 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005470 return false;
5471 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005472 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5473 {
5474 context->handleError(InvalidOperation()
5475 << "Base level must be 0 for multisampled textures.");
5476 return false;
5477 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005478 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5479 {
5480 context->handleError(InvalidOperation()
5481 << "Base level must be 0 for rectangle textures.");
5482 return false;
5483 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005484 break;
5485
5486 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005487 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005488 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005489 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005490 return false;
5491 }
5492 break;
5493
5494 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5495 if (context->getClientVersion() < Version(3, 1))
5496 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005497 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005498 return false;
5499 }
5500 switch (ConvertToGLenum(params[0]))
5501 {
5502 case GL_DEPTH_COMPONENT:
5503 case GL_STENCIL_INDEX:
5504 break;
5505
5506 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005507 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005508 return false;
5509 }
5510 break;
5511
5512 case GL_TEXTURE_SRGB_DECODE_EXT:
5513 if (!ValidateTextureSRGBDecodeValue(context, params))
5514 {
5515 return false;
5516 }
5517 break;
5518
5519 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005520 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005521 return false;
5522 }
5523
5524 return true;
5525}
5526
5527template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5528template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5529
Jamie Madill12e957f2017-08-26 21:42:26 -04005530bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5531{
5532 if (index >= MAX_VERTEX_ATTRIBS)
5533 {
5534 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5535 return false;
5536 }
5537
5538 return true;
5539}
5540
5541bool ValidateGetActiveUniformBlockivBase(Context *context,
5542 GLuint program,
5543 GLuint uniformBlockIndex,
5544 GLenum pname,
5545 GLsizei *length)
5546{
5547 if (length)
5548 {
5549 *length = 0;
5550 }
5551
5552 if (context->getClientMajorVersion() < 3)
5553 {
5554 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5555 return false;
5556 }
5557
5558 Program *programObject = GetValidProgram(context, program);
5559 if (!programObject)
5560 {
5561 return false;
5562 }
5563
5564 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5565 {
5566 context->handleError(InvalidValue()
5567 << "uniformBlockIndex exceeds active uniform block count.");
5568 return false;
5569 }
5570
5571 switch (pname)
5572 {
5573 case GL_UNIFORM_BLOCK_BINDING:
5574 case GL_UNIFORM_BLOCK_DATA_SIZE:
5575 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5576 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5577 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5578 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5579 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5580 break;
5581
5582 default:
5583 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5584 return false;
5585 }
5586
5587 if (length)
5588 {
5589 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5590 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005591 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005592 programObject->getUniformBlockByIndex(uniformBlockIndex);
5593 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5594 }
5595 else
5596 {
5597 *length = 1;
5598 }
5599 }
5600
5601 return true;
5602}
5603
Jamie Madill9696d072017-08-26 23:19:57 -04005604template <typename ParamType>
5605bool ValidateSamplerParameterBase(Context *context,
5606 GLuint sampler,
5607 GLenum pname,
5608 GLsizei bufSize,
5609 ParamType *params)
5610{
5611 if (context->getClientMajorVersion() < 3)
5612 {
5613 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5614 return false;
5615 }
5616
5617 if (!context->isSampler(sampler))
5618 {
5619 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5620 return false;
5621 }
5622
5623 const GLsizei minBufSize = 1;
5624 if (bufSize >= 0 && bufSize < minBufSize)
5625 {
5626 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5627 return false;
5628 }
5629
5630 switch (pname)
5631 {
5632 case GL_TEXTURE_WRAP_S:
5633 case GL_TEXTURE_WRAP_T:
5634 case GL_TEXTURE_WRAP_R:
5635 if (!ValidateTextureWrapModeValue(context, params, false))
5636 {
5637 return false;
5638 }
5639 break;
5640
5641 case GL_TEXTURE_MIN_FILTER:
5642 if (!ValidateTextureMinFilterValue(context, params, false))
5643 {
5644 return false;
5645 }
5646 break;
5647
5648 case GL_TEXTURE_MAG_FILTER:
5649 if (!ValidateTextureMagFilterValue(context, params))
5650 {
5651 return false;
5652 }
5653 break;
5654
5655 case GL_TEXTURE_MIN_LOD:
5656 case GL_TEXTURE_MAX_LOD:
5657 // any value is permissible
5658 break;
5659
5660 case GL_TEXTURE_COMPARE_MODE:
5661 if (!ValidateTextureCompareModeValue(context, params))
5662 {
5663 return false;
5664 }
5665 break;
5666
5667 case GL_TEXTURE_COMPARE_FUNC:
5668 if (!ValidateTextureCompareFuncValue(context, params))
5669 {
5670 return false;
5671 }
5672 break;
5673
5674 case GL_TEXTURE_SRGB_DECODE_EXT:
5675 if (!ValidateTextureSRGBDecodeValue(context, params))
5676 {
5677 return false;
5678 }
5679 break;
5680
5681 default:
5682 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5683 return false;
5684 }
5685
5686 return true;
5687}
5688
5689template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5690template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5691
5692bool ValidateGetSamplerParameterBase(Context *context,
5693 GLuint sampler,
5694 GLenum pname,
5695 GLsizei *length)
5696{
5697 if (length)
5698 {
5699 *length = 0;
5700 }
5701
5702 if (context->getClientMajorVersion() < 3)
5703 {
5704 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5705 return false;
5706 }
5707
5708 if (!context->isSampler(sampler))
5709 {
5710 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5711 return false;
5712 }
5713
5714 switch (pname)
5715 {
5716 case GL_TEXTURE_WRAP_S:
5717 case GL_TEXTURE_WRAP_T:
5718 case GL_TEXTURE_WRAP_R:
5719 case GL_TEXTURE_MIN_FILTER:
5720 case GL_TEXTURE_MAG_FILTER:
5721 case GL_TEXTURE_MIN_LOD:
5722 case GL_TEXTURE_MAX_LOD:
5723 case GL_TEXTURE_COMPARE_MODE:
5724 case GL_TEXTURE_COMPARE_FUNC:
5725 break;
5726
5727 case GL_TEXTURE_SRGB_DECODE_EXT:
5728 if (!context->getExtensions().textureSRGBDecode)
5729 {
5730 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5731 return false;
5732 }
5733 break;
5734
5735 default:
5736 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5737 return false;
5738 }
5739
5740 if (length)
5741 {
5742 *length = 1;
5743 }
5744 return true;
5745}
5746
5747bool ValidateGetInternalFormativBase(Context *context,
5748 GLenum target,
5749 GLenum internalformat,
5750 GLenum pname,
5751 GLsizei bufSize,
5752 GLsizei *numParams)
5753{
5754 if (numParams)
5755 {
5756 *numParams = 0;
5757 }
5758
5759 if (context->getClientMajorVersion() < 3)
5760 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005761 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005762 return false;
5763 }
5764
5765 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5766 if (!formatCaps.renderable)
5767 {
5768 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5769 return false;
5770 }
5771
5772 switch (target)
5773 {
5774 case GL_RENDERBUFFER:
5775 break;
5776
5777 case GL_TEXTURE_2D_MULTISAMPLE:
5778 if (context->getClientVersion() < ES_3_1)
5779 {
5780 context->handleError(InvalidOperation()
5781 << "Texture target requires at least OpenGL ES 3.1.");
5782 return false;
5783 }
5784 break;
5785
5786 default:
5787 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5788 return false;
5789 }
5790
5791 if (bufSize < 0)
5792 {
5793 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5794 return false;
5795 }
5796
5797 GLsizei maxWriteParams = 0;
5798 switch (pname)
5799 {
5800 case GL_NUM_SAMPLE_COUNTS:
5801 maxWriteParams = 1;
5802 break;
5803
5804 case GL_SAMPLES:
5805 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5806 break;
5807
5808 default:
5809 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5810 return false;
5811 }
5812
5813 if (numParams)
5814 {
5815 // glGetInternalFormativ will not overflow bufSize
5816 *numParams = std::min(bufSize, maxWriteParams);
5817 }
5818
5819 return true;
5820}
5821
Jamie Madillc29968b2016-01-20 11:17:23 -05005822} // namespace gl