blob: fc3587ee0074dc4bcf071a55bb28d4fb3c9eef73 [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 Lang62fce5b2016-09-30 10:46:35 -0400183bool ValidateReadPixelsBase(ValidationContext *context,
184 GLint x,
185 GLint y,
186 GLsizei width,
187 GLsizei height,
188 GLenum format,
189 GLenum type,
190 GLsizei bufSize,
191 GLsizei *length,
192 GLvoid *pixels)
193{
194 if (length != nullptr)
195 {
196 *length = 0;
197 }
198
199 if (width < 0 || height < 0)
200 {
201 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
202 return false;
203 }
204
205 auto readFramebuffer = context->getGLState().getReadFramebuffer();
206
207 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
208 {
209 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
210 return false;
211 }
212
213 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
214 {
215 context->handleError(Error(GL_INVALID_OPERATION));
216 return false;
217 }
218
219 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
220 ASSERT(framebuffer);
221
222 if (framebuffer->getReadBufferState() == GL_NONE)
223 {
224 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
225 return false;
226 }
227
228 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
229 if (!readBuffer)
230 {
231 context->handleError(Error(GL_INVALID_OPERATION));
232 return false;
233 }
234
235 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
236 GLenum currentType = framebuffer->getImplementationColorReadType();
237 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
238
239 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
240 bool validFormatTypeCombination =
241 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
242
243 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
244 {
245 context->handleError(Error(GL_INVALID_OPERATION));
246 return false;
247 }
248
249 // Check for pixel pack buffer related API errors
250 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
251 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
252 {
253 // ...the buffer object's data store is currently mapped.
254 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
255 return false;
256 }
257
258 // .. the data would be packed to the buffer object such that the memory writes required
259 // would exceed the data store size.
260 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
261 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
262 const gl::Extents size(width, height, 1);
263 const auto &pack = context->getGLState().getPackState();
264
265 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
266 if (endByteOrErr.isError())
267 {
268 context->handleError(endByteOrErr.getError());
269 return false;
270 }
271
272 size_t endByte = endByteOrErr.getResult();
273 if (bufSize >= 0)
274 {
275
276 if (static_cast<size_t>(bufSize) < endByte)
277 {
278 context->handleError(
279 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
280 return false;
281 }
282 }
283
284 if (pixelPackBuffer != nullptr)
285 {
286 CheckedNumeric<size_t> checkedEndByte(endByte);
287 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
288 checkedEndByte += checkedOffset;
289
290 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
291 {
292 // Overflow past the end of the buffer
293 context->handleError(
294 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
295 return false;
296 }
297 }
298
299 if (length != nullptr)
300 {
301 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
302 {
303 context->handleError(
304 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
305 return false;
306 }
307
308 *length = static_cast<GLsizei>(endByte);
309 }
310
311 return true;
312}
313
Geoff Langf41a7152016-09-19 15:11:17 -0400314} // anonymous namespace
315
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500316bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400317{
Jamie Madilld7460c72014-01-21 16:38:14 -0500318 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400319 {
Jamie Madilld7460c72014-01-21 16:38:14 -0500320 case GL_TEXTURE_2D:
321 case GL_TEXTURE_CUBE_MAP:
322 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400323
Jamie Madilld7460c72014-01-21 16:38:14 -0500324 case GL_TEXTURE_3D:
325 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300326 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500327
328 default:
329 return false;
330 }
Jamie Madill35d15012013-10-07 10:46:37 -0400331}
332
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500333bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
334{
335 switch (target)
336 {
337 case GL_TEXTURE_2D:
338 case GL_TEXTURE_CUBE_MAP:
339 return true;
340
341 default:
342 return false;
343 }
344}
345
346bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
347{
348 switch (target)
349 {
350 case GL_TEXTURE_3D:
351 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300352 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500353
354 default:
355 return false;
356 }
357}
358
Ian Ewellbda75592016-04-18 17:25:54 -0400359// Most texture GL calls are not compatible with external textures, so we have a separate validation
360// function for use in the GL calls that do
361bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
362{
363 return (target == GL_TEXTURE_EXTERNAL_OES) &&
364 (context->getExtensions().eglImageExternal ||
365 context->getExtensions().eglStreamConsumerExternal);
366}
367
Shannon Woods4dfed832014-03-17 20:03:39 -0400368// This function differs from ValidTextureTarget in that the target must be
369// usable as the destination of a 2D operation-- so a cube face is valid, but
370// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400371// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500372bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400373{
374 switch (target)
375 {
376 case GL_TEXTURE_2D:
377 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
378 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
379 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
380 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
381 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
382 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
383 return true;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500384 default:
385 return false;
386 }
387}
388
389bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
390{
391 switch (target)
392 {
Shannon Woods4dfed832014-03-17 20:03:39 -0400393 case GL_TEXTURE_3D:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500394 case GL_TEXTURE_2D_ARRAY:
395 return true;
Shannon Woods4dfed832014-03-17 20:03:39 -0400396 default:
397 return false;
398 }
399}
400
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500401bool ValidFramebufferTarget(GLenum target)
402{
Geoff Langd4475812015-03-18 10:53:05 -0400403 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
404 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500405
406 switch (target)
407 {
408 case GL_FRAMEBUFFER: return true;
409 case GL_READ_FRAMEBUFFER: return true;
410 case GL_DRAW_FRAMEBUFFER: return true;
411 default: return false;
412 }
413}
414
Jamie Madill29639852016-09-02 15:00:09 -0400415bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -0500416{
417 switch (target)
418 {
419 case GL_ARRAY_BUFFER:
420 case GL_ELEMENT_ARRAY_BUFFER:
421 return true;
422
Jamie Madill8c96d582014-03-05 15:01:23 -0500423 case GL_PIXEL_PACK_BUFFER:
424 case GL_PIXEL_UNPACK_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +0300425 return (context->getExtensions().pixelBufferObject ||
426 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -0400427
Shannon Woodsb3801742014-03-27 14:59:19 -0400428 case GL_COPY_READ_BUFFER:
429 case GL_COPY_WRITE_BUFFER:
Jamie Madill8c96d582014-03-05 15:01:23 -0500430 case GL_TRANSFORM_FEEDBACK_BUFFER:
431 case GL_UNIFORM_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +0300432 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -0500433
434 default:
435 return false;
436 }
437}
438
Geoff Langff5b2d52016-09-07 11:32:23 -0400439bool ValidBufferParameter(const ValidationContext *context, GLenum pname, GLsizei *numParams)
Jamie Madill70656a62014-03-05 15:01:26 -0500440{
Geoff Langff5b2d52016-09-07 11:32:23 -0400441 // All buffer parameter queries return one value.
442 *numParams = 1;
443
Geoff Langcc6f55d2015-03-20 13:01:02 -0400444 const Extensions &extensions = context->getExtensions();
445
Jamie Madill70656a62014-03-05 15:01:26 -0500446 switch (pname)
447 {
448 case GL_BUFFER_USAGE:
449 case GL_BUFFER_SIZE:
450 return true;
451
Geoff Langcc6f55d2015-03-20 13:01:02 -0400452 case GL_BUFFER_ACCESS_OES:
453 return extensions.mapBuffer;
454
455 case GL_BUFFER_MAPPED:
456 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
Martin Radev1be913c2016-07-11 17:59:16 +0300457 return (context->getClientMajorVersion() >= 3) || extensions.mapBuffer ||
458 extensions.mapBufferRange;
Geoff Langcc6f55d2015-03-20 13:01:02 -0400459
Jamie Madill70656a62014-03-05 15:01:26 -0500460 // GL_BUFFER_MAP_POINTER is a special case, and may only be
461 // queried with GetBufferPointerv
462 case GL_BUFFER_ACCESS_FLAGS:
Jamie Madill70656a62014-03-05 15:01:26 -0500463 case GL_BUFFER_MAP_OFFSET:
464 case GL_BUFFER_MAP_LENGTH:
Martin Radev1be913c2016-07-11 17:59:16 +0300465 return (context->getClientMajorVersion() >= 3) || extensions.mapBufferRange;
Jamie Madill70656a62014-03-05 15:01:26 -0500466
467 default:
468 return false;
469 }
470}
471
Jamie Madillc29968b2016-01-20 11:17:23 -0500472bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400473{
Jamie Madillc29968b2016-01-20 11:17:23 -0500474 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400475 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400476 switch (target)
477 {
Jamie Madillc29968b2016-01-20 11:17:23 -0500478 case GL_TEXTURE_2D:
479 maxDimension = caps.max2DTextureSize;
480 break;
Geoff Langce635692013-09-24 13:56:32 -0400481 case GL_TEXTURE_CUBE_MAP:
482 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
483 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
484 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
485 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
486 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
Jamie Madillc29968b2016-01-20 11:17:23 -0500487 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
488 maxDimension = caps.maxCubeMapTextureSize;
489 break;
490 case GL_TEXTURE_3D:
491 maxDimension = caps.max3DTextureSize;
492 break;
493 case GL_TEXTURE_2D_ARRAY:
494 maxDimension = caps.max2DTextureSize;
495 break;
Geoff Langce635692013-09-24 13:56:32 -0400496 default: UNREACHABLE();
497 }
498
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700499 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -0400500}
501
Austin Kinross08528e12015-10-07 16:24:40 -0700502bool ValidImageSizeParameters(const Context *context,
503 GLenum target,
504 GLint level,
505 GLsizei width,
506 GLsizei height,
507 GLsizei depth,
508 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400509{
510 if (level < 0 || width < 0 || height < 0 || depth < 0)
511 {
512 return false;
513 }
514
Austin Kinross08528e12015-10-07 16:24:40 -0700515 // TexSubImage parameters can be NPOT without textureNPOT extension,
516 // as long as the destination texture is POT.
517 if (!isSubImage && !context->getExtensions().textureNPOT &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400518 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400519 {
520 return false;
521 }
522
523 if (!ValidMipLevel(context, target, level))
524 {
525 return false;
526 }
527
528 return true;
529}
530
Geoff Lang0d8b7242015-09-09 14:56:53 -0400531bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
532{
533 // List of compressed format that require that the texture size is smaller than or a multiple of
534 // the compressed block size.
535 switch (internalFormat)
536 {
537 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
538 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
539 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
540 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -0800541 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -0400542 return true;
543
544 default:
545 return false;
546 }
547}
548
Jamie Madillc29968b2016-01-20 11:17:23 -0500549bool ValidCompressedImageSize(const ValidationContext *context,
550 GLenum internalFormat,
551 GLsizei width,
552 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400553{
Geoff Lang5d601382014-07-22 15:14:06 -0400554 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
555 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400556 {
557 return false;
558 }
559
Geoff Lang0d8b7242015-09-09 14:56:53 -0400560 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400561 {
562 return false;
563 }
564
Geoff Lang0d8b7242015-09-09 14:56:53 -0400565 if (CompressedTextureFormatRequiresExactSize(internalFormat))
566 {
567 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
568 width % formatInfo.compressedBlockWidth != 0) ||
569 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
570 height % formatInfo.compressedBlockHeight != 0))
571 {
572 return false;
573 }
574 }
575
Geoff Langd4f180b2013-09-24 13:57:44 -0400576 return true;
577}
578
Geoff Langff5b2d52016-09-07 11:32:23 -0400579bool ValidImageDataSize(ValidationContext *context,
580 GLenum textureTarget,
581 GLsizei width,
582 GLsizei height,
583 GLsizei depth,
584 GLenum internalFormat,
585 GLenum type,
586 const GLvoid *pixels,
587 GLsizei imageSize)
588{
589 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
590 if (pixelUnpackBuffer == nullptr && imageSize < 0)
591 {
592 // Checks are not required
593 return true;
594 }
595
596 // ...the data would be unpacked from the buffer object such that the memory reads required
597 // would exceed the data store size.
598 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
599 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
600 const gl::Extents size(width, height, depth);
601 const auto &unpack = context->getGLState().getUnpackState();
602
603 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
604 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
605 if (endByteOrErr.isError())
606 {
607 context->handleError(endByteOrErr.getError());
608 return false;
609 }
610
611 GLuint endByte = endByteOrErr.getResult();
612
613 if (pixelUnpackBuffer)
614 {
615 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
616 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
617 checkedEndByte += checkedOffset;
618
619 if (!checkedEndByte.IsValid() ||
620 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
621 {
622 // Overflow past the end of the buffer
623 context->handleError(Error(GL_INVALID_OPERATION));
624 return false;
625 }
626 }
627 else
628 {
629 ASSERT(imageSize >= 0);
630 if (pixels == nullptr && imageSize != 0)
631 {
632 context->handleError(
633 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
634 }
635
636 if (endByte > static_cast<GLuint>(imageSize))
637 {
638 context->handleError(
639 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
640 return false;
641 }
642 }
643
644 return true;
645}
646
Geoff Lang37dde692014-01-31 16:34:54 -0500647bool ValidQueryType(const Context *context, GLenum queryType)
648{
Geoff Langd4475812015-03-18 10:53:05 -0400649 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT, "GL extension enums not equal.");
650 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 -0500651
652 switch (queryType)
653 {
654 case GL_ANY_SAMPLES_PASSED:
655 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
656 return true;
657 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
Martin Radev1be913c2016-07-11 17:59:16 +0300658 return (context->getClientMajorVersion() >= 3);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500659 case GL_TIME_ELAPSED_EXT:
660 return context->getExtensions().disjointTimerQuery;
Geoff Lang2b4ce802016-04-28 13:34:50 -0400661 case GL_COMMANDS_COMPLETED_CHROMIUM:
662 return context->getExtensions().syncQuery;
Geoff Lang37dde692014-01-31 16:34:54 -0500663 default:
664 return false;
665 }
666}
667
Dian Xiang769769a2015-09-09 15:20:08 -0700668Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -0500669{
670 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the
671 // error INVALID_VALUE if the provided name is not the name of either a shader or program object and
672 // INVALID_OPERATION if the provided name identifies an object that is not the expected type."
673
Dian Xiang769769a2015-09-09 15:20:08 -0700674 Program *validProgram = context->getProgram(id);
675
676 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -0500677 {
Dian Xiang769769a2015-09-09 15:20:08 -0700678 if (context->getShader(id))
679 {
Jamie Madill437fa652016-05-03 15:13:24 -0400680 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -0700681 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
682 }
683 else
684 {
Jamie Madill437fa652016-05-03 15:13:24 -0400685 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -0700686 }
Geoff Lang48dcae72014-02-05 16:28:24 -0500687 }
Dian Xiang769769a2015-09-09 15:20:08 -0700688
689 return validProgram;
690}
691
692Shader *GetValidShader(Context *context, GLuint id)
693{
694 // See ValidProgram for spec details.
695
696 Shader *validShader = context->getShader(id);
697
698 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -0500699 {
Dian Xiang769769a2015-09-09 15:20:08 -0700700 if (context->getProgram(id))
701 {
Jamie Madill437fa652016-05-03 15:13:24 -0400702 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -0700703 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
704 }
705 else
706 {
Jamie Madill437fa652016-05-03 15:13:24 -0400707 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -0700708 }
Geoff Lang48dcae72014-02-05 16:28:24 -0500709 }
Dian Xiang769769a2015-09-09 15:20:08 -0700710
711 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -0500712}
713
Geoff Langb1196682014-07-23 13:47:29 -0400714bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -0400715{
716 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
717 {
718 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
719
Geoff Langaae65a42014-05-26 12:43:44 -0400720 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -0400721 {
Jamie Madill437fa652016-05-03 15:13:24 -0400722 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400723 return false;
Jamie Madillb4472272014-07-03 10:38:55 -0400724 }
725 }
726 else
727 {
728 switch (attachment)
729 {
730 case GL_DEPTH_ATTACHMENT:
731 case GL_STENCIL_ATTACHMENT:
Martin Radev1be913c2016-07-11 17:59:16 +0300732 break;
Jamie Madillb4472272014-07-03 10:38:55 -0400733
734 case GL_DEPTH_STENCIL_ATTACHMENT:
Geoff Langc287ea62016-09-16 14:46:51 -0400735 if (!context->getExtensions().webglCompatibility &&
736 context->getClientMajorVersion() < 3)
Martin Radev1be913c2016-07-11 17:59:16 +0300737 {
738 context->handleError(Error(GL_INVALID_ENUM));
739 return false;
740 }
741 break;
Jamie Madillb4472272014-07-03 10:38:55 -0400742
743 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400744 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +0300745 return false;
Jamie Madillb4472272014-07-03 10:38:55 -0400746 }
747 }
748
749 return true;
750}
751
Corentin Walleze0902642014-11-04 12:32:15 -0800752bool ValidateRenderbufferStorageParametersBase(gl::Context *context, GLenum target, GLsizei samples,
753 GLenum internalformat, GLsizei width, GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400754{
755 switch (target)
756 {
757 case GL_RENDERBUFFER:
758 break;
759 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400760 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400761 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400762 }
763
764 if (width < 0 || height < 0 || samples < 0)
765 {
Jamie Madill437fa652016-05-03 15:13:24 -0400766 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400767 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400768 }
769
Geoff Langd87878e2014-09-19 15:42:59 -0400770 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
771 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400772 {
Jamie Madill437fa652016-05-03 15:13:24 -0400773 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400774 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400775 }
776
777 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
778 // 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 -0800779 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -0400780 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400781 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400782 {
Jamie Madill437fa652016-05-03 15:13:24 -0400783 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400784 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400785 }
786
Geoff Langaae65a42014-05-26 12:43:44 -0400787 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400788 {
Jamie Madill437fa652016-05-03 15:13:24 -0400789 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400790 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400791 }
792
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700793 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400794 if (handle == 0)
795 {
Jamie Madill437fa652016-05-03 15:13:24 -0400796 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400797 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400798 }
799
800 return true;
801}
802
Corentin Walleze0902642014-11-04 12:32:15 -0800803bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum target, GLsizei samples,
804 GLenum internalformat, GLsizei width, GLsizei height)
805{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -0800806 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -0800807
808 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -0400809 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -0800810 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -0400811 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -0800812 {
Jamie Madill437fa652016-05-03 15:13:24 -0400813 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -0800814 return false;
815 }
816
817 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
818 // the specified storage. This is different than ES 3.0 in which a sample number higher
819 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -0800820 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +0300821 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -0800822 {
Geoff Langa4903b72015-03-02 16:02:48 -0800823 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
824 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
825 {
Jamie Madill437fa652016-05-03 15:13:24 -0400826 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -0800827 return false;
828 }
Corentin Walleze0902642014-11-04 12:32:15 -0800829 }
830
831 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height);
832}
833
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500834bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
835 GLenum renderbuffertarget, GLuint renderbuffer)
836{
Shannon Woods1da3cf62014-06-27 15:32:23 -0400837 if (!ValidFramebufferTarget(target))
838 {
Jamie Madill437fa652016-05-03 15:13:24 -0400839 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400840 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -0400841 }
842
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700843 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500844
Jamie Madill84115c92015-04-23 15:00:07 -0400845 ASSERT(framebuffer);
846 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500847 {
Jamie Madill437fa652016-05-03 15:13:24 -0400848 context->handleError(
849 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -0400850 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500851 }
852
Jamie Madillb4472272014-07-03 10:38:55 -0400853 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500854 {
Jamie Madillb4472272014-07-03 10:38:55 -0400855 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500856 }
857
Jamie Madillab9d82c2014-01-21 16:38:14 -0500858 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
859 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
860 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
861 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
862 if (renderbuffer != 0)
863 {
864 if (!context->getRenderbuffer(renderbuffer))
865 {
Jamie Madill437fa652016-05-03 15:13:24 -0400866 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400867 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -0500868 }
869 }
870
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500871 return true;
872}
873
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700874bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500875 GLint srcX0,
876 GLint srcY0,
877 GLint srcX1,
878 GLint srcY1,
879 GLint dstX0,
880 GLint dstY0,
881 GLint dstX1,
882 GLint dstY1,
883 GLbitfield mask,
884 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400885{
886 switch (filter)
887 {
888 case GL_NEAREST:
889 break;
890 case GL_LINEAR:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400891 break;
892 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400893 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400894 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400895 }
896
897 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
898 {
Jamie Madill437fa652016-05-03 15:13:24 -0400899 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400900 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400901 }
902
903 if (mask == 0)
904 {
905 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
906 // buffers are copied.
907 return false;
908 }
909
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400910 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
911 // color buffer, leaving only nearest being unfiltered from above
912 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
913 {
Jamie Madill437fa652016-05-03 15:13:24 -0400914 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400915 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400916 }
917
Jamie Madill51f40ec2016-06-15 14:06:00 -0400918 const auto &glState = context->getGLState();
919 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
920 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -0500921
922 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400923 {
Jamie Madill437fa652016-05-03 15:13:24 -0400924 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400925 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400926 }
927
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700928 if (readFramebuffer->id() == drawFramebuffer->id())
929 {
930 context->handleError(Error(GL_INVALID_OPERATION));
931 return false;
932 }
933
Jamie Madill51f40ec2016-06-15 14:06:00 -0400934 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -0500935 {
Jamie Madill437fa652016-05-03 15:13:24 -0400936 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -0500937 return false;
938 }
939
Jamie Madill51f40ec2016-06-15 14:06:00 -0400940 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -0500941 {
Jamie Madill437fa652016-05-03 15:13:24 -0400942 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -0500943 return false;
944 }
945
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700946 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400947 {
Jamie Madill437fa652016-05-03 15:13:24 -0400948 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400949 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400950 }
951
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400952 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
953
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400954 if (mask & GL_COLOR_BUFFER_BIT)
955 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400956 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
957 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -0500958 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400959
960 if (readColorBuffer && drawColorBuffer)
961 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400962 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400963
Geoff Langa15472a2015-08-11 11:48:03 -0400964 for (size_t drawbufferIdx = 0;
965 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400966 {
Geoff Langa15472a2015-08-11 11:48:03 -0400967 const FramebufferAttachment *attachment =
968 drawFramebuffer->getDrawBuffer(drawbufferIdx);
969 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400970 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400971 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400972
Geoff Langb2f3d052013-08-13 12:49:27 -0400973 // The GL ES 3.0.2 spec (pg 193) states that:
974 // 1) If the read buffer is fixed point format, the draw buffer must be as well
975 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
976 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
Jamie Madill6163c752015-12-07 16:32:59 -0500977 // Changes with EXT_color_buffer_float:
978 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -0400979 GLenum readComponentType = readFormat.info->componentType;
980 GLenum drawComponentType = drawFormat.info->componentType;
Jamie Madill6163c752015-12-07 16:32:59 -0500981 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
982 readComponentType == GL_SIGNED_NORMALIZED);
983 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
984 drawComponentType == GL_SIGNED_NORMALIZED);
985
986 if (extensions.colorBufferFloat)
987 {
988 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
989 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
990
991 if (readFixedOrFloat != drawFixedOrFloat)
992 {
Jamie Madill437fa652016-05-03 15:13:24 -0400993 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -0500994 "If the read buffer contains fixed-point or "
995 "floating-point values, the draw buffer "
996 "must as well."));
997 return false;
998 }
999 }
1000 else if (readFixedPoint != drawFixedPoint)
1001 {
Jamie Madill437fa652016-05-03 15:13:24 -04001002 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001003 "If the read buffer contains fixed-point "
1004 "values, the draw buffer must as well."));
1005 return false;
1006 }
1007
1008 if (readComponentType == GL_UNSIGNED_INT &&
1009 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001010 {
Jamie Madill437fa652016-05-03 15:13:24 -04001011 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001012 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001013 }
1014
Jamie Madill6163c752015-12-07 16:32:59 -05001015 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001016 {
Jamie Madill437fa652016-05-03 15:13:24 -04001017 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001018 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001019 }
1020
Jamie Madilla3944d42016-07-22 22:13:26 -04001021 if (readColorBuffer->getSamples() > 0 &&
1022 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001023 {
Jamie Madill437fa652016-05-03 15:13:24 -04001024 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001025 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001026 }
1027 }
1028 }
1029
Jamie Madilla3944d42016-07-22 22:13:26 -04001030 if ((readFormat.info->componentType == GL_INT ||
1031 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1032 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001033 {
Jamie Madill437fa652016-05-03 15:13:24 -04001034 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001035 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001036 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001037 }
1038 }
1039
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001040 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1041 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1042 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001043 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001044 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001045 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001046 const gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]);
1047 const gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001048
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001049 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001050 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001051 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001052 {
Jamie Madill437fa652016-05-03 15:13:24 -04001053 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001054 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001055 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001056
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001057 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001058 {
Jamie Madill437fa652016-05-03 15:13:24 -04001059 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001060 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001061 }
1062 }
1063 }
1064 }
1065
1066 return true;
1067}
1068
Geoff Langb1196682014-07-23 13:47:29 -04001069bool ValidateGetVertexAttribParameters(Context *context, GLenum pname)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001070{
1071 switch (pname)
1072 {
1073 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1074 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1075 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1076 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1077 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1078 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1079 case GL_CURRENT_VERTEX_ATTRIB:
Martin Radev1be913c2016-07-11 17:59:16 +03001080 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001081
1082 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
Martin Radev1be913c2016-07-11 17:59:16 +03001083 // Don't verify ES3 context because GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE uses
1084 // the same constant.
1085 static_assert(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1086 "ANGLE extension enums not equal to GL enums.");
1087 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001088
1089 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Martin Radev1be913c2016-07-11 17:59:16 +03001090 if (context->getClientMajorVersion() < 3)
1091 {
1092 context->handleError(Error(GL_INVALID_ENUM));
1093 return false;
1094 }
1095 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001096
1097 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001098 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03001099 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001100 }
1101}
1102
Ian Ewellbda75592016-04-18 17:25:54 -04001103bool ValidateTexParamParameters(gl::Context *context, GLenum target, GLenum pname, GLint param)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001104{
1105 switch (pname)
1106 {
1107 case GL_TEXTURE_WRAP_R:
1108 case GL_TEXTURE_SWIZZLE_R:
1109 case GL_TEXTURE_SWIZZLE_G:
1110 case GL_TEXTURE_SWIZZLE_B:
1111 case GL_TEXTURE_SWIZZLE_A:
1112 case GL_TEXTURE_BASE_LEVEL:
1113 case GL_TEXTURE_MAX_LEVEL:
1114 case GL_TEXTURE_COMPARE_MODE:
1115 case GL_TEXTURE_COMPARE_FUNC:
1116 case GL_TEXTURE_MIN_LOD:
1117 case GL_TEXTURE_MAX_LOD:
Martin Radev1be913c2016-07-11 17:59:16 +03001118 if (context->getClientMajorVersion() < 3)
1119 {
1120 context->handleError(Error(GL_INVALID_ENUM));
1121 return false;
1122 }
1123 if (target == GL_TEXTURE_EXTERNAL_OES && !context->getExtensions().eglImageExternalEssl3)
1124 {
1125 context->handleError(Error(GL_INVALID_ENUM,
1126 "ES3 texture parameters are not available without "
1127 "GL_OES_EGL_image_external_essl3."));
1128 return false;
1129 }
1130 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001131
1132 default: break;
1133 }
1134
1135 switch (pname)
1136 {
1137 case GL_TEXTURE_WRAP_S:
1138 case GL_TEXTURE_WRAP_T:
1139 case GL_TEXTURE_WRAP_R:
1140 switch (param)
1141 {
Corentin Wallez9670b032016-04-29 09:47:47 +00001142 case GL_CLAMP_TO_EDGE:
Ian Ewellbda75592016-04-18 17:25:54 -04001143 return true;
1144 case GL_REPEAT:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001145 case GL_MIRRORED_REPEAT:
Olli Etuahobd329092016-04-29 12:51:42 +03001146 if (target == GL_TEXTURE_EXTERNAL_OES)
1147 {
1148 // OES_EGL_image_external specifies this error.
Jamie Madill437fa652016-05-03 15:13:24 -04001149 context->handleError(Error(
Olli Etuahobd329092016-04-29 12:51:42 +03001150 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
1151 return false;
1152 }
1153 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001154 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001155 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001156 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001157 }
1158
1159 case GL_TEXTURE_MIN_FILTER:
1160 switch (param)
1161 {
1162 case GL_NEAREST:
1163 case GL_LINEAR:
Ian Ewellbda75592016-04-18 17:25:54 -04001164 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001165 case GL_NEAREST_MIPMAP_NEAREST:
1166 case GL_LINEAR_MIPMAP_NEAREST:
1167 case GL_NEAREST_MIPMAP_LINEAR:
1168 case GL_LINEAR_MIPMAP_LINEAR:
Olli Etuahobd329092016-04-29 12:51:42 +03001169 if (target == GL_TEXTURE_EXTERNAL_OES)
1170 {
1171 // OES_EGL_image_external specifies this error.
Jamie Madill437fa652016-05-03 15:13:24 -04001172 context->handleError(
Olli Etuahobd329092016-04-29 12:51:42 +03001173 Error(GL_INVALID_ENUM,
1174 "external textures only support NEAREST and LINEAR filtering"));
1175 return false;
1176 }
1177 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001178 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001179 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001180 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001181 }
1182 break;
1183
1184 case GL_TEXTURE_MAG_FILTER:
1185 switch (param)
1186 {
1187 case GL_NEAREST:
1188 case GL_LINEAR:
1189 return true;
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 break;
1195
1196 case GL_TEXTURE_USAGE_ANGLE:
1197 switch (param)
1198 {
1199 case GL_NONE:
1200 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
1201 return true;
1202 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001203 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001204 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001205 }
1206 break;
1207
1208 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001209 if (!context->getExtensions().textureFilterAnisotropic)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001210 {
Jamie Madill437fa652016-05-03 15:13:24 -04001211 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001212 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001213 }
1214
1215 // we assume the parameter passed to this validation method is truncated, not rounded
1216 if (param < 1)
1217 {
Jamie Madill437fa652016-05-03 15:13:24 -04001218 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001219 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001220 }
1221 return true;
1222
1223 case GL_TEXTURE_MIN_LOD:
1224 case GL_TEXTURE_MAX_LOD:
1225 // any value is permissible
1226 return true;
1227
1228 case GL_TEXTURE_COMPARE_MODE:
Geoff Lang63b5f1f2013-09-23 14:52:14 -04001229 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001230 switch (param)
1231 {
1232 case GL_NONE:
1233 case GL_COMPARE_REF_TO_TEXTURE:
1234 return true;
1235 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001236 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001237 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001238 }
1239 break;
1240
1241 case GL_TEXTURE_COMPARE_FUNC:
Geoff Lang63b5f1f2013-09-23 14:52:14 -04001242 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001243 switch (param)
1244 {
1245 case GL_LEQUAL:
1246 case GL_GEQUAL:
1247 case GL_LESS:
1248 case GL_GREATER:
1249 case GL_EQUAL:
1250 case GL_NOTEQUAL:
1251 case GL_ALWAYS:
1252 case GL_NEVER:
1253 return true;
1254 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001255 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001256 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001257 }
1258 break;
1259
1260 case GL_TEXTURE_SWIZZLE_R:
1261 case GL_TEXTURE_SWIZZLE_G:
1262 case GL_TEXTURE_SWIZZLE_B:
1263 case GL_TEXTURE_SWIZZLE_A:
Geoff Langbc90a482013-09-17 16:51:27 -04001264 switch (param)
1265 {
1266 case GL_RED:
1267 case GL_GREEN:
1268 case GL_BLUE:
1269 case GL_ALPHA:
1270 case GL_ZERO:
1271 case GL_ONE:
1272 return true;
1273 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001274 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001275 return false;
Geoff Langbc90a482013-09-17 16:51:27 -04001276 }
1277 break;
1278
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001279 case GL_TEXTURE_BASE_LEVEL:
Geoff Langb66a9092016-05-16 15:59:14 -04001280 if (param < 0)
Olli Etuahoa314b612016-03-10 16:43:00 +02001281 {
Geoff Langb66a9092016-05-16 15:59:14 -04001282 context->handleError(Error(GL_INVALID_VALUE));
Olli Etuahoa314b612016-03-10 16:43:00 +02001283 return false;
1284 }
Geoff Langb66a9092016-05-16 15:59:14 -04001285 if (target == GL_TEXTURE_EXTERNAL_OES && param != 0)
1286 {
1287 context->handleError(
1288 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
1289 return false;
1290 }
1291 return true;
1292
1293 case GL_TEXTURE_MAX_LEVEL:
Olli Etuahoa314b612016-03-10 16:43:00 +02001294 if (param < 0)
1295 {
1296 context->handleError(Error(GL_INVALID_VALUE));
1297 return false;
1298 }
1299 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001300 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001301 context->handleError(Error(GL_INVALID_ENUM));
Olli Etuahoa314b612016-03-10 16:43:00 +02001302 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001303 }
1304}
1305
Geoff Langb1196682014-07-23 13:47:29 -04001306bool ValidateSamplerObjectParameter(gl::Context *context, GLenum pname)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001307{
1308 switch (pname)
1309 {
1310 case GL_TEXTURE_MIN_FILTER:
1311 case GL_TEXTURE_MAG_FILTER:
1312 case GL_TEXTURE_WRAP_S:
1313 case GL_TEXTURE_WRAP_T:
1314 case GL_TEXTURE_WRAP_R:
1315 case GL_TEXTURE_MIN_LOD:
1316 case GL_TEXTURE_MAX_LOD:
1317 case GL_TEXTURE_COMPARE_MODE:
1318 case GL_TEXTURE_COMPARE_FUNC:
1319 return true;
1320
1321 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001322 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001323 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001324 }
1325}
1326
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001327bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001328 GLint x,
1329 GLint y,
1330 GLsizei width,
1331 GLsizei height,
1332 GLenum format,
1333 GLenum type,
1334 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05001335{
Geoff Lang62fce5b2016-09-30 10:46:35 -04001336 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
1337}
1338
1339bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
1340 GLint x,
1341 GLint y,
1342 GLsizei width,
1343 GLsizei height,
1344 GLenum format,
1345 GLenum type,
1346 GLsizei bufSize,
1347 GLsizei *length,
1348 GLvoid *pixels)
1349{
1350 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001351 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001352 return false;
1353 }
1354
Geoff Lang62fce5b2016-09-30 10:46:35 -04001355 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1356 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001357 {
Geoff Langb1196682014-07-23 13:47:29 -04001358 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001359 }
1360
Geoff Lang62fce5b2016-09-30 10:46:35 -04001361 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001362 {
Geoff Langb1196682014-07-23 13:47:29 -04001363 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001364 }
1365
Jamie Madillc29968b2016-01-20 11:17:23 -05001366 return true;
1367}
1368
1369bool ValidateReadnPixelsEXT(Context *context,
1370 GLint x,
1371 GLint y,
1372 GLsizei width,
1373 GLsizei height,
1374 GLenum format,
1375 GLenum type,
1376 GLsizei bufSize,
1377 GLvoid *pixels)
1378{
1379 if (bufSize < 0)
1380 {
Jamie Madill437fa652016-05-03 15:13:24 -04001381 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001382 return false;
1383 }
1384
Geoff Lang62fce5b2016-09-30 10:46:35 -04001385 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
1386 pixels);
1387}
Jamie Madill26e91952014-03-05 15:01:27 -05001388
Geoff Lang62fce5b2016-09-30 10:46:35 -04001389bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
1390 GLint x,
1391 GLint y,
1392 GLsizei width,
1393 GLsizei height,
1394 GLenum format,
1395 GLenum type,
1396 GLsizei bufSize,
1397 GLsizei *length,
1398 GLvoid *data)
1399{
1400 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001401 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001402 return false;
1403 }
1404
Geoff Lang62fce5b2016-09-30 10:46:35 -04001405 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001406 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001407 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001408 }
1409
Geoff Lang62fce5b2016-09-30 10:46:35 -04001410 if (!ValidateRobustBufferSize(context, bufSize, *length))
1411 {
1412 return false;
1413 }
1414
1415 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001416}
1417
Olli Etuaho41997e72016-03-10 13:38:39 +02001418bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001419{
1420 if (!context->getExtensions().occlusionQueryBoolean &&
1421 !context->getExtensions().disjointTimerQuery)
1422 {
Jamie Madill437fa652016-05-03 15:13:24 -04001423 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001424 return false;
1425 }
1426
Olli Etuaho41997e72016-03-10 13:38:39 +02001427 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001428}
1429
Olli Etuaho41997e72016-03-10 13:38:39 +02001430bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001431{
1432 if (!context->getExtensions().occlusionQueryBoolean &&
1433 !context->getExtensions().disjointTimerQuery)
1434 {
Jamie Madill437fa652016-05-03 15:13:24 -04001435 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001436 return false;
1437 }
1438
Olli Etuaho41997e72016-03-10 13:38:39 +02001439 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001440}
1441
1442bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001443{
1444 if (!ValidQueryType(context, target))
1445 {
Jamie Madill437fa652016-05-03 15:13:24 -04001446 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04001447 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001448 }
1449
1450 if (id == 0)
1451 {
Jamie Madill437fa652016-05-03 15:13:24 -04001452 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04001453 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001454 }
1455
1456 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1457 // of zero, if the active query object name for <target> is non-zero (for the
1458 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1459 // the active query for either target is non-zero), if <id> is the name of an
1460 // existing query object whose type does not match <target>, or if <id> is the
1461 // active query object name for any query type, the error INVALID_OPERATION is
1462 // generated.
1463
1464 // Ensure no other queries are active
1465 // NOTE: If other queries than occlusion are supported, we will need to check
1466 // separately that:
1467 // a) The query ID passed is not the current active query for any target/type
1468 // b) There are no active queries for the requested target (and in the case
1469 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1470 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001471
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001472 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001473 {
Jamie Madill437fa652016-05-03 15:13:24 -04001474 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04001475 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001476 }
1477
1478 Query *queryObject = context->getQuery(id, true, target);
1479
1480 // check that name was obtained with glGenQueries
1481 if (!queryObject)
1482 {
Jamie Madill437fa652016-05-03 15:13:24 -04001483 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04001484 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001485 }
1486
1487 // check for type mismatch
1488 if (queryObject->getType() != target)
1489 {
Jamie Madill437fa652016-05-03 15:13:24 -04001490 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04001491 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001492 }
1493
1494 return true;
1495}
1496
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001497bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1498{
1499 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001500 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001501 {
Jamie Madill437fa652016-05-03 15:13:24 -04001502 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001503 return false;
1504 }
1505
1506 return ValidateBeginQueryBase(context, target, id);
1507}
1508
1509bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001510{
1511 if (!ValidQueryType(context, target))
1512 {
Jamie Madill437fa652016-05-03 15:13:24 -04001513 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04001514 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001515 }
1516
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001517 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001518
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001519 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001520 {
Jamie Madill437fa652016-05-03 15:13:24 -04001521 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04001522 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001523 }
1524
Jamie Madill45c785d2014-05-13 14:09:34 -04001525 return true;
1526}
1527
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001528bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1529{
1530 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001531 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001532 {
Jamie Madill437fa652016-05-03 15:13:24 -04001533 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001534 return false;
1535 }
1536
1537 return ValidateEndQueryBase(context, target);
1538}
1539
1540bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1541{
1542 if (!context->getExtensions().disjointTimerQuery)
1543 {
Jamie Madill437fa652016-05-03 15:13:24 -04001544 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001545 return false;
1546 }
1547
1548 if (target != GL_TIMESTAMP_EXT)
1549 {
Jamie Madill437fa652016-05-03 15:13:24 -04001550 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001551 return false;
1552 }
1553
1554 Query *queryObject = context->getQuery(id, true, target);
1555 if (queryObject == nullptr)
1556 {
Jamie Madill437fa652016-05-03 15:13:24 -04001557 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001558 return false;
1559 }
1560
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001561 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001562 {
Jamie Madill437fa652016-05-03 15:13:24 -04001563 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001564 return false;
1565 }
1566
1567 return true;
1568}
1569
1570bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname)
1571{
1572 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1573 {
Jamie Madill437fa652016-05-03 15:13:24 -04001574 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001575 return false;
1576 }
1577
1578 switch (pname)
1579 {
1580 case GL_CURRENT_QUERY_EXT:
1581 if (target == GL_TIMESTAMP_EXT)
1582 {
Jamie Madill437fa652016-05-03 15:13:24 -04001583 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001584 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
1585 return false;
1586 }
1587 break;
1588 case GL_QUERY_COUNTER_BITS_EXT:
1589 if (!context->getExtensions().disjointTimerQuery ||
1590 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1591 {
Jamie Madill437fa652016-05-03 15:13:24 -04001592 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001593 return false;
1594 }
1595 break;
1596 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001597 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001598 return false;
1599 }
1600
1601 return true;
1602}
1603
1604bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1605{
1606 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001607 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001608 {
Jamie Madill437fa652016-05-03 15:13:24 -04001609 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001610 return false;
1611 }
1612
1613 return ValidateGetQueryivBase(context, target, pname);
1614}
1615
1616bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname)
1617{
1618 Query *queryObject = context->getQuery(id, false, GL_NONE);
1619
1620 if (!queryObject)
1621 {
Jamie Madill437fa652016-05-03 15:13:24 -04001622 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001623 return false;
1624 }
1625
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001626 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001627 {
Jamie Madill437fa652016-05-03 15:13:24 -04001628 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001629 return false;
1630 }
1631
1632 switch (pname)
1633 {
1634 case GL_QUERY_RESULT_EXT:
1635 case GL_QUERY_RESULT_AVAILABLE_EXT:
1636 break;
1637
1638 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001639 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001640 return false;
1641 }
1642
1643 return true;
1644}
1645
1646bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1647{
1648 if (!context->getExtensions().disjointTimerQuery)
1649 {
Jamie Madill437fa652016-05-03 15:13:24 -04001650 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001651 return false;
1652 }
1653 return ValidateGetQueryObjectValueBase(context, id, pname);
1654}
1655
1656bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1657{
1658 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001659 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001660 {
Jamie Madill437fa652016-05-03 15:13:24 -04001661 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001662 return false;
1663 }
1664 return ValidateGetQueryObjectValueBase(context, id, pname);
1665}
1666
1667bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1668{
1669 if (!context->getExtensions().disjointTimerQuery)
1670 {
Jamie Madill437fa652016-05-03 15:13:24 -04001671 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001672 return false;
1673 }
1674 return ValidateGetQueryObjectValueBase(context, id, pname);
1675}
1676
1677bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1678{
1679 if (!context->getExtensions().disjointTimerQuery)
1680 {
Jamie Madill437fa652016-05-03 15:13:24 -04001681 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001682 return false;
1683 }
1684 return ValidateGetQueryObjectValueBase(context, id, pname);
1685}
1686
Jamie Madill62d31cb2015-09-11 13:25:51 -04001687static bool ValidateUniformCommonBase(gl::Context *context,
1688 GLenum targetUniformType,
1689 GLint location,
1690 GLsizei count,
1691 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001692{
1693 if (count < 0)
1694 {
Jamie Madill437fa652016-05-03 15:13:24 -04001695 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001696 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001697 }
1698
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001699 gl::Program *program = context->getGLState().getProgram();
Geoff Lang7dd2e102014-11-10 15:19:26 -05001700 if (!program)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001701 {
Jamie Madill437fa652016-05-03 15:13:24 -04001702 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001703 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001704 }
1705
Geoff Langd8605522016-04-13 10:19:12 -04001706 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001707 {
1708 // Silently ignore the uniform command
1709 return false;
1710 }
1711
Geoff Lang7dd2e102014-11-10 15:19:26 -05001712 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04001713 {
Jamie Madill437fa652016-05-03 15:13:24 -04001714 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001715 return false;
Jamie Madill36398922014-05-20 14:51:53 -04001716 }
1717
Jamie Madill62d31cb2015-09-11 13:25:51 -04001718 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04001719
1720 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04001721 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04001722 {
Jamie Madill437fa652016-05-03 15:13:24 -04001723 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001724 return false;
Jamie Madill36398922014-05-20 14:51:53 -04001725 }
1726
Jamie Madill62d31cb2015-09-11 13:25:51 -04001727 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001728 return true;
1729}
1730
Jamie Madillaa981bd2014-05-20 10:55:55 -04001731bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
1732{
1733 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03001734 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
1735 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04001736 {
Jamie Madill437fa652016-05-03 15:13:24 -04001737 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001738 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001739 }
1740
Jamie Madill62d31cb2015-09-11 13:25:51 -04001741 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04001742 if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
1743 {
1744 return false;
1745 }
1746
Jamie Madillf2575982014-06-25 16:04:54 -04001747 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05001748 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04001749 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
1750 {
Jamie Madill437fa652016-05-03 15:13:24 -04001751 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001752 return false;
Jamie Madill36398922014-05-20 14:51:53 -04001753 }
1754
1755 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001756}
1757
1758bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count,
1759 GLboolean transpose)
1760{
1761 // Check for ES3 uniform entry points
1762 int rows = VariableRowCount(matrixType);
1763 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03001764 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04001765 {
Jamie Madill437fa652016-05-03 15:13:24 -04001766 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001767 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001768 }
1769
Martin Radev1be913c2016-07-11 17:59:16 +03001770 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04001771 {
Jamie Madill437fa652016-05-03 15:13:24 -04001772 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001773 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001774 }
1775
Jamie Madill62d31cb2015-09-11 13:25:51 -04001776 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04001777 if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
1778 {
1779 return false;
1780 }
1781
1782 if (uniform->type != matrixType)
1783 {
Jamie Madill437fa652016-05-03 15:13:24 -04001784 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001785 return false;
Jamie Madill36398922014-05-20 14:51:53 -04001786 }
1787
1788 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001789}
1790
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001791bool ValidateStateQuery(ValidationContext *context,
1792 GLenum pname,
1793 GLenum *nativeType,
1794 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04001795{
1796 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
1797 {
Jamie Madill437fa652016-05-03 15:13:24 -04001798 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001799 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001800 }
1801
Jamie Madill0af26e12015-03-05 19:54:33 -05001802 const Caps &caps = context->getCaps();
1803
Jamie Madill893ab082014-05-16 16:56:10 -04001804 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
1805 {
1806 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
1807
Jamie Madill0af26e12015-03-05 19:54:33 -05001808 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04001809 {
Jamie Madill437fa652016-05-03 15:13:24 -04001810 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001811 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001812 }
1813 }
1814
1815 switch (pname)
1816 {
1817 case GL_TEXTURE_BINDING_2D:
1818 case GL_TEXTURE_BINDING_CUBE_MAP:
1819 case GL_TEXTURE_BINDING_3D:
1820 case GL_TEXTURE_BINDING_2D_ARRAY:
Jamie Madill893ab082014-05-16 16:56:10 -04001821 break;
Ian Ewell54f87462016-03-10 13:47:21 -05001822 case GL_TEXTURE_BINDING_EXTERNAL_OES:
John Bauman18319182016-09-28 14:22:27 -07001823 if (!context->getExtensions().eglStreamConsumerExternal &&
1824 !context->getExtensions().eglImageExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05001825 {
John Bauman18319182016-09-28 14:22:27 -07001826 context->handleError(Error(GL_INVALID_ENUM,
1827 "Neither NV_EGL_stream_consumer_external nor "
1828 "GL_OES_EGL_image_external extensions enabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05001829 return false;
1830 }
1831 break;
Jamie Madill893ab082014-05-16 16:56:10 -04001832
1833 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1834 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1835 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04001836 if (context->getGLState().getReadFramebuffer()->checkStatus(
1837 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04001838 {
Jamie Madill437fa652016-05-03 15:13:24 -04001839 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001840 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001841 }
1842
Jamie Madill51f40ec2016-06-15 14:06:00 -04001843 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
1844 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03001845
1846 if (framebuffer->getReadBufferState() == GL_NONE)
1847 {
1848 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
1849 return false;
1850 }
1851
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001852 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04001853 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04001854 {
Jamie Madill437fa652016-05-03 15:13:24 -04001855 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001856 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001857 }
1858 }
1859 break;
1860
1861 default:
1862 break;
1863 }
1864
1865 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04001866 if (*numParams == 0)
1867 {
1868 return false;
1869 }
1870
1871 return true;
1872}
1873
1874bool ValidateRobustStateQuery(ValidationContext *context,
1875 GLenum pname,
1876 GLsizei bufSize,
1877 GLenum *nativeType,
1878 unsigned int *numParams)
1879{
1880 if (!ValidateRobustEntryPoint(context, bufSize))
1881 {
1882 return false;
1883 }
1884
1885 if (!ValidateStateQuery(context, pname, nativeType, numParams))
1886 {
1887 return false;
1888 }
1889
1890 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04001891 {
1892 return false;
1893 }
1894
1895 return true;
1896}
1897
Jamie Madillc29968b2016-01-20 11:17:23 -05001898bool ValidateCopyTexImageParametersBase(ValidationContext *context,
1899 GLenum target,
1900 GLint level,
1901 GLenum internalformat,
1902 bool isSubImage,
1903 GLint xoffset,
1904 GLint yoffset,
1905 GLint zoffset,
1906 GLint x,
1907 GLint y,
1908 GLsizei width,
1909 GLsizei height,
1910 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04001911 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04001912{
Jamie Madill560a8d82014-05-21 13:06:20 -04001913 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
1914 {
Jamie Madill437fa652016-05-03 15:13:24 -04001915 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001916 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001917 }
1918
1919 if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1920 {
Jamie Madill437fa652016-05-03 15:13:24 -04001921 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001922 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001923 }
1924
1925 if (border != 0)
1926 {
Jamie Madill437fa652016-05-03 15:13:24 -04001927 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001928 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001929 }
1930
1931 if (!ValidMipLevel(context, target, level))
1932 {
Jamie Madill437fa652016-05-03 15:13:24 -04001933 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001934 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001935 }
1936
Jamie Madill51f40ec2016-06-15 14:06:00 -04001937 const auto &state = context->getGLState();
1938 auto readFramebuffer = state.getReadFramebuffer();
1939 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04001940 {
Jamie Madill437fa652016-05-03 15:13:24 -04001941 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001942 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001943 }
1944
Jamie Madill51f40ec2016-06-15 14:06:00 -04001945 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04001946 {
Jamie Madill437fa652016-05-03 15:13:24 -04001947 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001948 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001949 }
1950
Martin Radev138064f2016-07-15 12:03:41 +03001951 if (readFramebuffer->getReadBufferState() == GL_NONE)
1952 {
1953 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
1954 return false;
1955 }
1956
Geoff Langaae65a42014-05-26 12:43:44 -04001957 const gl::Caps &caps = context->getCaps();
1958
Geoff Langaae65a42014-05-26 12:43:44 -04001959 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04001960 switch (target)
1961 {
1962 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05001963 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04001964 break;
1965
1966 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1967 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1968 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1969 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1970 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1971 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -05001972 maxDimension = caps.maxCubeMapTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04001973 break;
1974
1975 case GL_TEXTURE_2D_ARRAY:
Geoff Langa9be0dc2014-12-17 12:34:40 -05001976 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04001977 break;
1978
1979 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05001980 maxDimension = caps.max3DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04001981 break;
1982
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 Madill560a8d82014-05-21 13:06:20 -04001986 }
1987
Jamie Madillc29968b2016-01-20 11:17:23 -05001988 gl::Texture *texture =
1989 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04001990 if (!texture)
1991 {
Jamie Madill437fa652016-05-03 15:13:24 -04001992 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001993 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001994 }
1995
Geoff Lang69cce582015-09-17 13:20:36 -04001996 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04001997 {
Jamie Madill437fa652016-05-03 15:13:24 -04001998 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001999 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002000 }
2001
Geoff Lang5d601382014-07-22 15:14:06 -04002002 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
2003
2004 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002005 {
Jamie Madill437fa652016-05-03 15:13:24 -04002006 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002007 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002008 }
2009
Geoff Langa9be0dc2014-12-17 12:34:40 -05002010 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04002011 {
Jamie Madill437fa652016-05-03 15:13:24 -04002012 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002013 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002014 }
2015
2016 if (isSubImage)
2017 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002018 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2019 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2020 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002021 {
Jamie Madill437fa652016-05-03 15:13:24 -04002022 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002023 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002024 }
2025 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002026 else
2027 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002028 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002029 {
Jamie Madill437fa652016-05-03 15:13:24 -04002030 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002031 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002032 }
2033
Martin Radev1be913c2016-07-11 17:59:16 +03002034 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002035 {
Jamie Madill437fa652016-05-03 15:13:24 -04002036 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002037 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002038 }
2039
2040 int maxLevelDimension = (maxDimension >> level);
2041 if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension)
2042 {
Jamie Madill437fa652016-05-03 15:13:24 -04002043 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002044 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002045 }
2046 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002047
Jamie Madill0c8abca2016-07-22 20:21:26 -04002048 if (textureFormatOut)
2049 {
2050 *textureFormatOut = texture->getFormat(target, level);
2051 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002052 return true;
2053}
2054
Jamie Madillf25855c2015-11-03 11:06:18 -05002055static bool ValidateDrawBase(ValidationContext *context,
2056 GLenum mode,
2057 GLsizei count,
2058 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002059{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002060 switch (mode)
2061 {
2062 case GL_POINTS:
2063 case GL_LINES:
2064 case GL_LINE_LOOP:
2065 case GL_LINE_STRIP:
2066 case GL_TRIANGLES:
2067 case GL_TRIANGLE_STRIP:
2068 case GL_TRIANGLE_FAN:
2069 break;
2070 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002071 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002072 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002073 }
2074
Jamie Madill250d33f2014-06-06 17:09:03 -04002075 if (count < 0)
2076 {
Jamie Madill437fa652016-05-03 15:13:24 -04002077 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002078 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002079 }
2080
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002081 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002082
Jamie Madill250d33f2014-06-06 17:09:03 -04002083 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002084 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002085 {
Jamie Madill437fa652016-05-03 15:13:24 -04002086 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002087 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002088 }
2089
Jamie Madill51f40ec2016-06-15 14:06:00 -04002090 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04002091 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04002092 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04002093 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
2094 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
2095 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
2096 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2097 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2098 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04002099 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04002100 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2101 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04002102 {
2103 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2104 // Section 6.10 of the WebGL 1.0 spec
2105 ERR(
2106 "This ANGLE implementation does not support separate front/back stencil "
2107 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04002108 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04002109 return false;
2110 }
Jamie Madillac528012014-06-20 13:21:23 -04002111 }
2112
Jamie Madill51f40ec2016-06-15 14:06:00 -04002113 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002114 {
Jamie Madill437fa652016-05-03 15:13:24 -04002115 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002116 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002117 }
2118
Geoff Lang7dd2e102014-11-10 15:19:26 -05002119 gl::Program *program = state.getProgram();
2120 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002121 {
Jamie Madill437fa652016-05-03 15:13:24 -04002122 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002123 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002124 }
2125
Geoff Lang7dd2e102014-11-10 15:19:26 -05002126 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002127 {
Jamie Madill437fa652016-05-03 15:13:24 -04002128 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002129 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002130 }
2131
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002132 // Uniform buffer validation
2133 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2134 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002135 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002136 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002137 const OffsetBindingPointer<Buffer> &uniformBuffer =
2138 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002139
Geoff Lang5d124a62015-09-15 13:03:27 -04002140 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002141 {
2142 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002143 context->handleError(
2144 Error(GL_INVALID_OPERATION,
2145 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002146 return false;
2147 }
2148
Geoff Lang5d124a62015-09-15 13:03:27 -04002149 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002150 if (uniformBufferSize == 0)
2151 {
2152 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002153 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002154 }
2155
Jamie Madill62d31cb2015-09-11 13:25:51 -04002156 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002157 {
2158 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002159 context->handleError(
2160 Error(GL_INVALID_OPERATION,
2161 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002162 return false;
2163 }
2164 }
2165
Jamie Madill250d33f2014-06-06 17:09:03 -04002166 // No-op if zero count
2167 return (count > 0);
2168}
2169
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002170bool ValidateDrawArrays(ValidationContext *context,
2171 GLenum mode,
2172 GLint first,
2173 GLsizei count,
2174 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002175{
Jamie Madillfd716582014-06-06 17:09:04 -04002176 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002177 {
Jamie Madill437fa652016-05-03 15:13:24 -04002178 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002179 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002180 }
2181
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002182 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002183 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04002184 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused() &&
2185 curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002186 {
2187 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
2188 // that does not match the current transform feedback object's draw mode (if transform feedback
2189 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002190 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002191 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002192 }
2193
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002194 if (!ValidateDrawBase(context, mode, count, primcount))
2195 {
2196 return false;
2197 }
2198
2199 if (!ValidateDrawAttribs(context, primcount, count))
Jamie Madillfd716582014-06-06 17:09:04 -04002200 {
2201 return false;
2202 }
2203
2204 return true;
2205}
2206
Geoff Langb1196682014-07-23 13:47:29 -04002207bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002208{
2209 if (primcount < 0)
2210 {
Jamie Madill437fa652016-05-03 15:13:24 -04002211 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002212 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002213 }
2214
Jamie Madill2b976812014-08-25 15:47:49 -04002215 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04002216 {
2217 return false;
2218 }
2219
2220 // No-op if zero primitive count
2221 return (primcount > 0);
2222}
2223
Geoff Lang87a93302014-09-16 13:29:43 -04002224static bool ValidateDrawInstancedANGLE(Context *context)
2225{
2226 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002227 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04002228
Geoff Lang7dd2e102014-11-10 15:19:26 -05002229 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04002230
2231 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04002232 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04002233 {
2234 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04002235 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04002236 {
2237 return true;
2238 }
2239 }
2240
Jamie Madill437fa652016-05-03 15:13:24 -04002241 context->handleError(Error(GL_INVALID_OPERATION,
2242 "ANGLE_instanced_arrays requires that at least one active attribute"
2243 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04002244 return false;
2245}
2246
2247bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
2248{
2249 if (!ValidateDrawInstancedANGLE(context))
2250 {
2251 return false;
2252 }
2253
2254 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
2255}
2256
Jamie Madillf25855c2015-11-03 11:06:18 -05002257bool ValidateDrawElements(ValidationContext *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04002258 GLenum mode,
2259 GLsizei count,
2260 GLenum type,
2261 const GLvoid *indices,
2262 GLsizei primcount,
2263 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04002264{
Jamie Madill250d33f2014-06-06 17:09:03 -04002265 switch (type)
2266 {
2267 case GL_UNSIGNED_BYTE:
2268 case GL_UNSIGNED_SHORT:
Martin Radev1be913c2016-07-11 17:59:16 +03002269 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04002270 case GL_UNSIGNED_INT:
Martin Radev1be913c2016-07-11 17:59:16 +03002271 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2272 {
2273 context->handleError(Error(GL_INVALID_ENUM));
2274 return false;
2275 }
2276 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04002277 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002278 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03002279 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002280 }
2281
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002282 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002283
2284 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04002285 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002286 {
2287 // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
2288 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002289 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002290 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002291 }
2292
2293 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002294 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002295 {
Jamie Madill437fa652016-05-03 15:13:24 -04002296 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002297 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002298 }
2299
Jamie Madill2b976812014-08-25 15:47:49 -04002300 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002301 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madill2b976812014-08-25 15:47:49 -04002302 if (!indices && !elementArrayBuffer)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002303 {
Jamie Madill437fa652016-05-03 15:13:24 -04002304 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002305 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002306 }
2307
Jamie Madillae3000b2014-08-25 15:47:51 -04002308 if (elementArrayBuffer)
2309 {
2310 const gl::Type &typeInfo = gl::GetTypeInfo(type);
2311
2312 GLint64 offset = reinterpret_cast<GLint64>(indices);
2313 GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset;
2314
2315 // check for integer overflows
2316 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
2317 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
2318 {
Jamie Madill437fa652016-05-03 15:13:24 -04002319 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04002320 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002321 }
2322
2323 // Check for reading past the end of the bound buffer object
2324 if (byteCount > elementArrayBuffer->getSize())
2325 {
Jamie Madill437fa652016-05-03 15:13:24 -04002326 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002327 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002328 }
2329 }
2330 else if (!indices)
2331 {
2332 // Catch this programming error here
Jamie Madill437fa652016-05-03 15:13:24 -04002333 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002334 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002335 }
2336
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002337 if (!ValidateDrawBase(context, mode, count, primcount))
2338 {
2339 return false;
2340 }
2341
Jamie Madill2b976812014-08-25 15:47:49 -04002342 // Use max index to validate if our vertex buffers are large enough for the pull.
2343 // TODO: offer fast path, with disabled index validation.
2344 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
2345 if (elementArrayBuffer)
2346 {
Jacek Cabana5521de2014-10-01 17:23:46 +02002347 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04002348 Error error =
2349 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
2350 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04002351 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04002352 {
Jamie Madill437fa652016-05-03 15:13:24 -04002353 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04002354 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04002355 }
2356 }
2357 else
2358 {
Geoff Lang3edfe032015-09-04 16:38:24 -04002359 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04002360 }
2361
Jamie Madille79b1e12015-11-04 16:36:37 -05002362 // If we use an index greater than our maximum supported index range, return an error.
2363 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2364 // return an error if possible here.
2365 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
2366 {
Jamie Madill437fa652016-05-03 15:13:24 -04002367 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05002368 return false;
2369 }
2370
Jamie Madillbc4c4bc2016-03-23 21:04:43 -04002371 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04002372 {
2373 return false;
2374 }
2375
Geoff Lang3edfe032015-09-04 16:38:24 -04002376 // No op if there are no real indices in the index data (all are primitive restart).
2377 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04002378}
2379
Geoff Langb1196682014-07-23 13:47:29 -04002380bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04002381 GLenum mode,
2382 GLsizei count,
2383 GLenum type,
2384 const GLvoid *indices,
2385 GLsizei primcount,
2386 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04002387{
2388 if (primcount < 0)
2389 {
Jamie Madill437fa652016-05-03 15:13:24 -04002390 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002391 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002392 }
2393
Jamie Madill2b976812014-08-25 15:47:49 -04002394 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04002395 {
2396 return false;
2397 }
2398
2399 // No-op zero primitive count
2400 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04002401}
2402
Geoff Lang3edfe032015-09-04 16:38:24 -04002403bool ValidateDrawElementsInstancedANGLE(Context *context,
2404 GLenum mode,
2405 GLsizei count,
2406 GLenum type,
2407 const GLvoid *indices,
2408 GLsizei primcount,
2409 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04002410{
2411 if (!ValidateDrawInstancedANGLE(context))
2412 {
2413 return false;
2414 }
2415
2416 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut);
2417}
2418
Geoff Langb1196682014-07-23 13:47:29 -04002419bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04002420 GLuint texture, GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002421{
Jamie Madill55ec3b12014-07-03 10:38:57 -04002422 if (!ValidFramebufferTarget(target))
2423 {
Jamie Madill437fa652016-05-03 15:13:24 -04002424 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002425 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002426 }
2427
2428 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002429 {
2430 return false;
2431 }
2432
Jamie Madill55ec3b12014-07-03 10:38:57 -04002433 if (texture != 0)
2434 {
2435 gl::Texture *tex = context->getTexture(texture);
2436
2437 if (tex == NULL)
2438 {
Jamie Madill437fa652016-05-03 15:13:24 -04002439 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002440 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002441 }
2442
2443 if (level < 0)
2444 {
Jamie Madill437fa652016-05-03 15:13:24 -04002445 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002446 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002447 }
2448 }
2449
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002450 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002451 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002452
Jamie Madill84115c92015-04-23 15:00:07 -04002453 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002454 {
Jamie Madill437fa652016-05-03 15:13:24 -04002455 context->handleError(
2456 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002457 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002458 }
2459
2460 return true;
2461}
2462
Geoff Langb1196682014-07-23 13:47:29 -04002463bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04002464 GLenum textarget, GLuint texture, GLint level)
2465{
Geoff Lang95663912015-04-02 15:54:45 -04002466 // 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 +03002467 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
2468 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002469 {
Jamie Madill437fa652016-05-03 15:13:24 -04002470 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002471 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002472 }
2473
2474 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04002475 {
2476 return false;
2477 }
2478
Jamie Madill55ec3b12014-07-03 10:38:57 -04002479 if (texture != 0)
2480 {
2481 gl::Texture *tex = context->getTexture(texture);
2482 ASSERT(tex);
2483
Jamie Madill2a6564e2014-07-11 09:53:19 -04002484 const gl::Caps &caps = context->getCaps();
2485
Jamie Madill55ec3b12014-07-03 10:38:57 -04002486 switch (textarget)
2487 {
2488 case GL_TEXTURE_2D:
2489 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04002490 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002491 {
Jamie Madill437fa652016-05-03 15:13:24 -04002492 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002493 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002494 }
2495 if (tex->getTarget() != GL_TEXTURE_2D)
2496 {
Jamie Madill437fa652016-05-03 15:13:24 -04002497 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002498 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002499 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002500 }
2501 break;
2502
2503 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2504 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2505 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2506 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2507 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2508 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2509 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04002510 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002511 {
Jamie Madill437fa652016-05-03 15:13:24 -04002512 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002513 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002514 }
2515 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
2516 {
Jamie Madill437fa652016-05-03 15:13:24 -04002517 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002518 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002519 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002520 }
2521 break;
2522
2523 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002524 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002525 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002526 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05002527
Jamie Madilla3944d42016-07-22 22:13:26 -04002528 const Format &format = tex->getFormat(textarget, level);
2529 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05002530 {
Jamie Madill437fa652016-05-03 15:13:24 -04002531 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002532 return false;
2533 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002534 }
2535
Jamie Madill570f7c82014-07-03 10:38:54 -04002536 return true;
2537}
2538
Geoff Langb1196682014-07-23 13:47:29 -04002539bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04002540{
2541 if (program == 0)
2542 {
Jamie Madill437fa652016-05-03 15:13:24 -04002543 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002544 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002545 }
2546
Dian Xiang769769a2015-09-09 15:20:08 -07002547 gl::Program *programObject = GetValidProgram(context, program);
2548 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05002549 {
2550 return false;
2551 }
2552
Jamie Madill0063c512014-08-25 15:47:53 -04002553 if (!programObject || !programObject->isLinked())
2554 {
Jamie Madill437fa652016-05-03 15:13:24 -04002555 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002556 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002557 }
2558
Geoff Lang7dd2e102014-11-10 15:19:26 -05002559 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04002560 {
Jamie Madill437fa652016-05-03 15:13:24 -04002561 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002562 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04002563 }
2564
Jamie Madill0063c512014-08-25 15:47:53 -04002565 return true;
2566}
2567
Geoff Langb1196682014-07-23 13:47:29 -04002568bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params)
Jamie Madill78f41802014-08-25 15:47:55 -04002569{
2570 return ValidateGetUniformBase(context, program, location);
2571}
2572
Geoff Langb1196682014-07-23 13:47:29 -04002573bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04002574{
Jamie Madill78f41802014-08-25 15:47:55 -04002575 return ValidateGetUniformBase(context, program, location);
2576}
2577
Geoff Langb1196682014-07-23 13:47:29 -04002578static bool ValidateSizedGetUniform(Context *context, GLuint program, GLint location, GLsizei bufSize)
Jamie Madill78f41802014-08-25 15:47:55 -04002579{
2580 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04002581 {
Jamie Madill78f41802014-08-25 15:47:55 -04002582 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002583 }
2584
Jamie Madilla502c742014-08-28 17:19:13 -04002585 gl::Program *programObject = context->getProgram(program);
2586 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04002587
Jamie Madill78f41802014-08-25 15:47:55 -04002588 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04002589 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
2590 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04002591 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04002592 {
Jamie Madill437fa652016-05-03 15:13:24 -04002593 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002594 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002595 }
2596
2597 return true;
2598}
2599
Geoff Langb1196682014-07-23 13:47:29 -04002600bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
Jamie Madill0063c512014-08-25 15:47:53 -04002601{
Jamie Madill78f41802014-08-25 15:47:55 -04002602 return ValidateSizedGetUniform(context, program, location, bufSize);
Jamie Madill0063c512014-08-25 15:47:53 -04002603}
2604
Geoff Langb1196682014-07-23 13:47:29 -04002605bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04002606{
Jamie Madill78f41802014-08-25 15:47:55 -04002607 return ValidateSizedGetUniform(context, program, location, bufSize);
Jamie Madill0063c512014-08-25 15:47:53 -04002608}
2609
Austin Kinross08332632015-05-05 13:35:47 -07002610bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
2611 const GLenum *attachments, bool defaultFramebuffer)
2612{
2613 if (numAttachments < 0)
2614 {
Jamie Madill437fa652016-05-03 15:13:24 -04002615 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07002616 return false;
2617 }
2618
2619 for (GLsizei i = 0; i < numAttachments; ++i)
2620 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02002621 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07002622 {
2623 if (defaultFramebuffer)
2624 {
Jamie Madill437fa652016-05-03 15:13:24 -04002625 context->handleError(Error(
2626 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07002627 return false;
2628 }
2629
2630 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
2631 {
Jamie Madill437fa652016-05-03 15:13:24 -04002632 context->handleError(Error(GL_INVALID_OPERATION,
2633 "Requested color attachment is greater than the maximum "
2634 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07002635 return false;
2636 }
2637 }
2638 else
2639 {
2640 switch (attachments[i])
2641 {
2642 case GL_DEPTH_ATTACHMENT:
2643 case GL_STENCIL_ATTACHMENT:
2644 case GL_DEPTH_STENCIL_ATTACHMENT:
2645 if (defaultFramebuffer)
2646 {
Jamie Madill437fa652016-05-03 15:13:24 -04002647 context->handleError(
2648 Error(GL_INVALID_ENUM,
2649 "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07002650 return false;
2651 }
2652 break;
2653 case GL_COLOR:
2654 case GL_DEPTH:
2655 case GL_STENCIL:
2656 if (!defaultFramebuffer)
2657 {
Jamie Madill437fa652016-05-03 15:13:24 -04002658 context->handleError(
2659 Error(GL_INVALID_ENUM,
2660 "Invalid attachment when the default framebuffer is not bound"));
Austin Kinross08332632015-05-05 13:35:47 -07002661 return false;
2662 }
2663 break;
2664 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002665 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07002666 return false;
2667 }
2668 }
2669 }
2670
2671 return true;
2672}
2673
Austin Kinross6ee1e782015-05-29 17:05:37 -07002674bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
2675{
2676 // Note that debug marker calls must not set error state
2677
2678 if (length < 0)
2679 {
2680 return false;
2681 }
2682
2683 if (marker == nullptr)
2684 {
2685 return false;
2686 }
2687
2688 return true;
2689}
2690
2691bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
2692{
2693 // Note that debug marker calls must not set error state
2694
2695 if (length < 0)
2696 {
2697 return false;
2698 }
2699
2700 if (length > 0 && marker == nullptr)
2701 {
2702 return false;
2703 }
2704
2705 return true;
2706}
2707
Geoff Langdcab33b2015-07-21 13:03:16 -04002708bool ValidateEGLImageTargetTexture2DOES(Context *context,
2709 egl::Display *display,
2710 GLenum target,
2711 egl::Image *image)
2712{
Geoff Langa8406172015-07-21 16:53:39 -04002713 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
2714 {
Jamie Madill437fa652016-05-03 15:13:24 -04002715 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04002716 return false;
2717 }
2718
2719 switch (target)
2720 {
2721 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04002722 if (!context->getExtensions().eglImage)
2723 {
2724 context->handleError(Error(
2725 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
2726 }
2727 break;
2728
2729 case GL_TEXTURE_EXTERNAL_OES:
2730 if (!context->getExtensions().eglImageExternal)
2731 {
2732 context->handleError(Error(
2733 GL_INVALID_ENUM,
2734 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
2735 }
Geoff Langa8406172015-07-21 16:53:39 -04002736 break;
2737
2738 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002739 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04002740 return false;
2741 }
2742
2743 if (!display->isValidImage(image))
2744 {
Jamie Madill437fa652016-05-03 15:13:24 -04002745 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04002746 return false;
2747 }
2748
2749 if (image->getSamples() > 0)
2750 {
Jamie Madill437fa652016-05-03 15:13:24 -04002751 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04002752 "cannot create a 2D texture from a multisampled EGL image."));
2753 return false;
2754 }
2755
Jamie Madilla3944d42016-07-22 22:13:26 -04002756 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04002757 if (!textureCaps.texturable)
2758 {
Jamie Madill437fa652016-05-03 15:13:24 -04002759 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04002760 "EGL image internal format is not supported as a texture."));
2761 return false;
2762 }
2763
Geoff Langdcab33b2015-07-21 13:03:16 -04002764 return true;
2765}
2766
2767bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
2768 egl::Display *display,
2769 GLenum target,
2770 egl::Image *image)
2771{
Geoff Langa8406172015-07-21 16:53:39 -04002772 if (!context->getExtensions().eglImage)
2773 {
Jamie Madill437fa652016-05-03 15:13:24 -04002774 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04002775 return false;
2776 }
2777
2778 switch (target)
2779 {
2780 case GL_RENDERBUFFER:
2781 break;
2782
2783 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002784 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04002785 return false;
2786 }
2787
2788 if (!display->isValidImage(image))
2789 {
Jamie Madill437fa652016-05-03 15:13:24 -04002790 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04002791 return false;
2792 }
2793
Jamie Madilla3944d42016-07-22 22:13:26 -04002794 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04002795 if (!textureCaps.renderable)
2796 {
Jamie Madill437fa652016-05-03 15:13:24 -04002797 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04002798 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
2799 return false;
2800 }
2801
Geoff Langdcab33b2015-07-21 13:03:16 -04002802 return true;
2803}
Austin Kinrossbc781f32015-10-26 09:27:38 -07002804
2805bool ValidateBindVertexArrayBase(Context *context, GLuint array)
2806{
Geoff Lang36167ab2015-12-07 10:27:14 -05002807 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07002808 {
2809 // The default VAO should always exist
2810 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04002811 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07002812 return false;
2813 }
2814
2815 return true;
2816}
2817
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002818bool ValidateLinkProgram(Context *context, GLuint program)
2819{
2820 if (context->hasActiveTransformFeedback(program))
2821 {
2822 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04002823 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002824 "Cannot link program while program is associated with an active "
2825 "transform feedback object."));
2826 return false;
2827 }
2828 return true;
2829}
2830
Geoff Langc5629752015-12-07 16:29:04 -05002831bool ValidateProgramBinaryBase(Context *context,
2832 GLuint program,
2833 GLenum binaryFormat,
2834 const void *binary,
2835 GLint length)
2836{
2837 Program *programObject = GetValidProgram(context, program);
2838 if (programObject == nullptr)
2839 {
2840 return false;
2841 }
2842
2843 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
2844 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
2845 programBinaryFormats.end())
2846 {
Jamie Madill437fa652016-05-03 15:13:24 -04002847 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05002848 return false;
2849 }
2850
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002851 if (context->hasActiveTransformFeedback(program))
2852 {
2853 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04002854 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002855 "Cannot change program binary while program is associated with "
2856 "an active transform feedback object."));
2857 return false;
2858 }
2859
Geoff Langc5629752015-12-07 16:29:04 -05002860 return true;
2861}
2862
2863bool ValidateGetProgramBinaryBase(Context *context,
2864 GLuint program,
2865 GLsizei bufSize,
2866 GLsizei *length,
2867 GLenum *binaryFormat,
2868 void *binary)
2869{
2870 Program *programObject = GetValidProgram(context, program);
2871 if (programObject == nullptr)
2872 {
2873 return false;
2874 }
2875
2876 if (!programObject->isLinked())
2877 {
Jamie Madill437fa652016-05-03 15:13:24 -04002878 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05002879 return false;
2880 }
2881
2882 return true;
2883}
Jamie Madillc29968b2016-01-20 11:17:23 -05002884
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002885bool ValidateUseProgram(Context *context, GLuint program)
2886{
2887 if (program != 0)
2888 {
2889 Program *programObject = context->getProgram(program);
2890 if (!programObject)
2891 {
2892 // ES 3.1.0 section 7.3 page 72
2893 if (context->getShader(program))
2894 {
Jamie Madill437fa652016-05-03 15:13:24 -04002895 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002896 Error(GL_INVALID_OPERATION,
2897 "Attempted to use a single shader instead of a shader program."));
2898 return false;
2899 }
2900 else
2901 {
Jamie Madill437fa652016-05-03 15:13:24 -04002902 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002903 return false;
2904 }
2905 }
2906 if (!programObject->isLinked())
2907 {
Jamie Madill437fa652016-05-03 15:13:24 -04002908 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002909 return false;
2910 }
2911 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002912 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002913 {
2914 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04002915 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002916 Error(GL_INVALID_OPERATION,
2917 "Cannot change active program while transform feedback is unpaused."));
2918 return false;
2919 }
2920
2921 return true;
2922}
2923
Jamie Madillc29968b2016-01-20 11:17:23 -05002924bool ValidateCopyTexImage2D(ValidationContext *context,
2925 GLenum target,
2926 GLint level,
2927 GLenum internalformat,
2928 GLint x,
2929 GLint y,
2930 GLsizei width,
2931 GLsizei height,
2932 GLint border)
2933{
Martin Radev1be913c2016-07-11 17:59:16 +03002934 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05002935 {
2936 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
2937 0, x, y, width, height, border);
2938 }
2939
Martin Radev1be913c2016-07-11 17:59:16 +03002940 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05002941 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
2942 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002943}
Jamie Madillc29968b2016-01-20 11:17:23 -05002944
2945bool ValidateFramebufferRenderbuffer(Context *context,
2946 GLenum target,
2947 GLenum attachment,
2948 GLenum renderbuffertarget,
2949 GLuint renderbuffer)
2950{
2951 if (!ValidFramebufferTarget(target) ||
2952 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
2953 {
Jamie Madill437fa652016-05-03 15:13:24 -04002954 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05002955 return false;
2956 }
2957
2958 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
2959 renderbuffertarget, renderbuffer);
2960}
2961
2962bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
2963{
2964 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
2965 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
2966 {
Jamie Madill437fa652016-05-03 15:13:24 -04002967 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05002968 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
2969 return false;
2970 }
2971
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002972 ASSERT(context->getGLState().getDrawFramebuffer());
2973 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05002974 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
2975
2976 // This should come first before the check for the default frame buffer
2977 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
2978 // rather than INVALID_OPERATION
2979 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
2980 {
2981 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
2982
2983 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02002984 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
2985 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05002986 {
2987 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02002988 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
2989 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
2990 // 3.1 is still a bit ambiguous about the error, but future specs are
2991 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04002992 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02002993 return false;
2994 }
2995 else if (bufs[colorAttachment] >= maxColorAttachment)
2996 {
Jamie Madill437fa652016-05-03 15:13:24 -04002997 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02002998 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002999 return false;
3000 }
3001 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3002 frameBufferId != 0)
3003 {
3004 // INVALID_OPERATION-GL is bound to buffer and ith argument
3005 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04003006 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003007 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
3008 return false;
3009 }
3010 }
3011
3012 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3013 // and n is not 1 or bufs is bound to value other than BACK and NONE
3014 if (frameBufferId == 0)
3015 {
3016 if (n != 1)
3017 {
Jamie Madill437fa652016-05-03 15:13:24 -04003018 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05003019 "n must be 1 when GL is bound to the default framebuffer"));
3020 return false;
3021 }
3022
3023 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3024 {
Jamie Madill437fa652016-05-03 15:13:24 -04003025 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05003026 GL_INVALID_OPERATION,
3027 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
3028 return false;
3029 }
3030 }
3031
3032 return true;
3033}
3034
3035bool ValidateCopyTexSubImage2D(Context *context,
3036 GLenum target,
3037 GLint level,
3038 GLint xoffset,
3039 GLint yoffset,
3040 GLint x,
3041 GLint y,
3042 GLsizei width,
3043 GLsizei height)
3044{
Martin Radev1be913c2016-07-11 17:59:16 +03003045 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003046 {
3047 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
3048 yoffset, x, y, width, height, 0);
3049 }
3050
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003051 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
3052 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05003053}
3054
Olli Etuaho4f667482016-03-30 15:56:35 +03003055bool ValidateGetBufferPointervBase(Context *context, GLenum target, GLenum pname, void **params)
3056{
3057 if (!ValidBufferTarget(context, target))
3058 {
Jamie Madill437fa652016-05-03 15:13:24 -04003059 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03003060 return false;
3061 }
3062
3063 if (pname != GL_BUFFER_MAP_POINTER)
3064 {
Jamie Madill437fa652016-05-03 15:13:24 -04003065 context->handleError(Error(GL_INVALID_ENUM, "pname not valid: 0x%X", pname));
Olli Etuaho4f667482016-03-30 15:56:35 +03003066 return false;
3067 }
3068
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003069 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003070
3071 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3072 // target bound to zero generate an INVALID_OPERATION error."
3073 // GLES 3.1 section 6.6 explicitly specifies this error.
3074 if (!buffer)
3075 {
Jamie Madill437fa652016-05-03 15:13:24 -04003076 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003077 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
3078 return false;
3079 }
3080
3081 return true;
3082}
3083
3084bool ValidateUnmapBufferBase(Context *context, GLenum target)
3085{
3086 if (!ValidBufferTarget(context, target))
3087 {
Jamie Madill437fa652016-05-03 15:13:24 -04003088 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003089 return false;
3090 }
3091
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003092 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003093
3094 if (buffer == nullptr || !buffer->isMapped())
3095 {
Jamie Madill437fa652016-05-03 15:13:24 -04003096 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003097 return false;
3098 }
3099
3100 return true;
3101}
3102
3103bool ValidateMapBufferRangeBase(Context *context,
3104 GLenum target,
3105 GLintptr offset,
3106 GLsizeiptr length,
3107 GLbitfield access)
3108{
3109 if (!ValidBufferTarget(context, target))
3110 {
Jamie Madill437fa652016-05-03 15:13:24 -04003111 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003112 return false;
3113 }
3114
3115 if (offset < 0 || length < 0)
3116 {
Jamie Madill437fa652016-05-03 15:13:24 -04003117 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003118 return false;
3119 }
3120
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003121 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003122
3123 if (!buffer)
3124 {
Jamie Madill437fa652016-05-03 15:13:24 -04003125 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003126 return false;
3127 }
3128
3129 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003130 CheckedNumeric<size_t> checkedOffset(offset);
3131 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003132
Jamie Madille2e406c2016-06-02 13:04:10 -04003133 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003134 {
Jamie Madill437fa652016-05-03 15:13:24 -04003135 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003136 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
3137 return false;
3138 }
3139
3140 // Check for invalid bits in the mask
3141 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3142 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3143 GL_MAP_UNSYNCHRONIZED_BIT;
3144
3145 if (access & ~(allAccessBits))
3146 {
Jamie Madill437fa652016-05-03 15:13:24 -04003147 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03003148 return false;
3149 }
3150
3151 if (length == 0)
3152 {
Jamie Madill437fa652016-05-03 15:13:24 -04003153 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003154 return false;
3155 }
3156
3157 if (buffer->isMapped())
3158 {
Jamie Madill437fa652016-05-03 15:13:24 -04003159 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003160 return false;
3161 }
3162
3163 // Check for invalid bit combinations
3164 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3165 {
Jamie Madill437fa652016-05-03 15:13:24 -04003166 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003167 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
3168 return false;
3169 }
3170
3171 GLbitfield writeOnlyBits =
3172 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3173
3174 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3175 {
Jamie Madill437fa652016-05-03 15:13:24 -04003176 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03003177 "Invalid access bits when mapping buffer for reading: 0x%X.",
3178 access));
3179 return false;
3180 }
3181
3182 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3183 {
Jamie Madill437fa652016-05-03 15:13:24 -04003184 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003185 GL_INVALID_OPERATION,
3186 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
3187 return false;
3188 }
3189 return true;
3190}
3191
3192bool ValidateFlushMappedBufferRangeBase(Context *context,
3193 GLenum target,
3194 GLintptr offset,
3195 GLsizeiptr length)
3196{
3197 if (offset < 0 || length < 0)
3198 {
Jamie Madill437fa652016-05-03 15:13:24 -04003199 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003200 return false;
3201 }
3202
3203 if (!ValidBufferTarget(context, target))
3204 {
Jamie Madill437fa652016-05-03 15:13:24 -04003205 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003206 return false;
3207 }
3208
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003209 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003210
3211 if (buffer == nullptr)
3212 {
Jamie Madill437fa652016-05-03 15:13:24 -04003213 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003214 return false;
3215 }
3216
3217 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3218 {
Jamie Madill437fa652016-05-03 15:13:24 -04003219 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003220 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
3221 return false;
3222 }
3223
3224 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003225 CheckedNumeric<size_t> checkedOffset(offset);
3226 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003227
Jamie Madille2e406c2016-06-02 13:04:10 -04003228 if (!checkedSize.IsValid() ||
3229 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003230 {
Jamie Madill437fa652016-05-03 15:13:24 -04003231 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003232 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
3233 return false;
3234 }
3235
3236 return true;
3237}
3238
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003239bool ValidateGenerateMipmap(Context *context, GLenum target)
3240{
3241 if (!ValidTextureTarget(context, target))
3242 {
3243 context->handleError(Error(GL_INVALID_ENUM));
3244 return false;
3245 }
3246
3247 Texture *texture = context->getTargetTexture(target);
3248
3249 if (texture == nullptr)
3250 {
3251 context->handleError(Error(GL_INVALID_OPERATION));
3252 return false;
3253 }
3254
3255 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
3256
3257 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
3258 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
3259 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
3260 {
3261 context->handleError(Error(GL_INVALID_OPERATION));
3262 return false;
3263 }
3264
Jamie Madilla3944d42016-07-22 22:13:26 -04003265 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
3266 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
3267 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003268
3269 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
3270 // unsized formats or that are color renderable and filterable. Since we do not track if
3271 // the texture was created with sized or unsized format (only sized formats are stored),
3272 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
3273 // be able to) because they aren't color renderable. Simply do a special case for LUMA
3274 // textures since they're the only texture format that can be created with unsized formats
3275 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
3276 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04003277 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
3278 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003279 {
3280 context->handleError(Error(GL_INVALID_OPERATION));
3281 return false;
3282 }
3283
3284 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04003285 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003286 {
3287 context->handleError(Error(GL_INVALID_OPERATION));
3288 return false;
3289 }
3290
3291 // Non-power of 2 ES2 check
3292 if (!context->getExtensions().textureNPOT &&
3293 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
3294 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
3295 {
Martin Radev1be913c2016-07-11 17:59:16 +03003296 ASSERT(context->getClientMajorVersion() <= 2 &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003297 (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
3298 context->handleError(Error(GL_INVALID_OPERATION));
3299 return false;
3300 }
3301
3302 // Cube completeness check
3303 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
3304 {
3305 context->handleError(Error(GL_INVALID_OPERATION));
3306 return false;
3307 }
3308
3309 return true;
3310}
3311
Olli Etuaho41997e72016-03-10 13:38:39 +02003312bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
3313{
3314 return ValidateGenOrDelete(context, n);
3315}
3316
3317bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
3318{
3319 return ValidateGenOrDelete(context, n);
3320}
3321
3322bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
3323{
3324 return ValidateGenOrDelete(context, n);
3325}
3326
3327bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
3328{
3329 return ValidateGenOrDelete(context, n);
3330}
3331
3332bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
3333{
3334 return ValidateGenOrDelete(context, n);
3335}
3336
3337bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
3338{
3339 return ValidateGenOrDelete(context, n);
3340}
3341
3342bool ValidateGenTextures(Context *context, GLint n, GLuint *)
3343{
3344 return ValidateGenOrDelete(context, n);
3345}
3346
3347bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
3348{
3349 return ValidateGenOrDelete(context, n);
3350}
3351
3352bool ValidateGenOrDelete(Context *context, GLint n)
3353{
3354 if (n < 0)
3355 {
Jamie Madill437fa652016-05-03 15:13:24 -04003356 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02003357 return false;
3358 }
3359 return true;
3360}
3361
Geoff Langf41a7152016-09-19 15:11:17 -04003362bool ValidateEnable(Context *context, GLenum cap)
3363{
3364 if (!ValidCap(context, cap, false))
3365 {
3366 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
3367 return false;
3368 }
3369
3370 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
3371 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
3372 {
3373 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
3374 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
3375
3376 // We also output an error message to the debugger window if tracing is active, so that
3377 // developers can see the error message.
3378 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04003379 return false;
3380 }
3381
3382 return true;
3383}
3384
3385bool ValidateDisable(Context *context, GLenum cap)
3386{
3387 if (!ValidCap(context, cap, false))
3388 {
3389 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
3390 return false;
3391 }
3392
3393 return true;
3394}
3395
3396bool ValidateIsEnabled(Context *context, GLenum cap)
3397{
3398 if (!ValidCap(context, cap, true))
3399 {
3400 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
3401 return false;
3402 }
3403
3404 return true;
3405}
3406
Geoff Langff5b2d52016-09-07 11:32:23 -04003407bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3408{
3409 if (!context->getExtensions().robustClientMemory)
3410 {
3411 context->handleError(
3412 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
3413 return false;
3414 }
3415
3416 if (bufSize < 0)
3417 {
3418 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3419 return false;
3420 }
3421
3422 return true;
3423}
3424
3425bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
3426 GLenum target,
3427 GLenum attachment,
3428 GLenum pname,
3429 GLsizei *numParams)
3430{
3431 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
3432 *numParams = 1;
3433
3434 if (!ValidFramebufferTarget(target))
3435 {
3436 context->handleError(Error(GL_INVALID_ENUM));
3437 return false;
3438 }
3439
3440 int clientVersion = context->getClientMajorVersion();
3441
3442 switch (pname)
3443 {
3444 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3445 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3446 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3447 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3448 break;
3449
3450 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3451 if (clientVersion < 3 && !context->getExtensions().sRGB)
3452 {
3453 context->handleError(Error(GL_INVALID_ENUM));
3454 return false;
3455 }
3456 break;
3457
3458 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3459 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3460 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3461 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3462 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3463 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3464 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3465 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3466 if (clientVersion < 3)
3467 {
3468 context->handleError(Error(GL_INVALID_ENUM));
3469 return false;
3470 }
3471 break;
3472
3473 default:
3474 context->handleError(Error(GL_INVALID_ENUM));
3475 return false;
3476 }
3477
3478 // Determine if the attachment is a valid enum
3479 switch (attachment)
3480 {
3481 case GL_BACK:
3482 case GL_FRONT:
3483 case GL_DEPTH:
3484 case GL_STENCIL:
3485 case GL_DEPTH_STENCIL_ATTACHMENT:
3486 if (clientVersion < 3)
3487 {
3488 context->handleError(Error(GL_INVALID_ENUM));
3489 return false;
3490 }
3491 break;
3492
3493 case GL_DEPTH_ATTACHMENT:
3494 case GL_STENCIL_ATTACHMENT:
3495 break;
3496
3497 default:
3498 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
3499 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3500 {
3501 context->handleError(Error(GL_INVALID_ENUM));
3502 return false;
3503 }
3504 break;
3505 }
3506
3507 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3508 ASSERT(framebuffer);
3509
3510 if (framebuffer->id() == 0)
3511 {
3512 if (clientVersion < 3)
3513 {
3514 context->handleError(Error(GL_INVALID_OPERATION));
3515 return false;
3516 }
3517
3518 switch (attachment)
3519 {
3520 case GL_BACK:
3521 case GL_DEPTH:
3522 case GL_STENCIL:
3523 break;
3524
3525 default:
3526 context->handleError(Error(GL_INVALID_OPERATION));
3527 return false;
3528 }
3529 }
3530 else
3531 {
3532 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3533 {
3534 // Valid attachment query
3535 }
3536 else
3537 {
3538 switch (attachment)
3539 {
3540 case GL_DEPTH_ATTACHMENT:
3541 case GL_STENCIL_ATTACHMENT:
3542 break;
3543
3544 case GL_DEPTH_STENCIL_ATTACHMENT:
3545 if (!framebuffer->hasValidDepthStencil())
3546 {
3547 context->handleError(Error(GL_INVALID_OPERATION));
3548 return false;
3549 }
3550 break;
3551
3552 default:
3553 context->handleError(Error(GL_INVALID_OPERATION));
3554 return false;
3555 }
3556 }
3557 }
3558
3559 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3560 if (attachmentObject)
3561 {
3562 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3563 attachmentObject->type() == GL_TEXTURE ||
3564 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3565
3566 switch (pname)
3567 {
3568 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3569 if (attachmentObject->type() != GL_RENDERBUFFER &&
3570 attachmentObject->type() != GL_TEXTURE)
3571 {
3572 context->handleError(Error(GL_INVALID_ENUM));
3573 return false;
3574 }
3575 break;
3576
3577 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3578 if (attachmentObject->type() != GL_TEXTURE)
3579 {
3580 context->handleError(Error(GL_INVALID_ENUM));
3581 return false;
3582 }
3583 break;
3584
3585 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3586 if (attachmentObject->type() != GL_TEXTURE)
3587 {
3588 context->handleError(Error(GL_INVALID_ENUM));
3589 return false;
3590 }
3591 break;
3592
3593 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3594 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3595 {
3596 context->handleError(Error(GL_INVALID_OPERATION));
3597 return false;
3598 }
3599 break;
3600
3601 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3602 if (attachmentObject->type() != GL_TEXTURE)
3603 {
3604 context->handleError(Error(GL_INVALID_ENUM));
3605 return false;
3606 }
3607 break;
3608
3609 default:
3610 break;
3611 }
3612 }
3613 else
3614 {
3615 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3616 // is NONE, then querying any other pname will generate INVALID_ENUM.
3617
3618 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3619 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3620 // INVALID_OPERATION for all other pnames
3621
3622 switch (pname)
3623 {
3624 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3625 break;
3626
3627 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3628 if (clientVersion < 3)
3629 {
3630 context->handleError(Error(GL_INVALID_ENUM));
3631 return false;
3632 }
3633 break;
3634
3635 default:
3636 if (clientVersion < 3)
3637 {
3638 context->handleError(Error(GL_INVALID_ENUM));
3639 return false;
3640 }
3641 else
3642 {
3643 context->handleError(Error(GL_INVALID_OPERATION));
3644 return false;
3645 }
3646 }
3647 }
3648
3649 return true;
3650}
3651
3652bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
3653 GLenum target,
3654 GLenum attachment,
3655 GLenum pname,
3656 GLsizei bufSize,
3657 GLsizei *numParams)
3658{
3659 if (!ValidateRobustEntryPoint(context, bufSize))
3660 {
3661 return false;
3662 }
3663
3664 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
3665 {
3666 return false;
3667 }
3668
3669 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
3670 {
3671 return false;
3672 }
3673
3674 return true;
3675}
3676
3677bool ValidateGetBufferParameteriv(ValidationContext *context,
3678 GLenum target,
3679 GLenum pname,
3680 GLsizei *numParams)
3681{
3682 // Initialize result
3683 *numParams = 0;
3684
3685 if (!ValidBufferTarget(context, target))
3686 {
3687 context->handleError(Error(GL_INVALID_ENUM));
3688 return false;
3689 }
3690
3691 if (!ValidBufferParameter(context, pname, numParams))
3692 {
3693 context->handleError(Error(GL_INVALID_ENUM));
3694 return false;
3695 }
3696
3697 if (context->getGLState().getTargetBuffer(target) == nullptr)
3698 {
3699 // A null buffer means that "0" is bound to the requested buffer target
3700 context->handleError(Error(GL_INVALID_OPERATION));
3701 return false;
3702 }
3703
3704 return true;
3705}
3706
3707bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
3708 GLenum target,
3709 GLenum pname,
3710 GLsizei bufSize,
3711 GLsizei *numParams)
3712{
3713 if (!ValidateRobustEntryPoint(context, bufSize))
3714 {
3715 return false;
3716 }
3717
3718 if (!ValidateGetBufferParameteriv(context, target, pname, numParams))
3719 {
3720 return false;
3721 }
3722
3723 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
3724 {
3725 return false;
3726 }
3727
3728 return true;
3729}
3730
3731bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
3732{
3733 // Currently, all GetProgramiv queries return 1 parameter
3734 *numParams = 1;
3735
3736 Program *programObject = GetValidProgram(context, program);
3737 if (!programObject)
3738 {
3739 return false;
3740 }
3741
3742 switch (pname)
3743 {
3744 case GL_DELETE_STATUS:
3745 case GL_LINK_STATUS:
3746 case GL_VALIDATE_STATUS:
3747 case GL_INFO_LOG_LENGTH:
3748 case GL_ATTACHED_SHADERS:
3749 case GL_ACTIVE_ATTRIBUTES:
3750 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
3751 case GL_ACTIVE_UNIFORMS:
3752 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
3753 break;
3754
3755 case GL_PROGRAM_BINARY_LENGTH:
3756 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
3757 {
3758 context->handleError(Error(GL_INVALID_ENUM,
3759 "Querying GL_PROGRAM_BINARY_LENGTH requires "
3760 "GL_OES_get_program_binary or ES 3.0."));
3761 return false;
3762 }
3763 break;
3764
3765 case GL_ACTIVE_UNIFORM_BLOCKS:
3766 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
3767 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
3768 case GL_TRANSFORM_FEEDBACK_VARYINGS:
3769 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
3770 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
3771 if (context->getClientMajorVersion() < 3)
3772 {
3773 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
3774 return false;
3775 }
3776 break;
3777
3778 default:
3779 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
3780 return false;
3781 }
3782
3783 return true;
3784}
3785
3786bool ValidateGetProgramivRobustANGLE(Context *context,
3787 GLuint program,
3788 GLenum pname,
3789 GLsizei bufSize,
3790 GLsizei *numParams)
3791{
3792 if (!ValidateRobustEntryPoint(context, bufSize))
3793 {
3794 return false;
3795 }
3796
3797 if (!ValidateGetProgramiv(context, program, pname, numParams))
3798 {
3799 return false;
3800 }
3801
3802 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
3803 {
3804 return false;
3805 }
3806
3807 return true;
3808}
3809
Jamie Madillc29968b2016-01-20 11:17:23 -05003810} // namespace gl