blob: fff9088f7fa7fe38e026e75d0a4b6463892fabcd [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/validationES2.h"
12#include "libANGLE/validationES3.h"
13#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040014#include "libANGLE/Display.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Texture.h"
16#include "libANGLE/Framebuffer.h"
17#include "libANGLE/FramebufferAttachment.h"
18#include "libANGLE/formatutils.h"
Geoff Langa8406172015-07-21 16:53:39 -040019#include "libANGLE/Image.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/Query.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050021#include "libANGLE/Program.h"
22#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050023#include "libANGLE/TransformFeedback.h"
24#include "libANGLE/VertexArray.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025
26#include "common/mathutil.h"
27#include "common/utilities.h"
28
Jamie Madille2e406c2016-06-02 13:04:10 -040029using namespace angle;
30
Geoff Lange8ebe7f2013-08-05 15:03:13 -040031namespace gl
32{
Jamie Madille79b1e12015-11-04 16:36:37 -050033const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum element index.";
34
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
Jamie Madillf25855c2015-11-03 11:06:18 -050037bool ValidateDrawAttribs(ValidationContext *context, GLint primcount, GLint maxVertex)
Jamie Madill1ca74672015-07-21 15:14:11 -040038{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070039 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040040 const gl::Program *program = state.getProgram();
41
42 const VertexArray *vao = state.getVertexArray();
43 const auto &vertexAttribs = vao->getVertexAttributes();
Jamie Madill1ca74672015-07-21 15:14:11 -040044 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
45 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
46 {
47 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Jamie Madill63805b42015-08-25 13:17:39 -040048 if (program->isAttribLocationActive(attributeIndex) && attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040049 {
50 gl::Buffer *buffer = attrib.buffer.get();
51
52 if (buffer)
53 {
54 GLint64 attribStride = static_cast<GLint64>(ComputeVertexAttributeStride(attrib));
55 GLint64 maxVertexElement = 0;
56
57 if (attrib.divisor > 0)
58 {
59 maxVertexElement =
60 static_cast<GLint64>(primcount) / static_cast<GLint64>(attrib.divisor);
61 }
62 else
63 {
64 maxVertexElement = static_cast<GLint64>(maxVertex);
65 }
66
67 // If we're drawing zero vertices, we have enough data.
68 if (maxVertexElement > 0)
69 {
70 // Note: Last vertex element does not take the full stride!
71 GLint64 attribSize =
72 static_cast<GLint64>(ComputeVertexAttributeTypeSize(attrib));
73 GLint64 attribDataSize = (maxVertexElement - 1) * attribStride + attribSize;
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040074 GLint64 attribOffset = static_cast<GLint64>(attrib.offset);
Jamie Madill1ca74672015-07-21 15:14:11 -040075
76 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
77 // We can return INVALID_OPERATION if our vertex attribute does not have
78 // enough backing data.
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040079 if (attribDataSize + attribOffset > buffer->getSize())
Jamie Madill1ca74672015-07-21 15:14:11 -040080 {
Jamie Madill437fa652016-05-03 15:13:24 -040081 context->handleError(
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040082 Error(GL_INVALID_OPERATION,
83 "Vertex buffer is not big enough for the draw call"));
Jamie Madill1ca74672015-07-21 15:14:11 -040084 return false;
85 }
86 }
87 }
88 else if (attrib.pointer == NULL)
89 {
90 // This is an application error that would normally result in a crash,
91 // but we catch it and return an error
Jamie Madill437fa652016-05-03 15:13:24 -040092 context->handleError(Error(
Jamie Madill1ca74672015-07-21 15:14:11 -040093 GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer."));
94 return false;
95 }
96 }
97 }
98
99 return true;
100}
101
Geoff Langf607c602016-09-21 11:46:48 -0400102bool ValidReadPixelsFormatType(ValidationContext *context,
103 GLenum framebufferComponentType,
104 GLenum format,
105 GLenum type)
106{
107 switch (framebufferComponentType)
108 {
109 case GL_UNSIGNED_NORMALIZED:
110 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
111 // ReadPixels with BGRA even if the extension is not present
112 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
113 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
114 type == GL_UNSIGNED_BYTE);
115
116 case GL_SIGNED_NORMALIZED:
117 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
118
119 case GL_INT:
120 return (format == GL_RGBA_INTEGER && type == GL_INT);
121
122 case GL_UNSIGNED_INT:
123 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
124
125 case GL_FLOAT:
126 return (format == GL_RGBA && type == GL_FLOAT);
127
128 default:
129 UNREACHABLE();
130 return false;
131 }
132}
133
Geoff Langf41a7152016-09-19 15:11:17 -0400134bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
Geoff Lang0550d032014-01-30 11:29:07 -0500135{
136 switch (cap)
137 {
Geoff Langf41a7152016-09-19 15:11:17 -0400138 // EXT_multisample_compatibility
139 case GL_MULTISAMPLE_EXT:
140 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
141 return context->getExtensions().multisampleCompatibility;
Sami Väisänen74c23472016-05-09 17:30:30 +0300142
Geoff Langf41a7152016-09-19 15:11:17 -0400143 case GL_CULL_FACE:
144 case GL_POLYGON_OFFSET_FILL:
145 case GL_SAMPLE_ALPHA_TO_COVERAGE:
146 case GL_SAMPLE_COVERAGE:
147 case GL_SCISSOR_TEST:
148 case GL_STENCIL_TEST:
149 case GL_DEPTH_TEST:
150 case GL_BLEND:
151 case GL_DITHER:
152 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -0500153
Geoff Langf41a7152016-09-19 15:11:17 -0400154 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
155 case GL_RASTERIZER_DISCARD:
156 return (context->getClientMajorVersion() >= 3);
Geoff Lang70d0f492015-12-10 17:45:46 -0500157
Geoff Langf41a7152016-09-19 15:11:17 -0400158 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
159 case GL_DEBUG_OUTPUT:
160 return context->getExtensions().debug;
Geoff Lang70d0f492015-12-10 17:45:46 -0500161
Geoff Langf41a7152016-09-19 15:11:17 -0400162 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
163 return queryOnly && context->getExtensions().bindGeneratesResource;
164
165 default:
166 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500167 }
168}
169
Geoff Langff5b2d52016-09-07 11:32:23 -0400170bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
171{
172 if (bufSize < numParams)
173 {
174 context->handleError(Error(GL_INVALID_OPERATION,
175 "%u parameters are required but %i were provided.", numParams,
176 bufSize));
177 return false;
178 }
179
180 return true;
181}
182
Geoff Langf41a7152016-09-19 15:11:17 -0400183} // anonymous namespace
184
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500185bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400186{
Jamie Madilld7460c72014-01-21 16:38:14 -0500187 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400188 {
Jamie Madilld7460c72014-01-21 16:38:14 -0500189 case GL_TEXTURE_2D:
190 case GL_TEXTURE_CUBE_MAP:
191 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400192
Jamie Madilld7460c72014-01-21 16:38:14 -0500193 case GL_TEXTURE_3D:
194 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300195 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500196
197 default:
198 return false;
199 }
Jamie Madill35d15012013-10-07 10:46:37 -0400200}
201
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500202bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
203{
204 switch (target)
205 {
206 case GL_TEXTURE_2D:
207 case GL_TEXTURE_CUBE_MAP:
208 return true;
209
210 default:
211 return false;
212 }
213}
214
215bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
216{
217 switch (target)
218 {
219 case GL_TEXTURE_3D:
220 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300221 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500222
223 default:
224 return false;
225 }
226}
227
Ian Ewellbda75592016-04-18 17:25:54 -0400228// Most texture GL calls are not compatible with external textures, so we have a separate validation
229// function for use in the GL calls that do
230bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
231{
232 return (target == GL_TEXTURE_EXTERNAL_OES) &&
233 (context->getExtensions().eglImageExternal ||
234 context->getExtensions().eglStreamConsumerExternal);
235}
236
Shannon Woods4dfed832014-03-17 20:03:39 -0400237// This function differs from ValidTextureTarget in that the target must be
238// usable as the destination of a 2D operation-- so a cube face is valid, but
239// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400240// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500241bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400242{
243 switch (target)
244 {
245 case GL_TEXTURE_2D:
246 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
247 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
248 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
249 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
250 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
251 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
252 return true;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500253 default:
254 return false;
255 }
256}
257
258bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
259{
260 switch (target)
261 {
Shannon Woods4dfed832014-03-17 20:03:39 -0400262 case GL_TEXTURE_3D:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500263 case GL_TEXTURE_2D_ARRAY:
264 return true;
Shannon Woods4dfed832014-03-17 20:03:39 -0400265 default:
266 return false;
267 }
268}
269
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500270bool ValidFramebufferTarget(GLenum target)
271{
Geoff Langd4475812015-03-18 10:53:05 -0400272 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
273 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500274
275 switch (target)
276 {
277 case GL_FRAMEBUFFER: return true;
278 case GL_READ_FRAMEBUFFER: return true;
279 case GL_DRAW_FRAMEBUFFER: return true;
280 default: return false;
281 }
282}
283
Jamie Madill29639852016-09-02 15:00:09 -0400284bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -0500285{
286 switch (target)
287 {
288 case GL_ARRAY_BUFFER:
289 case GL_ELEMENT_ARRAY_BUFFER:
290 return true;
291
Jamie Madill8c96d582014-03-05 15:01:23 -0500292 case GL_PIXEL_PACK_BUFFER:
293 case GL_PIXEL_UNPACK_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +0300294 return (context->getExtensions().pixelBufferObject ||
295 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -0400296
Shannon Woodsb3801742014-03-27 14:59:19 -0400297 case GL_COPY_READ_BUFFER:
298 case GL_COPY_WRITE_BUFFER:
Jamie Madill8c96d582014-03-05 15:01:23 -0500299 case GL_TRANSFORM_FEEDBACK_BUFFER:
300 case GL_UNIFORM_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +0300301 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -0500302
303 default:
304 return false;
305 }
306}
307
Geoff Langff5b2d52016-09-07 11:32:23 -0400308bool ValidBufferParameter(const ValidationContext *context, GLenum pname, GLsizei *numParams)
Jamie Madill70656a62014-03-05 15:01:26 -0500309{
Geoff Langff5b2d52016-09-07 11:32:23 -0400310 // All buffer parameter queries return one value.
311 *numParams = 1;
312
Geoff Langcc6f55d2015-03-20 13:01:02 -0400313 const Extensions &extensions = context->getExtensions();
314
Jamie Madill70656a62014-03-05 15:01:26 -0500315 switch (pname)
316 {
317 case GL_BUFFER_USAGE:
318 case GL_BUFFER_SIZE:
319 return true;
320
Geoff Langcc6f55d2015-03-20 13:01:02 -0400321 case GL_BUFFER_ACCESS_OES:
322 return extensions.mapBuffer;
323
324 case GL_BUFFER_MAPPED:
325 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
Martin Radev1be913c2016-07-11 17:59:16 +0300326 return (context->getClientMajorVersion() >= 3) || extensions.mapBuffer ||
327 extensions.mapBufferRange;
Geoff Langcc6f55d2015-03-20 13:01:02 -0400328
Jamie Madill70656a62014-03-05 15:01:26 -0500329 // GL_BUFFER_MAP_POINTER is a special case, and may only be
330 // queried with GetBufferPointerv
331 case GL_BUFFER_ACCESS_FLAGS:
Jamie Madill70656a62014-03-05 15:01:26 -0500332 case GL_BUFFER_MAP_OFFSET:
333 case GL_BUFFER_MAP_LENGTH:
Martin Radev1be913c2016-07-11 17:59:16 +0300334 return (context->getClientMajorVersion() >= 3) || extensions.mapBufferRange;
Jamie Madill70656a62014-03-05 15:01:26 -0500335
336 default:
337 return false;
338 }
339}
340
Jamie Madillc29968b2016-01-20 11:17:23 -0500341bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400342{
Jamie Madillc29968b2016-01-20 11:17:23 -0500343 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400344 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400345 switch (target)
346 {
Jamie Madillc29968b2016-01-20 11:17:23 -0500347 case GL_TEXTURE_2D:
348 maxDimension = caps.max2DTextureSize;
349 break;
Geoff Langce635692013-09-24 13:56:32 -0400350 case GL_TEXTURE_CUBE_MAP:
351 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
352 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
353 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
354 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
355 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
Jamie Madillc29968b2016-01-20 11:17:23 -0500356 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
357 maxDimension = caps.maxCubeMapTextureSize;
358 break;
359 case GL_TEXTURE_3D:
360 maxDimension = caps.max3DTextureSize;
361 break;
362 case GL_TEXTURE_2D_ARRAY:
363 maxDimension = caps.max2DTextureSize;
364 break;
Geoff Langce635692013-09-24 13:56:32 -0400365 default: UNREACHABLE();
366 }
367
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700368 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -0400369}
370
Austin Kinross08528e12015-10-07 16:24:40 -0700371bool ValidImageSizeParameters(const Context *context,
372 GLenum target,
373 GLint level,
374 GLsizei width,
375 GLsizei height,
376 GLsizei depth,
377 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400378{
379 if (level < 0 || width < 0 || height < 0 || depth < 0)
380 {
381 return false;
382 }
383
Austin Kinross08528e12015-10-07 16:24:40 -0700384 // TexSubImage parameters can be NPOT without textureNPOT extension,
385 // as long as the destination texture is POT.
386 if (!isSubImage && !context->getExtensions().textureNPOT &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400387 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400388 {
389 return false;
390 }
391
392 if (!ValidMipLevel(context, target, level))
393 {
394 return false;
395 }
396
397 return true;
398}
399
Geoff Lang0d8b7242015-09-09 14:56:53 -0400400bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
401{
402 // List of compressed format that require that the texture size is smaller than or a multiple of
403 // the compressed block size.
404 switch (internalFormat)
405 {
406 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
407 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
408 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
409 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -0800410 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -0400411 return true;
412
413 default:
414 return false;
415 }
416}
417
Jamie Madillc29968b2016-01-20 11:17:23 -0500418bool ValidCompressedImageSize(const ValidationContext *context,
419 GLenum internalFormat,
420 GLsizei width,
421 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400422{
Geoff Lang5d601382014-07-22 15:14:06 -0400423 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
424 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400425 {
426 return false;
427 }
428
Geoff Lang0d8b7242015-09-09 14:56:53 -0400429 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400430 {
431 return false;
432 }
433
Geoff Lang0d8b7242015-09-09 14:56:53 -0400434 if (CompressedTextureFormatRequiresExactSize(internalFormat))
435 {
436 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
437 width % formatInfo.compressedBlockWidth != 0) ||
438 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
439 height % formatInfo.compressedBlockHeight != 0))
440 {
441 return false;
442 }
443 }
444
Geoff Langd4f180b2013-09-24 13:57:44 -0400445 return true;
446}
447
Geoff Langff5b2d52016-09-07 11:32:23 -0400448bool ValidImageDataSize(ValidationContext *context,
449 GLenum textureTarget,
450 GLsizei width,
451 GLsizei height,
452 GLsizei depth,
453 GLenum internalFormat,
454 GLenum type,
455 const GLvoid *pixels,
456 GLsizei imageSize)
457{
458 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
459 if (pixelUnpackBuffer == nullptr && imageSize < 0)
460 {
461 // Checks are not required
462 return true;
463 }
464
465 // ...the data would be unpacked from the buffer object such that the memory reads required
466 // would exceed the data store size.
467 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
468 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
469 const gl::Extents size(width, height, depth);
470 const auto &unpack = context->getGLState().getUnpackState();
471
472 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
473 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
474 if (endByteOrErr.isError())
475 {
476 context->handleError(endByteOrErr.getError());
477 return false;
478 }
479
480 GLuint endByte = endByteOrErr.getResult();
481
482 if (pixelUnpackBuffer)
483 {
484 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
485 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
486 checkedEndByte += checkedOffset;
487
488 if (!checkedEndByte.IsValid() ||
489 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
490 {
491 // Overflow past the end of the buffer
492 context->handleError(Error(GL_INVALID_OPERATION));
493 return false;
494 }
495 }
496 else
497 {
498 ASSERT(imageSize >= 0);
499 if (pixels == nullptr && imageSize != 0)
500 {
501 context->handleError(
502 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
503 }
504
505 if (endByte > static_cast<GLuint>(imageSize))
506 {
507 context->handleError(
508 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
509 return false;
510 }
511 }
512
513 return true;
514}
515
Geoff Lang37dde692014-01-31 16:34:54 -0500516bool ValidQueryType(const Context *context, GLenum queryType)
517{
Geoff Langd4475812015-03-18 10:53:05 -0400518 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT, "GL extension enums not equal.");
519 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 -0500520
521 switch (queryType)
522 {
523 case GL_ANY_SAMPLES_PASSED:
524 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
525 return true;
526 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
Martin Radev1be913c2016-07-11 17:59:16 +0300527 return (context->getClientMajorVersion() >= 3);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500528 case GL_TIME_ELAPSED_EXT:
529 return context->getExtensions().disjointTimerQuery;
Geoff Lang2b4ce802016-04-28 13:34:50 -0400530 case GL_COMMANDS_COMPLETED_CHROMIUM:
531 return context->getExtensions().syncQuery;
Geoff Lang37dde692014-01-31 16:34:54 -0500532 default:
533 return false;
534 }
535}
536
Dian Xiang769769a2015-09-09 15:20:08 -0700537Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -0500538{
539 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the
540 // error INVALID_VALUE if the provided name is not the name of either a shader or program object and
541 // INVALID_OPERATION if the provided name identifies an object that is not the expected type."
542
Dian Xiang769769a2015-09-09 15:20:08 -0700543 Program *validProgram = context->getProgram(id);
544
545 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -0500546 {
Dian Xiang769769a2015-09-09 15:20:08 -0700547 if (context->getShader(id))
548 {
Jamie Madill437fa652016-05-03 15:13:24 -0400549 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -0700550 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
551 }
552 else
553 {
Jamie Madill437fa652016-05-03 15:13:24 -0400554 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -0700555 }
Geoff Lang48dcae72014-02-05 16:28:24 -0500556 }
Dian Xiang769769a2015-09-09 15:20:08 -0700557
558 return validProgram;
559}
560
561Shader *GetValidShader(Context *context, GLuint id)
562{
563 // See ValidProgram for spec details.
564
565 Shader *validShader = context->getShader(id);
566
567 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -0500568 {
Dian Xiang769769a2015-09-09 15:20:08 -0700569 if (context->getProgram(id))
570 {
Jamie Madill437fa652016-05-03 15:13:24 -0400571 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -0700572 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
573 }
574 else
575 {
Jamie Madill437fa652016-05-03 15:13:24 -0400576 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -0700577 }
Geoff Lang48dcae72014-02-05 16:28:24 -0500578 }
Dian Xiang769769a2015-09-09 15:20:08 -0700579
580 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -0500581}
582
Geoff Langb1196682014-07-23 13:47:29 -0400583bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -0400584{
585 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
586 {
587 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
588
Geoff Langaae65a42014-05-26 12:43:44 -0400589 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -0400590 {
Jamie Madill437fa652016-05-03 15:13:24 -0400591 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400592 return false;
Jamie Madillb4472272014-07-03 10:38:55 -0400593 }
594 }
595 else
596 {
597 switch (attachment)
598 {
599 case GL_DEPTH_ATTACHMENT:
600 case GL_STENCIL_ATTACHMENT:
Martin Radev1be913c2016-07-11 17:59:16 +0300601 break;
Jamie Madillb4472272014-07-03 10:38:55 -0400602
603 case GL_DEPTH_STENCIL_ATTACHMENT:
Geoff Langc287ea62016-09-16 14:46:51 -0400604 if (!context->getExtensions().webglCompatibility &&
605 context->getClientMajorVersion() < 3)
Martin Radev1be913c2016-07-11 17:59:16 +0300606 {
607 context->handleError(Error(GL_INVALID_ENUM));
608 return false;
609 }
610 break;
Jamie Madillb4472272014-07-03 10:38:55 -0400611
612 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400613 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +0300614 return false;
Jamie Madillb4472272014-07-03 10:38:55 -0400615 }
616 }
617
618 return true;
619}
620
Corentin Walleze0902642014-11-04 12:32:15 -0800621bool ValidateRenderbufferStorageParametersBase(gl::Context *context, GLenum target, GLsizei samples,
622 GLenum internalformat, GLsizei width, GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400623{
624 switch (target)
625 {
626 case GL_RENDERBUFFER:
627 break;
628 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400629 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400630 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400631 }
632
633 if (width < 0 || height < 0 || samples < 0)
634 {
Jamie Madill437fa652016-05-03 15:13:24 -0400635 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400636 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400637 }
638
Geoff Langd87878e2014-09-19 15:42:59 -0400639 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
640 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400641 {
Jamie Madill437fa652016-05-03 15:13:24 -0400642 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400643 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400644 }
645
646 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
647 // 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 -0800648 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -0400649 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400650 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400651 {
Jamie Madill437fa652016-05-03 15:13:24 -0400652 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400653 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400654 }
655
Geoff Langaae65a42014-05-26 12:43:44 -0400656 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400657 {
Jamie Madill437fa652016-05-03 15:13:24 -0400658 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400659 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400660 }
661
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700662 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400663 if (handle == 0)
664 {
Jamie Madill437fa652016-05-03 15:13:24 -0400665 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400666 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400667 }
668
669 return true;
670}
671
Corentin Walleze0902642014-11-04 12:32:15 -0800672bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum target, GLsizei samples,
673 GLenum internalformat, GLsizei width, GLsizei height)
674{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -0800675 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -0800676
677 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -0400678 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -0800679 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -0400680 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -0800681 {
Jamie Madill437fa652016-05-03 15:13:24 -0400682 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -0800683 return false;
684 }
685
686 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
687 // the specified storage. This is different than ES 3.0 in which a sample number higher
688 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -0800689 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +0300690 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -0800691 {
Geoff Langa4903b72015-03-02 16:02:48 -0800692 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
693 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
694 {
Jamie Madill437fa652016-05-03 15:13:24 -0400695 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -0800696 return false;
697 }
Corentin Walleze0902642014-11-04 12:32:15 -0800698 }
699
700 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height);
701}
702
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500703bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
704 GLenum renderbuffertarget, GLuint renderbuffer)
705{
Shannon Woods1da3cf62014-06-27 15:32:23 -0400706 if (!ValidFramebufferTarget(target))
707 {
Jamie Madill437fa652016-05-03 15:13:24 -0400708 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400709 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -0400710 }
711
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700712 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500713
Jamie Madill84115c92015-04-23 15:00:07 -0400714 ASSERT(framebuffer);
715 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500716 {
Jamie Madill437fa652016-05-03 15:13:24 -0400717 context->handleError(
718 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -0400719 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500720 }
721
Jamie Madillb4472272014-07-03 10:38:55 -0400722 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500723 {
Jamie Madillb4472272014-07-03 10:38:55 -0400724 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500725 }
726
Jamie Madillab9d82c2014-01-21 16:38:14 -0500727 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
728 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
729 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
730 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
731 if (renderbuffer != 0)
732 {
733 if (!context->getRenderbuffer(renderbuffer))
734 {
Jamie Madill437fa652016-05-03 15:13:24 -0400735 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400736 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -0500737 }
738 }
739
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500740 return true;
741}
742
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700743bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500744 GLint srcX0,
745 GLint srcY0,
746 GLint srcX1,
747 GLint srcY1,
748 GLint dstX0,
749 GLint dstY0,
750 GLint dstX1,
751 GLint dstY1,
752 GLbitfield mask,
753 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400754{
755 switch (filter)
756 {
757 case GL_NEAREST:
758 break;
759 case GL_LINEAR:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400760 break;
761 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400762 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400763 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400764 }
765
766 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
767 {
Jamie Madill437fa652016-05-03 15:13:24 -0400768 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400769 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400770 }
771
772 if (mask == 0)
773 {
774 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
775 // buffers are copied.
776 return false;
777 }
778
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400779 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
780 // color buffer, leaving only nearest being unfiltered from above
781 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
782 {
Jamie Madill437fa652016-05-03 15:13:24 -0400783 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400784 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400785 }
786
Jamie Madill51f40ec2016-06-15 14:06:00 -0400787 const auto &glState = context->getGLState();
788 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
789 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -0500790
791 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400792 {
Jamie Madill437fa652016-05-03 15:13:24 -0400793 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400794 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400795 }
796
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700797 if (readFramebuffer->id() == drawFramebuffer->id())
798 {
799 context->handleError(Error(GL_INVALID_OPERATION));
800 return false;
801 }
802
Jamie Madill51f40ec2016-06-15 14:06:00 -0400803 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -0500804 {
Jamie Madill437fa652016-05-03 15:13:24 -0400805 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -0500806 return false;
807 }
808
Jamie Madill51f40ec2016-06-15 14:06:00 -0400809 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -0500810 {
Jamie Madill437fa652016-05-03 15:13:24 -0400811 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -0500812 return false;
813 }
814
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700815 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400816 {
Jamie Madill437fa652016-05-03 15:13:24 -0400817 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400818 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400819 }
820
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400821 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
822
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400823 if (mask & GL_COLOR_BUFFER_BIT)
824 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400825 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
826 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -0500827 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400828
829 if (readColorBuffer && drawColorBuffer)
830 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400831 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400832
Geoff Langa15472a2015-08-11 11:48:03 -0400833 for (size_t drawbufferIdx = 0;
834 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400835 {
Geoff Langa15472a2015-08-11 11:48:03 -0400836 const FramebufferAttachment *attachment =
837 drawFramebuffer->getDrawBuffer(drawbufferIdx);
838 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400839 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400840 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400841
Geoff Langb2f3d052013-08-13 12:49:27 -0400842 // The GL ES 3.0.2 spec (pg 193) states that:
843 // 1) If the read buffer is fixed point format, the draw buffer must be as well
844 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
845 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
Jamie Madill6163c752015-12-07 16:32:59 -0500846 // Changes with EXT_color_buffer_float:
847 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -0400848 GLenum readComponentType = readFormat.info->componentType;
849 GLenum drawComponentType = drawFormat.info->componentType;
Jamie Madill6163c752015-12-07 16:32:59 -0500850 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
851 readComponentType == GL_SIGNED_NORMALIZED);
852 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
853 drawComponentType == GL_SIGNED_NORMALIZED);
854
855 if (extensions.colorBufferFloat)
856 {
857 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
858 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
859
860 if (readFixedOrFloat != drawFixedOrFloat)
861 {
Jamie Madill437fa652016-05-03 15:13:24 -0400862 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -0500863 "If the read buffer contains fixed-point or "
864 "floating-point values, the draw buffer "
865 "must as well."));
866 return false;
867 }
868 }
869 else if (readFixedPoint != drawFixedPoint)
870 {
Jamie Madill437fa652016-05-03 15:13:24 -0400871 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -0500872 "If the read buffer contains fixed-point "
873 "values, the draw buffer must as well."));
874 return false;
875 }
876
877 if (readComponentType == GL_UNSIGNED_INT &&
878 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400879 {
Jamie Madill437fa652016-05-03 15:13:24 -0400880 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400881 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400882 }
883
Jamie Madill6163c752015-12-07 16:32:59 -0500884 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400885 {
Jamie Madill437fa652016-05-03 15:13:24 -0400886 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400887 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400888 }
889
Jamie Madilla3944d42016-07-22 22:13:26 -0400890 if (readColorBuffer->getSamples() > 0 &&
891 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400892 {
Jamie Madill437fa652016-05-03 15:13:24 -0400893 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400894 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400895 }
896 }
897 }
898
Jamie Madilla3944d42016-07-22 22:13:26 -0400899 if ((readFormat.info->componentType == GL_INT ||
900 readFormat.info->componentType == GL_UNSIGNED_INT) &&
901 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400902 {
Jamie Madill437fa652016-05-03 15:13:24 -0400903 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400904 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400905 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400906 }
907 }
908
Dongseong Hwang44b422c2014-12-09 15:42:01 +0200909 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
910 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
911 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400912 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +0200913 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400914 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400915 const gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]);
916 const gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400917
Dongseong Hwang44b422c2014-12-09 15:42:01 +0200918 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400919 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400920 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400921 {
Jamie Madill437fa652016-05-03 15:13:24 -0400922 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400923 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400924 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400925
Dongseong Hwang44b422c2014-12-09 15:42:01 +0200926 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400927 {
Jamie Madill437fa652016-05-03 15:13:24 -0400928 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400929 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400930 }
931 }
932 }
933 }
934
935 return true;
936}
937
Geoff Langb1196682014-07-23 13:47:29 -0400938bool ValidateGetVertexAttribParameters(Context *context, GLenum pname)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400939{
940 switch (pname)
941 {
942 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
943 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
944 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
945 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
946 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
947 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
948 case GL_CURRENT_VERTEX_ATTRIB:
Martin Radev1be913c2016-07-11 17:59:16 +0300949 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400950
951 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
Martin Radev1be913c2016-07-11 17:59:16 +0300952 // Don't verify ES3 context because GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE uses
953 // the same constant.
954 static_assert(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
955 "ANGLE extension enums not equal to GL enums.");
956 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400957
958 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Martin Radev1be913c2016-07-11 17:59:16 +0300959 if (context->getClientMajorVersion() < 3)
960 {
961 context->handleError(Error(GL_INVALID_ENUM));
962 return false;
963 }
964 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400965
966 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400967 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +0300968 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400969 }
970}
971
Ian Ewellbda75592016-04-18 17:25:54 -0400972bool ValidateTexParamParameters(gl::Context *context, GLenum target, GLenum pname, GLint param)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400973{
974 switch (pname)
975 {
976 case GL_TEXTURE_WRAP_R:
977 case GL_TEXTURE_SWIZZLE_R:
978 case GL_TEXTURE_SWIZZLE_G:
979 case GL_TEXTURE_SWIZZLE_B:
980 case GL_TEXTURE_SWIZZLE_A:
981 case GL_TEXTURE_BASE_LEVEL:
982 case GL_TEXTURE_MAX_LEVEL:
983 case GL_TEXTURE_COMPARE_MODE:
984 case GL_TEXTURE_COMPARE_FUNC:
985 case GL_TEXTURE_MIN_LOD:
986 case GL_TEXTURE_MAX_LOD:
Martin Radev1be913c2016-07-11 17:59:16 +0300987 if (context->getClientMajorVersion() < 3)
988 {
989 context->handleError(Error(GL_INVALID_ENUM));
990 return false;
991 }
992 if (target == GL_TEXTURE_EXTERNAL_OES && !context->getExtensions().eglImageExternalEssl3)
993 {
994 context->handleError(Error(GL_INVALID_ENUM,
995 "ES3 texture parameters are not available without "
996 "GL_OES_EGL_image_external_essl3."));
997 return false;
998 }
999 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001000
1001 default: break;
1002 }
1003
1004 switch (pname)
1005 {
1006 case GL_TEXTURE_WRAP_S:
1007 case GL_TEXTURE_WRAP_T:
1008 case GL_TEXTURE_WRAP_R:
1009 switch (param)
1010 {
Corentin Wallez9670b032016-04-29 09:47:47 +00001011 case GL_CLAMP_TO_EDGE:
Ian Ewellbda75592016-04-18 17:25:54 -04001012 return true;
1013 case GL_REPEAT:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001014 case GL_MIRRORED_REPEAT:
Olli Etuahobd329092016-04-29 12:51:42 +03001015 if (target == GL_TEXTURE_EXTERNAL_OES)
1016 {
1017 // OES_EGL_image_external specifies this error.
Jamie Madill437fa652016-05-03 15:13:24 -04001018 context->handleError(Error(
Olli Etuahobd329092016-04-29 12:51:42 +03001019 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
1020 return false;
1021 }
1022 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001023 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001024 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001025 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001026 }
1027
1028 case GL_TEXTURE_MIN_FILTER:
1029 switch (param)
1030 {
1031 case GL_NEAREST:
1032 case GL_LINEAR:
Ian Ewellbda75592016-04-18 17:25:54 -04001033 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001034 case GL_NEAREST_MIPMAP_NEAREST:
1035 case GL_LINEAR_MIPMAP_NEAREST:
1036 case GL_NEAREST_MIPMAP_LINEAR:
1037 case GL_LINEAR_MIPMAP_LINEAR:
Olli Etuahobd329092016-04-29 12:51:42 +03001038 if (target == GL_TEXTURE_EXTERNAL_OES)
1039 {
1040 // OES_EGL_image_external specifies this error.
Jamie Madill437fa652016-05-03 15:13:24 -04001041 context->handleError(
Olli Etuahobd329092016-04-29 12:51:42 +03001042 Error(GL_INVALID_ENUM,
1043 "external textures only support NEAREST and LINEAR filtering"));
1044 return false;
1045 }
1046 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001047 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001048 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001049 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001050 }
1051 break;
1052
1053 case GL_TEXTURE_MAG_FILTER:
1054 switch (param)
1055 {
1056 case GL_NEAREST:
1057 case GL_LINEAR:
1058 return true;
1059 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001060 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001061 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001062 }
1063 break;
1064
1065 case GL_TEXTURE_USAGE_ANGLE:
1066 switch (param)
1067 {
1068 case GL_NONE:
1069 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
1070 return true;
1071 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001072 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001073 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001074 }
1075 break;
1076
1077 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001078 if (!context->getExtensions().textureFilterAnisotropic)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001079 {
Jamie Madill437fa652016-05-03 15:13:24 -04001080 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001081 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001082 }
1083
1084 // we assume the parameter passed to this validation method is truncated, not rounded
1085 if (param < 1)
1086 {
Jamie Madill437fa652016-05-03 15:13:24 -04001087 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001088 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001089 }
1090 return true;
1091
1092 case GL_TEXTURE_MIN_LOD:
1093 case GL_TEXTURE_MAX_LOD:
1094 // any value is permissible
1095 return true;
1096
1097 case GL_TEXTURE_COMPARE_MODE:
Geoff Lang63b5f1f2013-09-23 14:52:14 -04001098 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001099 switch (param)
1100 {
1101 case GL_NONE:
1102 case GL_COMPARE_REF_TO_TEXTURE:
1103 return true;
1104 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001105 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001106 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001107 }
1108 break;
1109
1110 case GL_TEXTURE_COMPARE_FUNC:
Geoff Lang63b5f1f2013-09-23 14:52:14 -04001111 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001112 switch (param)
1113 {
1114 case GL_LEQUAL:
1115 case GL_GEQUAL:
1116 case GL_LESS:
1117 case GL_GREATER:
1118 case GL_EQUAL:
1119 case GL_NOTEQUAL:
1120 case GL_ALWAYS:
1121 case GL_NEVER:
1122 return true;
1123 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001124 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001125 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001126 }
1127 break;
1128
1129 case GL_TEXTURE_SWIZZLE_R:
1130 case GL_TEXTURE_SWIZZLE_G:
1131 case GL_TEXTURE_SWIZZLE_B:
1132 case GL_TEXTURE_SWIZZLE_A:
Geoff Langbc90a482013-09-17 16:51:27 -04001133 switch (param)
1134 {
1135 case GL_RED:
1136 case GL_GREEN:
1137 case GL_BLUE:
1138 case GL_ALPHA:
1139 case GL_ZERO:
1140 case GL_ONE:
1141 return true;
1142 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001143 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001144 return false;
Geoff Langbc90a482013-09-17 16:51:27 -04001145 }
1146 break;
1147
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001148 case GL_TEXTURE_BASE_LEVEL:
Geoff Langb66a9092016-05-16 15:59:14 -04001149 if (param < 0)
Olli Etuahoa314b612016-03-10 16:43:00 +02001150 {
Geoff Langb66a9092016-05-16 15:59:14 -04001151 context->handleError(Error(GL_INVALID_VALUE));
Olli Etuahoa314b612016-03-10 16:43:00 +02001152 return false;
1153 }
Geoff Langb66a9092016-05-16 15:59:14 -04001154 if (target == GL_TEXTURE_EXTERNAL_OES && param != 0)
1155 {
1156 context->handleError(
1157 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
1158 return false;
1159 }
1160 return true;
1161
1162 case GL_TEXTURE_MAX_LEVEL:
Olli Etuahoa314b612016-03-10 16:43:00 +02001163 if (param < 0)
1164 {
1165 context->handleError(Error(GL_INVALID_VALUE));
1166 return false;
1167 }
1168 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001169 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001170 context->handleError(Error(GL_INVALID_ENUM));
Olli Etuahoa314b612016-03-10 16:43:00 +02001171 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001172 }
1173}
1174
Geoff Langb1196682014-07-23 13:47:29 -04001175bool ValidateSamplerObjectParameter(gl::Context *context, GLenum pname)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001176{
1177 switch (pname)
1178 {
1179 case GL_TEXTURE_MIN_FILTER:
1180 case GL_TEXTURE_MAG_FILTER:
1181 case GL_TEXTURE_WRAP_S:
1182 case GL_TEXTURE_WRAP_T:
1183 case GL_TEXTURE_WRAP_R:
1184 case GL_TEXTURE_MIN_LOD:
1185 case GL_TEXTURE_MAX_LOD:
1186 case GL_TEXTURE_COMPARE_MODE:
1187 case GL_TEXTURE_COMPARE_FUNC:
1188 return true;
1189
1190 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001191 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001192 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001193 }
1194}
1195
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001196bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001197 GLint x,
1198 GLint y,
1199 GLsizei width,
1200 GLsizei height,
1201 GLenum format,
1202 GLenum type,
1203 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05001204{
Jamie Madillc29968b2016-01-20 11:17:23 -05001205 if (width < 0 || height < 0)
1206 {
Jamie Madill437fa652016-05-03 15:13:24 -04001207 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001208 return false;
1209 }
1210
Jamie Madill51f40ec2016-06-15 14:06:00 -04001211 auto readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madill26e91952014-03-05 15:01:27 -05001212
Jamie Madill51f40ec2016-06-15 14:06:00 -04001213 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill26e91952014-03-05 15:01:27 -05001214 {
Jamie Madill437fa652016-05-03 15:13:24 -04001215 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001216 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001217 }
1218
Jamie Madill51f40ec2016-06-15 14:06:00 -04001219 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill26e91952014-03-05 15:01:27 -05001220 {
Jamie Madill437fa652016-05-03 15:13:24 -04001221 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001222 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001223 }
1224
Jamie Madill51f40ec2016-06-15 14:06:00 -04001225 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
1226 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03001227
1228 if (framebuffer->getReadBufferState() == GL_NONE)
1229 {
1230 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
1231 return false;
1232 }
1233
Geoff Langbce529e2014-12-01 12:48:41 -05001234 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
1235 if (!readBuffer)
Jamie Madill893ab082014-05-16 16:56:10 -04001236 {
Jamie Madill437fa652016-05-03 15:13:24 -04001237 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001238 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001239 }
1240
Geoff Langbce529e2014-12-01 12:48:41 -05001241 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
1242 GLenum currentType = framebuffer->getImplementationColorReadType();
Jamie Madilla3944d42016-07-22 22:13:26 -04001243 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
Jamie Madill26e91952014-03-05 15:01:27 -05001244
Geoff Langf607c602016-09-21 11:46:48 -04001245 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
1246 bool validFormatTypeCombination =
1247 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
Jamie Madill26e91952014-03-05 15:01:27 -05001248
Geoff Langf607c602016-09-21 11:46:48 -04001249 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
Jamie Madill26e91952014-03-05 15:01:27 -05001250 {
Jamie Madill437fa652016-05-03 15:13:24 -04001251 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001252 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001253 }
1254
Corentin Wallezece7c5a2016-09-21 15:28:23 -04001255 // Check for pixel pack buffer related API errors
1256 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
1257 if (pixelPackBuffer != nullptr)
1258 {
1259 // .. the data would be packed to the buffer object such that the memory writes required
1260 // would exceed the data store size.
1261 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
1262 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
1263 const gl::Extents size(width, height, 1);
1264 const auto &pack = context->getGLState().getPackState();
1265
Corentin Wallez886de362016-09-27 10:49:35 -04001266 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
Corentin Wallezece7c5a2016-09-21 15:28:23 -04001267 if (endByteOrErr.isError())
1268 {
1269 context->handleError(endByteOrErr.getError());
1270 return false;
1271 }
1272
1273 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1274 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1275 checkedEndByte += checkedOffset;
1276
1277 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
1278 {
1279 // Overflow past the end of the buffer
1280 context->handleError(
1281 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
1282 return false;
1283 }
1284
1285 // ...the buffer object's data store is currently mapped.
1286 if (pixelPackBuffer->isMapped())
1287 {
1288 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
1289 return false;
1290 }
1291 }
1292
Jamie Madillc29968b2016-01-20 11:17:23 -05001293 return true;
1294}
1295
1296bool ValidateReadnPixelsEXT(Context *context,
1297 GLint x,
1298 GLint y,
1299 GLsizei width,
1300 GLsizei height,
1301 GLenum format,
1302 GLenum type,
1303 GLsizei bufSize,
1304 GLvoid *pixels)
1305{
1306 if (bufSize < 0)
1307 {
Jamie Madill437fa652016-05-03 15:13:24 -04001308 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001309 return false;
1310 }
1311
Geoff Lang5d601382014-07-22 15:14:06 -04001312 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
Corentin Wallezece7c5a2016-09-21 15:28:23 -04001313 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
1314 const gl::Extents size(width, height, 1);
1315 const auto &pack = context->getGLState().getPackState();
Jamie Madill26e91952014-03-05 15:01:27 -05001316
Corentin Wallez886de362016-09-27 10:49:35 -04001317 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
Corentin Wallezece7c5a2016-09-21 15:28:23 -04001318 if (endByteOrErr.isError())
Jamie Madille2e406c2016-06-02 13:04:10 -04001319 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -04001320 context->handleError(endByteOrErr.getError());
Jamie Madille2e406c2016-06-02 13:04:10 -04001321 return false;
1322 }
1323
Corentin Wallezece7c5a2016-09-21 15:28:23 -04001324 if (endByteOrErr.getResult() > static_cast<GLuint>(bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001325 {
Corentin Wallezece7c5a2016-09-21 15:28:23 -04001326 context->handleError(Error(GL_INVALID_OPERATION, "Writes would overflow past bufSize."));
Jamie Madillc29968b2016-01-20 11:17:23 -05001327 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001328 }
1329
Jamie Madillc29968b2016-01-20 11:17:23 -05001330 return ValidateReadPixels(context, x, y, width, height, format, type, pixels);
Jamie Madill26e91952014-03-05 15:01:27 -05001331}
1332
Olli Etuaho41997e72016-03-10 13:38:39 +02001333bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001334{
1335 if (!context->getExtensions().occlusionQueryBoolean &&
1336 !context->getExtensions().disjointTimerQuery)
1337 {
Jamie Madill437fa652016-05-03 15:13:24 -04001338 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001339 return false;
1340 }
1341
Olli Etuaho41997e72016-03-10 13:38:39 +02001342 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001343}
1344
Olli Etuaho41997e72016-03-10 13:38:39 +02001345bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001346{
1347 if (!context->getExtensions().occlusionQueryBoolean &&
1348 !context->getExtensions().disjointTimerQuery)
1349 {
Jamie Madill437fa652016-05-03 15:13:24 -04001350 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001351 return false;
1352 }
1353
Olli Etuaho41997e72016-03-10 13:38:39 +02001354 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001355}
1356
1357bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001358{
1359 if (!ValidQueryType(context, target))
1360 {
Jamie Madill437fa652016-05-03 15:13:24 -04001361 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04001362 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001363 }
1364
1365 if (id == 0)
1366 {
Jamie Madill437fa652016-05-03 15:13:24 -04001367 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04001368 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001369 }
1370
1371 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1372 // of zero, if the active query object name for <target> is non-zero (for the
1373 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1374 // the active query for either target is non-zero), if <id> is the name of an
1375 // existing query object whose type does not match <target>, or if <id> is the
1376 // active query object name for any query type, the error INVALID_OPERATION is
1377 // generated.
1378
1379 // Ensure no other queries are active
1380 // NOTE: If other queries than occlusion are supported, we will need to check
1381 // separately that:
1382 // a) The query ID passed is not the current active query for any target/type
1383 // b) There are no active queries for the requested target (and in the case
1384 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1385 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001386
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001387 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001388 {
Jamie Madill437fa652016-05-03 15:13:24 -04001389 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04001390 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001391 }
1392
1393 Query *queryObject = context->getQuery(id, true, target);
1394
1395 // check that name was obtained with glGenQueries
1396 if (!queryObject)
1397 {
Jamie Madill437fa652016-05-03 15:13:24 -04001398 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04001399 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001400 }
1401
1402 // check for type mismatch
1403 if (queryObject->getType() != target)
1404 {
Jamie Madill437fa652016-05-03 15:13:24 -04001405 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04001406 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001407 }
1408
1409 return true;
1410}
1411
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001412bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1413{
1414 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001415 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001416 {
Jamie Madill437fa652016-05-03 15:13:24 -04001417 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001418 return false;
1419 }
1420
1421 return ValidateBeginQueryBase(context, target, id);
1422}
1423
1424bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001425{
1426 if (!ValidQueryType(context, target))
1427 {
Jamie Madill437fa652016-05-03 15:13:24 -04001428 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04001429 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001430 }
1431
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001432 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001433
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001434 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001435 {
Jamie Madill437fa652016-05-03 15:13:24 -04001436 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04001437 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001438 }
1439
Jamie Madill45c785d2014-05-13 14:09:34 -04001440 return true;
1441}
1442
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001443bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1444{
1445 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001446 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001447 {
Jamie Madill437fa652016-05-03 15:13:24 -04001448 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001449 return false;
1450 }
1451
1452 return ValidateEndQueryBase(context, target);
1453}
1454
1455bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1456{
1457 if (!context->getExtensions().disjointTimerQuery)
1458 {
Jamie Madill437fa652016-05-03 15:13:24 -04001459 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001460 return false;
1461 }
1462
1463 if (target != GL_TIMESTAMP_EXT)
1464 {
Jamie Madill437fa652016-05-03 15:13:24 -04001465 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001466 return false;
1467 }
1468
1469 Query *queryObject = context->getQuery(id, true, target);
1470 if (queryObject == nullptr)
1471 {
Jamie Madill437fa652016-05-03 15:13:24 -04001472 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001473 return false;
1474 }
1475
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001476 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001477 {
Jamie Madill437fa652016-05-03 15:13:24 -04001478 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001479 return false;
1480 }
1481
1482 return true;
1483}
1484
1485bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname)
1486{
1487 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1488 {
Jamie Madill437fa652016-05-03 15:13:24 -04001489 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001490 return false;
1491 }
1492
1493 switch (pname)
1494 {
1495 case GL_CURRENT_QUERY_EXT:
1496 if (target == GL_TIMESTAMP_EXT)
1497 {
Jamie Madill437fa652016-05-03 15:13:24 -04001498 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001499 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
1500 return false;
1501 }
1502 break;
1503 case GL_QUERY_COUNTER_BITS_EXT:
1504 if (!context->getExtensions().disjointTimerQuery ||
1505 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1506 {
Jamie Madill437fa652016-05-03 15:13:24 -04001507 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001508 return false;
1509 }
1510 break;
1511 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001512 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001513 return false;
1514 }
1515
1516 return true;
1517}
1518
1519bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1520{
1521 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001522 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001523 {
Jamie Madill437fa652016-05-03 15:13:24 -04001524 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001525 return false;
1526 }
1527
1528 return ValidateGetQueryivBase(context, target, pname);
1529}
1530
1531bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname)
1532{
1533 Query *queryObject = context->getQuery(id, false, GL_NONE);
1534
1535 if (!queryObject)
1536 {
Jamie Madill437fa652016-05-03 15:13:24 -04001537 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001538 return false;
1539 }
1540
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001541 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001542 {
Jamie Madill437fa652016-05-03 15:13:24 -04001543 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001544 return false;
1545 }
1546
1547 switch (pname)
1548 {
1549 case GL_QUERY_RESULT_EXT:
1550 case GL_QUERY_RESULT_AVAILABLE_EXT:
1551 break;
1552
1553 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001554 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001555 return false;
1556 }
1557
1558 return true;
1559}
1560
1561bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1562{
1563 if (!context->getExtensions().disjointTimerQuery)
1564 {
Jamie Madill437fa652016-05-03 15:13:24 -04001565 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001566 return false;
1567 }
1568 return ValidateGetQueryObjectValueBase(context, id, pname);
1569}
1570
1571bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1572{
1573 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001574 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001575 {
Jamie Madill437fa652016-05-03 15:13:24 -04001576 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001577 return false;
1578 }
1579 return ValidateGetQueryObjectValueBase(context, id, pname);
1580}
1581
1582bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1583{
1584 if (!context->getExtensions().disjointTimerQuery)
1585 {
Jamie Madill437fa652016-05-03 15:13:24 -04001586 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001587 return false;
1588 }
1589 return ValidateGetQueryObjectValueBase(context, id, pname);
1590}
1591
1592bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1593{
1594 if (!context->getExtensions().disjointTimerQuery)
1595 {
Jamie Madill437fa652016-05-03 15:13:24 -04001596 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001597 return false;
1598 }
1599 return ValidateGetQueryObjectValueBase(context, id, pname);
1600}
1601
Jamie Madill62d31cb2015-09-11 13:25:51 -04001602static bool ValidateUniformCommonBase(gl::Context *context,
1603 GLenum targetUniformType,
1604 GLint location,
1605 GLsizei count,
1606 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001607{
1608 if (count < 0)
1609 {
Jamie Madill437fa652016-05-03 15:13:24 -04001610 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001611 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001612 }
1613
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001614 gl::Program *program = context->getGLState().getProgram();
Geoff Lang7dd2e102014-11-10 15:19:26 -05001615 if (!program)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001616 {
Jamie Madill437fa652016-05-03 15:13:24 -04001617 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001618 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001619 }
1620
Geoff Langd8605522016-04-13 10:19:12 -04001621 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001622 {
1623 // Silently ignore the uniform command
1624 return false;
1625 }
1626
Geoff Lang7dd2e102014-11-10 15:19:26 -05001627 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04001628 {
Jamie Madill437fa652016-05-03 15:13:24 -04001629 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001630 return false;
Jamie Madill36398922014-05-20 14:51:53 -04001631 }
1632
Jamie Madill62d31cb2015-09-11 13:25:51 -04001633 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04001634
1635 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04001636 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04001637 {
Jamie Madill437fa652016-05-03 15:13:24 -04001638 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001639 return false;
Jamie Madill36398922014-05-20 14:51:53 -04001640 }
1641
Jamie Madill62d31cb2015-09-11 13:25:51 -04001642 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001643 return true;
1644}
1645
Jamie Madillaa981bd2014-05-20 10:55:55 -04001646bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
1647{
1648 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03001649 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
1650 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04001651 {
Jamie Madill437fa652016-05-03 15:13:24 -04001652 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001653 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001654 }
1655
Jamie Madill62d31cb2015-09-11 13:25:51 -04001656 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04001657 if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
1658 {
1659 return false;
1660 }
1661
Jamie Madillf2575982014-06-25 16:04:54 -04001662 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05001663 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04001664 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
1665 {
Jamie Madill437fa652016-05-03 15:13:24 -04001666 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001667 return false;
Jamie Madill36398922014-05-20 14:51:53 -04001668 }
1669
1670 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001671}
1672
1673bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count,
1674 GLboolean transpose)
1675{
1676 // Check for ES3 uniform entry points
1677 int rows = VariableRowCount(matrixType);
1678 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03001679 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04001680 {
Jamie Madill437fa652016-05-03 15:13:24 -04001681 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001682 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001683 }
1684
Martin Radev1be913c2016-07-11 17:59:16 +03001685 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04001686 {
Jamie Madill437fa652016-05-03 15:13:24 -04001687 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001688 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001689 }
1690
Jamie Madill62d31cb2015-09-11 13:25:51 -04001691 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04001692 if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
1693 {
1694 return false;
1695 }
1696
1697 if (uniform->type != matrixType)
1698 {
Jamie Madill437fa652016-05-03 15:13:24 -04001699 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001700 return false;
Jamie Madill36398922014-05-20 14:51:53 -04001701 }
1702
1703 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001704}
1705
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001706bool ValidateStateQuery(ValidationContext *context,
1707 GLenum pname,
1708 GLenum *nativeType,
1709 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04001710{
1711 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
1712 {
Jamie Madill437fa652016-05-03 15:13:24 -04001713 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001714 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001715 }
1716
Jamie Madill0af26e12015-03-05 19:54:33 -05001717 const Caps &caps = context->getCaps();
1718
Jamie Madill893ab082014-05-16 16:56:10 -04001719 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
1720 {
1721 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
1722
Jamie Madill0af26e12015-03-05 19:54:33 -05001723 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04001724 {
Jamie Madill437fa652016-05-03 15:13:24 -04001725 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001726 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001727 }
1728 }
1729
1730 switch (pname)
1731 {
1732 case GL_TEXTURE_BINDING_2D:
1733 case GL_TEXTURE_BINDING_CUBE_MAP:
1734 case GL_TEXTURE_BINDING_3D:
1735 case GL_TEXTURE_BINDING_2D_ARRAY:
Jamie Madill893ab082014-05-16 16:56:10 -04001736 break;
Ian Ewell54f87462016-03-10 13:47:21 -05001737 case GL_TEXTURE_BINDING_EXTERNAL_OES:
John Bauman18319182016-09-28 14:22:27 -07001738 if (!context->getExtensions().eglStreamConsumerExternal &&
1739 !context->getExtensions().eglImageExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05001740 {
John Bauman18319182016-09-28 14:22:27 -07001741 context->handleError(Error(GL_INVALID_ENUM,
1742 "Neither NV_EGL_stream_consumer_external nor "
1743 "GL_OES_EGL_image_external extensions enabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05001744 return false;
1745 }
1746 break;
Jamie Madill893ab082014-05-16 16:56:10 -04001747
1748 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1749 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1750 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04001751 if (context->getGLState().getReadFramebuffer()->checkStatus(
1752 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04001753 {
Jamie Madill437fa652016-05-03 15:13:24 -04001754 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001755 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001756 }
1757
Jamie Madill51f40ec2016-06-15 14:06:00 -04001758 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
1759 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03001760
1761 if (framebuffer->getReadBufferState() == GL_NONE)
1762 {
1763 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
1764 return false;
1765 }
1766
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001767 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04001768 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04001769 {
Jamie Madill437fa652016-05-03 15:13:24 -04001770 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001771 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001772 }
1773 }
1774 break;
1775
1776 default:
1777 break;
1778 }
1779
1780 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04001781 if (*numParams == 0)
1782 {
1783 return false;
1784 }
1785
1786 return true;
1787}
1788
1789bool ValidateRobustStateQuery(ValidationContext *context,
1790 GLenum pname,
1791 GLsizei bufSize,
1792 GLenum *nativeType,
1793 unsigned int *numParams)
1794{
1795 if (!ValidateRobustEntryPoint(context, bufSize))
1796 {
1797 return false;
1798 }
1799
1800 if (!ValidateStateQuery(context, pname, nativeType, numParams))
1801 {
1802 return false;
1803 }
1804
1805 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04001806 {
1807 return false;
1808 }
1809
1810 return true;
1811}
1812
Jamie Madillc29968b2016-01-20 11:17:23 -05001813bool ValidateCopyTexImageParametersBase(ValidationContext *context,
1814 GLenum target,
1815 GLint level,
1816 GLenum internalformat,
1817 bool isSubImage,
1818 GLint xoffset,
1819 GLint yoffset,
1820 GLint zoffset,
1821 GLint x,
1822 GLint y,
1823 GLsizei width,
1824 GLsizei height,
1825 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04001826 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04001827{
Jamie Madill560a8d82014-05-21 13:06:20 -04001828 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
1829 {
Jamie Madill437fa652016-05-03 15:13:24 -04001830 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001831 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001832 }
1833
1834 if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1835 {
Jamie Madill437fa652016-05-03 15:13:24 -04001836 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001837 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001838 }
1839
1840 if (border != 0)
1841 {
Jamie Madill437fa652016-05-03 15:13:24 -04001842 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001843 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001844 }
1845
1846 if (!ValidMipLevel(context, target, level))
1847 {
Jamie Madill437fa652016-05-03 15:13:24 -04001848 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001849 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001850 }
1851
Jamie Madill51f40ec2016-06-15 14:06:00 -04001852 const auto &state = context->getGLState();
1853 auto readFramebuffer = state.getReadFramebuffer();
1854 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04001855 {
Jamie Madill437fa652016-05-03 15:13:24 -04001856 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001857 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001858 }
1859
Jamie Madill51f40ec2016-06-15 14:06:00 -04001860 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04001861 {
Jamie Madill437fa652016-05-03 15:13:24 -04001862 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001863 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001864 }
1865
Martin Radev138064f2016-07-15 12:03:41 +03001866 if (readFramebuffer->getReadBufferState() == GL_NONE)
1867 {
1868 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
1869 return false;
1870 }
1871
Geoff Langaae65a42014-05-26 12:43:44 -04001872 const gl::Caps &caps = context->getCaps();
1873
Geoff Langaae65a42014-05-26 12:43:44 -04001874 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04001875 switch (target)
1876 {
1877 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05001878 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04001879 break;
1880
1881 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1882 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1883 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1884 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1885 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1886 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -05001887 maxDimension = caps.maxCubeMapTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04001888 break;
1889
1890 case GL_TEXTURE_2D_ARRAY:
Geoff Langa9be0dc2014-12-17 12:34:40 -05001891 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04001892 break;
1893
1894 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05001895 maxDimension = caps.max3DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04001896 break;
1897
1898 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001899 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001900 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001901 }
1902
Jamie Madillc29968b2016-01-20 11:17:23 -05001903 gl::Texture *texture =
1904 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04001905 if (!texture)
1906 {
Jamie Madill437fa652016-05-03 15:13:24 -04001907 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001908 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001909 }
1910
Geoff Lang69cce582015-09-17 13:20:36 -04001911 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04001912 {
Jamie Madill437fa652016-05-03 15:13:24 -04001913 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001914 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001915 }
1916
Geoff Lang5d601382014-07-22 15:14:06 -04001917 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1918
1919 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04001920 {
Jamie Madill437fa652016-05-03 15:13:24 -04001921 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001922 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001923 }
1924
Geoff Langa9be0dc2014-12-17 12:34:40 -05001925 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04001926 {
Jamie Madill437fa652016-05-03 15:13:24 -04001927 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001928 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001929 }
1930
1931 if (isSubImage)
1932 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05001933 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
1934 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
1935 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04001936 {
Jamie Madill437fa652016-05-03 15:13:24 -04001937 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001938 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001939 }
1940 }
Jamie Madill6f38f822014-06-06 17:12:20 -04001941 else
1942 {
Geoff Lang691e58c2014-12-19 17:03:25 -05001943 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04001944 {
Jamie Madill437fa652016-05-03 15:13:24 -04001945 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001946 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04001947 }
1948
Martin Radev1be913c2016-07-11 17:59:16 +03001949 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04001950 {
Jamie Madill437fa652016-05-03 15:13:24 -04001951 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001952 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04001953 }
1954
1955 int maxLevelDimension = (maxDimension >> level);
1956 if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension)
1957 {
Jamie Madill437fa652016-05-03 15:13:24 -04001958 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001959 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04001960 }
1961 }
Jamie Madill560a8d82014-05-21 13:06:20 -04001962
Jamie Madill0c8abca2016-07-22 20:21:26 -04001963 if (textureFormatOut)
1964 {
1965 *textureFormatOut = texture->getFormat(target, level);
1966 }
Jamie Madill560a8d82014-05-21 13:06:20 -04001967 return true;
1968}
1969
Jamie Madillf25855c2015-11-03 11:06:18 -05001970static bool ValidateDrawBase(ValidationContext *context,
1971 GLenum mode,
1972 GLsizei count,
1973 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04001974{
Jamie Madill1aeb1312014-06-20 13:21:25 -04001975 switch (mode)
1976 {
1977 case GL_POINTS:
1978 case GL_LINES:
1979 case GL_LINE_LOOP:
1980 case GL_LINE_STRIP:
1981 case GL_TRIANGLES:
1982 case GL_TRIANGLE_STRIP:
1983 case GL_TRIANGLE_FAN:
1984 break;
1985 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001986 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001987 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04001988 }
1989
Jamie Madill250d33f2014-06-06 17:09:03 -04001990 if (count < 0)
1991 {
Jamie Madill437fa652016-05-03 15:13:24 -04001992 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001993 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04001994 }
1995
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001996 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04001997
Jamie Madill250d33f2014-06-06 17:09:03 -04001998 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04001999 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002000 {
Jamie Madill437fa652016-05-03 15:13:24 -04002001 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002002 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002003 }
2004
Jamie Madill51f40ec2016-06-15 14:06:00 -04002005 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04002006 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04002007 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04002008 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
2009 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
2010 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
2011 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2012 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2013 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04002014 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04002015 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2016 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04002017 {
2018 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2019 // Section 6.10 of the WebGL 1.0 spec
2020 ERR(
2021 "This ANGLE implementation does not support separate front/back stencil "
2022 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04002023 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04002024 return false;
2025 }
Jamie Madillac528012014-06-20 13:21:23 -04002026 }
2027
Jamie Madill51f40ec2016-06-15 14:06:00 -04002028 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002029 {
Jamie Madill437fa652016-05-03 15:13:24 -04002030 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002031 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002032 }
2033
Geoff Lang7dd2e102014-11-10 15:19:26 -05002034 gl::Program *program = state.getProgram();
2035 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002036 {
Jamie Madill437fa652016-05-03 15:13:24 -04002037 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002038 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002039 }
2040
Geoff Lang7dd2e102014-11-10 15:19:26 -05002041 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002042 {
Jamie Madill437fa652016-05-03 15:13:24 -04002043 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002044 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002045 }
2046
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002047 // Uniform buffer validation
2048 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2049 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002050 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002051 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002052 const OffsetBindingPointer<Buffer> &uniformBuffer =
2053 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002054
Geoff Lang5d124a62015-09-15 13:03:27 -04002055 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002056 {
2057 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002058 context->handleError(
2059 Error(GL_INVALID_OPERATION,
2060 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002061 return false;
2062 }
2063
Geoff Lang5d124a62015-09-15 13:03:27 -04002064 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002065 if (uniformBufferSize == 0)
2066 {
2067 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002068 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002069 }
2070
Jamie Madill62d31cb2015-09-11 13:25:51 -04002071 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002072 {
2073 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002074 context->handleError(
2075 Error(GL_INVALID_OPERATION,
2076 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002077 return false;
2078 }
2079 }
2080
Jamie Madill250d33f2014-06-06 17:09:03 -04002081 // No-op if zero count
2082 return (count > 0);
2083}
2084
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002085bool ValidateDrawArrays(ValidationContext *context,
2086 GLenum mode,
2087 GLint first,
2088 GLsizei count,
2089 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002090{
Jamie Madillfd716582014-06-06 17:09:04 -04002091 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002092 {
Jamie Madill437fa652016-05-03 15:13:24 -04002093 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002094 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002095 }
2096
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002097 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002098 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04002099 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused() &&
2100 curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002101 {
2102 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
2103 // that does not match the current transform feedback object's draw mode (if transform feedback
2104 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002105 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002106 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002107 }
2108
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002109 if (!ValidateDrawBase(context, mode, count, primcount))
2110 {
2111 return false;
2112 }
2113
2114 if (!ValidateDrawAttribs(context, primcount, count))
Jamie Madillfd716582014-06-06 17:09:04 -04002115 {
2116 return false;
2117 }
2118
2119 return true;
2120}
2121
Geoff Langb1196682014-07-23 13:47:29 -04002122bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002123{
2124 if (primcount < 0)
2125 {
Jamie Madill437fa652016-05-03 15:13:24 -04002126 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002127 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002128 }
2129
Jamie Madill2b976812014-08-25 15:47:49 -04002130 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04002131 {
2132 return false;
2133 }
2134
2135 // No-op if zero primitive count
2136 return (primcount > 0);
2137}
2138
Geoff Lang87a93302014-09-16 13:29:43 -04002139static bool ValidateDrawInstancedANGLE(Context *context)
2140{
2141 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002142 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04002143
Geoff Lang7dd2e102014-11-10 15:19:26 -05002144 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04002145
2146 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04002147 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04002148 {
2149 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04002150 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04002151 {
2152 return true;
2153 }
2154 }
2155
Jamie Madill437fa652016-05-03 15:13:24 -04002156 context->handleError(Error(GL_INVALID_OPERATION,
2157 "ANGLE_instanced_arrays requires that at least one active attribute"
2158 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04002159 return false;
2160}
2161
2162bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
2163{
2164 if (!ValidateDrawInstancedANGLE(context))
2165 {
2166 return false;
2167 }
2168
2169 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
2170}
2171
Jamie Madillf25855c2015-11-03 11:06:18 -05002172bool ValidateDrawElements(ValidationContext *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04002173 GLenum mode,
2174 GLsizei count,
2175 GLenum type,
2176 const GLvoid *indices,
2177 GLsizei primcount,
2178 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04002179{
Jamie Madill250d33f2014-06-06 17:09:03 -04002180 switch (type)
2181 {
2182 case GL_UNSIGNED_BYTE:
2183 case GL_UNSIGNED_SHORT:
Martin Radev1be913c2016-07-11 17:59:16 +03002184 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04002185 case GL_UNSIGNED_INT:
Martin Radev1be913c2016-07-11 17:59:16 +03002186 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2187 {
2188 context->handleError(Error(GL_INVALID_ENUM));
2189 return false;
2190 }
2191 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04002192 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002193 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03002194 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002195 }
2196
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002197 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002198
2199 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04002200 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002201 {
2202 // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
2203 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002204 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002205 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002206 }
2207
2208 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002209 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002210 {
Jamie Madill437fa652016-05-03 15:13:24 -04002211 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002212 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002213 }
2214
Jamie Madill2b976812014-08-25 15:47:49 -04002215 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002216 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madill2b976812014-08-25 15:47:49 -04002217 if (!indices && !elementArrayBuffer)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002218 {
Jamie Madill437fa652016-05-03 15:13:24 -04002219 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002220 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002221 }
2222
Jamie Madillae3000b2014-08-25 15:47:51 -04002223 if (elementArrayBuffer)
2224 {
2225 const gl::Type &typeInfo = gl::GetTypeInfo(type);
2226
2227 GLint64 offset = reinterpret_cast<GLint64>(indices);
2228 GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset;
2229
2230 // check for integer overflows
2231 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
2232 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
2233 {
Jamie Madill437fa652016-05-03 15:13:24 -04002234 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04002235 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002236 }
2237
2238 // Check for reading past the end of the bound buffer object
2239 if (byteCount > elementArrayBuffer->getSize())
2240 {
Jamie Madill437fa652016-05-03 15:13:24 -04002241 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002242 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002243 }
2244 }
2245 else if (!indices)
2246 {
2247 // Catch this programming error here
Jamie Madill437fa652016-05-03 15:13:24 -04002248 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002249 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002250 }
2251
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002252 if (!ValidateDrawBase(context, mode, count, primcount))
2253 {
2254 return false;
2255 }
2256
Jamie Madill2b976812014-08-25 15:47:49 -04002257 // Use max index to validate if our vertex buffers are large enough for the pull.
2258 // TODO: offer fast path, with disabled index validation.
2259 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
2260 if (elementArrayBuffer)
2261 {
Jacek Cabana5521de2014-10-01 17:23:46 +02002262 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04002263 Error error =
2264 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
2265 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04002266 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04002267 {
Jamie Madill437fa652016-05-03 15:13:24 -04002268 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04002269 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04002270 }
2271 }
2272 else
2273 {
Geoff Lang3edfe032015-09-04 16:38:24 -04002274 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04002275 }
2276
Jamie Madille79b1e12015-11-04 16:36:37 -05002277 // If we use an index greater than our maximum supported index range, return an error.
2278 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2279 // return an error if possible here.
2280 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
2281 {
Jamie Madill437fa652016-05-03 15:13:24 -04002282 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05002283 return false;
2284 }
2285
Jamie Madillbc4c4bc2016-03-23 21:04:43 -04002286 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04002287 {
2288 return false;
2289 }
2290
Geoff Lang3edfe032015-09-04 16:38:24 -04002291 // No op if there are no real indices in the index data (all are primitive restart).
2292 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04002293}
2294
Geoff Langb1196682014-07-23 13:47:29 -04002295bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04002296 GLenum mode,
2297 GLsizei count,
2298 GLenum type,
2299 const GLvoid *indices,
2300 GLsizei primcount,
2301 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04002302{
2303 if (primcount < 0)
2304 {
Jamie Madill437fa652016-05-03 15:13:24 -04002305 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002306 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002307 }
2308
Jamie Madill2b976812014-08-25 15:47:49 -04002309 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04002310 {
2311 return false;
2312 }
2313
2314 // No-op zero primitive count
2315 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04002316}
2317
Geoff Lang3edfe032015-09-04 16:38:24 -04002318bool ValidateDrawElementsInstancedANGLE(Context *context,
2319 GLenum mode,
2320 GLsizei count,
2321 GLenum type,
2322 const GLvoid *indices,
2323 GLsizei primcount,
2324 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04002325{
2326 if (!ValidateDrawInstancedANGLE(context))
2327 {
2328 return false;
2329 }
2330
2331 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut);
2332}
2333
Geoff Langb1196682014-07-23 13:47:29 -04002334bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04002335 GLuint texture, GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002336{
Jamie Madill55ec3b12014-07-03 10:38:57 -04002337 if (!ValidFramebufferTarget(target))
2338 {
Jamie Madill437fa652016-05-03 15:13:24 -04002339 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002340 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002341 }
2342
2343 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002344 {
2345 return false;
2346 }
2347
Jamie Madill55ec3b12014-07-03 10:38:57 -04002348 if (texture != 0)
2349 {
2350 gl::Texture *tex = context->getTexture(texture);
2351
2352 if (tex == NULL)
2353 {
Jamie Madill437fa652016-05-03 15:13:24 -04002354 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002355 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002356 }
2357
2358 if (level < 0)
2359 {
Jamie Madill437fa652016-05-03 15:13:24 -04002360 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002361 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002362 }
2363 }
2364
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002365 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002366 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002367
Jamie Madill84115c92015-04-23 15:00:07 -04002368 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002369 {
Jamie Madill437fa652016-05-03 15:13:24 -04002370 context->handleError(
2371 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002372 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002373 }
2374
2375 return true;
2376}
2377
Geoff Langb1196682014-07-23 13:47:29 -04002378bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04002379 GLenum textarget, GLuint texture, GLint level)
2380{
Geoff Lang95663912015-04-02 15:54:45 -04002381 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap extension
Martin Radev1be913c2016-07-11 17:59:16 +03002382 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
2383 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002384 {
Jamie Madill437fa652016-05-03 15:13:24 -04002385 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002386 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002387 }
2388
2389 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04002390 {
2391 return false;
2392 }
2393
Jamie Madill55ec3b12014-07-03 10:38:57 -04002394 if (texture != 0)
2395 {
2396 gl::Texture *tex = context->getTexture(texture);
2397 ASSERT(tex);
2398
Jamie Madill2a6564e2014-07-11 09:53:19 -04002399 const gl::Caps &caps = context->getCaps();
2400
Jamie Madill55ec3b12014-07-03 10:38:57 -04002401 switch (textarget)
2402 {
2403 case GL_TEXTURE_2D:
2404 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04002405 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002406 {
Jamie Madill437fa652016-05-03 15:13:24 -04002407 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002408 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002409 }
2410 if (tex->getTarget() != GL_TEXTURE_2D)
2411 {
Jamie Madill437fa652016-05-03 15:13:24 -04002412 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002413 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002414 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002415 }
2416 break;
2417
2418 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2419 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2420 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2421 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2422 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2423 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2424 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04002425 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002426 {
Jamie Madill437fa652016-05-03 15:13:24 -04002427 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002428 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002429 }
2430 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
2431 {
Jamie Madill437fa652016-05-03 15:13:24 -04002432 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002433 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002434 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002435 }
2436 break;
2437
2438 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002439 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002440 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002441 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05002442
Jamie Madilla3944d42016-07-22 22:13:26 -04002443 const Format &format = tex->getFormat(textarget, level);
2444 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05002445 {
Jamie Madill437fa652016-05-03 15:13:24 -04002446 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002447 return false;
2448 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002449 }
2450
Jamie Madill570f7c82014-07-03 10:38:54 -04002451 return true;
2452}
2453
Geoff Langb1196682014-07-23 13:47:29 -04002454bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04002455{
2456 if (program == 0)
2457 {
Jamie Madill437fa652016-05-03 15:13:24 -04002458 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002459 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002460 }
2461
Dian Xiang769769a2015-09-09 15:20:08 -07002462 gl::Program *programObject = GetValidProgram(context, program);
2463 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05002464 {
2465 return false;
2466 }
2467
Jamie Madill0063c512014-08-25 15:47:53 -04002468 if (!programObject || !programObject->isLinked())
2469 {
Jamie Madill437fa652016-05-03 15:13:24 -04002470 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002471 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002472 }
2473
Geoff Lang7dd2e102014-11-10 15:19:26 -05002474 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04002475 {
Jamie Madill437fa652016-05-03 15:13:24 -04002476 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002477 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04002478 }
2479
Jamie Madill0063c512014-08-25 15:47:53 -04002480 return true;
2481}
2482
Geoff Langb1196682014-07-23 13:47:29 -04002483bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params)
Jamie Madill78f41802014-08-25 15:47:55 -04002484{
2485 return ValidateGetUniformBase(context, program, location);
2486}
2487
Geoff Langb1196682014-07-23 13:47:29 -04002488bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04002489{
Jamie Madill78f41802014-08-25 15:47:55 -04002490 return ValidateGetUniformBase(context, program, location);
2491}
2492
Geoff Langb1196682014-07-23 13:47:29 -04002493static bool ValidateSizedGetUniform(Context *context, GLuint program, GLint location, GLsizei bufSize)
Jamie Madill78f41802014-08-25 15:47:55 -04002494{
2495 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04002496 {
Jamie Madill78f41802014-08-25 15:47:55 -04002497 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002498 }
2499
Jamie Madilla502c742014-08-28 17:19:13 -04002500 gl::Program *programObject = context->getProgram(program);
2501 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04002502
Jamie Madill78f41802014-08-25 15:47:55 -04002503 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04002504 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
2505 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04002506 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04002507 {
Jamie Madill437fa652016-05-03 15:13:24 -04002508 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002509 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002510 }
2511
2512 return true;
2513}
2514
Geoff Langb1196682014-07-23 13:47:29 -04002515bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
Jamie Madill0063c512014-08-25 15:47:53 -04002516{
Jamie Madill78f41802014-08-25 15:47:55 -04002517 return ValidateSizedGetUniform(context, program, location, bufSize);
Jamie Madill0063c512014-08-25 15:47:53 -04002518}
2519
Geoff Langb1196682014-07-23 13:47:29 -04002520bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04002521{
Jamie Madill78f41802014-08-25 15:47:55 -04002522 return ValidateSizedGetUniform(context, program, location, bufSize);
Jamie Madill0063c512014-08-25 15:47:53 -04002523}
2524
Austin Kinross08332632015-05-05 13:35:47 -07002525bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
2526 const GLenum *attachments, bool defaultFramebuffer)
2527{
2528 if (numAttachments < 0)
2529 {
Jamie Madill437fa652016-05-03 15:13:24 -04002530 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07002531 return false;
2532 }
2533
2534 for (GLsizei i = 0; i < numAttachments; ++i)
2535 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02002536 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07002537 {
2538 if (defaultFramebuffer)
2539 {
Jamie Madill437fa652016-05-03 15:13:24 -04002540 context->handleError(Error(
2541 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07002542 return false;
2543 }
2544
2545 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
2546 {
Jamie Madill437fa652016-05-03 15:13:24 -04002547 context->handleError(Error(GL_INVALID_OPERATION,
2548 "Requested color attachment is greater than the maximum "
2549 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07002550 return false;
2551 }
2552 }
2553 else
2554 {
2555 switch (attachments[i])
2556 {
2557 case GL_DEPTH_ATTACHMENT:
2558 case GL_STENCIL_ATTACHMENT:
2559 case GL_DEPTH_STENCIL_ATTACHMENT:
2560 if (defaultFramebuffer)
2561 {
Jamie Madill437fa652016-05-03 15:13:24 -04002562 context->handleError(
2563 Error(GL_INVALID_ENUM,
2564 "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07002565 return false;
2566 }
2567 break;
2568 case GL_COLOR:
2569 case GL_DEPTH:
2570 case GL_STENCIL:
2571 if (!defaultFramebuffer)
2572 {
Jamie Madill437fa652016-05-03 15:13:24 -04002573 context->handleError(
2574 Error(GL_INVALID_ENUM,
2575 "Invalid attachment when the default framebuffer is not bound"));
Austin Kinross08332632015-05-05 13:35:47 -07002576 return false;
2577 }
2578 break;
2579 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002580 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07002581 return false;
2582 }
2583 }
2584 }
2585
2586 return true;
2587}
2588
Austin Kinross6ee1e782015-05-29 17:05:37 -07002589bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
2590{
2591 // Note that debug marker calls must not set error state
2592
2593 if (length < 0)
2594 {
2595 return false;
2596 }
2597
2598 if (marker == nullptr)
2599 {
2600 return false;
2601 }
2602
2603 return true;
2604}
2605
2606bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
2607{
2608 // Note that debug marker calls must not set error state
2609
2610 if (length < 0)
2611 {
2612 return false;
2613 }
2614
2615 if (length > 0 && marker == nullptr)
2616 {
2617 return false;
2618 }
2619
2620 return true;
2621}
2622
Geoff Langdcab33b2015-07-21 13:03:16 -04002623bool ValidateEGLImageTargetTexture2DOES(Context *context,
2624 egl::Display *display,
2625 GLenum target,
2626 egl::Image *image)
2627{
Geoff Langa8406172015-07-21 16:53:39 -04002628 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
2629 {
Jamie Madill437fa652016-05-03 15:13:24 -04002630 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04002631 return false;
2632 }
2633
2634 switch (target)
2635 {
2636 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04002637 if (!context->getExtensions().eglImage)
2638 {
2639 context->handleError(Error(
2640 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
2641 }
2642 break;
2643
2644 case GL_TEXTURE_EXTERNAL_OES:
2645 if (!context->getExtensions().eglImageExternal)
2646 {
2647 context->handleError(Error(
2648 GL_INVALID_ENUM,
2649 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
2650 }
Geoff Langa8406172015-07-21 16:53:39 -04002651 break;
2652
2653 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002654 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04002655 return false;
2656 }
2657
2658 if (!display->isValidImage(image))
2659 {
Jamie Madill437fa652016-05-03 15:13:24 -04002660 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04002661 return false;
2662 }
2663
2664 if (image->getSamples() > 0)
2665 {
Jamie Madill437fa652016-05-03 15:13:24 -04002666 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04002667 "cannot create a 2D texture from a multisampled EGL image."));
2668 return false;
2669 }
2670
Jamie Madilla3944d42016-07-22 22:13:26 -04002671 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04002672 if (!textureCaps.texturable)
2673 {
Jamie Madill437fa652016-05-03 15:13:24 -04002674 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04002675 "EGL image internal format is not supported as a texture."));
2676 return false;
2677 }
2678
Geoff Langdcab33b2015-07-21 13:03:16 -04002679 return true;
2680}
2681
2682bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
2683 egl::Display *display,
2684 GLenum target,
2685 egl::Image *image)
2686{
Geoff Langa8406172015-07-21 16:53:39 -04002687 if (!context->getExtensions().eglImage)
2688 {
Jamie Madill437fa652016-05-03 15:13:24 -04002689 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04002690 return false;
2691 }
2692
2693 switch (target)
2694 {
2695 case GL_RENDERBUFFER:
2696 break;
2697
2698 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002699 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04002700 return false;
2701 }
2702
2703 if (!display->isValidImage(image))
2704 {
Jamie Madill437fa652016-05-03 15:13:24 -04002705 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04002706 return false;
2707 }
2708
Jamie Madilla3944d42016-07-22 22:13:26 -04002709 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04002710 if (!textureCaps.renderable)
2711 {
Jamie Madill437fa652016-05-03 15:13:24 -04002712 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04002713 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
2714 return false;
2715 }
2716
Geoff Langdcab33b2015-07-21 13:03:16 -04002717 return true;
2718}
Austin Kinrossbc781f32015-10-26 09:27:38 -07002719
2720bool ValidateBindVertexArrayBase(Context *context, GLuint array)
2721{
Geoff Lang36167ab2015-12-07 10:27:14 -05002722 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07002723 {
2724 // The default VAO should always exist
2725 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04002726 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07002727 return false;
2728 }
2729
2730 return true;
2731}
2732
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002733bool ValidateLinkProgram(Context *context, GLuint program)
2734{
2735 if (context->hasActiveTransformFeedback(program))
2736 {
2737 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04002738 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002739 "Cannot link program while program is associated with an active "
2740 "transform feedback object."));
2741 return false;
2742 }
2743 return true;
2744}
2745
Geoff Langc5629752015-12-07 16:29:04 -05002746bool ValidateProgramBinaryBase(Context *context,
2747 GLuint program,
2748 GLenum binaryFormat,
2749 const void *binary,
2750 GLint length)
2751{
2752 Program *programObject = GetValidProgram(context, program);
2753 if (programObject == nullptr)
2754 {
2755 return false;
2756 }
2757
2758 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
2759 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
2760 programBinaryFormats.end())
2761 {
Jamie Madill437fa652016-05-03 15:13:24 -04002762 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05002763 return false;
2764 }
2765
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002766 if (context->hasActiveTransformFeedback(program))
2767 {
2768 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04002769 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002770 "Cannot change program binary while program is associated with "
2771 "an active transform feedback object."));
2772 return false;
2773 }
2774
Geoff Langc5629752015-12-07 16:29:04 -05002775 return true;
2776}
2777
2778bool ValidateGetProgramBinaryBase(Context *context,
2779 GLuint program,
2780 GLsizei bufSize,
2781 GLsizei *length,
2782 GLenum *binaryFormat,
2783 void *binary)
2784{
2785 Program *programObject = GetValidProgram(context, program);
2786 if (programObject == nullptr)
2787 {
2788 return false;
2789 }
2790
2791 if (!programObject->isLinked())
2792 {
Jamie Madill437fa652016-05-03 15:13:24 -04002793 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05002794 return false;
2795 }
2796
2797 return true;
2798}
Jamie Madillc29968b2016-01-20 11:17:23 -05002799
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002800bool ValidateUseProgram(Context *context, GLuint program)
2801{
2802 if (program != 0)
2803 {
2804 Program *programObject = context->getProgram(program);
2805 if (!programObject)
2806 {
2807 // ES 3.1.0 section 7.3 page 72
2808 if (context->getShader(program))
2809 {
Jamie Madill437fa652016-05-03 15:13:24 -04002810 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002811 Error(GL_INVALID_OPERATION,
2812 "Attempted to use a single shader instead of a shader program."));
2813 return false;
2814 }
2815 else
2816 {
Jamie Madill437fa652016-05-03 15:13:24 -04002817 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002818 return false;
2819 }
2820 }
2821 if (!programObject->isLinked())
2822 {
Jamie Madill437fa652016-05-03 15:13:24 -04002823 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002824 return false;
2825 }
2826 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002827 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002828 {
2829 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04002830 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002831 Error(GL_INVALID_OPERATION,
2832 "Cannot change active program while transform feedback is unpaused."));
2833 return false;
2834 }
2835
2836 return true;
2837}
2838
Jamie Madillc29968b2016-01-20 11:17:23 -05002839bool ValidateCopyTexImage2D(ValidationContext *context,
2840 GLenum target,
2841 GLint level,
2842 GLenum internalformat,
2843 GLint x,
2844 GLint y,
2845 GLsizei width,
2846 GLsizei height,
2847 GLint border)
2848{
Martin Radev1be913c2016-07-11 17:59:16 +03002849 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05002850 {
2851 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
2852 0, x, y, width, height, border);
2853 }
2854
Martin Radev1be913c2016-07-11 17:59:16 +03002855 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05002856 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
2857 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002858}
Jamie Madillc29968b2016-01-20 11:17:23 -05002859
2860bool ValidateFramebufferRenderbuffer(Context *context,
2861 GLenum target,
2862 GLenum attachment,
2863 GLenum renderbuffertarget,
2864 GLuint renderbuffer)
2865{
2866 if (!ValidFramebufferTarget(target) ||
2867 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
2868 {
Jamie Madill437fa652016-05-03 15:13:24 -04002869 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05002870 return false;
2871 }
2872
2873 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
2874 renderbuffertarget, renderbuffer);
2875}
2876
2877bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
2878{
2879 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
2880 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
2881 {
Jamie Madill437fa652016-05-03 15:13:24 -04002882 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05002883 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
2884 return false;
2885 }
2886
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002887 ASSERT(context->getGLState().getDrawFramebuffer());
2888 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05002889 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
2890
2891 // This should come first before the check for the default frame buffer
2892 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
2893 // rather than INVALID_OPERATION
2894 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
2895 {
2896 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
2897
2898 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02002899 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
2900 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05002901 {
2902 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02002903 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
2904 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
2905 // 3.1 is still a bit ambiguous about the error, but future specs are
2906 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04002907 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02002908 return false;
2909 }
2910 else if (bufs[colorAttachment] >= maxColorAttachment)
2911 {
Jamie Madill437fa652016-05-03 15:13:24 -04002912 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02002913 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002914 return false;
2915 }
2916 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
2917 frameBufferId != 0)
2918 {
2919 // INVALID_OPERATION-GL is bound to buffer and ith argument
2920 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04002921 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05002922 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
2923 return false;
2924 }
2925 }
2926
2927 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
2928 // and n is not 1 or bufs is bound to value other than BACK and NONE
2929 if (frameBufferId == 0)
2930 {
2931 if (n != 1)
2932 {
Jamie Madill437fa652016-05-03 15:13:24 -04002933 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05002934 "n must be 1 when GL is bound to the default framebuffer"));
2935 return false;
2936 }
2937
2938 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
2939 {
Jamie Madill437fa652016-05-03 15:13:24 -04002940 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05002941 GL_INVALID_OPERATION,
2942 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
2943 return false;
2944 }
2945 }
2946
2947 return true;
2948}
2949
2950bool ValidateCopyTexSubImage2D(Context *context,
2951 GLenum target,
2952 GLint level,
2953 GLint xoffset,
2954 GLint yoffset,
2955 GLint x,
2956 GLint y,
2957 GLsizei width,
2958 GLsizei height)
2959{
Martin Radev1be913c2016-07-11 17:59:16 +03002960 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05002961 {
2962 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
2963 yoffset, x, y, width, height, 0);
2964 }
2965
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05002966 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
2967 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05002968}
2969
Olli Etuaho4f667482016-03-30 15:56:35 +03002970bool ValidateGetBufferPointervBase(Context *context, GLenum target, GLenum pname, void **params)
2971{
2972 if (!ValidBufferTarget(context, target))
2973 {
Jamie Madill437fa652016-05-03 15:13:24 -04002974 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03002975 return false;
2976 }
2977
2978 if (pname != GL_BUFFER_MAP_POINTER)
2979 {
Jamie Madill437fa652016-05-03 15:13:24 -04002980 context->handleError(Error(GL_INVALID_ENUM, "pname not valid: 0x%X", pname));
Olli Etuaho4f667482016-03-30 15:56:35 +03002981 return false;
2982 }
2983
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002984 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002985
2986 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
2987 // target bound to zero generate an INVALID_OPERATION error."
2988 // GLES 3.1 section 6.6 explicitly specifies this error.
2989 if (!buffer)
2990 {
Jamie Madill437fa652016-05-03 15:13:24 -04002991 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002992 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
2993 return false;
2994 }
2995
2996 return true;
2997}
2998
2999bool ValidateUnmapBufferBase(Context *context, GLenum target)
3000{
3001 if (!ValidBufferTarget(context, target))
3002 {
Jamie Madill437fa652016-05-03 15:13:24 -04003003 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003004 return false;
3005 }
3006
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003007 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003008
3009 if (buffer == nullptr || !buffer->isMapped())
3010 {
Jamie Madill437fa652016-05-03 15:13:24 -04003011 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003012 return false;
3013 }
3014
3015 return true;
3016}
3017
3018bool ValidateMapBufferRangeBase(Context *context,
3019 GLenum target,
3020 GLintptr offset,
3021 GLsizeiptr length,
3022 GLbitfield access)
3023{
3024 if (!ValidBufferTarget(context, target))
3025 {
Jamie Madill437fa652016-05-03 15:13:24 -04003026 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003027 return false;
3028 }
3029
3030 if (offset < 0 || length < 0)
3031 {
Jamie Madill437fa652016-05-03 15:13:24 -04003032 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003033 return false;
3034 }
3035
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003036 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003037
3038 if (!buffer)
3039 {
Jamie Madill437fa652016-05-03 15:13:24 -04003040 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003041 return false;
3042 }
3043
3044 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003045 CheckedNumeric<size_t> checkedOffset(offset);
3046 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003047
Jamie Madille2e406c2016-06-02 13:04:10 -04003048 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003049 {
Jamie Madill437fa652016-05-03 15:13:24 -04003050 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003051 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
3052 return false;
3053 }
3054
3055 // Check for invalid bits in the mask
3056 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3057 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3058 GL_MAP_UNSYNCHRONIZED_BIT;
3059
3060 if (access & ~(allAccessBits))
3061 {
Jamie Madill437fa652016-05-03 15:13:24 -04003062 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03003063 return false;
3064 }
3065
3066 if (length == 0)
3067 {
Jamie Madill437fa652016-05-03 15:13:24 -04003068 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003069 return false;
3070 }
3071
3072 if (buffer->isMapped())
3073 {
Jamie Madill437fa652016-05-03 15:13:24 -04003074 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003075 return false;
3076 }
3077
3078 // Check for invalid bit combinations
3079 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3080 {
Jamie Madill437fa652016-05-03 15:13:24 -04003081 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003082 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
3083 return false;
3084 }
3085
3086 GLbitfield writeOnlyBits =
3087 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3088
3089 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3090 {
Jamie Madill437fa652016-05-03 15:13:24 -04003091 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03003092 "Invalid access bits when mapping buffer for reading: 0x%X.",
3093 access));
3094 return false;
3095 }
3096
3097 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3098 {
Jamie Madill437fa652016-05-03 15:13:24 -04003099 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003100 GL_INVALID_OPERATION,
3101 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
3102 return false;
3103 }
3104 return true;
3105}
3106
3107bool ValidateFlushMappedBufferRangeBase(Context *context,
3108 GLenum target,
3109 GLintptr offset,
3110 GLsizeiptr length)
3111{
3112 if (offset < 0 || length < 0)
3113 {
Jamie Madill437fa652016-05-03 15:13:24 -04003114 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003115 return false;
3116 }
3117
3118 if (!ValidBufferTarget(context, target))
3119 {
Jamie Madill437fa652016-05-03 15:13:24 -04003120 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003121 return false;
3122 }
3123
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003124 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003125
3126 if (buffer == nullptr)
3127 {
Jamie Madill437fa652016-05-03 15:13:24 -04003128 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003129 return false;
3130 }
3131
3132 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3133 {
Jamie Madill437fa652016-05-03 15:13:24 -04003134 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003135 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
3136 return false;
3137 }
3138
3139 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003140 CheckedNumeric<size_t> checkedOffset(offset);
3141 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003142
Jamie Madille2e406c2016-06-02 13:04:10 -04003143 if (!checkedSize.IsValid() ||
3144 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003145 {
Jamie Madill437fa652016-05-03 15:13:24 -04003146 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003147 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
3148 return false;
3149 }
3150
3151 return true;
3152}
3153
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003154bool ValidateGenerateMipmap(Context *context, GLenum target)
3155{
3156 if (!ValidTextureTarget(context, target))
3157 {
3158 context->handleError(Error(GL_INVALID_ENUM));
3159 return false;
3160 }
3161
3162 Texture *texture = context->getTargetTexture(target);
3163
3164 if (texture == nullptr)
3165 {
3166 context->handleError(Error(GL_INVALID_OPERATION));
3167 return false;
3168 }
3169
3170 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
3171
3172 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
3173 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
3174 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
3175 {
3176 context->handleError(Error(GL_INVALID_OPERATION));
3177 return false;
3178 }
3179
Jamie Madilla3944d42016-07-22 22:13:26 -04003180 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
3181 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
3182 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003183
3184 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
3185 // unsized formats or that are color renderable and filterable. Since we do not track if
3186 // the texture was created with sized or unsized format (only sized formats are stored),
3187 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
3188 // be able to) because they aren't color renderable. Simply do a special case for LUMA
3189 // textures since they're the only texture format that can be created with unsized formats
3190 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
3191 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04003192 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
3193 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003194 {
3195 context->handleError(Error(GL_INVALID_OPERATION));
3196 return false;
3197 }
3198
3199 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04003200 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003201 {
3202 context->handleError(Error(GL_INVALID_OPERATION));
3203 return false;
3204 }
3205
3206 // Non-power of 2 ES2 check
3207 if (!context->getExtensions().textureNPOT &&
3208 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
3209 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
3210 {
Martin Radev1be913c2016-07-11 17:59:16 +03003211 ASSERT(context->getClientMajorVersion() <= 2 &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003212 (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
3213 context->handleError(Error(GL_INVALID_OPERATION));
3214 return false;
3215 }
3216
3217 // Cube completeness check
3218 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
3219 {
3220 context->handleError(Error(GL_INVALID_OPERATION));
3221 return false;
3222 }
3223
3224 return true;
3225}
3226
Olli Etuaho41997e72016-03-10 13:38:39 +02003227bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
3228{
3229 return ValidateGenOrDelete(context, n);
3230}
3231
3232bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
3233{
3234 return ValidateGenOrDelete(context, n);
3235}
3236
3237bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
3238{
3239 return ValidateGenOrDelete(context, n);
3240}
3241
3242bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
3243{
3244 return ValidateGenOrDelete(context, n);
3245}
3246
3247bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
3248{
3249 return ValidateGenOrDelete(context, n);
3250}
3251
3252bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
3253{
3254 return ValidateGenOrDelete(context, n);
3255}
3256
3257bool ValidateGenTextures(Context *context, GLint n, GLuint *)
3258{
3259 return ValidateGenOrDelete(context, n);
3260}
3261
3262bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
3263{
3264 return ValidateGenOrDelete(context, n);
3265}
3266
3267bool ValidateGenOrDelete(Context *context, GLint n)
3268{
3269 if (n < 0)
3270 {
Jamie Madill437fa652016-05-03 15:13:24 -04003271 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02003272 return false;
3273 }
3274 return true;
3275}
3276
Geoff Langf41a7152016-09-19 15:11:17 -04003277bool ValidateEnable(Context *context, GLenum cap)
3278{
3279 if (!ValidCap(context, cap, false))
3280 {
3281 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
3282 return false;
3283 }
3284
3285 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
3286 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
3287 {
3288 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
3289 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
3290
3291 // We also output an error message to the debugger window if tracing is active, so that
3292 // developers can see the error message.
3293 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04003294 return false;
3295 }
3296
3297 return true;
3298}
3299
3300bool ValidateDisable(Context *context, GLenum cap)
3301{
3302 if (!ValidCap(context, cap, false))
3303 {
3304 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
3305 return false;
3306 }
3307
3308 return true;
3309}
3310
3311bool ValidateIsEnabled(Context *context, GLenum cap)
3312{
3313 if (!ValidCap(context, cap, true))
3314 {
3315 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
3316 return false;
3317 }
3318
3319 return true;
3320}
3321
Geoff Langff5b2d52016-09-07 11:32:23 -04003322bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3323{
3324 if (!context->getExtensions().robustClientMemory)
3325 {
3326 context->handleError(
3327 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
3328 return false;
3329 }
3330
3331 if (bufSize < 0)
3332 {
3333 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3334 return false;
3335 }
3336
3337 return true;
3338}
3339
3340bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
3341 GLenum target,
3342 GLenum attachment,
3343 GLenum pname,
3344 GLsizei *numParams)
3345{
3346 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
3347 *numParams = 1;
3348
3349 if (!ValidFramebufferTarget(target))
3350 {
3351 context->handleError(Error(GL_INVALID_ENUM));
3352 return false;
3353 }
3354
3355 int clientVersion = context->getClientMajorVersion();
3356
3357 switch (pname)
3358 {
3359 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3360 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3361 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3362 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3363 break;
3364
3365 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3366 if (clientVersion < 3 && !context->getExtensions().sRGB)
3367 {
3368 context->handleError(Error(GL_INVALID_ENUM));
3369 return false;
3370 }
3371 break;
3372
3373 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3374 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3375 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3376 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3377 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3378 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3379 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3380 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3381 if (clientVersion < 3)
3382 {
3383 context->handleError(Error(GL_INVALID_ENUM));
3384 return false;
3385 }
3386 break;
3387
3388 default:
3389 context->handleError(Error(GL_INVALID_ENUM));
3390 return false;
3391 }
3392
3393 // Determine if the attachment is a valid enum
3394 switch (attachment)
3395 {
3396 case GL_BACK:
3397 case GL_FRONT:
3398 case GL_DEPTH:
3399 case GL_STENCIL:
3400 case GL_DEPTH_STENCIL_ATTACHMENT:
3401 if (clientVersion < 3)
3402 {
3403 context->handleError(Error(GL_INVALID_ENUM));
3404 return false;
3405 }
3406 break;
3407
3408 case GL_DEPTH_ATTACHMENT:
3409 case GL_STENCIL_ATTACHMENT:
3410 break;
3411
3412 default:
3413 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
3414 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3415 {
3416 context->handleError(Error(GL_INVALID_ENUM));
3417 return false;
3418 }
3419 break;
3420 }
3421
3422 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3423 ASSERT(framebuffer);
3424
3425 if (framebuffer->id() == 0)
3426 {
3427 if (clientVersion < 3)
3428 {
3429 context->handleError(Error(GL_INVALID_OPERATION));
3430 return false;
3431 }
3432
3433 switch (attachment)
3434 {
3435 case GL_BACK:
3436 case GL_DEPTH:
3437 case GL_STENCIL:
3438 break;
3439
3440 default:
3441 context->handleError(Error(GL_INVALID_OPERATION));
3442 return false;
3443 }
3444 }
3445 else
3446 {
3447 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3448 {
3449 // Valid attachment query
3450 }
3451 else
3452 {
3453 switch (attachment)
3454 {
3455 case GL_DEPTH_ATTACHMENT:
3456 case GL_STENCIL_ATTACHMENT:
3457 break;
3458
3459 case GL_DEPTH_STENCIL_ATTACHMENT:
3460 if (!framebuffer->hasValidDepthStencil())
3461 {
3462 context->handleError(Error(GL_INVALID_OPERATION));
3463 return false;
3464 }
3465 break;
3466
3467 default:
3468 context->handleError(Error(GL_INVALID_OPERATION));
3469 return false;
3470 }
3471 }
3472 }
3473
3474 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3475 if (attachmentObject)
3476 {
3477 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3478 attachmentObject->type() == GL_TEXTURE ||
3479 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3480
3481 switch (pname)
3482 {
3483 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3484 if (attachmentObject->type() != GL_RENDERBUFFER &&
3485 attachmentObject->type() != GL_TEXTURE)
3486 {
3487 context->handleError(Error(GL_INVALID_ENUM));
3488 return false;
3489 }
3490 break;
3491
3492 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3493 if (attachmentObject->type() != GL_TEXTURE)
3494 {
3495 context->handleError(Error(GL_INVALID_ENUM));
3496 return false;
3497 }
3498 break;
3499
3500 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3501 if (attachmentObject->type() != GL_TEXTURE)
3502 {
3503 context->handleError(Error(GL_INVALID_ENUM));
3504 return false;
3505 }
3506 break;
3507
3508 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3509 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3510 {
3511 context->handleError(Error(GL_INVALID_OPERATION));
3512 return false;
3513 }
3514 break;
3515
3516 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3517 if (attachmentObject->type() != GL_TEXTURE)
3518 {
3519 context->handleError(Error(GL_INVALID_ENUM));
3520 return false;
3521 }
3522 break;
3523
3524 default:
3525 break;
3526 }
3527 }
3528 else
3529 {
3530 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3531 // is NONE, then querying any other pname will generate INVALID_ENUM.
3532
3533 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3534 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3535 // INVALID_OPERATION for all other pnames
3536
3537 switch (pname)
3538 {
3539 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3540 break;
3541
3542 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3543 if (clientVersion < 3)
3544 {
3545 context->handleError(Error(GL_INVALID_ENUM));
3546 return false;
3547 }
3548 break;
3549
3550 default:
3551 if (clientVersion < 3)
3552 {
3553 context->handleError(Error(GL_INVALID_ENUM));
3554 return false;
3555 }
3556 else
3557 {
3558 context->handleError(Error(GL_INVALID_OPERATION));
3559 return false;
3560 }
3561 }
3562 }
3563
3564 return true;
3565}
3566
3567bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
3568 GLenum target,
3569 GLenum attachment,
3570 GLenum pname,
3571 GLsizei bufSize,
3572 GLsizei *numParams)
3573{
3574 if (!ValidateRobustEntryPoint(context, bufSize))
3575 {
3576 return false;
3577 }
3578
3579 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
3580 {
3581 return false;
3582 }
3583
3584 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
3585 {
3586 return false;
3587 }
3588
3589 return true;
3590}
3591
3592bool ValidateGetBufferParameteriv(ValidationContext *context,
3593 GLenum target,
3594 GLenum pname,
3595 GLsizei *numParams)
3596{
3597 // Initialize result
3598 *numParams = 0;
3599
3600 if (!ValidBufferTarget(context, target))
3601 {
3602 context->handleError(Error(GL_INVALID_ENUM));
3603 return false;
3604 }
3605
3606 if (!ValidBufferParameter(context, pname, numParams))
3607 {
3608 context->handleError(Error(GL_INVALID_ENUM));
3609 return false;
3610 }
3611
3612 if (context->getGLState().getTargetBuffer(target) == nullptr)
3613 {
3614 // A null buffer means that "0" is bound to the requested buffer target
3615 context->handleError(Error(GL_INVALID_OPERATION));
3616 return false;
3617 }
3618
3619 return true;
3620}
3621
3622bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
3623 GLenum target,
3624 GLenum pname,
3625 GLsizei bufSize,
3626 GLsizei *numParams)
3627{
3628 if (!ValidateRobustEntryPoint(context, bufSize))
3629 {
3630 return false;
3631 }
3632
3633 if (!ValidateGetBufferParameteriv(context, target, pname, numParams))
3634 {
3635 return false;
3636 }
3637
3638 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
3639 {
3640 return false;
3641 }
3642
3643 return true;
3644}
3645
3646bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
3647{
3648 // Currently, all GetProgramiv queries return 1 parameter
3649 *numParams = 1;
3650
3651 Program *programObject = GetValidProgram(context, program);
3652 if (!programObject)
3653 {
3654 return false;
3655 }
3656
3657 switch (pname)
3658 {
3659 case GL_DELETE_STATUS:
3660 case GL_LINK_STATUS:
3661 case GL_VALIDATE_STATUS:
3662 case GL_INFO_LOG_LENGTH:
3663 case GL_ATTACHED_SHADERS:
3664 case GL_ACTIVE_ATTRIBUTES:
3665 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
3666 case GL_ACTIVE_UNIFORMS:
3667 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
3668 break;
3669
3670 case GL_PROGRAM_BINARY_LENGTH:
3671 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
3672 {
3673 context->handleError(Error(GL_INVALID_ENUM,
3674 "Querying GL_PROGRAM_BINARY_LENGTH requires "
3675 "GL_OES_get_program_binary or ES 3.0."));
3676 return false;
3677 }
3678 break;
3679
3680 case GL_ACTIVE_UNIFORM_BLOCKS:
3681 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
3682 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
3683 case GL_TRANSFORM_FEEDBACK_VARYINGS:
3684 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
3685 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
3686 if (context->getClientMajorVersion() < 3)
3687 {
3688 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
3689 return false;
3690 }
3691 break;
3692
3693 default:
3694 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
3695 return false;
3696 }
3697
3698 return true;
3699}
3700
3701bool ValidateGetProgramivRobustANGLE(Context *context,
3702 GLuint program,
3703 GLenum pname,
3704 GLsizei bufSize,
3705 GLsizei *numParams)
3706{
3707 if (!ValidateRobustEntryPoint(context, bufSize))
3708 {
3709 return false;
3710 }
3711
3712 if (!ValidateGetProgramiv(context, program, pname, numParams))
3713 {
3714 return false;
3715 }
3716
3717 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
3718 {
3719 return false;
3720 }
3721
3722 return true;
3723}
3724
Jamie Madillc29968b2016-01-20 11:17:23 -05003725} // namespace gl