blob: 4521be572756c8d6e2bfd8517411414a51833a6d [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:
1738 if (!context->getExtensions().eglStreamConsumerExternal)
1739 {
Jamie Madill437fa652016-05-03 15:13:24 -04001740 context->handleError(
Ian Ewell54f87462016-03-10 13:47:21 -05001741 Error(GL_INVALID_ENUM, "NV_EGL_stream_consumer_external extension not enabled"));
1742 return false;
1743 }
1744 break;
Jamie Madill893ab082014-05-16 16:56:10 -04001745
1746 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1747 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1748 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04001749 if (context->getGLState().getReadFramebuffer()->checkStatus(
1750 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04001751 {
Jamie Madill437fa652016-05-03 15:13:24 -04001752 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001753 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001754 }
1755
Jamie Madill51f40ec2016-06-15 14:06:00 -04001756 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
1757 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03001758
1759 if (framebuffer->getReadBufferState() == GL_NONE)
1760 {
1761 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
1762 return false;
1763 }
1764
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001765 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04001766 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04001767 {
Jamie Madill437fa652016-05-03 15:13:24 -04001768 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001769 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001770 }
1771 }
1772 break;
1773
1774 default:
1775 break;
1776 }
1777
1778 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04001779 if (*numParams == 0)
1780 {
1781 return false;
1782 }
1783
1784 return true;
1785}
1786
1787bool ValidateRobustStateQuery(ValidationContext *context,
1788 GLenum pname,
1789 GLsizei bufSize,
1790 GLenum *nativeType,
1791 unsigned int *numParams)
1792{
1793 if (!ValidateRobustEntryPoint(context, bufSize))
1794 {
1795 return false;
1796 }
1797
1798 if (!ValidateStateQuery(context, pname, nativeType, numParams))
1799 {
1800 return false;
1801 }
1802
1803 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04001804 {
1805 return false;
1806 }
1807
1808 return true;
1809}
1810
Jamie Madillc29968b2016-01-20 11:17:23 -05001811bool ValidateCopyTexImageParametersBase(ValidationContext *context,
1812 GLenum target,
1813 GLint level,
1814 GLenum internalformat,
1815 bool isSubImage,
1816 GLint xoffset,
1817 GLint yoffset,
1818 GLint zoffset,
1819 GLint x,
1820 GLint y,
1821 GLsizei width,
1822 GLsizei height,
1823 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04001824 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04001825{
Jamie Madill560a8d82014-05-21 13:06:20 -04001826 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
1827 {
Jamie Madill437fa652016-05-03 15:13:24 -04001828 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001829 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001830 }
1831
1832 if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1833 {
Jamie Madill437fa652016-05-03 15:13:24 -04001834 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001835 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001836 }
1837
1838 if (border != 0)
1839 {
Jamie Madill437fa652016-05-03 15:13:24 -04001840 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001841 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001842 }
1843
1844 if (!ValidMipLevel(context, target, level))
1845 {
Jamie Madill437fa652016-05-03 15:13:24 -04001846 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001847 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001848 }
1849
Jamie Madill51f40ec2016-06-15 14:06:00 -04001850 const auto &state = context->getGLState();
1851 auto readFramebuffer = state.getReadFramebuffer();
1852 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04001853 {
Jamie Madill437fa652016-05-03 15:13:24 -04001854 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001855 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001856 }
1857
Jamie Madill51f40ec2016-06-15 14:06:00 -04001858 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04001859 {
Jamie Madill437fa652016-05-03 15:13:24 -04001860 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001861 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001862 }
1863
Martin Radev138064f2016-07-15 12:03:41 +03001864 if (readFramebuffer->getReadBufferState() == GL_NONE)
1865 {
1866 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
1867 return false;
1868 }
1869
Geoff Langaae65a42014-05-26 12:43:44 -04001870 const gl::Caps &caps = context->getCaps();
1871
Geoff Langaae65a42014-05-26 12:43:44 -04001872 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04001873 switch (target)
1874 {
1875 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05001876 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04001877 break;
1878
1879 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1880 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1881 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1882 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1883 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1884 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -05001885 maxDimension = caps.maxCubeMapTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04001886 break;
1887
1888 case GL_TEXTURE_2D_ARRAY:
Geoff Langa9be0dc2014-12-17 12:34:40 -05001889 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04001890 break;
1891
1892 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05001893 maxDimension = caps.max3DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04001894 break;
1895
1896 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001897 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001898 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001899 }
1900
Jamie Madillc29968b2016-01-20 11:17:23 -05001901 gl::Texture *texture =
1902 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04001903 if (!texture)
1904 {
Jamie Madill437fa652016-05-03 15:13:24 -04001905 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001906 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001907 }
1908
Geoff Lang69cce582015-09-17 13:20:36 -04001909 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04001910 {
Jamie Madill437fa652016-05-03 15:13:24 -04001911 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001912 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001913 }
1914
Geoff Lang5d601382014-07-22 15:14:06 -04001915 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1916
1917 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04001918 {
Jamie Madill437fa652016-05-03 15:13:24 -04001919 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001920 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001921 }
1922
Geoff Langa9be0dc2014-12-17 12:34:40 -05001923 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04001924 {
Jamie Madill437fa652016-05-03 15:13:24 -04001925 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05001926 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001927 }
1928
1929 if (isSubImage)
1930 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05001931 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
1932 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
1933 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04001934 {
Jamie Madill437fa652016-05-03 15:13:24 -04001935 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001936 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001937 }
1938 }
Jamie Madill6f38f822014-06-06 17:12:20 -04001939 else
1940 {
Geoff Lang691e58c2014-12-19 17:03:25 -05001941 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04001942 {
Jamie Madill437fa652016-05-03 15:13:24 -04001943 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001944 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04001945 }
1946
Martin Radev1be913c2016-07-11 17:59:16 +03001947 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04001948 {
Jamie Madill437fa652016-05-03 15:13:24 -04001949 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001950 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04001951 }
1952
1953 int maxLevelDimension = (maxDimension >> level);
1954 if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension)
1955 {
Jamie Madill437fa652016-05-03 15:13:24 -04001956 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001957 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04001958 }
1959 }
Jamie Madill560a8d82014-05-21 13:06:20 -04001960
Jamie Madill0c8abca2016-07-22 20:21:26 -04001961 if (textureFormatOut)
1962 {
1963 *textureFormatOut = texture->getFormat(target, level);
1964 }
Jamie Madill560a8d82014-05-21 13:06:20 -04001965 return true;
1966}
1967
Jamie Madillf25855c2015-11-03 11:06:18 -05001968static bool ValidateDrawBase(ValidationContext *context,
1969 GLenum mode,
1970 GLsizei count,
1971 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04001972{
Jamie Madill1aeb1312014-06-20 13:21:25 -04001973 switch (mode)
1974 {
1975 case GL_POINTS:
1976 case GL_LINES:
1977 case GL_LINE_LOOP:
1978 case GL_LINE_STRIP:
1979 case GL_TRIANGLES:
1980 case GL_TRIANGLE_STRIP:
1981 case GL_TRIANGLE_FAN:
1982 break;
1983 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001984 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001985 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04001986 }
1987
Jamie Madill250d33f2014-06-06 17:09:03 -04001988 if (count < 0)
1989 {
Jamie Madill437fa652016-05-03 15:13:24 -04001990 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001991 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04001992 }
1993
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001994 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04001995
Jamie Madill250d33f2014-06-06 17:09:03 -04001996 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04001997 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04001998 {
Jamie Madill437fa652016-05-03 15:13:24 -04001999 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002000 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002001 }
2002
Jamie Madill51f40ec2016-06-15 14:06:00 -04002003 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04002004 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04002005 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04002006 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
2007 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
2008 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
2009 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2010 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2011 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04002012 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04002013 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2014 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04002015 {
2016 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2017 // Section 6.10 of the WebGL 1.0 spec
2018 ERR(
2019 "This ANGLE implementation does not support separate front/back stencil "
2020 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04002021 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04002022 return false;
2023 }
Jamie Madillac528012014-06-20 13:21:23 -04002024 }
2025
Jamie Madill51f40ec2016-06-15 14:06:00 -04002026 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002027 {
Jamie Madill437fa652016-05-03 15:13:24 -04002028 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002029 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002030 }
2031
Geoff Lang7dd2e102014-11-10 15:19:26 -05002032 gl::Program *program = state.getProgram();
2033 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002034 {
Jamie Madill437fa652016-05-03 15:13:24 -04002035 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002036 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002037 }
2038
Geoff Lang7dd2e102014-11-10 15:19:26 -05002039 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002040 {
Jamie Madill437fa652016-05-03 15:13:24 -04002041 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002042 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002043 }
2044
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002045 // Uniform buffer validation
2046 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2047 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002048 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002049 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002050 const OffsetBindingPointer<Buffer> &uniformBuffer =
2051 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002052
Geoff Lang5d124a62015-09-15 13:03:27 -04002053 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002054 {
2055 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002056 context->handleError(
2057 Error(GL_INVALID_OPERATION,
2058 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002059 return false;
2060 }
2061
Geoff Lang5d124a62015-09-15 13:03:27 -04002062 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002063 if (uniformBufferSize == 0)
2064 {
2065 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002066 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002067 }
2068
Jamie Madill62d31cb2015-09-11 13:25:51 -04002069 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002070 {
2071 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002072 context->handleError(
2073 Error(GL_INVALID_OPERATION,
2074 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002075 return false;
2076 }
2077 }
2078
Jamie Madill250d33f2014-06-06 17:09:03 -04002079 // No-op if zero count
2080 return (count > 0);
2081}
2082
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002083bool ValidateDrawArrays(ValidationContext *context,
2084 GLenum mode,
2085 GLint first,
2086 GLsizei count,
2087 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002088{
Jamie Madillfd716582014-06-06 17:09:04 -04002089 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002090 {
Jamie Madill437fa652016-05-03 15:13:24 -04002091 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002092 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002093 }
2094
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002095 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002096 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04002097 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused() &&
2098 curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002099 {
2100 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
2101 // that does not match the current transform feedback object's draw mode (if transform feedback
2102 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002103 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002104 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002105 }
2106
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002107 if (!ValidateDrawBase(context, mode, count, primcount))
2108 {
2109 return false;
2110 }
2111
2112 if (!ValidateDrawAttribs(context, primcount, count))
Jamie Madillfd716582014-06-06 17:09:04 -04002113 {
2114 return false;
2115 }
2116
2117 return true;
2118}
2119
Geoff Langb1196682014-07-23 13:47:29 -04002120bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002121{
2122 if (primcount < 0)
2123 {
Jamie Madill437fa652016-05-03 15:13:24 -04002124 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002125 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002126 }
2127
Jamie Madill2b976812014-08-25 15:47:49 -04002128 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04002129 {
2130 return false;
2131 }
2132
2133 // No-op if zero primitive count
2134 return (primcount > 0);
2135}
2136
Geoff Lang87a93302014-09-16 13:29:43 -04002137static bool ValidateDrawInstancedANGLE(Context *context)
2138{
2139 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002140 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04002141
Geoff Lang7dd2e102014-11-10 15:19:26 -05002142 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04002143
2144 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04002145 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04002146 {
2147 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04002148 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04002149 {
2150 return true;
2151 }
2152 }
2153
Jamie Madill437fa652016-05-03 15:13:24 -04002154 context->handleError(Error(GL_INVALID_OPERATION,
2155 "ANGLE_instanced_arrays requires that at least one active attribute"
2156 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04002157 return false;
2158}
2159
2160bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
2161{
2162 if (!ValidateDrawInstancedANGLE(context))
2163 {
2164 return false;
2165 }
2166
2167 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
2168}
2169
Jamie Madillf25855c2015-11-03 11:06:18 -05002170bool ValidateDrawElements(ValidationContext *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04002171 GLenum mode,
2172 GLsizei count,
2173 GLenum type,
2174 const GLvoid *indices,
2175 GLsizei primcount,
2176 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04002177{
Jamie Madill250d33f2014-06-06 17:09:03 -04002178 switch (type)
2179 {
2180 case GL_UNSIGNED_BYTE:
2181 case GL_UNSIGNED_SHORT:
Martin Radev1be913c2016-07-11 17:59:16 +03002182 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04002183 case GL_UNSIGNED_INT:
Martin Radev1be913c2016-07-11 17:59:16 +03002184 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2185 {
2186 context->handleError(Error(GL_INVALID_ENUM));
2187 return false;
2188 }
2189 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04002190 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002191 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03002192 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002193 }
2194
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002195 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002196
2197 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04002198 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002199 {
2200 // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
2201 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002202 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002203 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002204 }
2205
2206 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002207 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002208 {
Jamie Madill437fa652016-05-03 15:13:24 -04002209 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002210 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002211 }
2212
Jamie Madill2b976812014-08-25 15:47:49 -04002213 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002214 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madill2b976812014-08-25 15:47:49 -04002215 if (!indices && !elementArrayBuffer)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002216 {
Jamie Madill437fa652016-05-03 15:13:24 -04002217 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002218 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002219 }
2220
Jamie Madillae3000b2014-08-25 15:47:51 -04002221 if (elementArrayBuffer)
2222 {
2223 const gl::Type &typeInfo = gl::GetTypeInfo(type);
2224
2225 GLint64 offset = reinterpret_cast<GLint64>(indices);
2226 GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset;
2227
2228 // check for integer overflows
2229 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
2230 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
2231 {
Jamie Madill437fa652016-05-03 15:13:24 -04002232 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04002233 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002234 }
2235
2236 // Check for reading past the end of the bound buffer object
2237 if (byteCount > elementArrayBuffer->getSize())
2238 {
Jamie Madill437fa652016-05-03 15:13:24 -04002239 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002240 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002241 }
2242 }
2243 else if (!indices)
2244 {
2245 // Catch this programming error here
Jamie Madill437fa652016-05-03 15:13:24 -04002246 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002247 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002248 }
2249
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002250 if (!ValidateDrawBase(context, mode, count, primcount))
2251 {
2252 return false;
2253 }
2254
Jamie Madill2b976812014-08-25 15:47:49 -04002255 // Use max index to validate if our vertex buffers are large enough for the pull.
2256 // TODO: offer fast path, with disabled index validation.
2257 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
2258 if (elementArrayBuffer)
2259 {
Jacek Cabana5521de2014-10-01 17:23:46 +02002260 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04002261 Error error =
2262 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
2263 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04002264 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04002265 {
Jamie Madill437fa652016-05-03 15:13:24 -04002266 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04002267 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04002268 }
2269 }
2270 else
2271 {
Geoff Lang3edfe032015-09-04 16:38:24 -04002272 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04002273 }
2274
Jamie Madille79b1e12015-11-04 16:36:37 -05002275 // If we use an index greater than our maximum supported index range, return an error.
2276 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2277 // return an error if possible here.
2278 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
2279 {
Jamie Madill437fa652016-05-03 15:13:24 -04002280 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05002281 return false;
2282 }
2283
Jamie Madillbc4c4bc2016-03-23 21:04:43 -04002284 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04002285 {
2286 return false;
2287 }
2288
Geoff Lang3edfe032015-09-04 16:38:24 -04002289 // No op if there are no real indices in the index data (all are primitive restart).
2290 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04002291}
2292
Geoff Langb1196682014-07-23 13:47:29 -04002293bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04002294 GLenum mode,
2295 GLsizei count,
2296 GLenum type,
2297 const GLvoid *indices,
2298 GLsizei primcount,
2299 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04002300{
2301 if (primcount < 0)
2302 {
Jamie Madill437fa652016-05-03 15:13:24 -04002303 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002304 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002305 }
2306
Jamie Madill2b976812014-08-25 15:47:49 -04002307 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04002308 {
2309 return false;
2310 }
2311
2312 // No-op zero primitive count
2313 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04002314}
2315
Geoff Lang3edfe032015-09-04 16:38:24 -04002316bool ValidateDrawElementsInstancedANGLE(Context *context,
2317 GLenum mode,
2318 GLsizei count,
2319 GLenum type,
2320 const GLvoid *indices,
2321 GLsizei primcount,
2322 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04002323{
2324 if (!ValidateDrawInstancedANGLE(context))
2325 {
2326 return false;
2327 }
2328
2329 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut);
2330}
2331
Geoff Langb1196682014-07-23 13:47:29 -04002332bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04002333 GLuint texture, GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002334{
Jamie Madill55ec3b12014-07-03 10:38:57 -04002335 if (!ValidFramebufferTarget(target))
2336 {
Jamie Madill437fa652016-05-03 15:13:24 -04002337 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002338 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002339 }
2340
2341 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002342 {
2343 return false;
2344 }
2345
Jamie Madill55ec3b12014-07-03 10:38:57 -04002346 if (texture != 0)
2347 {
2348 gl::Texture *tex = context->getTexture(texture);
2349
2350 if (tex == NULL)
2351 {
Jamie Madill437fa652016-05-03 15:13:24 -04002352 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002353 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002354 }
2355
2356 if (level < 0)
2357 {
Jamie Madill437fa652016-05-03 15:13:24 -04002358 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002359 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002360 }
2361 }
2362
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002363 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002364 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002365
Jamie Madill84115c92015-04-23 15:00:07 -04002366 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002367 {
Jamie Madill437fa652016-05-03 15:13:24 -04002368 context->handleError(
2369 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002370 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002371 }
2372
2373 return true;
2374}
2375
Geoff Langb1196682014-07-23 13:47:29 -04002376bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04002377 GLenum textarget, GLuint texture, GLint level)
2378{
Geoff Lang95663912015-04-02 15:54:45 -04002379 // 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 +03002380 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
2381 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002382 {
Jamie Madill437fa652016-05-03 15:13:24 -04002383 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002384 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002385 }
2386
2387 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04002388 {
2389 return false;
2390 }
2391
Jamie Madill55ec3b12014-07-03 10:38:57 -04002392 if (texture != 0)
2393 {
2394 gl::Texture *tex = context->getTexture(texture);
2395 ASSERT(tex);
2396
Jamie Madill2a6564e2014-07-11 09:53:19 -04002397 const gl::Caps &caps = context->getCaps();
2398
Jamie Madill55ec3b12014-07-03 10:38:57 -04002399 switch (textarget)
2400 {
2401 case GL_TEXTURE_2D:
2402 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04002403 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002404 {
Jamie Madill437fa652016-05-03 15:13:24 -04002405 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002406 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002407 }
2408 if (tex->getTarget() != GL_TEXTURE_2D)
2409 {
Jamie Madill437fa652016-05-03 15:13:24 -04002410 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002411 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002412 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002413 }
2414 break;
2415
2416 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2417 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2418 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2419 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2420 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2421 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2422 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04002423 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002424 {
Jamie Madill437fa652016-05-03 15:13:24 -04002425 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002426 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002427 }
2428 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
2429 {
Jamie Madill437fa652016-05-03 15:13:24 -04002430 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002431 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002432 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002433 }
2434 break;
2435
2436 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002437 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002438 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002439 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05002440
Jamie Madilla3944d42016-07-22 22:13:26 -04002441 const Format &format = tex->getFormat(textarget, level);
2442 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05002443 {
Jamie Madill437fa652016-05-03 15:13:24 -04002444 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002445 return false;
2446 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002447 }
2448
Jamie Madill570f7c82014-07-03 10:38:54 -04002449 return true;
2450}
2451
Geoff Langb1196682014-07-23 13:47:29 -04002452bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04002453{
2454 if (program == 0)
2455 {
Jamie Madill437fa652016-05-03 15:13:24 -04002456 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002457 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002458 }
2459
Dian Xiang769769a2015-09-09 15:20:08 -07002460 gl::Program *programObject = GetValidProgram(context, program);
2461 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05002462 {
2463 return false;
2464 }
2465
Jamie Madill0063c512014-08-25 15:47:53 -04002466 if (!programObject || !programObject->isLinked())
2467 {
Jamie Madill437fa652016-05-03 15:13:24 -04002468 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002469 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002470 }
2471
Geoff Lang7dd2e102014-11-10 15:19:26 -05002472 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04002473 {
Jamie Madill437fa652016-05-03 15:13:24 -04002474 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002475 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04002476 }
2477
Jamie Madill0063c512014-08-25 15:47:53 -04002478 return true;
2479}
2480
Geoff Langb1196682014-07-23 13:47:29 -04002481bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params)
Jamie Madill78f41802014-08-25 15:47:55 -04002482{
2483 return ValidateGetUniformBase(context, program, location);
2484}
2485
Geoff Langb1196682014-07-23 13:47:29 -04002486bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04002487{
Jamie Madill78f41802014-08-25 15:47:55 -04002488 return ValidateGetUniformBase(context, program, location);
2489}
2490
Geoff Langb1196682014-07-23 13:47:29 -04002491static bool ValidateSizedGetUniform(Context *context, GLuint program, GLint location, GLsizei bufSize)
Jamie Madill78f41802014-08-25 15:47:55 -04002492{
2493 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04002494 {
Jamie Madill78f41802014-08-25 15:47:55 -04002495 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002496 }
2497
Jamie Madilla502c742014-08-28 17:19:13 -04002498 gl::Program *programObject = context->getProgram(program);
2499 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04002500
Jamie Madill78f41802014-08-25 15:47:55 -04002501 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04002502 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
2503 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04002504 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04002505 {
Jamie Madill437fa652016-05-03 15:13:24 -04002506 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002507 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002508 }
2509
2510 return true;
2511}
2512
Geoff Langb1196682014-07-23 13:47:29 -04002513bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
Jamie Madill0063c512014-08-25 15:47:53 -04002514{
Jamie Madill78f41802014-08-25 15:47:55 -04002515 return ValidateSizedGetUniform(context, program, location, bufSize);
Jamie Madill0063c512014-08-25 15:47:53 -04002516}
2517
Geoff Langb1196682014-07-23 13:47:29 -04002518bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04002519{
Jamie Madill78f41802014-08-25 15:47:55 -04002520 return ValidateSizedGetUniform(context, program, location, bufSize);
Jamie Madill0063c512014-08-25 15:47:53 -04002521}
2522
Austin Kinross08332632015-05-05 13:35:47 -07002523bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
2524 const GLenum *attachments, bool defaultFramebuffer)
2525{
2526 if (numAttachments < 0)
2527 {
Jamie Madill437fa652016-05-03 15:13:24 -04002528 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07002529 return false;
2530 }
2531
2532 for (GLsizei i = 0; i < numAttachments; ++i)
2533 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02002534 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07002535 {
2536 if (defaultFramebuffer)
2537 {
Jamie Madill437fa652016-05-03 15:13:24 -04002538 context->handleError(Error(
2539 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07002540 return false;
2541 }
2542
2543 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
2544 {
Jamie Madill437fa652016-05-03 15:13:24 -04002545 context->handleError(Error(GL_INVALID_OPERATION,
2546 "Requested color attachment is greater than the maximum "
2547 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07002548 return false;
2549 }
2550 }
2551 else
2552 {
2553 switch (attachments[i])
2554 {
2555 case GL_DEPTH_ATTACHMENT:
2556 case GL_STENCIL_ATTACHMENT:
2557 case GL_DEPTH_STENCIL_ATTACHMENT:
2558 if (defaultFramebuffer)
2559 {
Jamie Madill437fa652016-05-03 15:13:24 -04002560 context->handleError(
2561 Error(GL_INVALID_ENUM,
2562 "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07002563 return false;
2564 }
2565 break;
2566 case GL_COLOR:
2567 case GL_DEPTH:
2568 case GL_STENCIL:
2569 if (!defaultFramebuffer)
2570 {
Jamie Madill437fa652016-05-03 15:13:24 -04002571 context->handleError(
2572 Error(GL_INVALID_ENUM,
2573 "Invalid attachment when the default framebuffer is not bound"));
Austin Kinross08332632015-05-05 13:35:47 -07002574 return false;
2575 }
2576 break;
2577 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002578 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07002579 return false;
2580 }
2581 }
2582 }
2583
2584 return true;
2585}
2586
Austin Kinross6ee1e782015-05-29 17:05:37 -07002587bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
2588{
2589 // Note that debug marker calls must not set error state
2590
2591 if (length < 0)
2592 {
2593 return false;
2594 }
2595
2596 if (marker == nullptr)
2597 {
2598 return false;
2599 }
2600
2601 return true;
2602}
2603
2604bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
2605{
2606 // Note that debug marker calls must not set error state
2607
2608 if (length < 0)
2609 {
2610 return false;
2611 }
2612
2613 if (length > 0 && marker == nullptr)
2614 {
2615 return false;
2616 }
2617
2618 return true;
2619}
2620
Geoff Langdcab33b2015-07-21 13:03:16 -04002621bool ValidateEGLImageTargetTexture2DOES(Context *context,
2622 egl::Display *display,
2623 GLenum target,
2624 egl::Image *image)
2625{
Geoff Langa8406172015-07-21 16:53:39 -04002626 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
2627 {
Jamie Madill437fa652016-05-03 15:13:24 -04002628 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04002629 return false;
2630 }
2631
2632 switch (target)
2633 {
2634 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04002635 if (!context->getExtensions().eglImage)
2636 {
2637 context->handleError(Error(
2638 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
2639 }
2640 break;
2641
2642 case GL_TEXTURE_EXTERNAL_OES:
2643 if (!context->getExtensions().eglImageExternal)
2644 {
2645 context->handleError(Error(
2646 GL_INVALID_ENUM,
2647 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
2648 }
Geoff Langa8406172015-07-21 16:53:39 -04002649 break;
2650
2651 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002652 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04002653 return false;
2654 }
2655
2656 if (!display->isValidImage(image))
2657 {
Jamie Madill437fa652016-05-03 15:13:24 -04002658 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04002659 return false;
2660 }
2661
2662 if (image->getSamples() > 0)
2663 {
Jamie Madill437fa652016-05-03 15:13:24 -04002664 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04002665 "cannot create a 2D texture from a multisampled EGL image."));
2666 return false;
2667 }
2668
Jamie Madilla3944d42016-07-22 22:13:26 -04002669 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04002670 if (!textureCaps.texturable)
2671 {
Jamie Madill437fa652016-05-03 15:13:24 -04002672 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04002673 "EGL image internal format is not supported as a texture."));
2674 return false;
2675 }
2676
Geoff Langdcab33b2015-07-21 13:03:16 -04002677 return true;
2678}
2679
2680bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
2681 egl::Display *display,
2682 GLenum target,
2683 egl::Image *image)
2684{
Geoff Langa8406172015-07-21 16:53:39 -04002685 if (!context->getExtensions().eglImage)
2686 {
Jamie Madill437fa652016-05-03 15:13:24 -04002687 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04002688 return false;
2689 }
2690
2691 switch (target)
2692 {
2693 case GL_RENDERBUFFER:
2694 break;
2695
2696 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002697 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04002698 return false;
2699 }
2700
2701 if (!display->isValidImage(image))
2702 {
Jamie Madill437fa652016-05-03 15:13:24 -04002703 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04002704 return false;
2705 }
2706
Jamie Madilla3944d42016-07-22 22:13:26 -04002707 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04002708 if (!textureCaps.renderable)
2709 {
Jamie Madill437fa652016-05-03 15:13:24 -04002710 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04002711 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
2712 return false;
2713 }
2714
Geoff Langdcab33b2015-07-21 13:03:16 -04002715 return true;
2716}
Austin Kinrossbc781f32015-10-26 09:27:38 -07002717
2718bool ValidateBindVertexArrayBase(Context *context, GLuint array)
2719{
Geoff Lang36167ab2015-12-07 10:27:14 -05002720 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07002721 {
2722 // The default VAO should always exist
2723 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04002724 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07002725 return false;
2726 }
2727
2728 return true;
2729}
2730
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002731bool ValidateLinkProgram(Context *context, GLuint program)
2732{
2733 if (context->hasActiveTransformFeedback(program))
2734 {
2735 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04002736 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002737 "Cannot link program while program is associated with an active "
2738 "transform feedback object."));
2739 return false;
2740 }
2741 return true;
2742}
2743
Geoff Langc5629752015-12-07 16:29:04 -05002744bool ValidateProgramBinaryBase(Context *context,
2745 GLuint program,
2746 GLenum binaryFormat,
2747 const void *binary,
2748 GLint length)
2749{
2750 Program *programObject = GetValidProgram(context, program);
2751 if (programObject == nullptr)
2752 {
2753 return false;
2754 }
2755
2756 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
2757 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
2758 programBinaryFormats.end())
2759 {
Jamie Madill437fa652016-05-03 15:13:24 -04002760 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05002761 return false;
2762 }
2763
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002764 if (context->hasActiveTransformFeedback(program))
2765 {
2766 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04002767 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002768 "Cannot change program binary while program is associated with "
2769 "an active transform feedback object."));
2770 return false;
2771 }
2772
Geoff Langc5629752015-12-07 16:29:04 -05002773 return true;
2774}
2775
2776bool ValidateGetProgramBinaryBase(Context *context,
2777 GLuint program,
2778 GLsizei bufSize,
2779 GLsizei *length,
2780 GLenum *binaryFormat,
2781 void *binary)
2782{
2783 Program *programObject = GetValidProgram(context, program);
2784 if (programObject == nullptr)
2785 {
2786 return false;
2787 }
2788
2789 if (!programObject->isLinked())
2790 {
Jamie Madill437fa652016-05-03 15:13:24 -04002791 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05002792 return false;
2793 }
2794
2795 return true;
2796}
Jamie Madillc29968b2016-01-20 11:17:23 -05002797
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002798bool ValidateUseProgram(Context *context, GLuint program)
2799{
2800 if (program != 0)
2801 {
2802 Program *programObject = context->getProgram(program);
2803 if (!programObject)
2804 {
2805 // ES 3.1.0 section 7.3 page 72
2806 if (context->getShader(program))
2807 {
Jamie Madill437fa652016-05-03 15:13:24 -04002808 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002809 Error(GL_INVALID_OPERATION,
2810 "Attempted to use a single shader instead of a shader program."));
2811 return false;
2812 }
2813 else
2814 {
Jamie Madill437fa652016-05-03 15:13:24 -04002815 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002816 return false;
2817 }
2818 }
2819 if (!programObject->isLinked())
2820 {
Jamie Madill437fa652016-05-03 15:13:24 -04002821 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002822 return false;
2823 }
2824 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002825 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002826 {
2827 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04002828 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002829 Error(GL_INVALID_OPERATION,
2830 "Cannot change active program while transform feedback is unpaused."));
2831 return false;
2832 }
2833
2834 return true;
2835}
2836
Jamie Madillc29968b2016-01-20 11:17:23 -05002837bool ValidateCopyTexImage2D(ValidationContext *context,
2838 GLenum target,
2839 GLint level,
2840 GLenum internalformat,
2841 GLint x,
2842 GLint y,
2843 GLsizei width,
2844 GLsizei height,
2845 GLint border)
2846{
Martin Radev1be913c2016-07-11 17:59:16 +03002847 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05002848 {
2849 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
2850 0, x, y, width, height, border);
2851 }
2852
Martin Radev1be913c2016-07-11 17:59:16 +03002853 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05002854 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
2855 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002856}
Jamie Madillc29968b2016-01-20 11:17:23 -05002857
2858bool ValidateFramebufferRenderbuffer(Context *context,
2859 GLenum target,
2860 GLenum attachment,
2861 GLenum renderbuffertarget,
2862 GLuint renderbuffer)
2863{
2864 if (!ValidFramebufferTarget(target) ||
2865 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
2866 {
Jamie Madill437fa652016-05-03 15:13:24 -04002867 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05002868 return false;
2869 }
2870
2871 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
2872 renderbuffertarget, renderbuffer);
2873}
2874
2875bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
2876{
2877 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
2878 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
2879 {
Jamie Madill437fa652016-05-03 15:13:24 -04002880 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05002881 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
2882 return false;
2883 }
2884
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002885 ASSERT(context->getGLState().getDrawFramebuffer());
2886 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05002887 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
2888
2889 // This should come first before the check for the default frame buffer
2890 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
2891 // rather than INVALID_OPERATION
2892 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
2893 {
2894 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
2895
2896 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02002897 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
2898 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05002899 {
2900 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02002901 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
2902 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
2903 // 3.1 is still a bit ambiguous about the error, but future specs are
2904 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04002905 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02002906 return false;
2907 }
2908 else if (bufs[colorAttachment] >= maxColorAttachment)
2909 {
Jamie Madill437fa652016-05-03 15:13:24 -04002910 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02002911 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002912 return false;
2913 }
2914 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
2915 frameBufferId != 0)
2916 {
2917 // INVALID_OPERATION-GL is bound to buffer and ith argument
2918 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04002919 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05002920 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
2921 return false;
2922 }
2923 }
2924
2925 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
2926 // and n is not 1 or bufs is bound to value other than BACK and NONE
2927 if (frameBufferId == 0)
2928 {
2929 if (n != 1)
2930 {
Jamie Madill437fa652016-05-03 15:13:24 -04002931 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05002932 "n must be 1 when GL is bound to the default framebuffer"));
2933 return false;
2934 }
2935
2936 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
2937 {
Jamie Madill437fa652016-05-03 15:13:24 -04002938 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05002939 GL_INVALID_OPERATION,
2940 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
2941 return false;
2942 }
2943 }
2944
2945 return true;
2946}
2947
2948bool ValidateCopyTexSubImage2D(Context *context,
2949 GLenum target,
2950 GLint level,
2951 GLint xoffset,
2952 GLint yoffset,
2953 GLint x,
2954 GLint y,
2955 GLsizei width,
2956 GLsizei height)
2957{
Martin Radev1be913c2016-07-11 17:59:16 +03002958 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05002959 {
2960 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
2961 yoffset, x, y, width, height, 0);
2962 }
2963
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05002964 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
2965 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05002966}
2967
Olli Etuaho4f667482016-03-30 15:56:35 +03002968bool ValidateGetBufferPointervBase(Context *context, GLenum target, GLenum pname, void **params)
2969{
2970 if (!ValidBufferTarget(context, target))
2971 {
Jamie Madill437fa652016-05-03 15:13:24 -04002972 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03002973 return false;
2974 }
2975
2976 if (pname != GL_BUFFER_MAP_POINTER)
2977 {
Jamie Madill437fa652016-05-03 15:13:24 -04002978 context->handleError(Error(GL_INVALID_ENUM, "pname not valid: 0x%X", pname));
Olli Etuaho4f667482016-03-30 15:56:35 +03002979 return false;
2980 }
2981
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002982 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03002983
2984 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
2985 // target bound to zero generate an INVALID_OPERATION error."
2986 // GLES 3.1 section 6.6 explicitly specifies this error.
2987 if (!buffer)
2988 {
Jamie Madill437fa652016-05-03 15:13:24 -04002989 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03002990 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
2991 return false;
2992 }
2993
2994 return true;
2995}
2996
2997bool ValidateUnmapBufferBase(Context *context, GLenum target)
2998{
2999 if (!ValidBufferTarget(context, target))
3000 {
Jamie Madill437fa652016-05-03 15:13:24 -04003001 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003002 return false;
3003 }
3004
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003005 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003006
3007 if (buffer == nullptr || !buffer->isMapped())
3008 {
Jamie Madill437fa652016-05-03 15:13:24 -04003009 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003010 return false;
3011 }
3012
3013 return true;
3014}
3015
3016bool ValidateMapBufferRangeBase(Context *context,
3017 GLenum target,
3018 GLintptr offset,
3019 GLsizeiptr length,
3020 GLbitfield access)
3021{
3022 if (!ValidBufferTarget(context, target))
3023 {
Jamie Madill437fa652016-05-03 15:13:24 -04003024 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003025 return false;
3026 }
3027
3028 if (offset < 0 || length < 0)
3029 {
Jamie Madill437fa652016-05-03 15:13:24 -04003030 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003031 return false;
3032 }
3033
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003034 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003035
3036 if (!buffer)
3037 {
Jamie Madill437fa652016-05-03 15:13:24 -04003038 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003039 return false;
3040 }
3041
3042 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003043 CheckedNumeric<size_t> checkedOffset(offset);
3044 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003045
Jamie Madille2e406c2016-06-02 13:04:10 -04003046 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003047 {
Jamie Madill437fa652016-05-03 15:13:24 -04003048 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003049 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
3050 return false;
3051 }
3052
3053 // Check for invalid bits in the mask
3054 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3055 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3056 GL_MAP_UNSYNCHRONIZED_BIT;
3057
3058 if (access & ~(allAccessBits))
3059 {
Jamie Madill437fa652016-05-03 15:13:24 -04003060 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03003061 return false;
3062 }
3063
3064 if (length == 0)
3065 {
Jamie Madill437fa652016-05-03 15:13:24 -04003066 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003067 return false;
3068 }
3069
3070 if (buffer->isMapped())
3071 {
Jamie Madill437fa652016-05-03 15:13:24 -04003072 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003073 return false;
3074 }
3075
3076 // Check for invalid bit combinations
3077 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3078 {
Jamie Madill437fa652016-05-03 15:13:24 -04003079 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003080 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
3081 return false;
3082 }
3083
3084 GLbitfield writeOnlyBits =
3085 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3086
3087 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3088 {
Jamie Madill437fa652016-05-03 15:13:24 -04003089 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03003090 "Invalid access bits when mapping buffer for reading: 0x%X.",
3091 access));
3092 return false;
3093 }
3094
3095 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3096 {
Jamie Madill437fa652016-05-03 15:13:24 -04003097 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003098 GL_INVALID_OPERATION,
3099 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
3100 return false;
3101 }
3102 return true;
3103}
3104
3105bool ValidateFlushMappedBufferRangeBase(Context *context,
3106 GLenum target,
3107 GLintptr offset,
3108 GLsizeiptr length)
3109{
3110 if (offset < 0 || length < 0)
3111 {
Jamie Madill437fa652016-05-03 15:13:24 -04003112 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003113 return false;
3114 }
3115
3116 if (!ValidBufferTarget(context, target))
3117 {
Jamie Madill437fa652016-05-03 15:13:24 -04003118 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003119 return false;
3120 }
3121
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003122 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003123
3124 if (buffer == nullptr)
3125 {
Jamie Madill437fa652016-05-03 15:13:24 -04003126 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003127 return false;
3128 }
3129
3130 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3131 {
Jamie Madill437fa652016-05-03 15:13:24 -04003132 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003133 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
3134 return false;
3135 }
3136
3137 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003138 CheckedNumeric<size_t> checkedOffset(offset);
3139 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003140
Jamie Madille2e406c2016-06-02 13:04:10 -04003141 if (!checkedSize.IsValid() ||
3142 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003143 {
Jamie Madill437fa652016-05-03 15:13:24 -04003144 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003145 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
3146 return false;
3147 }
3148
3149 return true;
3150}
3151
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003152bool ValidateGenerateMipmap(Context *context, GLenum target)
3153{
3154 if (!ValidTextureTarget(context, target))
3155 {
3156 context->handleError(Error(GL_INVALID_ENUM));
3157 return false;
3158 }
3159
3160 Texture *texture = context->getTargetTexture(target);
3161
3162 if (texture == nullptr)
3163 {
3164 context->handleError(Error(GL_INVALID_OPERATION));
3165 return false;
3166 }
3167
3168 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
3169
3170 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
3171 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
3172 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
3173 {
3174 context->handleError(Error(GL_INVALID_OPERATION));
3175 return false;
3176 }
3177
Jamie Madilla3944d42016-07-22 22:13:26 -04003178 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
3179 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
3180 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003181
3182 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
3183 // unsized formats or that are color renderable and filterable. Since we do not track if
3184 // the texture was created with sized or unsized format (only sized formats are stored),
3185 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
3186 // be able to) because they aren't color renderable. Simply do a special case for LUMA
3187 // textures since they're the only texture format that can be created with unsized formats
3188 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
3189 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04003190 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
3191 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003192 {
3193 context->handleError(Error(GL_INVALID_OPERATION));
3194 return false;
3195 }
3196
3197 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04003198 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003199 {
3200 context->handleError(Error(GL_INVALID_OPERATION));
3201 return false;
3202 }
3203
3204 // Non-power of 2 ES2 check
3205 if (!context->getExtensions().textureNPOT &&
3206 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
3207 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
3208 {
Martin Radev1be913c2016-07-11 17:59:16 +03003209 ASSERT(context->getClientMajorVersion() <= 2 &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003210 (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
3211 context->handleError(Error(GL_INVALID_OPERATION));
3212 return false;
3213 }
3214
3215 // Cube completeness check
3216 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
3217 {
3218 context->handleError(Error(GL_INVALID_OPERATION));
3219 return false;
3220 }
3221
3222 return true;
3223}
3224
Olli Etuaho41997e72016-03-10 13:38:39 +02003225bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
3226{
3227 return ValidateGenOrDelete(context, n);
3228}
3229
3230bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
3231{
3232 return ValidateGenOrDelete(context, n);
3233}
3234
3235bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
3236{
3237 return ValidateGenOrDelete(context, n);
3238}
3239
3240bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
3241{
3242 return ValidateGenOrDelete(context, n);
3243}
3244
3245bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
3246{
3247 return ValidateGenOrDelete(context, n);
3248}
3249
3250bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
3251{
3252 return ValidateGenOrDelete(context, n);
3253}
3254
3255bool ValidateGenTextures(Context *context, GLint n, GLuint *)
3256{
3257 return ValidateGenOrDelete(context, n);
3258}
3259
3260bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
3261{
3262 return ValidateGenOrDelete(context, n);
3263}
3264
3265bool ValidateGenOrDelete(Context *context, GLint n)
3266{
3267 if (n < 0)
3268 {
Jamie Madill437fa652016-05-03 15:13:24 -04003269 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02003270 return false;
3271 }
3272 return true;
3273}
3274
Geoff Langf41a7152016-09-19 15:11:17 -04003275bool ValidateEnable(Context *context, GLenum cap)
3276{
3277 if (!ValidCap(context, cap, false))
3278 {
3279 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
3280 return false;
3281 }
3282
3283 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
3284 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
3285 {
3286 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
3287 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
3288
3289 // We also output an error message to the debugger window if tracing is active, so that
3290 // developers can see the error message.
3291 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04003292 return false;
3293 }
3294
3295 return true;
3296}
3297
3298bool ValidateDisable(Context *context, GLenum cap)
3299{
3300 if (!ValidCap(context, cap, false))
3301 {
3302 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
3303 return false;
3304 }
3305
3306 return true;
3307}
3308
3309bool ValidateIsEnabled(Context *context, GLenum cap)
3310{
3311 if (!ValidCap(context, cap, true))
3312 {
3313 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
3314 return false;
3315 }
3316
3317 return true;
3318}
3319
Geoff Langff5b2d52016-09-07 11:32:23 -04003320bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3321{
3322 if (!context->getExtensions().robustClientMemory)
3323 {
3324 context->handleError(
3325 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
3326 return false;
3327 }
3328
3329 if (bufSize < 0)
3330 {
3331 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3332 return false;
3333 }
3334
3335 return true;
3336}
3337
3338bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
3339 GLenum target,
3340 GLenum attachment,
3341 GLenum pname,
3342 GLsizei *numParams)
3343{
3344 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
3345 *numParams = 1;
3346
3347 if (!ValidFramebufferTarget(target))
3348 {
3349 context->handleError(Error(GL_INVALID_ENUM));
3350 return false;
3351 }
3352
3353 int clientVersion = context->getClientMajorVersion();
3354
3355 switch (pname)
3356 {
3357 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3358 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3359 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3360 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3361 break;
3362
3363 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3364 if (clientVersion < 3 && !context->getExtensions().sRGB)
3365 {
3366 context->handleError(Error(GL_INVALID_ENUM));
3367 return false;
3368 }
3369 break;
3370
3371 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3372 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3373 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3374 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3375 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3376 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3377 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3378 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3379 if (clientVersion < 3)
3380 {
3381 context->handleError(Error(GL_INVALID_ENUM));
3382 return false;
3383 }
3384 break;
3385
3386 default:
3387 context->handleError(Error(GL_INVALID_ENUM));
3388 return false;
3389 }
3390
3391 // Determine if the attachment is a valid enum
3392 switch (attachment)
3393 {
3394 case GL_BACK:
3395 case GL_FRONT:
3396 case GL_DEPTH:
3397 case GL_STENCIL:
3398 case GL_DEPTH_STENCIL_ATTACHMENT:
3399 if (clientVersion < 3)
3400 {
3401 context->handleError(Error(GL_INVALID_ENUM));
3402 return false;
3403 }
3404 break;
3405
3406 case GL_DEPTH_ATTACHMENT:
3407 case GL_STENCIL_ATTACHMENT:
3408 break;
3409
3410 default:
3411 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
3412 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3413 {
3414 context->handleError(Error(GL_INVALID_ENUM));
3415 return false;
3416 }
3417 break;
3418 }
3419
3420 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3421 ASSERT(framebuffer);
3422
3423 if (framebuffer->id() == 0)
3424 {
3425 if (clientVersion < 3)
3426 {
3427 context->handleError(Error(GL_INVALID_OPERATION));
3428 return false;
3429 }
3430
3431 switch (attachment)
3432 {
3433 case GL_BACK:
3434 case GL_DEPTH:
3435 case GL_STENCIL:
3436 break;
3437
3438 default:
3439 context->handleError(Error(GL_INVALID_OPERATION));
3440 return false;
3441 }
3442 }
3443 else
3444 {
3445 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3446 {
3447 // Valid attachment query
3448 }
3449 else
3450 {
3451 switch (attachment)
3452 {
3453 case GL_DEPTH_ATTACHMENT:
3454 case GL_STENCIL_ATTACHMENT:
3455 break;
3456
3457 case GL_DEPTH_STENCIL_ATTACHMENT:
3458 if (!framebuffer->hasValidDepthStencil())
3459 {
3460 context->handleError(Error(GL_INVALID_OPERATION));
3461 return false;
3462 }
3463 break;
3464
3465 default:
3466 context->handleError(Error(GL_INVALID_OPERATION));
3467 return false;
3468 }
3469 }
3470 }
3471
3472 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3473 if (attachmentObject)
3474 {
3475 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3476 attachmentObject->type() == GL_TEXTURE ||
3477 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3478
3479 switch (pname)
3480 {
3481 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3482 if (attachmentObject->type() != GL_RENDERBUFFER &&
3483 attachmentObject->type() != GL_TEXTURE)
3484 {
3485 context->handleError(Error(GL_INVALID_ENUM));
3486 return false;
3487 }
3488 break;
3489
3490 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3491 if (attachmentObject->type() != GL_TEXTURE)
3492 {
3493 context->handleError(Error(GL_INVALID_ENUM));
3494 return false;
3495 }
3496 break;
3497
3498 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3499 if (attachmentObject->type() != GL_TEXTURE)
3500 {
3501 context->handleError(Error(GL_INVALID_ENUM));
3502 return false;
3503 }
3504 break;
3505
3506 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3507 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3508 {
3509 context->handleError(Error(GL_INVALID_OPERATION));
3510 return false;
3511 }
3512 break;
3513
3514 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3515 if (attachmentObject->type() != GL_TEXTURE)
3516 {
3517 context->handleError(Error(GL_INVALID_ENUM));
3518 return false;
3519 }
3520 break;
3521
3522 default:
3523 break;
3524 }
3525 }
3526 else
3527 {
3528 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3529 // is NONE, then querying any other pname will generate INVALID_ENUM.
3530
3531 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3532 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3533 // INVALID_OPERATION for all other pnames
3534
3535 switch (pname)
3536 {
3537 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3538 break;
3539
3540 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3541 if (clientVersion < 3)
3542 {
3543 context->handleError(Error(GL_INVALID_ENUM));
3544 return false;
3545 }
3546 break;
3547
3548 default:
3549 if (clientVersion < 3)
3550 {
3551 context->handleError(Error(GL_INVALID_ENUM));
3552 return false;
3553 }
3554 else
3555 {
3556 context->handleError(Error(GL_INVALID_OPERATION));
3557 return false;
3558 }
3559 }
3560 }
3561
3562 return true;
3563}
3564
3565bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
3566 GLenum target,
3567 GLenum attachment,
3568 GLenum pname,
3569 GLsizei bufSize,
3570 GLsizei *numParams)
3571{
3572 if (!ValidateRobustEntryPoint(context, bufSize))
3573 {
3574 return false;
3575 }
3576
3577 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
3578 {
3579 return false;
3580 }
3581
3582 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
3583 {
3584 return false;
3585 }
3586
3587 return true;
3588}
3589
3590bool ValidateGetBufferParameteriv(ValidationContext *context,
3591 GLenum target,
3592 GLenum pname,
3593 GLsizei *numParams)
3594{
3595 // Initialize result
3596 *numParams = 0;
3597
3598 if (!ValidBufferTarget(context, target))
3599 {
3600 context->handleError(Error(GL_INVALID_ENUM));
3601 return false;
3602 }
3603
3604 if (!ValidBufferParameter(context, pname, numParams))
3605 {
3606 context->handleError(Error(GL_INVALID_ENUM));
3607 return false;
3608 }
3609
3610 if (context->getGLState().getTargetBuffer(target) == nullptr)
3611 {
3612 // A null buffer means that "0" is bound to the requested buffer target
3613 context->handleError(Error(GL_INVALID_OPERATION));
3614 return false;
3615 }
3616
3617 return true;
3618}
3619
3620bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
3621 GLenum target,
3622 GLenum pname,
3623 GLsizei bufSize,
3624 GLsizei *numParams)
3625{
3626 if (!ValidateRobustEntryPoint(context, bufSize))
3627 {
3628 return false;
3629 }
3630
3631 if (!ValidateGetBufferParameteriv(context, target, pname, numParams))
3632 {
3633 return false;
3634 }
3635
3636 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
3637 {
3638 return false;
3639 }
3640
3641 return true;
3642}
3643
3644bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
3645{
3646 // Currently, all GetProgramiv queries return 1 parameter
3647 *numParams = 1;
3648
3649 Program *programObject = GetValidProgram(context, program);
3650 if (!programObject)
3651 {
3652 return false;
3653 }
3654
3655 switch (pname)
3656 {
3657 case GL_DELETE_STATUS:
3658 case GL_LINK_STATUS:
3659 case GL_VALIDATE_STATUS:
3660 case GL_INFO_LOG_LENGTH:
3661 case GL_ATTACHED_SHADERS:
3662 case GL_ACTIVE_ATTRIBUTES:
3663 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
3664 case GL_ACTIVE_UNIFORMS:
3665 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
3666 break;
3667
3668 case GL_PROGRAM_BINARY_LENGTH:
3669 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
3670 {
3671 context->handleError(Error(GL_INVALID_ENUM,
3672 "Querying GL_PROGRAM_BINARY_LENGTH requires "
3673 "GL_OES_get_program_binary or ES 3.0."));
3674 return false;
3675 }
3676 break;
3677
3678 case GL_ACTIVE_UNIFORM_BLOCKS:
3679 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
3680 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
3681 case GL_TRANSFORM_FEEDBACK_VARYINGS:
3682 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
3683 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
3684 if (context->getClientMajorVersion() < 3)
3685 {
3686 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
3687 return false;
3688 }
3689 break;
3690
3691 default:
3692 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
3693 return false;
3694 }
3695
3696 return true;
3697}
3698
3699bool ValidateGetProgramivRobustANGLE(Context *context,
3700 GLuint program,
3701 GLenum pname,
3702 GLsizei bufSize,
3703 GLsizei *numParams)
3704{
3705 if (!ValidateRobustEntryPoint(context, bufSize))
3706 {
3707 return false;
3708 }
3709
3710 if (!ValidateGetProgramiv(context, program, pname, numParams))
3711 {
3712 return false;
3713 }
3714
3715 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
3716 {
3717 return false;
3718 }
3719
3720 return true;
3721}
3722
Jamie Madillc29968b2016-01-20 11:17:23 -05003723} // namespace gl