blob: a41bfa75e847677e80e1242685b5b779c64e0acc [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"
10#include "libANGLE/validationES2.h"
11#include "libANGLE/validationES3.h"
12#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040013#include "libANGLE/Display.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Texture.h"
15#include "libANGLE/Framebuffer.h"
16#include "libANGLE/FramebufferAttachment.h"
17#include "libANGLE/formatutils.h"
Geoff Langa8406172015-07-21 16:53:39 -040018#include "libANGLE/Image.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050019#include "libANGLE/Query.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050020#include "libANGLE/Program.h"
21#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050022#include "libANGLE/TransformFeedback.h"
23#include "libANGLE/VertexArray.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040024
25#include "common/mathutil.h"
26#include "common/utilities.h"
27
28namespace gl
29{
Jamie Madille79b1e12015-11-04 16:36:37 -050030const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum element index.";
31
Jamie Madill1ca74672015-07-21 15:14:11 -040032namespace
33{
Jamie Madillf25855c2015-11-03 11:06:18 -050034bool ValidateDrawAttribs(ValidationContext *context, GLint primcount, GLint maxVertex)
Jamie Madill1ca74672015-07-21 15:14:11 -040035{
36 const gl::State &state = context->getState();
37 const gl::Program *program = state.getProgram();
38
39 const VertexArray *vao = state.getVertexArray();
40 const auto &vertexAttribs = vao->getVertexAttributes();
Jamie Madill1ca74672015-07-21 15:14:11 -040041 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
42 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
43 {
44 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Jamie Madill63805b42015-08-25 13:17:39 -040045 if (program->isAttribLocationActive(attributeIndex) && attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040046 {
47 gl::Buffer *buffer = attrib.buffer.get();
48
49 if (buffer)
50 {
51 GLint64 attribStride = static_cast<GLint64>(ComputeVertexAttributeStride(attrib));
52 GLint64 maxVertexElement = 0;
53
54 if (attrib.divisor > 0)
55 {
56 maxVertexElement =
57 static_cast<GLint64>(primcount) / static_cast<GLint64>(attrib.divisor);
58 }
59 else
60 {
61 maxVertexElement = static_cast<GLint64>(maxVertex);
62 }
63
64 // If we're drawing zero vertices, we have enough data.
65 if (maxVertexElement > 0)
66 {
67 // Note: Last vertex element does not take the full stride!
68 GLint64 attribSize =
69 static_cast<GLint64>(ComputeVertexAttributeTypeSize(attrib));
70 GLint64 attribDataSize = (maxVertexElement - 1) * attribStride + attribSize;
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040071 GLint64 attribOffset = static_cast<GLint64>(attrib.offset);
Jamie Madill1ca74672015-07-21 15:14:11 -040072
73 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
74 // We can return INVALID_OPERATION if our vertex attribute does not have
75 // enough backing data.
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040076 if (attribDataSize + attribOffset > buffer->getSize())
Jamie Madill1ca74672015-07-21 15:14:11 -040077 {
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040078 context->recordError(
79 Error(GL_INVALID_OPERATION,
80 "Vertex buffer is not big enough for the draw call"));
Jamie Madill1ca74672015-07-21 15:14:11 -040081 return false;
82 }
83 }
84 }
85 else if (attrib.pointer == NULL)
86 {
87 // This is an application error that would normally result in a crash,
88 // but we catch it and return an error
89 context->recordError(Error(
90 GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer."));
91 return false;
92 }
93 }
94 }
95
96 return true;
97}
98
99} // anonymous namespace
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400100
Geoff Lang0550d032014-01-30 11:29:07 -0500101bool ValidCap(const Context *context, GLenum cap)
102{
103 switch (cap)
104 {
105 case GL_CULL_FACE:
106 case GL_POLYGON_OFFSET_FILL:
107 case GL_SAMPLE_ALPHA_TO_COVERAGE:
108 case GL_SAMPLE_COVERAGE:
109 case GL_SCISSOR_TEST:
110 case GL_STENCIL_TEST:
111 case GL_DEPTH_TEST:
112 case GL_BLEND:
113 case GL_DITHER:
114 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -0500115
Geoff Lang0550d032014-01-30 11:29:07 -0500116 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
117 case GL_RASTERIZER_DISCARD:
118 return (context->getClientVersion() >= 3);
Geoff Lang70d0f492015-12-10 17:45:46 -0500119
120 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
121 case GL_DEBUG_OUTPUT:
122 return context->getExtensions().debug;
123
Geoff Lang0550d032014-01-30 11:29:07 -0500124 default:
125 return false;
126 }
127}
128
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500129bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400130{
Jamie Madilld7460c72014-01-21 16:38:14 -0500131 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400132 {
Jamie Madilld7460c72014-01-21 16:38:14 -0500133 case GL_TEXTURE_2D:
134 case GL_TEXTURE_CUBE_MAP:
135 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400136
Jamie Madilld7460c72014-01-21 16:38:14 -0500137 case GL_TEXTURE_3D:
138 case GL_TEXTURE_2D_ARRAY:
139 return (context->getClientVersion() >= 3);
140
141 default:
142 return false;
143 }
Jamie Madill35d15012013-10-07 10:46:37 -0400144}
145
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500146bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
147{
148 switch (target)
149 {
150 case GL_TEXTURE_2D:
151 case GL_TEXTURE_CUBE_MAP:
152 return true;
153
154 default:
155 return false;
156 }
157}
158
159bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
160{
161 switch (target)
162 {
163 case GL_TEXTURE_3D:
164 case GL_TEXTURE_2D_ARRAY:
165 return (context->getClientVersion() >= 3);
166
167 default:
168 return false;
169 }
170}
171
Ian Ewellbda75592016-04-18 17:25:54 -0400172// Most texture GL calls are not compatible with external textures, so we have a separate validation
173// function for use in the GL calls that do
174bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
175{
176 return (target == GL_TEXTURE_EXTERNAL_OES) &&
177 (context->getExtensions().eglImageExternal ||
178 context->getExtensions().eglStreamConsumerExternal);
179}
180
Shannon Woods4dfed832014-03-17 20:03:39 -0400181// This function differs from ValidTextureTarget in that the target must be
182// usable as the destination of a 2D operation-- so a cube face is valid, but
183// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400184// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500185bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400186{
187 switch (target)
188 {
189 case GL_TEXTURE_2D:
190 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
191 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
192 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
193 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
194 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
195 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
196 return true;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500197 default:
198 return false;
199 }
200}
201
202bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
203{
204 switch (target)
205 {
Shannon Woods4dfed832014-03-17 20:03:39 -0400206 case GL_TEXTURE_3D:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500207 case GL_TEXTURE_2D_ARRAY:
208 return true;
Shannon Woods4dfed832014-03-17 20:03:39 -0400209 default:
210 return false;
211 }
212}
213
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500214bool ValidFramebufferTarget(GLenum target)
215{
Geoff Langd4475812015-03-18 10:53:05 -0400216 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
217 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500218
219 switch (target)
220 {
221 case GL_FRAMEBUFFER: return true;
222 case GL_READ_FRAMEBUFFER: return true;
223 case GL_DRAW_FRAMEBUFFER: return true;
224 default: return false;
225 }
226}
227
Jamie Madill8c96d582014-03-05 15:01:23 -0500228bool ValidBufferTarget(const Context *context, GLenum target)
229{
230 switch (target)
231 {
232 case GL_ARRAY_BUFFER:
233 case GL_ELEMENT_ARRAY_BUFFER:
234 return true;
235
Jamie Madill8c96d582014-03-05 15:01:23 -0500236 case GL_PIXEL_PACK_BUFFER:
237 case GL_PIXEL_UNPACK_BUFFER:
Geoff Lange4de3072015-09-02 11:01:32 -0400238 return (context->getExtensions().pixelBufferObject || context->getClientVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -0400239
Shannon Woodsb3801742014-03-27 14:59:19 -0400240 case GL_COPY_READ_BUFFER:
241 case GL_COPY_WRITE_BUFFER:
Jamie Madill8c96d582014-03-05 15:01:23 -0500242 case GL_TRANSFORM_FEEDBACK_BUFFER:
243 case GL_UNIFORM_BUFFER:
244 return (context->getClientVersion() >= 3);
245
246 default:
247 return false;
248 }
249}
250
Jamie Madill70656a62014-03-05 15:01:26 -0500251bool ValidBufferParameter(const Context *context, GLenum pname)
252{
Geoff Langcc6f55d2015-03-20 13:01:02 -0400253 const Extensions &extensions = context->getExtensions();
254
Jamie Madill70656a62014-03-05 15:01:26 -0500255 switch (pname)
256 {
257 case GL_BUFFER_USAGE:
258 case GL_BUFFER_SIZE:
259 return true;
260
Geoff Langcc6f55d2015-03-20 13:01:02 -0400261 case GL_BUFFER_ACCESS_OES:
262 return extensions.mapBuffer;
263
264 case GL_BUFFER_MAPPED:
265 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
266 return (context->getClientVersion() >= 3) || extensions.mapBuffer || extensions.mapBufferRange;
267
Jamie Madill70656a62014-03-05 15:01:26 -0500268 // GL_BUFFER_MAP_POINTER is a special case, and may only be
269 // queried with GetBufferPointerv
270 case GL_BUFFER_ACCESS_FLAGS:
Jamie Madill70656a62014-03-05 15:01:26 -0500271 case GL_BUFFER_MAP_OFFSET:
272 case GL_BUFFER_MAP_LENGTH:
Geoff Langcc6f55d2015-03-20 13:01:02 -0400273 return (context->getClientVersion() >= 3) || extensions.mapBufferRange;
Jamie Madill70656a62014-03-05 15:01:26 -0500274
275 default:
276 return false;
277 }
278}
279
Jamie Madillc29968b2016-01-20 11:17:23 -0500280bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400281{
Jamie Madillc29968b2016-01-20 11:17:23 -0500282 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400283 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400284 switch (target)
285 {
Jamie Madillc29968b2016-01-20 11:17:23 -0500286 case GL_TEXTURE_2D:
287 maxDimension = caps.max2DTextureSize;
288 break;
Geoff Langce635692013-09-24 13:56:32 -0400289 case GL_TEXTURE_CUBE_MAP:
290 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
291 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
292 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
293 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
294 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
Jamie Madillc29968b2016-01-20 11:17:23 -0500295 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
296 maxDimension = caps.maxCubeMapTextureSize;
297 break;
298 case GL_TEXTURE_3D:
299 maxDimension = caps.max3DTextureSize;
300 break;
301 case GL_TEXTURE_2D_ARRAY:
302 maxDimension = caps.max2DTextureSize;
303 break;
Geoff Langce635692013-09-24 13:56:32 -0400304 default: UNREACHABLE();
305 }
306
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700307 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -0400308}
309
Austin Kinross08528e12015-10-07 16:24:40 -0700310bool ValidImageSizeParameters(const Context *context,
311 GLenum target,
312 GLint level,
313 GLsizei width,
314 GLsizei height,
315 GLsizei depth,
316 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400317{
318 if (level < 0 || width < 0 || height < 0 || depth < 0)
319 {
320 return false;
321 }
322
Austin Kinross08528e12015-10-07 16:24:40 -0700323 // TexSubImage parameters can be NPOT without textureNPOT extension,
324 // as long as the destination texture is POT.
325 if (!isSubImage && !context->getExtensions().textureNPOT &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400326 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400327 {
328 return false;
329 }
330
331 if (!ValidMipLevel(context, target, level))
332 {
333 return false;
334 }
335
336 return true;
337}
338
Geoff Lang0d8b7242015-09-09 14:56:53 -0400339bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
340{
341 // List of compressed format that require that the texture size is smaller than or a multiple of
342 // the compressed block size.
343 switch (internalFormat)
344 {
345 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
346 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
347 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
348 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -0800349 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -0400350 return true;
351
352 default:
353 return false;
354 }
355}
356
Jamie Madillc29968b2016-01-20 11:17:23 -0500357bool ValidCompressedImageSize(const ValidationContext *context,
358 GLenum internalFormat,
359 GLsizei width,
360 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400361{
Geoff Lang5d601382014-07-22 15:14:06 -0400362 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
363 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400364 {
365 return false;
366 }
367
Geoff Lang0d8b7242015-09-09 14:56:53 -0400368 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400369 {
370 return false;
371 }
372
Geoff Lang0d8b7242015-09-09 14:56:53 -0400373 if (CompressedTextureFormatRequiresExactSize(internalFormat))
374 {
375 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
376 width % formatInfo.compressedBlockWidth != 0) ||
377 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
378 height % formatInfo.compressedBlockHeight != 0))
379 {
380 return false;
381 }
382 }
383
Geoff Langd4f180b2013-09-24 13:57:44 -0400384 return true;
385}
386
Geoff Lang37dde692014-01-31 16:34:54 -0500387bool ValidQueryType(const Context *context, GLenum queryType)
388{
Geoff Langd4475812015-03-18 10:53:05 -0400389 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT, "GL extension enums not equal.");
390 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -0500391
392 switch (queryType)
393 {
394 case GL_ANY_SAMPLES_PASSED:
395 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
396 return true;
397 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
398 return (context->getClientVersion() >= 3);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500399 case GL_TIME_ELAPSED_EXT:
400 return context->getExtensions().disjointTimerQuery;
Geoff Lang37dde692014-01-31 16:34:54 -0500401 default:
402 return false;
403 }
404}
405
Dian Xiang769769a2015-09-09 15:20:08 -0700406Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -0500407{
408 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the
409 // error INVALID_VALUE if the provided name is not the name of either a shader or program object and
410 // INVALID_OPERATION if the provided name identifies an object that is not the expected type."
411
Dian Xiang769769a2015-09-09 15:20:08 -0700412 Program *validProgram = context->getProgram(id);
413
414 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -0500415 {
Dian Xiang769769a2015-09-09 15:20:08 -0700416 if (context->getShader(id))
417 {
418 context->recordError(
419 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
420 }
421 else
422 {
423 context->recordError(Error(GL_INVALID_VALUE, "Program name is not valid"));
424 }
Geoff Lang48dcae72014-02-05 16:28:24 -0500425 }
Dian Xiang769769a2015-09-09 15:20:08 -0700426
427 return validProgram;
428}
429
430Shader *GetValidShader(Context *context, GLuint id)
431{
432 // See ValidProgram for spec details.
433
434 Shader *validShader = context->getShader(id);
435
436 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -0500437 {
Dian Xiang769769a2015-09-09 15:20:08 -0700438 if (context->getProgram(id))
439 {
440 context->recordError(
441 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
442 }
443 else
444 {
445 context->recordError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
446 }
Geoff Lang48dcae72014-02-05 16:28:24 -0500447 }
Dian Xiang769769a2015-09-09 15:20:08 -0700448
449 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -0500450}
451
Geoff Langb1196682014-07-23 13:47:29 -0400452bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -0400453{
454 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
455 {
456 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
457
Geoff Langaae65a42014-05-26 12:43:44 -0400458 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -0400459 {
Geoff Langb1196682014-07-23 13:47:29 -0400460 context->recordError(Error(GL_INVALID_VALUE));
461 return false;
Jamie Madillb4472272014-07-03 10:38:55 -0400462 }
463 }
464 else
465 {
466 switch (attachment)
467 {
468 case GL_DEPTH_ATTACHMENT:
469 case GL_STENCIL_ATTACHMENT:
470 break;
471
472 case GL_DEPTH_STENCIL_ATTACHMENT:
473 if (context->getClientVersion() < 3)
474 {
Geoff Langb1196682014-07-23 13:47:29 -0400475 context->recordError(Error(GL_INVALID_ENUM));
476 return false;
Jamie Madillb4472272014-07-03 10:38:55 -0400477 }
478 break;
479
480 default:
Geoff Langb1196682014-07-23 13:47:29 -0400481 context->recordError(Error(GL_INVALID_ENUM));
482 return false;
Jamie Madillb4472272014-07-03 10:38:55 -0400483 }
484 }
485
486 return true;
487}
488
Corentin Walleze0902642014-11-04 12:32:15 -0800489bool ValidateRenderbufferStorageParametersBase(gl::Context *context, GLenum target, GLsizei samples,
490 GLenum internalformat, GLsizei width, GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400491{
492 switch (target)
493 {
494 case GL_RENDERBUFFER:
495 break;
496 default:
Geoff Langb1196682014-07-23 13:47:29 -0400497 context->recordError(Error(GL_INVALID_ENUM));
498 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400499 }
500
501 if (width < 0 || height < 0 || samples < 0)
502 {
Geoff Langb1196682014-07-23 13:47:29 -0400503 context->recordError(Error(GL_INVALID_VALUE));
504 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400505 }
506
Geoff Langd87878e2014-09-19 15:42:59 -0400507 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
508 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400509 {
Geoff Langb1196682014-07-23 13:47:29 -0400510 context->recordError(Error(GL_INVALID_ENUM));
511 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400512 }
513
514 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
515 // 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 -0800516 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -0400517 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400518 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400519 {
Geoff Langb1196682014-07-23 13:47:29 -0400520 context->recordError(Error(GL_INVALID_ENUM));
521 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400522 }
523
Geoff Langaae65a42014-05-26 12:43:44 -0400524 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400525 {
Geoff Langb1196682014-07-23 13:47:29 -0400526 context->recordError(Error(GL_INVALID_VALUE));
527 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400528 }
529
Shannon Woods53a94a82014-06-24 15:20:36 -0400530 GLuint handle = context->getState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400531 if (handle == 0)
532 {
Geoff Langb1196682014-07-23 13:47:29 -0400533 context->recordError(Error(GL_INVALID_OPERATION));
534 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400535 }
536
537 return true;
538}
539
Corentin Walleze0902642014-11-04 12:32:15 -0800540bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum target, GLsizei samples,
541 GLenum internalformat, GLsizei width, GLsizei height)
542{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -0800543 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -0800544
545 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -0400546 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -0800547 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -0400548 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -0800549 {
550 context->recordError(Error(GL_INVALID_VALUE));
551 return false;
552 }
553
554 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
555 // the specified storage. This is different than ES 3.0 in which a sample number higher
556 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -0800557 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
558 if (context->getClientVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -0800559 {
Geoff Langa4903b72015-03-02 16:02:48 -0800560 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
561 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
562 {
563 context->recordError(Error(GL_OUT_OF_MEMORY));
564 return false;
565 }
Corentin Walleze0902642014-11-04 12:32:15 -0800566 }
567
568 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height);
569}
570
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500571bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
572 GLenum renderbuffertarget, GLuint renderbuffer)
573{
Shannon Woods1da3cf62014-06-27 15:32:23 -0400574 if (!ValidFramebufferTarget(target))
575 {
Geoff Langb1196682014-07-23 13:47:29 -0400576 context->recordError(Error(GL_INVALID_ENUM));
577 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -0400578 }
579
Shannon Woods53a94a82014-06-24 15:20:36 -0400580 gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500581
Jamie Madill84115c92015-04-23 15:00:07 -0400582 ASSERT(framebuffer);
583 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500584 {
Jamie Madill84115c92015-04-23 15:00:07 -0400585 context->recordError(Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -0400586 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500587 }
588
Jamie Madillb4472272014-07-03 10:38:55 -0400589 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500590 {
Jamie Madillb4472272014-07-03 10:38:55 -0400591 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500592 }
593
Jamie Madillab9d82c2014-01-21 16:38:14 -0500594 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
595 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
596 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
597 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
598 if (renderbuffer != 0)
599 {
600 if (!context->getRenderbuffer(renderbuffer))
601 {
Geoff Langb1196682014-07-23 13:47:29 -0400602 context->recordError(Error(GL_INVALID_OPERATION));
603 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -0500604 }
605 }
606
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500607 return true;
608}
609
Jamie Madillc29968b2016-01-20 11:17:23 -0500610bool ValidateBlitFramebufferParameters(gl::Context *context,
611 GLint srcX0,
612 GLint srcY0,
613 GLint srcX1,
614 GLint srcY1,
615 GLint dstX0,
616 GLint dstY0,
617 GLint dstX1,
618 GLint dstY1,
619 GLbitfield mask,
620 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400621{
622 switch (filter)
623 {
624 case GL_NEAREST:
625 break;
626 case GL_LINEAR:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400627 break;
628 default:
Geoff Langb1196682014-07-23 13:47:29 -0400629 context->recordError(Error(GL_INVALID_ENUM));
630 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400631 }
632
633 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
634 {
Geoff Langb1196682014-07-23 13:47:29 -0400635 context->recordError(Error(GL_INVALID_VALUE));
636 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400637 }
638
639 if (mask == 0)
640 {
641 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
642 // buffers are copied.
643 return false;
644 }
645
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400646 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
647 // color buffer, leaving only nearest being unfiltered from above
648 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
649 {
Geoff Langb1196682014-07-23 13:47:29 -0400650 context->recordError(Error(GL_INVALID_OPERATION));
651 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400652 }
653
Shannon Woods53a94a82014-06-24 15:20:36 -0400654 if (context->getState().getReadFramebuffer()->id() == context->getState().getDrawFramebuffer()->id())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400655 {
Geoff Langb1196682014-07-23 13:47:29 -0400656 context->recordError(Error(GL_INVALID_OPERATION));
657 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400658 }
659
Jamie Madille3ef7152015-04-28 16:55:17 +0000660 const gl::Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
661 const gl::Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -0500662
663 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400664 {
Geoff Langb1196682014-07-23 13:47:29 -0400665 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
666 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400667 }
668
Geoff Lang748f74e2014-12-01 11:25:34 -0500669 if (!readFramebuffer->checkStatus(context->getData()))
Jamie Madill48faf802014-11-06 15:27:22 -0500670 {
671 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
672 return false;
673 }
674
Geoff Lang748f74e2014-12-01 11:25:34 -0500675 if (!drawFramebuffer->checkStatus(context->getData()))
Jamie Madill48faf802014-11-06 15:27:22 -0500676 {
677 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
678 return false;
679 }
680
681 if (drawFramebuffer->getSamples(context->getData()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400682 {
Geoff Langb1196682014-07-23 13:47:29 -0400683 context->recordError(Error(GL_INVALID_OPERATION));
684 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400685 }
686
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400687 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
688
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400689 if (mask & GL_COLOR_BUFFER_BIT)
690 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400691 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
692 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -0500693 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400694
695 if (readColorBuffer && drawColorBuffer)
696 {
Geoff Langd8a22582014-12-17 15:28:23 -0500697 GLenum readInternalFormat = readColorBuffer->getInternalFormat();
Geoff Lang5d601382014-07-22 15:14:06 -0400698 const InternalFormat &readFormatInfo = GetInternalFormatInfo(readInternalFormat);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400699
Geoff Langa15472a2015-08-11 11:48:03 -0400700 for (size_t drawbufferIdx = 0;
701 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400702 {
Geoff Langa15472a2015-08-11 11:48:03 -0400703 const FramebufferAttachment *attachment =
704 drawFramebuffer->getDrawBuffer(drawbufferIdx);
705 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400706 {
Geoff Langa15472a2015-08-11 11:48:03 -0400707 GLenum drawInternalFormat = attachment->getInternalFormat();
Geoff Lang5d601382014-07-22 15:14:06 -0400708 const InternalFormat &drawFormatInfo = GetInternalFormatInfo(drawInternalFormat);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400709
Geoff Langb2f3d052013-08-13 12:49:27 -0400710 // The GL ES 3.0.2 spec (pg 193) states that:
711 // 1) If the read buffer is fixed point format, the draw buffer must be as well
712 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
713 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
Jamie Madill6163c752015-12-07 16:32:59 -0500714 // Changes with EXT_color_buffer_float:
715 // Case 1) is changed to fixed point OR floating point
716 GLenum readComponentType = readFormatInfo.componentType;
717 GLenum drawComponentType = drawFormatInfo.componentType;
718 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
719 readComponentType == GL_SIGNED_NORMALIZED);
720 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
721 drawComponentType == GL_SIGNED_NORMALIZED);
722
723 if (extensions.colorBufferFloat)
724 {
725 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
726 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
727
728 if (readFixedOrFloat != drawFixedOrFloat)
729 {
730 context->recordError(Error(GL_INVALID_OPERATION,
731 "If the read buffer contains fixed-point or "
732 "floating-point values, the draw buffer "
733 "must as well."));
734 return false;
735 }
736 }
737 else if (readFixedPoint != drawFixedPoint)
738 {
739 context->recordError(Error(GL_INVALID_OPERATION,
740 "If the read buffer contains fixed-point "
741 "values, the draw buffer must as well."));
742 return false;
743 }
744
745 if (readComponentType == GL_UNSIGNED_INT &&
746 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400747 {
Geoff Langb1196682014-07-23 13:47:29 -0400748 context->recordError(Error(GL_INVALID_OPERATION));
749 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400750 }
751
Jamie Madill6163c752015-12-07 16:32:59 -0500752 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400753 {
Geoff Langb1196682014-07-23 13:47:29 -0400754 context->recordError(Error(GL_INVALID_OPERATION));
755 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400756 }
757
Geoff Langb2f3d052013-08-13 12:49:27 -0400758 if (readColorBuffer->getSamples() > 0 && (readInternalFormat != drawInternalFormat || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400759 {
Geoff Langb1196682014-07-23 13:47:29 -0400760 context->recordError(Error(GL_INVALID_OPERATION));
761 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400762 }
763 }
764 }
765
Geoff Lang5d601382014-07-22 15:14:06 -0400766 if ((readFormatInfo.componentType == GL_INT || readFormatInfo.componentType == GL_UNSIGNED_INT) && filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400767 {
Geoff Langb1196682014-07-23 13:47:29 -0400768 context->recordError(Error(GL_INVALID_OPERATION));
769 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400770 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400771 }
772 }
773
Dongseong Hwang44b422c2014-12-09 15:42:01 +0200774 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
775 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
776 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400777 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +0200778 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400779 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400780 const gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]);
781 const gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400782
Dongseong Hwang44b422c2014-12-09 15:42:01 +0200783 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400784 {
Geoff Langd8a22582014-12-17 15:28:23 -0500785 if (readBuffer->getInternalFormat() != drawBuffer->getInternalFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400786 {
Geoff Langb1196682014-07-23 13:47:29 -0400787 context->recordError(Error(GL_INVALID_OPERATION));
788 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400789 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400790
Dongseong Hwang44b422c2014-12-09 15:42:01 +0200791 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400792 {
Geoff Langb1196682014-07-23 13:47:29 -0400793 context->recordError(Error(GL_INVALID_OPERATION));
794 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400795 }
796 }
797 }
798 }
799
800 return true;
801}
802
Geoff Langb1196682014-07-23 13:47:29 -0400803bool ValidateGetVertexAttribParameters(Context *context, GLenum pname)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400804{
805 switch (pname)
806 {
807 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
808 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
809 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
810 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
811 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
812 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
813 case GL_CURRENT_VERTEX_ATTRIB:
814 return true;
815
816 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
817 // Don't verify ES3 context because GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE uses
818 // the same constant.
Geoff Langd4475812015-03-18 10:53:05 -0400819 static_assert(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
820 "ANGLE extension enums not equal to GL enums.");
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400821 return true;
822
823 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Geoff Langb1196682014-07-23 13:47:29 -0400824 if (context->getClientVersion() < 3)
825 {
826 context->recordError(Error(GL_INVALID_ENUM));
827 return false;
828 }
829 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400830
831 default:
Geoff Langb1196682014-07-23 13:47:29 -0400832 context->recordError(Error(GL_INVALID_ENUM));
833 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400834 }
835}
836
Ian Ewellbda75592016-04-18 17:25:54 -0400837bool ValidateTexParamParameters(gl::Context *context, GLenum target, GLenum pname, GLint param)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400838{
839 switch (pname)
840 {
841 case GL_TEXTURE_WRAP_R:
842 case GL_TEXTURE_SWIZZLE_R:
843 case GL_TEXTURE_SWIZZLE_G:
844 case GL_TEXTURE_SWIZZLE_B:
845 case GL_TEXTURE_SWIZZLE_A:
846 case GL_TEXTURE_BASE_LEVEL:
847 case GL_TEXTURE_MAX_LEVEL:
848 case GL_TEXTURE_COMPARE_MODE:
849 case GL_TEXTURE_COMPARE_FUNC:
850 case GL_TEXTURE_MIN_LOD:
851 case GL_TEXTURE_MAX_LOD:
Ian Ewellbda75592016-04-18 17:25:54 -0400852 // ES3 texture paramters are not supported on external textures as the extension is
853 // written against ES2.
854 if (context->getClientVersion() < 3 || target == GL_TEXTURE_EXTERNAL_OES)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400855 {
Geoff Langb1196682014-07-23 13:47:29 -0400856 context->recordError(Error(GL_INVALID_ENUM));
857 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400858 }
859 break;
860
861 default: break;
862 }
863
864 switch (pname)
865 {
866 case GL_TEXTURE_WRAP_S:
867 case GL_TEXTURE_WRAP_T:
868 case GL_TEXTURE_WRAP_R:
869 switch (param)
870 {
Corentin Wallez9670b032016-04-29 09:47:47 +0000871 case GL_CLAMP_TO_EDGE:
Ian Ewellbda75592016-04-18 17:25:54 -0400872 return true;
873 case GL_REPEAT:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400874 case GL_MIRRORED_REPEAT:
Olli Etuahobd329092016-04-29 12:51:42 +0300875 if (target == GL_TEXTURE_EXTERNAL_OES)
876 {
877 // OES_EGL_image_external specifies this error.
878 context->recordError(Error(
879 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
880 return false;
881 }
882 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400883 default:
Geoff Langb1196682014-07-23 13:47:29 -0400884 context->recordError(Error(GL_INVALID_ENUM));
885 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400886 }
887
888 case GL_TEXTURE_MIN_FILTER:
889 switch (param)
890 {
891 case GL_NEAREST:
892 case GL_LINEAR:
Ian Ewellbda75592016-04-18 17:25:54 -0400893 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400894 case GL_NEAREST_MIPMAP_NEAREST:
895 case GL_LINEAR_MIPMAP_NEAREST:
896 case GL_NEAREST_MIPMAP_LINEAR:
897 case GL_LINEAR_MIPMAP_LINEAR:
Olli Etuahobd329092016-04-29 12:51:42 +0300898 if (target == GL_TEXTURE_EXTERNAL_OES)
899 {
900 // OES_EGL_image_external specifies this error.
901 context->recordError(
902 Error(GL_INVALID_ENUM,
903 "external textures only support NEAREST and LINEAR filtering"));
904 return false;
905 }
906 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400907 default:
Geoff Langb1196682014-07-23 13:47:29 -0400908 context->recordError(Error(GL_INVALID_ENUM));
909 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400910 }
911 break;
912
913 case GL_TEXTURE_MAG_FILTER:
914 switch (param)
915 {
916 case GL_NEAREST:
917 case GL_LINEAR:
918 return true;
919 default:
Geoff Langb1196682014-07-23 13:47:29 -0400920 context->recordError(Error(GL_INVALID_ENUM));
921 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400922 }
923 break;
924
925 case GL_TEXTURE_USAGE_ANGLE:
926 switch (param)
927 {
928 case GL_NONE:
929 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
930 return true;
931 default:
Geoff Langb1196682014-07-23 13:47:29 -0400932 context->recordError(Error(GL_INVALID_ENUM));
933 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400934 }
935 break;
936
937 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400938 if (!context->getExtensions().textureFilterAnisotropic)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400939 {
Geoff Langb1196682014-07-23 13:47:29 -0400940 context->recordError(Error(GL_INVALID_ENUM));
941 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400942 }
943
944 // we assume the parameter passed to this validation method is truncated, not rounded
945 if (param < 1)
946 {
Geoff Langb1196682014-07-23 13:47:29 -0400947 context->recordError(Error(GL_INVALID_VALUE));
948 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400949 }
950 return true;
951
952 case GL_TEXTURE_MIN_LOD:
953 case GL_TEXTURE_MAX_LOD:
954 // any value is permissible
955 return true;
956
957 case GL_TEXTURE_COMPARE_MODE:
Geoff Lang63b5f1f2013-09-23 14:52:14 -0400958 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400959 switch (param)
960 {
961 case GL_NONE:
962 case GL_COMPARE_REF_TO_TEXTURE:
963 return true;
964 default:
Geoff Langb1196682014-07-23 13:47:29 -0400965 context->recordError(Error(GL_INVALID_ENUM));
966 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400967 }
968 break;
969
970 case GL_TEXTURE_COMPARE_FUNC:
Geoff Lang63b5f1f2013-09-23 14:52:14 -0400971 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400972 switch (param)
973 {
974 case GL_LEQUAL:
975 case GL_GEQUAL:
976 case GL_LESS:
977 case GL_GREATER:
978 case GL_EQUAL:
979 case GL_NOTEQUAL:
980 case GL_ALWAYS:
981 case GL_NEVER:
982 return true;
983 default:
Geoff Langb1196682014-07-23 13:47:29 -0400984 context->recordError(Error(GL_INVALID_ENUM));
985 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400986 }
987 break;
988
989 case GL_TEXTURE_SWIZZLE_R:
990 case GL_TEXTURE_SWIZZLE_G:
991 case GL_TEXTURE_SWIZZLE_B:
992 case GL_TEXTURE_SWIZZLE_A:
Geoff Langbc90a482013-09-17 16:51:27 -0400993 switch (param)
994 {
995 case GL_RED:
996 case GL_GREEN:
997 case GL_BLUE:
998 case GL_ALPHA:
999 case GL_ZERO:
1000 case GL_ONE:
1001 return true;
1002 default:
Geoff Langb1196682014-07-23 13:47:29 -04001003 context->recordError(Error(GL_INVALID_ENUM));
1004 return false;
Geoff Langbc90a482013-09-17 16:51:27 -04001005 }
1006 break;
1007
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001008 case GL_TEXTURE_BASE_LEVEL:
1009 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens8de68282014-04-04 11:10:27 -04001010 if (param < 0)
1011 {
Geoff Langb1196682014-07-23 13:47:29 -04001012 context->recordError(Error(GL_INVALID_VALUE));
1013 return false;
Nicolas Capens8de68282014-04-04 11:10:27 -04001014 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001015 return true;
1016
1017 default:
Geoff Langb1196682014-07-23 13:47:29 -04001018 context->recordError(Error(GL_INVALID_ENUM));
1019 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001020 }
1021}
1022
Geoff Langb1196682014-07-23 13:47:29 -04001023bool ValidateSamplerObjectParameter(gl::Context *context, GLenum pname)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001024{
1025 switch (pname)
1026 {
1027 case GL_TEXTURE_MIN_FILTER:
1028 case GL_TEXTURE_MAG_FILTER:
1029 case GL_TEXTURE_WRAP_S:
1030 case GL_TEXTURE_WRAP_T:
1031 case GL_TEXTURE_WRAP_R:
1032 case GL_TEXTURE_MIN_LOD:
1033 case GL_TEXTURE_MAX_LOD:
1034 case GL_TEXTURE_COMPARE_MODE:
1035 case GL_TEXTURE_COMPARE_FUNC:
1036 return true;
1037
1038 default:
Geoff Langb1196682014-07-23 13:47:29 -04001039 context->recordError(Error(GL_INVALID_ENUM));
1040 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001041 }
1042}
1043
Jamie Madillc29968b2016-01-20 11:17:23 -05001044bool ValidateReadPixels(Context *context,
1045 GLint x,
1046 GLint y,
1047 GLsizei width,
1048 GLsizei height,
1049 GLenum format,
1050 GLenum type,
1051 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05001052{
Jamie Madillc29968b2016-01-20 11:17:23 -05001053 if (width < 0 || height < 0)
1054 {
1055 context->recordError(Error(GL_INVALID_VALUE, "width and height must be positive"));
1056 return false;
1057 }
1058
1059 Framebuffer *framebuffer = context->getState().getReadFramebuffer();
Jamie Madill893ab082014-05-16 16:56:10 -04001060 ASSERT(framebuffer);
Jamie Madill26e91952014-03-05 15:01:27 -05001061
Geoff Lang748f74e2014-12-01 11:25:34 -05001062 if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill26e91952014-03-05 15:01:27 -05001063 {
Geoff Langb1196682014-07-23 13:47:29 -04001064 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
1065 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001066 }
1067
Jamie Madill48faf802014-11-06 15:27:22 -05001068 if (context->getState().getReadFramebuffer()->id() != 0 &&
1069 framebuffer->getSamples(context->getData()) != 0)
Jamie Madill26e91952014-03-05 15:01:27 -05001070 {
Geoff Langb1196682014-07-23 13:47:29 -04001071 context->recordError(Error(GL_INVALID_OPERATION));
1072 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001073 }
1074
Geoff Langbce529e2014-12-01 12:48:41 -05001075 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
1076 if (!readBuffer)
Jamie Madill893ab082014-05-16 16:56:10 -04001077 {
Geoff Langb1196682014-07-23 13:47:29 -04001078 context->recordError(Error(GL_INVALID_OPERATION));
1079 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001080 }
1081
Geoff Langbce529e2014-12-01 12:48:41 -05001082 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
1083 GLenum currentType = framebuffer->getImplementationColorReadType();
Geoff Langd8a22582014-12-17 15:28:23 -05001084 GLenum currentInternalFormat = readBuffer->getInternalFormat();
Geoff Lange4a492b2014-06-19 14:14:41 -04001085 GLuint clientVersion = context->getClientVersion();
Jamie Madill26e91952014-03-05 15:01:27 -05001086
Geoff Langbdc9b2f2014-04-16 14:41:54 -04001087 bool validReadFormat = (clientVersion < 3) ? ValidES2ReadFormatType(context, format, type) :
1088 ValidES3ReadFormatType(context, currentInternalFormat, format, type);
Jamie Madill26e91952014-03-05 15:01:27 -05001089
1090 if (!(currentFormat == format && currentType == type) && !validReadFormat)
1091 {
Geoff Langb1196682014-07-23 13:47:29 -04001092 context->recordError(Error(GL_INVALID_OPERATION));
1093 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001094 }
1095
Jamie Madillc29968b2016-01-20 11:17:23 -05001096 return true;
1097}
1098
1099bool ValidateReadnPixelsEXT(Context *context,
1100 GLint x,
1101 GLint y,
1102 GLsizei width,
1103 GLsizei height,
1104 GLenum format,
1105 GLenum type,
1106 GLsizei bufSize,
1107 GLvoid *pixels)
1108{
1109 if (bufSize < 0)
1110 {
1111 context->recordError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
1112 return false;
1113 }
1114
Geoff Lang5d601382014-07-22 15:14:06 -04001115 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
1116 const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat);
Jamie Madill26e91952014-03-05 15:01:27 -05001117
Minmin Gongadff67b2015-10-14 10:34:45 -04001118 GLsizei outputPitch =
1119 sizedFormatInfo.computeRowPitch(type, width, context->getState().getPackAlignment(),
1120 context->getState().getPackRowLength());
Jamie Madill26e91952014-03-05 15:01:27 -05001121 // sized query sanity check
Jamie Madillc29968b2016-01-20 11:17:23 -05001122 int requiredSize = outputPitch * height;
1123 if (requiredSize > bufSize)
Jamie Madill26e91952014-03-05 15:01:27 -05001124 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001125 context->recordError(Error(GL_INVALID_OPERATION));
1126 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001127 }
1128
Jamie Madillc29968b2016-01-20 11:17:23 -05001129 return ValidateReadPixels(context, x, y, width, height, format, type, pixels);
Jamie Madill26e91952014-03-05 15:01:27 -05001130}
1131
Olli Etuaho41997e72016-03-10 13:38:39 +02001132bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001133{
1134 if (!context->getExtensions().occlusionQueryBoolean &&
1135 !context->getExtensions().disjointTimerQuery)
1136 {
1137 context->recordError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
1138 return false;
1139 }
1140
Olli Etuaho41997e72016-03-10 13:38:39 +02001141 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001142}
1143
Olli Etuaho41997e72016-03-10 13:38:39 +02001144bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001145{
1146 if (!context->getExtensions().occlusionQueryBoolean &&
1147 !context->getExtensions().disjointTimerQuery)
1148 {
1149 context->recordError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
1150 return false;
1151 }
1152
Olli Etuaho41997e72016-03-10 13:38:39 +02001153 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001154}
1155
1156bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001157{
1158 if (!ValidQueryType(context, target))
1159 {
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001160 context->recordError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04001161 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001162 }
1163
1164 if (id == 0)
1165 {
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001166 context->recordError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04001167 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001168 }
1169
1170 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1171 // of zero, if the active query object name for <target> is non-zero (for the
1172 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1173 // the active query for either target is non-zero), if <id> is the name of an
1174 // existing query object whose type does not match <target>, or if <id> is the
1175 // active query object name for any query type, the error INVALID_OPERATION is
1176 // generated.
1177
1178 // Ensure no other queries are active
1179 // NOTE: If other queries than occlusion are supported, we will need to check
1180 // separately that:
1181 // a) The query ID passed is not the current active query for any target/type
1182 // b) There are no active queries for the requested target (and in the case
1183 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1184 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001185
Corentin Walleze71ea192016-04-19 13:16:37 -04001186 if (context->getState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001187 {
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001188 context->recordError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04001189 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001190 }
1191
1192 Query *queryObject = context->getQuery(id, true, target);
1193
1194 // check that name was obtained with glGenQueries
1195 if (!queryObject)
1196 {
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001197 context->recordError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04001198 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001199 }
1200
1201 // check for type mismatch
1202 if (queryObject->getType() != target)
1203 {
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001204 context->recordError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04001205 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001206 }
1207
1208 return true;
1209}
1210
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001211bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1212{
1213 if (!context->getExtensions().occlusionQueryBoolean &&
1214 !context->getExtensions().disjointTimerQuery)
1215 {
1216 context->recordError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
1217 return false;
1218 }
1219
1220 return ValidateBeginQueryBase(context, target, id);
1221}
1222
1223bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001224{
1225 if (!ValidQueryType(context, target))
1226 {
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001227 context->recordError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04001228 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001229 }
1230
Shannon Woods53a94a82014-06-24 15:20:36 -04001231 const Query *queryObject = context->getState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001232
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001233 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001234 {
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001235 context->recordError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04001236 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001237 }
1238
Jamie Madill45c785d2014-05-13 14:09:34 -04001239 return true;
1240}
1241
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001242bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1243{
1244 if (!context->getExtensions().occlusionQueryBoolean &&
1245 !context->getExtensions().disjointTimerQuery)
1246 {
1247 context->recordError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
1248 return false;
1249 }
1250
1251 return ValidateEndQueryBase(context, target);
1252}
1253
1254bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1255{
1256 if (!context->getExtensions().disjointTimerQuery)
1257 {
1258 context->recordError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
1259 return false;
1260 }
1261
1262 if (target != GL_TIMESTAMP_EXT)
1263 {
1264 context->recordError(Error(GL_INVALID_ENUM, "Invalid query target"));
1265 return false;
1266 }
1267
1268 Query *queryObject = context->getQuery(id, true, target);
1269 if (queryObject == nullptr)
1270 {
1271 context->recordError(Error(GL_INVALID_OPERATION, "Invalid query id"));
1272 return false;
1273 }
1274
1275 if (context->getState().isQueryActive(queryObject))
1276 {
1277 context->recordError(Error(GL_INVALID_OPERATION, "Query is active"));
1278 return false;
1279 }
1280
1281 return true;
1282}
1283
1284bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname)
1285{
1286 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1287 {
1288 context->recordError(Error(GL_INVALID_ENUM, "Invalid query type"));
1289 return false;
1290 }
1291
1292 switch (pname)
1293 {
1294 case GL_CURRENT_QUERY_EXT:
1295 if (target == GL_TIMESTAMP_EXT)
1296 {
1297 context->recordError(
1298 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
1299 return false;
1300 }
1301 break;
1302 case GL_QUERY_COUNTER_BITS_EXT:
1303 if (!context->getExtensions().disjointTimerQuery ||
1304 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1305 {
1306 context->recordError(Error(GL_INVALID_ENUM, "Invalid pname"));
1307 return false;
1308 }
1309 break;
1310 default:
1311 context->recordError(Error(GL_INVALID_ENUM, "Invalid pname"));
1312 return false;
1313 }
1314
1315 return true;
1316}
1317
1318bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1319{
1320 if (!context->getExtensions().occlusionQueryBoolean &&
1321 !context->getExtensions().disjointTimerQuery)
1322 {
1323 context->recordError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
1324 return false;
1325 }
1326
1327 return ValidateGetQueryivBase(context, target, pname);
1328}
1329
1330bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname)
1331{
1332 Query *queryObject = context->getQuery(id, false, GL_NONE);
1333
1334 if (!queryObject)
1335 {
1336 context->recordError(Error(GL_INVALID_OPERATION, "Query does not exist"));
1337 return false;
1338 }
1339
1340 if (context->getState().isQueryActive(queryObject))
1341 {
1342 context->recordError(Error(GL_INVALID_OPERATION, "Query currently active"));
1343 return false;
1344 }
1345
1346 switch (pname)
1347 {
1348 case GL_QUERY_RESULT_EXT:
1349 case GL_QUERY_RESULT_AVAILABLE_EXT:
1350 break;
1351
1352 default:
1353 context->recordError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
1354 return false;
1355 }
1356
1357 return true;
1358}
1359
1360bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1361{
1362 if (!context->getExtensions().disjointTimerQuery)
1363 {
1364 context->recordError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
1365 return false;
1366 }
1367 return ValidateGetQueryObjectValueBase(context, id, pname);
1368}
1369
1370bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1371{
1372 if (!context->getExtensions().disjointTimerQuery &&
1373 !context->getExtensions().occlusionQueryBoolean)
1374 {
1375 context->recordError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
1376 return false;
1377 }
1378 return ValidateGetQueryObjectValueBase(context, id, pname);
1379}
1380
1381bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1382{
1383 if (!context->getExtensions().disjointTimerQuery)
1384 {
1385 context->recordError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
1386 return false;
1387 }
1388 return ValidateGetQueryObjectValueBase(context, id, pname);
1389}
1390
1391bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1392{
1393 if (!context->getExtensions().disjointTimerQuery)
1394 {
1395 context->recordError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
1396 return false;
1397 }
1398 return ValidateGetQueryObjectValueBase(context, id, pname);
1399}
1400
Jamie Madill62d31cb2015-09-11 13:25:51 -04001401static bool ValidateUniformCommonBase(gl::Context *context,
1402 GLenum targetUniformType,
1403 GLint location,
1404 GLsizei count,
1405 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001406{
1407 if (count < 0)
1408 {
Geoff Langb1196682014-07-23 13:47:29 -04001409 context->recordError(Error(GL_INVALID_VALUE));
1410 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001411 }
1412
Geoff Lang7dd2e102014-11-10 15:19:26 -05001413 gl::Program *program = context->getState().getProgram();
1414 if (!program)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001415 {
Geoff Langb1196682014-07-23 13:47:29 -04001416 context->recordError(Error(GL_INVALID_OPERATION));
1417 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001418 }
1419
Geoff Langd8605522016-04-13 10:19:12 -04001420 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001421 {
1422 // Silently ignore the uniform command
1423 return false;
1424 }
1425
Geoff Lang7dd2e102014-11-10 15:19:26 -05001426 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04001427 {
Geoff Langb1196682014-07-23 13:47:29 -04001428 context->recordError(Error(GL_INVALID_OPERATION));
1429 return false;
Jamie Madill36398922014-05-20 14:51:53 -04001430 }
1431
Jamie Madill62d31cb2015-09-11 13:25:51 -04001432 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04001433
1434 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04001435 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04001436 {
Geoff Langb1196682014-07-23 13:47:29 -04001437 context->recordError(Error(GL_INVALID_OPERATION));
1438 return false;
Jamie Madill36398922014-05-20 14:51:53 -04001439 }
1440
Jamie Madill62d31cb2015-09-11 13:25:51 -04001441 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001442 return true;
1443}
1444
Jamie Madillaa981bd2014-05-20 10:55:55 -04001445bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
1446{
1447 // Check for ES3 uniform entry points
Jamie Madillf2575982014-06-25 16:04:54 -04001448 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT && context->getClientVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04001449 {
Geoff Langb1196682014-07-23 13:47:29 -04001450 context->recordError(Error(GL_INVALID_OPERATION));
1451 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001452 }
1453
Jamie Madill62d31cb2015-09-11 13:25:51 -04001454 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04001455 if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
1456 {
1457 return false;
1458 }
1459
Jamie Madillf2575982014-06-25 16:04:54 -04001460 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05001461 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04001462 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
1463 {
Geoff Langb1196682014-07-23 13:47:29 -04001464 context->recordError(Error(GL_INVALID_OPERATION));
1465 return false;
Jamie Madill36398922014-05-20 14:51:53 -04001466 }
1467
1468 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001469}
1470
1471bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count,
1472 GLboolean transpose)
1473{
1474 // Check for ES3 uniform entry points
1475 int rows = VariableRowCount(matrixType);
1476 int cols = VariableColumnCount(matrixType);
1477 if (rows != cols && context->getClientVersion() < 3)
1478 {
Geoff Langb1196682014-07-23 13:47:29 -04001479 context->recordError(Error(GL_INVALID_OPERATION));
1480 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001481 }
1482
1483 if (transpose != GL_FALSE && context->getClientVersion() < 3)
1484 {
Geoff Langb1196682014-07-23 13:47:29 -04001485 context->recordError(Error(GL_INVALID_VALUE));
1486 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001487 }
1488
Jamie Madill62d31cb2015-09-11 13:25:51 -04001489 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04001490 if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
1491 {
1492 return false;
1493 }
1494
1495 if (uniform->type != matrixType)
1496 {
Geoff Langb1196682014-07-23 13:47:29 -04001497 context->recordError(Error(GL_INVALID_OPERATION));
1498 return false;
Jamie Madill36398922014-05-20 14:51:53 -04001499 }
1500
1501 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001502}
1503
Jamie Madill893ab082014-05-16 16:56:10 -04001504bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
1505{
1506 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
1507 {
Geoff Langb1196682014-07-23 13:47:29 -04001508 context->recordError(Error(GL_INVALID_ENUM));
1509 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001510 }
1511
Jamie Madill0af26e12015-03-05 19:54:33 -05001512 const Caps &caps = context->getCaps();
1513
Jamie Madill893ab082014-05-16 16:56:10 -04001514 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
1515 {
1516 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
1517
Jamie Madill0af26e12015-03-05 19:54:33 -05001518 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04001519 {
Geoff Langb1196682014-07-23 13:47:29 -04001520 context->recordError(Error(GL_INVALID_OPERATION));
1521 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001522 }
1523 }
1524
1525 switch (pname)
1526 {
1527 case GL_TEXTURE_BINDING_2D:
1528 case GL_TEXTURE_BINDING_CUBE_MAP:
1529 case GL_TEXTURE_BINDING_3D:
1530 case GL_TEXTURE_BINDING_2D_ARRAY:
Jamie Madill893ab082014-05-16 16:56:10 -04001531 break;
Ian Ewell54f87462016-03-10 13:47:21 -05001532 case GL_TEXTURE_BINDING_EXTERNAL_OES:
1533 if (!context->getExtensions().eglStreamConsumerExternal)
1534 {
1535 context->recordError(
1536 Error(GL_INVALID_ENUM, "NV_EGL_stream_consumer_external extension not enabled"));
1537 return false;
1538 }
1539 break;
Jamie Madill893ab082014-05-16 16:56:10 -04001540
1541 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1542 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1543 {
Shannon Woods53a94a82014-06-24 15:20:36 -04001544 Framebuffer *framebuffer = context->getState().getReadFramebuffer();
Jamie Madill893ab082014-05-16 16:56:10 -04001545 ASSERT(framebuffer);
Geoff Lang748f74e2014-12-01 11:25:34 -05001546 if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04001547 {
Geoff Langb1196682014-07-23 13:47:29 -04001548 context->recordError(Error(GL_INVALID_OPERATION));
1549 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001550 }
1551
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001552 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04001553 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04001554 {
Geoff Langb1196682014-07-23 13:47:29 -04001555 context->recordError(Error(GL_INVALID_OPERATION));
1556 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001557 }
1558 }
1559 break;
1560
1561 default:
1562 break;
1563 }
1564
1565 // pname is valid, but there are no parameters to return
1566 if (numParams == 0)
1567 {
1568 return false;
1569 }
1570
1571 return true;
1572}
1573
Jamie Madillc29968b2016-01-20 11:17:23 -05001574bool ValidateCopyTexImageParametersBase(ValidationContext *context,
1575 GLenum target,
1576 GLint level,
1577 GLenum internalformat,
1578 bool isSubImage,
1579 GLint xoffset,
1580 GLint yoffset,
1581 GLint zoffset,
1582 GLint x,
1583 GLint y,
1584 GLsizei width,
1585 GLsizei height,
1586 GLint border,
1587 GLenum *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04001588{
Jamie Madill560a8d82014-05-21 13:06:20 -04001589 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
1590 {
Geoff Langb1196682014-07-23 13:47:29 -04001591 context->recordError(Error(GL_INVALID_VALUE));
1592 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001593 }
1594
1595 if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1596 {
Geoff Langb1196682014-07-23 13:47:29 -04001597 context->recordError(Error(GL_INVALID_VALUE));
1598 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001599 }
1600
1601 if (border != 0)
1602 {
Geoff Langb1196682014-07-23 13:47:29 -04001603 context->recordError(Error(GL_INVALID_VALUE));
1604 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001605 }
1606
1607 if (!ValidMipLevel(context, target, level))
1608 {
Geoff Langb1196682014-07-23 13:47:29 -04001609 context->recordError(Error(GL_INVALID_VALUE));
1610 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001611 }
1612
Jamie Madillc29968b2016-01-20 11:17:23 -05001613 const gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
Geoff Lang748f74e2014-12-01 11:25:34 -05001614 if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04001615 {
Geoff Langb1196682014-07-23 13:47:29 -04001616 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
1617 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001618 }
1619
Jamie Madillc29968b2016-01-20 11:17:23 -05001620 const auto &state = context->getState();
1621 if (state.getReadFramebuffer()->id() != 0 && framebuffer->getSamples(context->getData()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04001622 {
Geoff Langb1196682014-07-23 13:47:29 -04001623 context->recordError(Error(GL_INVALID_OPERATION));
1624 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001625 }
1626
Geoff Langaae65a42014-05-26 12:43:44 -04001627 const gl::Caps &caps = context->getCaps();
1628
Geoff Langaae65a42014-05-26 12:43:44 -04001629 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04001630 switch (target)
1631 {
1632 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05001633 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04001634 break;
1635
1636 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1637 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1638 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1639 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1640 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1641 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -05001642 maxDimension = caps.maxCubeMapTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04001643 break;
1644
1645 case GL_TEXTURE_2D_ARRAY:
Geoff Langa9be0dc2014-12-17 12:34:40 -05001646 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04001647 break;
1648
1649 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05001650 maxDimension = caps.max3DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04001651 break;
1652
1653 default:
Geoff Langb1196682014-07-23 13:47:29 -04001654 context->recordError(Error(GL_INVALID_ENUM));
1655 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001656 }
1657
Jamie Madillc29968b2016-01-20 11:17:23 -05001658 gl::Texture *texture =
1659 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04001660 if (!texture)
1661 {
Geoff Langb1196682014-07-23 13:47:29 -04001662 context->recordError(Error(GL_INVALID_OPERATION));
1663 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001664 }
1665
Geoff Lang69cce582015-09-17 13:20:36 -04001666 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04001667 {
Geoff Langb1196682014-07-23 13:47:29 -04001668 context->recordError(Error(GL_INVALID_OPERATION));
1669 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001670 }
1671
Geoff Lang5d601382014-07-22 15:14:06 -04001672 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1673
1674 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04001675 {
Geoff Langb1196682014-07-23 13:47:29 -04001676 context->recordError(Error(GL_INVALID_OPERATION));
1677 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001678 }
1679
Geoff Langa9be0dc2014-12-17 12:34:40 -05001680 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04001681 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05001682 context->recordError(Error(GL_INVALID_OPERATION));
1683 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001684 }
1685
1686 if (isSubImage)
1687 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05001688 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
1689 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
1690 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04001691 {
Geoff Langb1196682014-07-23 13:47:29 -04001692 context->recordError(Error(GL_INVALID_VALUE));
1693 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001694 }
1695 }
Jamie Madill6f38f822014-06-06 17:12:20 -04001696 else
1697 {
Geoff Lang691e58c2014-12-19 17:03:25 -05001698 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04001699 {
Geoff Langb1196682014-07-23 13:47:29 -04001700 context->recordError(Error(GL_INVALID_VALUE));
1701 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04001702 }
1703
Geoff Lang5d601382014-07-22 15:14:06 -04001704 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04001705 {
Geoff Langb1196682014-07-23 13:47:29 -04001706 context->recordError(Error(GL_INVALID_ENUM));
1707 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04001708 }
1709
1710 int maxLevelDimension = (maxDimension >> level);
1711 if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension)
1712 {
Geoff Langb1196682014-07-23 13:47:29 -04001713 context->recordError(Error(GL_INVALID_VALUE));
1714 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04001715 }
1716 }
Jamie Madill560a8d82014-05-21 13:06:20 -04001717
Geoff Langa9be0dc2014-12-17 12:34:40 -05001718 *textureFormatOut = texture->getInternalFormat(target, level);
Jamie Madill560a8d82014-05-21 13:06:20 -04001719 return true;
1720}
1721
Jamie Madillf25855c2015-11-03 11:06:18 -05001722static bool ValidateDrawBase(ValidationContext *context,
1723 GLenum mode,
1724 GLsizei count,
1725 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04001726{
Jamie Madill1aeb1312014-06-20 13:21:25 -04001727 switch (mode)
1728 {
1729 case GL_POINTS:
1730 case GL_LINES:
1731 case GL_LINE_LOOP:
1732 case GL_LINE_STRIP:
1733 case GL_TRIANGLES:
1734 case GL_TRIANGLE_STRIP:
1735 case GL_TRIANGLE_FAN:
1736 break;
1737 default:
Geoff Langb1196682014-07-23 13:47:29 -04001738 context->recordError(Error(GL_INVALID_ENUM));
1739 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04001740 }
1741
Jamie Madill250d33f2014-06-06 17:09:03 -04001742 if (count < 0)
1743 {
Geoff Langb1196682014-07-23 13:47:29 -04001744 context->recordError(Error(GL_INVALID_VALUE));
1745 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04001746 }
1747
Geoff Langb1196682014-07-23 13:47:29 -04001748 const State &state = context->getState();
1749
Jamie Madill250d33f2014-06-06 17:09:03 -04001750 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04001751 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04001752 {
Geoff Langb1196682014-07-23 13:47:29 -04001753 context->recordError(Error(GL_INVALID_OPERATION));
1754 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04001755 }
1756
Geoff Lang3a86ad32015-09-01 11:47:05 -04001757 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04001758 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04001759 const Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
1760 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
1761 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
1762 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
1763 const DepthStencilState &depthStencilState = state.getDepthStencilState();
1764 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
1765 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04001766 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04001767 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
1768 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04001769 {
1770 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
1771 // Section 6.10 of the WebGL 1.0 spec
1772 ERR(
1773 "This ANGLE implementation does not support separate front/back stencil "
1774 "writemasks, reference values, or stencil mask values.");
1775 context->recordError(Error(GL_INVALID_OPERATION));
1776 return false;
1777 }
Jamie Madillac528012014-06-20 13:21:23 -04001778 }
1779
Jamie Madilld9ba4f72014-08-04 10:47:59 -04001780 const gl::Framebuffer *fbo = state.getDrawFramebuffer();
Geoff Lang748f74e2014-12-01 11:25:34 -05001781 if (!fbo || fbo->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001782 {
Geoff Langb1196682014-07-23 13:47:29 -04001783 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
1784 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001785 }
1786
Geoff Lang7dd2e102014-11-10 15:19:26 -05001787 gl::Program *program = state.getProgram();
1788 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04001789 {
Geoff Langb1196682014-07-23 13:47:29 -04001790 context->recordError(Error(GL_INVALID_OPERATION));
1791 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04001792 }
1793
Geoff Lang7dd2e102014-11-10 15:19:26 -05001794 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04001795 {
Geoff Langb1196682014-07-23 13:47:29 -04001796 context->recordError(Error(GL_INVALID_OPERATION));
1797 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04001798 }
1799
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001800 // Uniform buffer validation
1801 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
1802 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04001803 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001804 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04001805 const OffsetBindingPointer<Buffer> &uniformBuffer =
1806 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001807
Geoff Lang5d124a62015-09-15 13:03:27 -04001808 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001809 {
1810 // undefined behaviour
1811 context->recordError(Error(GL_INVALID_OPERATION, "It is undefined behaviour to have a used but unbound uniform buffer."));
1812 return false;
1813 }
1814
Geoff Lang5d124a62015-09-15 13:03:27 -04001815 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001816 if (uniformBufferSize == 0)
1817 {
1818 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07001819 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001820 }
1821
Jamie Madill62d31cb2015-09-11 13:25:51 -04001822 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00001823 {
1824 // undefined behaviour
1825 context->recordError(Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small."));
1826 return false;
1827 }
1828 }
1829
Jamie Madill250d33f2014-06-06 17:09:03 -04001830 // No-op if zero count
1831 return (count > 0);
1832}
1833
Geoff Langb1196682014-07-23 13:47:29 -04001834bool ValidateDrawArrays(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04001835{
Jamie Madillfd716582014-06-06 17:09:04 -04001836 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04001837 {
Geoff Langb1196682014-07-23 13:47:29 -04001838 context->recordError(Error(GL_INVALID_VALUE));
1839 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04001840 }
1841
Jamie Madilld9ba4f72014-08-04 10:47:59 -04001842 const State &state = context->getState();
1843 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04001844 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused() &&
1845 curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04001846 {
1847 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
1848 // that does not match the current transform feedback object's draw mode (if transform feedback
1849 // is active), (3.0.2, section 2.14, pg 86)
Geoff Langb1196682014-07-23 13:47:29 -04001850 context->recordError(Error(GL_INVALID_OPERATION));
1851 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04001852 }
1853
Corentin Wallez18a2fb32015-08-10 12:58:14 -07001854 if (!ValidateDrawBase(context, mode, count, primcount))
1855 {
1856 return false;
1857 }
1858
1859 if (!ValidateDrawAttribs(context, primcount, count))
Jamie Madillfd716582014-06-06 17:09:04 -04001860 {
1861 return false;
1862 }
1863
1864 return true;
1865}
1866
Geoff Langb1196682014-07-23 13:47:29 -04001867bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04001868{
1869 if (primcount < 0)
1870 {
Geoff Langb1196682014-07-23 13:47:29 -04001871 context->recordError(Error(GL_INVALID_VALUE));
1872 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04001873 }
1874
Jamie Madill2b976812014-08-25 15:47:49 -04001875 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04001876 {
1877 return false;
1878 }
1879
1880 // No-op if zero primitive count
1881 return (primcount > 0);
1882}
1883
Geoff Lang87a93302014-09-16 13:29:43 -04001884static bool ValidateDrawInstancedANGLE(Context *context)
1885{
1886 // Verify there is at least one active attribute with a divisor of zero
1887 const gl::State& state = context->getState();
1888
Geoff Lang7dd2e102014-11-10 15:19:26 -05001889 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04001890
1891 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04001892 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04001893 {
1894 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04001895 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04001896 {
1897 return true;
1898 }
1899 }
1900
1901 context->recordError(Error(GL_INVALID_OPERATION, "ANGLE_instanced_arrays requires that at least one active attribute"
1902 "has a divisor of zero."));
1903 return false;
1904}
1905
1906bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
1907{
1908 if (!ValidateDrawInstancedANGLE(context))
1909 {
1910 return false;
1911 }
1912
1913 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
1914}
1915
Jamie Madillf25855c2015-11-03 11:06:18 -05001916bool ValidateDrawElements(ValidationContext *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04001917 GLenum mode,
1918 GLsizei count,
1919 GLenum type,
1920 const GLvoid *indices,
1921 GLsizei primcount,
1922 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04001923{
Jamie Madill250d33f2014-06-06 17:09:03 -04001924 switch (type)
1925 {
1926 case GL_UNSIGNED_BYTE:
1927 case GL_UNSIGNED_SHORT:
1928 break;
1929 case GL_UNSIGNED_INT:
Jamie Madille79b1e12015-11-04 16:36:37 -05001930 if (context->getClientVersion() < 3 && !context->getExtensions().elementIndexUint)
Jamie Madill250d33f2014-06-06 17:09:03 -04001931 {
Geoff Langb1196682014-07-23 13:47:29 -04001932 context->recordError(Error(GL_INVALID_ENUM));
1933 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04001934 }
1935 break;
1936 default:
Geoff Langb1196682014-07-23 13:47:29 -04001937 context->recordError(Error(GL_INVALID_ENUM));
1938 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04001939 }
1940
Jamie Madilld9ba4f72014-08-04 10:47:59 -04001941 const State &state = context->getState();
1942
1943 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04001944 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04001945 {
1946 // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
1947 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Geoff Langb1196682014-07-23 13:47:29 -04001948 context->recordError(Error(GL_INVALID_OPERATION));
1949 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04001950 }
1951
1952 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04001953 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04001954 {
Geoff Langb1196682014-07-23 13:47:29 -04001955 context->recordError(Error(GL_INVALID_OPERATION));
1956 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04001957 }
1958
Jamie Madill2b976812014-08-25 15:47:49 -04001959 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04001960 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madill2b976812014-08-25 15:47:49 -04001961 if (!indices && !elementArrayBuffer)
Jamie Madilld4cfa572014-07-08 10:00:32 -04001962 {
Geoff Langb1196682014-07-23 13:47:29 -04001963 context->recordError(Error(GL_INVALID_OPERATION));
1964 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04001965 }
1966
Jamie Madillae3000b2014-08-25 15:47:51 -04001967 if (elementArrayBuffer)
1968 {
1969 const gl::Type &typeInfo = gl::GetTypeInfo(type);
1970
1971 GLint64 offset = reinterpret_cast<GLint64>(indices);
1972 GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset;
1973
1974 // check for integer overflows
1975 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
1976 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
1977 {
Geoff Langb1196682014-07-23 13:47:29 -04001978 context->recordError(Error(GL_OUT_OF_MEMORY));
1979 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04001980 }
1981
1982 // Check for reading past the end of the bound buffer object
1983 if (byteCount > elementArrayBuffer->getSize())
1984 {
Geoff Langb1196682014-07-23 13:47:29 -04001985 context->recordError(Error(GL_INVALID_OPERATION));
1986 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04001987 }
1988 }
1989 else if (!indices)
1990 {
1991 // Catch this programming error here
Geoff Langb1196682014-07-23 13:47:29 -04001992 context->recordError(Error(GL_INVALID_OPERATION));
1993 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04001994 }
1995
Corentin Wallez18a2fb32015-08-10 12:58:14 -07001996 if (!ValidateDrawBase(context, mode, count, primcount))
1997 {
1998 return false;
1999 }
2000
Jamie Madill2b976812014-08-25 15:47:49 -04002001 // Use max index to validate if our vertex buffers are large enough for the pull.
2002 // TODO: offer fast path, with disabled index validation.
2003 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
2004 if (elementArrayBuffer)
2005 {
Jacek Cabana5521de2014-10-01 17:23:46 +02002006 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04002007 Error error =
2008 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
2009 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04002010 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04002011 {
Geoff Lang520c4ae2015-05-05 13:12:36 -04002012 context->recordError(error);
2013 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04002014 }
2015 }
2016 else
2017 {
Geoff Lang3edfe032015-09-04 16:38:24 -04002018 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04002019 }
2020
Jamie Madille79b1e12015-11-04 16:36:37 -05002021 // If we use an index greater than our maximum supported index range, return an error.
2022 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2023 // return an error if possible here.
2024 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
2025 {
2026 context->recordError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
2027 return false;
2028 }
2029
Jamie Madillbc4c4bc2016-03-23 21:04:43 -04002030 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04002031 {
2032 return false;
2033 }
2034
Geoff Lang3edfe032015-09-04 16:38:24 -04002035 // No op if there are no real indices in the index data (all are primitive restart).
2036 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04002037}
2038
Geoff Langb1196682014-07-23 13:47:29 -04002039bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04002040 GLenum mode,
2041 GLsizei count,
2042 GLenum type,
2043 const GLvoid *indices,
2044 GLsizei primcount,
2045 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04002046{
2047 if (primcount < 0)
2048 {
Geoff Langb1196682014-07-23 13:47:29 -04002049 context->recordError(Error(GL_INVALID_VALUE));
2050 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002051 }
2052
Jamie Madill2b976812014-08-25 15:47:49 -04002053 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04002054 {
2055 return false;
2056 }
2057
2058 // No-op zero primitive count
2059 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04002060}
2061
Geoff Lang3edfe032015-09-04 16:38:24 -04002062bool ValidateDrawElementsInstancedANGLE(Context *context,
2063 GLenum mode,
2064 GLsizei count,
2065 GLenum type,
2066 const GLvoid *indices,
2067 GLsizei primcount,
2068 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04002069{
2070 if (!ValidateDrawInstancedANGLE(context))
2071 {
2072 return false;
2073 }
2074
2075 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut);
2076}
2077
Geoff Langb1196682014-07-23 13:47:29 -04002078bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04002079 GLuint texture, GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002080{
Jamie Madill55ec3b12014-07-03 10:38:57 -04002081 if (!ValidFramebufferTarget(target))
2082 {
Geoff Langb1196682014-07-23 13:47:29 -04002083 context->recordError(Error(GL_INVALID_ENUM));
2084 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002085 }
2086
2087 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002088 {
2089 return false;
2090 }
2091
Jamie Madill55ec3b12014-07-03 10:38:57 -04002092 if (texture != 0)
2093 {
2094 gl::Texture *tex = context->getTexture(texture);
2095
2096 if (tex == NULL)
2097 {
Geoff Langb1196682014-07-23 13:47:29 -04002098 context->recordError(Error(GL_INVALID_OPERATION));
2099 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002100 }
2101
2102 if (level < 0)
2103 {
Geoff Langb1196682014-07-23 13:47:29 -04002104 context->recordError(Error(GL_INVALID_VALUE));
2105 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002106 }
2107 }
2108
Shannon Woods53a94a82014-06-24 15:20:36 -04002109 const gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002110 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002111
Jamie Madill84115c92015-04-23 15:00:07 -04002112 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002113 {
Jamie Madill84115c92015-04-23 15:00:07 -04002114 context->recordError(Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002115 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002116 }
2117
2118 return true;
2119}
2120
Geoff Langb1196682014-07-23 13:47:29 -04002121bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04002122 GLenum textarget, GLuint texture, GLint level)
2123{
Geoff Lang95663912015-04-02 15:54:45 -04002124 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap extension
2125 if (context->getClientVersion() < 3 && !context->getExtensions().fboRenderMipmap && level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002126 {
Geoff Langb1196682014-07-23 13:47:29 -04002127 context->recordError(Error(GL_INVALID_VALUE));
2128 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002129 }
2130
2131 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04002132 {
2133 return false;
2134 }
2135
Jamie Madill55ec3b12014-07-03 10:38:57 -04002136 if (texture != 0)
2137 {
2138 gl::Texture *tex = context->getTexture(texture);
2139 ASSERT(tex);
2140
Jamie Madill2a6564e2014-07-11 09:53:19 -04002141 const gl::Caps &caps = context->getCaps();
2142
Jamie Madill55ec3b12014-07-03 10:38:57 -04002143 switch (textarget)
2144 {
2145 case GL_TEXTURE_2D:
2146 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04002147 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002148 {
Geoff Langb1196682014-07-23 13:47:29 -04002149 context->recordError(Error(GL_INVALID_VALUE));
2150 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002151 }
2152 if (tex->getTarget() != GL_TEXTURE_2D)
2153 {
Geoff Langb1196682014-07-23 13:47:29 -04002154 context->recordError(Error(GL_INVALID_OPERATION));
2155 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002156 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002157 }
2158 break;
2159
2160 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2161 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2162 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2163 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2164 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2165 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2166 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04002167 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002168 {
Geoff Langb1196682014-07-23 13:47:29 -04002169 context->recordError(Error(GL_INVALID_VALUE));
2170 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002171 }
2172 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
2173 {
Geoff Langb1196682014-07-23 13:47:29 -04002174 context->recordError(Error(GL_INVALID_OPERATION));
2175 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002176 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002177 }
2178 break;
2179
2180 default:
Geoff Langb1196682014-07-23 13:47:29 -04002181 context->recordError(Error(GL_INVALID_ENUM));
2182 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002183 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05002184
2185 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(textarget, level));
2186 if (internalFormatInfo.compressed)
2187 {
2188 context->recordError(Error(GL_INVALID_OPERATION));
2189 return false;
2190 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002191 }
2192
Jamie Madill570f7c82014-07-03 10:38:54 -04002193 return true;
2194}
2195
Geoff Langb1196682014-07-23 13:47:29 -04002196bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04002197{
2198 if (program == 0)
2199 {
Geoff Langb1196682014-07-23 13:47:29 -04002200 context->recordError(Error(GL_INVALID_VALUE));
2201 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002202 }
2203
Dian Xiang769769a2015-09-09 15:20:08 -07002204 gl::Program *programObject = GetValidProgram(context, program);
2205 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05002206 {
2207 return false;
2208 }
2209
Jamie Madill0063c512014-08-25 15:47:53 -04002210 if (!programObject || !programObject->isLinked())
2211 {
Geoff Langb1196682014-07-23 13:47:29 -04002212 context->recordError(Error(GL_INVALID_OPERATION));
2213 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002214 }
2215
Geoff Lang7dd2e102014-11-10 15:19:26 -05002216 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04002217 {
Geoff Langb1196682014-07-23 13:47:29 -04002218 context->recordError(Error(GL_INVALID_OPERATION));
2219 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04002220 }
2221
Jamie Madill0063c512014-08-25 15:47:53 -04002222 return true;
2223}
2224
Geoff Langb1196682014-07-23 13:47:29 -04002225bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params)
Jamie Madill78f41802014-08-25 15:47:55 -04002226{
2227 return ValidateGetUniformBase(context, program, location);
2228}
2229
Geoff Langb1196682014-07-23 13:47:29 -04002230bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04002231{
Jamie Madill78f41802014-08-25 15:47:55 -04002232 return ValidateGetUniformBase(context, program, location);
2233}
2234
Geoff Langb1196682014-07-23 13:47:29 -04002235static bool ValidateSizedGetUniform(Context *context, GLuint program, GLint location, GLsizei bufSize)
Jamie Madill78f41802014-08-25 15:47:55 -04002236{
2237 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04002238 {
Jamie Madill78f41802014-08-25 15:47:55 -04002239 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002240 }
2241
Jamie Madilla502c742014-08-28 17:19:13 -04002242 gl::Program *programObject = context->getProgram(program);
2243 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04002244
Jamie Madill78f41802014-08-25 15:47:55 -04002245 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04002246 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
2247 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04002248 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04002249 {
Geoff Langb1196682014-07-23 13:47:29 -04002250 context->recordError(Error(GL_INVALID_OPERATION));
2251 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002252 }
2253
2254 return true;
2255}
2256
Geoff Langb1196682014-07-23 13:47:29 -04002257bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
Jamie Madill0063c512014-08-25 15:47:53 -04002258{
Jamie Madill78f41802014-08-25 15:47:55 -04002259 return ValidateSizedGetUniform(context, program, location, bufSize);
Jamie Madill0063c512014-08-25 15:47:53 -04002260}
2261
Geoff Langb1196682014-07-23 13:47:29 -04002262bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04002263{
Jamie Madill78f41802014-08-25 15:47:55 -04002264 return ValidateSizedGetUniform(context, program, location, bufSize);
Jamie Madill0063c512014-08-25 15:47:53 -04002265}
2266
Austin Kinross08332632015-05-05 13:35:47 -07002267bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
2268 const GLenum *attachments, bool defaultFramebuffer)
2269{
2270 if (numAttachments < 0)
2271 {
2272 context->recordError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
2273 return false;
2274 }
2275
2276 for (GLsizei i = 0; i < numAttachments; ++i)
2277 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02002278 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07002279 {
2280 if (defaultFramebuffer)
2281 {
2282 context->recordError(Error(GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
2283 return false;
2284 }
2285
2286 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
2287 {
2288 context->recordError(Error(GL_INVALID_OPERATION,
2289 "Requested color attachment is greater than the maximum supported color attachments"));
2290 return false;
2291 }
2292 }
2293 else
2294 {
2295 switch (attachments[i])
2296 {
2297 case GL_DEPTH_ATTACHMENT:
2298 case GL_STENCIL_ATTACHMENT:
2299 case GL_DEPTH_STENCIL_ATTACHMENT:
2300 if (defaultFramebuffer)
2301 {
2302 context->recordError(Error(GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
2303 return false;
2304 }
2305 break;
2306 case GL_COLOR:
2307 case GL_DEPTH:
2308 case GL_STENCIL:
2309 if (!defaultFramebuffer)
2310 {
2311 context->recordError(Error(GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is not bound"));
2312 return false;
2313 }
2314 break;
2315 default:
2316 context->recordError(Error(GL_INVALID_ENUM, "Invalid attachment"));
2317 return false;
2318 }
2319 }
2320 }
2321
2322 return true;
2323}
2324
Austin Kinross6ee1e782015-05-29 17:05:37 -07002325bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
2326{
2327 // Note that debug marker calls must not set error state
2328
2329 if (length < 0)
2330 {
2331 return false;
2332 }
2333
2334 if (marker == nullptr)
2335 {
2336 return false;
2337 }
2338
2339 return true;
2340}
2341
2342bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
2343{
2344 // Note that debug marker calls must not set error state
2345
2346 if (length < 0)
2347 {
2348 return false;
2349 }
2350
2351 if (length > 0 && marker == nullptr)
2352 {
2353 return false;
2354 }
2355
2356 return true;
2357}
2358
Geoff Langdcab33b2015-07-21 13:03:16 -04002359bool ValidateEGLImageTargetTexture2DOES(Context *context,
2360 egl::Display *display,
2361 GLenum target,
2362 egl::Image *image)
2363{
Geoff Langa8406172015-07-21 16:53:39 -04002364 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
2365 {
2366 context->recordError(Error(GL_INVALID_OPERATION));
2367 return false;
2368 }
2369
2370 switch (target)
2371 {
2372 case GL_TEXTURE_2D:
2373 break;
2374
2375 default:
2376 context->recordError(Error(GL_INVALID_ENUM, "invalid texture target."));
2377 return false;
2378 }
2379
2380 if (!display->isValidImage(image))
2381 {
2382 context->recordError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
2383 return false;
2384 }
2385
2386 if (image->getSamples() > 0)
2387 {
2388 context->recordError(Error(GL_INVALID_OPERATION,
2389 "cannot create a 2D texture from a multisampled EGL image."));
2390 return false;
2391 }
2392
2393 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getInternalFormat());
2394 if (!textureCaps.texturable)
2395 {
2396 context->recordError(Error(GL_INVALID_OPERATION,
2397 "EGL image internal format is not supported as a texture."));
2398 return false;
2399 }
2400
Geoff Langdcab33b2015-07-21 13:03:16 -04002401 return true;
2402}
2403
2404bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
2405 egl::Display *display,
2406 GLenum target,
2407 egl::Image *image)
2408{
Geoff Langa8406172015-07-21 16:53:39 -04002409 if (!context->getExtensions().eglImage)
2410 {
2411 context->recordError(Error(GL_INVALID_OPERATION));
2412 return false;
2413 }
2414
2415 switch (target)
2416 {
2417 case GL_RENDERBUFFER:
2418 break;
2419
2420 default:
2421 context->recordError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
2422 return false;
2423 }
2424
2425 if (!display->isValidImage(image))
2426 {
2427 context->recordError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
2428 return false;
2429 }
2430
2431 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getInternalFormat());
2432 if (!textureCaps.renderable)
2433 {
2434 context->recordError(Error(
2435 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
2436 return false;
2437 }
2438
Geoff Langdcab33b2015-07-21 13:03:16 -04002439 return true;
2440}
Austin Kinrossbc781f32015-10-26 09:27:38 -07002441
2442bool ValidateBindVertexArrayBase(Context *context, GLuint array)
2443{
Geoff Lang36167ab2015-12-07 10:27:14 -05002444 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07002445 {
2446 // The default VAO should always exist
2447 ASSERT(array != 0);
2448 context->recordError(Error(GL_INVALID_OPERATION));
2449 return false;
2450 }
2451
2452 return true;
2453}
2454
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002455bool ValidateLinkProgram(Context *context, GLuint program)
2456{
2457 if (context->hasActiveTransformFeedback(program))
2458 {
2459 // ES 3.0.4 section 2.15 page 91
2460 context->recordError(Error(GL_INVALID_OPERATION,
2461 "Cannot link program while program is associated with an active "
2462 "transform feedback object."));
2463 return false;
2464 }
2465 return true;
2466}
2467
Geoff Langc5629752015-12-07 16:29:04 -05002468bool ValidateProgramBinaryBase(Context *context,
2469 GLuint program,
2470 GLenum binaryFormat,
2471 const void *binary,
2472 GLint length)
2473{
2474 Program *programObject = GetValidProgram(context, program);
2475 if (programObject == nullptr)
2476 {
2477 return false;
2478 }
2479
2480 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
2481 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
2482 programBinaryFormats.end())
2483 {
2484 context->recordError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
2485 return false;
2486 }
2487
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002488 if (context->hasActiveTransformFeedback(program))
2489 {
2490 // ES 3.0.4 section 2.15 page 91
2491 context->recordError(Error(GL_INVALID_OPERATION,
2492 "Cannot change program binary while program is associated with "
2493 "an active transform feedback object."));
2494 return false;
2495 }
2496
Geoff Langc5629752015-12-07 16:29:04 -05002497 return true;
2498}
2499
2500bool ValidateGetProgramBinaryBase(Context *context,
2501 GLuint program,
2502 GLsizei bufSize,
2503 GLsizei *length,
2504 GLenum *binaryFormat,
2505 void *binary)
2506{
2507 Program *programObject = GetValidProgram(context, program);
2508 if (programObject == nullptr)
2509 {
2510 return false;
2511 }
2512
2513 if (!programObject->isLinked())
2514 {
2515 context->recordError(Error(GL_INVALID_OPERATION, "Program is not linked."));
2516 return false;
2517 }
2518
2519 return true;
2520}
Jamie Madillc29968b2016-01-20 11:17:23 -05002521
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002522bool ValidateUseProgram(Context *context, GLuint program)
2523{
2524 if (program != 0)
2525 {
2526 Program *programObject = context->getProgram(program);
2527 if (!programObject)
2528 {
2529 // ES 3.1.0 section 7.3 page 72
2530 if (context->getShader(program))
2531 {
2532 context->recordError(
2533 Error(GL_INVALID_OPERATION,
2534 "Attempted to use a single shader instead of a shader program."));
2535 return false;
2536 }
2537 else
2538 {
2539 context->recordError(Error(GL_INVALID_VALUE, "Program invalid."));
2540 return false;
2541 }
2542 }
2543 if (!programObject->isLinked())
2544 {
2545 context->recordError(Error(GL_INVALID_OPERATION, "Program not linked."));
2546 return false;
2547 }
2548 }
2549 if (context->getState().isTransformFeedbackActiveUnpaused())
2550 {
2551 // ES 3.0.4 section 2.15 page 91
2552 context->recordError(
2553 Error(GL_INVALID_OPERATION,
2554 "Cannot change active program while transform feedback is unpaused."));
2555 return false;
2556 }
2557
2558 return true;
2559}
2560
Jamie Madillc29968b2016-01-20 11:17:23 -05002561bool ValidateCopyTexImage2D(ValidationContext *context,
2562 GLenum target,
2563 GLint level,
2564 GLenum internalformat,
2565 GLint x,
2566 GLint y,
2567 GLsizei width,
2568 GLsizei height,
2569 GLint border)
2570{
2571 if (context->getClientVersion() < 3)
2572 {
2573 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
2574 0, x, y, width, height, border);
2575 }
2576
2577 ASSERT(context->getClientVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05002578 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
2579 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002580}
Jamie Madillc29968b2016-01-20 11:17:23 -05002581
2582bool ValidateFramebufferRenderbuffer(Context *context,
2583 GLenum target,
2584 GLenum attachment,
2585 GLenum renderbuffertarget,
2586 GLuint renderbuffer)
2587{
2588 if (!ValidFramebufferTarget(target) ||
2589 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
2590 {
2591 context->recordError(Error(GL_INVALID_ENUM));
2592 return false;
2593 }
2594
2595 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
2596 renderbuffertarget, renderbuffer);
2597}
2598
2599bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
2600{
2601 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
2602 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
2603 {
2604 context->recordError(
2605 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
2606 return false;
2607 }
2608
2609 ASSERT(context->getState().getDrawFramebuffer());
2610 GLuint frameBufferId = context->getState().getDrawFramebuffer()->id();
2611 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
2612
2613 // This should come first before the check for the default frame buffer
2614 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
2615 // rather than INVALID_OPERATION
2616 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
2617 {
2618 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
2619
2620 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02002621 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
2622 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05002623 {
2624 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02002625 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
2626 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
2627 // 3.1 is still a bit ambiguous about the error, but future specs are
2628 // expected to clarify that GL_INVALID_ENUM is the correct error.
2629 context->recordError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
2630 return false;
2631 }
2632 else if (bufs[colorAttachment] >= maxColorAttachment)
2633 {
2634 context->recordError(
2635 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002636 return false;
2637 }
2638 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
2639 frameBufferId != 0)
2640 {
2641 // INVALID_OPERATION-GL is bound to buffer and ith argument
2642 // is not COLOR_ATTACHMENTi or NONE
2643 context->recordError(
2644 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
2645 return false;
2646 }
2647 }
2648
2649 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
2650 // and n is not 1 or bufs is bound to value other than BACK and NONE
2651 if (frameBufferId == 0)
2652 {
2653 if (n != 1)
2654 {
2655 context->recordError(Error(GL_INVALID_OPERATION,
2656 "n must be 1 when GL is bound to the default framebuffer"));
2657 return false;
2658 }
2659
2660 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
2661 {
2662 context->recordError(Error(
2663 GL_INVALID_OPERATION,
2664 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
2665 return false;
2666 }
2667 }
2668
2669 return true;
2670}
2671
2672bool ValidateCopyTexSubImage2D(Context *context,
2673 GLenum target,
2674 GLint level,
2675 GLint xoffset,
2676 GLint yoffset,
2677 GLint x,
2678 GLint y,
2679 GLsizei width,
2680 GLsizei height)
2681{
2682 if (context->getClientVersion() < 3)
2683 {
2684 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
2685 yoffset, x, y, width, height, 0);
2686 }
2687
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05002688 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
2689 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05002690}
2691
Olli Etuaho4f667482016-03-30 15:56:35 +03002692bool ValidateGetBufferPointervBase(Context *context, GLenum target, GLenum pname, void **params)
2693{
2694 if (!ValidBufferTarget(context, target))
2695 {
2696 context->recordError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
2697 return false;
2698 }
2699
2700 if (pname != GL_BUFFER_MAP_POINTER)
2701 {
2702 context->recordError(Error(GL_INVALID_ENUM, "pname not valid: 0x%X", pname));
2703 return false;
2704 }
2705
2706 Buffer *buffer = context->getState().getTargetBuffer(target);
2707
2708 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
2709 // target bound to zero generate an INVALID_OPERATION error."
2710 // GLES 3.1 section 6.6 explicitly specifies this error.
2711 if (!buffer)
2712 {
2713 context->recordError(
2714 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
2715 return false;
2716 }
2717
2718 return true;
2719}
2720
2721bool ValidateUnmapBufferBase(Context *context, GLenum target)
2722{
2723 if (!ValidBufferTarget(context, target))
2724 {
2725 context->recordError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
2726 return false;
2727 }
2728
2729 Buffer *buffer = context->getState().getTargetBuffer(target);
2730
2731 if (buffer == nullptr || !buffer->isMapped())
2732 {
2733 context->recordError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
2734 return false;
2735 }
2736
2737 return true;
2738}
2739
2740bool ValidateMapBufferRangeBase(Context *context,
2741 GLenum target,
2742 GLintptr offset,
2743 GLsizeiptr length,
2744 GLbitfield access)
2745{
2746 if (!ValidBufferTarget(context, target))
2747 {
2748 context->recordError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
2749 return false;
2750 }
2751
2752 if (offset < 0 || length < 0)
2753 {
2754 context->recordError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
2755 return false;
2756 }
2757
2758 Buffer *buffer = context->getState().getTargetBuffer(target);
2759
2760 if (!buffer)
2761 {
2762 context->recordError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
2763 return false;
2764 }
2765
2766 // Check for buffer overflow
2767 size_t offsetSize = static_cast<size_t>(offset);
2768 size_t lengthSize = static_cast<size_t>(length);
2769
2770 if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) ||
2771 offsetSize + lengthSize > static_cast<size_t>(buffer->getSize()))
2772 {
2773 context->recordError(
2774 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
2775 return false;
2776 }
2777
2778 // Check for invalid bits in the mask
2779 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
2780 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
2781 GL_MAP_UNSYNCHRONIZED_BIT;
2782
2783 if (access & ~(allAccessBits))
2784 {
2785 context->recordError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
2786 return false;
2787 }
2788
2789 if (length == 0)
2790 {
2791 context->recordError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
2792 return false;
2793 }
2794
2795 if (buffer->isMapped())
2796 {
2797 context->recordError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
2798 return false;
2799 }
2800
2801 // Check for invalid bit combinations
2802 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
2803 {
2804 context->recordError(
2805 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
2806 return false;
2807 }
2808
2809 GLbitfield writeOnlyBits =
2810 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
2811
2812 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
2813 {
2814 context->recordError(Error(GL_INVALID_OPERATION,
2815 "Invalid access bits when mapping buffer for reading: 0x%X.",
2816 access));
2817 return false;
2818 }
2819
2820 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
2821 {
2822 context->recordError(Error(
2823 GL_INVALID_OPERATION,
2824 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
2825 return false;
2826 }
2827 return true;
2828}
2829
2830bool ValidateFlushMappedBufferRangeBase(Context *context,
2831 GLenum target,
2832 GLintptr offset,
2833 GLsizeiptr length)
2834{
2835 if (offset < 0 || length < 0)
2836 {
2837 context->recordError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
2838 return false;
2839 }
2840
2841 if (!ValidBufferTarget(context, target))
2842 {
2843 context->recordError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
2844 return false;
2845 }
2846
2847 Buffer *buffer = context->getState().getTargetBuffer(target);
2848
2849 if (buffer == nullptr)
2850 {
2851 context->recordError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
2852 return false;
2853 }
2854
2855 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
2856 {
2857 context->recordError(Error(
2858 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
2859 return false;
2860 }
2861
2862 // Check for buffer overflow
2863 size_t offsetSize = static_cast<size_t>(offset);
2864 size_t lengthSize = static_cast<size_t>(length);
2865
2866 if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) ||
2867 offsetSize + lengthSize > static_cast<size_t>(buffer->getMapLength()))
2868 {
2869 context->recordError(
2870 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
2871 return false;
2872 }
2873
2874 return true;
2875}
2876
Olli Etuaho41997e72016-03-10 13:38:39 +02002877bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
2878{
2879 return ValidateGenOrDelete(context, n);
2880}
2881
2882bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
2883{
2884 return ValidateGenOrDelete(context, n);
2885}
2886
2887bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
2888{
2889 return ValidateGenOrDelete(context, n);
2890}
2891
2892bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
2893{
2894 return ValidateGenOrDelete(context, n);
2895}
2896
2897bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
2898{
2899 return ValidateGenOrDelete(context, n);
2900}
2901
2902bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
2903{
2904 return ValidateGenOrDelete(context, n);
2905}
2906
2907bool ValidateGenTextures(Context *context, GLint n, GLuint *)
2908{
2909 return ValidateGenOrDelete(context, n);
2910}
2911
2912bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
2913{
2914 return ValidateGenOrDelete(context, n);
2915}
2916
2917bool ValidateGenOrDelete(Context *context, GLint n)
2918{
2919 if (n < 0)
2920 {
2921 context->recordError(Error(GL_INVALID_VALUE, "n < 0"));
2922 return false;
2923 }
2924 return true;
2925}
2926
Jamie Madillc29968b2016-01-20 11:17:23 -05002927} // namespace gl