blob: f92212eefdac80b9ec7f606ca246b5f005b87a40 [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 Lang740d9022016-10-07 11:20:52 -0400314bool ValidateGetRenderbufferParameterivBase(Context *context,
315 GLenum target,
316 GLenum pname,
317 GLsizei *length)
318{
319 if (length)
320 {
321 *length = 0;
322 }
323
324 if (target != GL_RENDERBUFFER)
325 {
326 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
327 return false;
328 }
329
330 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
331 if (renderbuffer == nullptr)
332 {
333 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
334 return false;
335 }
336
337 switch (pname)
338 {
339 case GL_RENDERBUFFER_WIDTH:
340 case GL_RENDERBUFFER_HEIGHT:
341 case GL_RENDERBUFFER_INTERNAL_FORMAT:
342 case GL_RENDERBUFFER_RED_SIZE:
343 case GL_RENDERBUFFER_GREEN_SIZE:
344 case GL_RENDERBUFFER_BLUE_SIZE:
345 case GL_RENDERBUFFER_ALPHA_SIZE:
346 case GL_RENDERBUFFER_DEPTH_SIZE:
347 case GL_RENDERBUFFER_STENCIL_SIZE:
348 break;
349
350 case GL_RENDERBUFFER_SAMPLES_ANGLE:
351 if (!context->getExtensions().framebufferMultisample)
352 {
353 context->handleError(
354 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
355 return false;
356 }
357 break;
358
359 default:
360 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
361 return false;
362 }
363
364 if (length)
365 {
366 *length = 1;
367 }
368 return true;
369}
370
Geoff Langf41a7152016-09-19 15:11:17 -0400371} // anonymous namespace
372
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500373bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400374{
Jamie Madilld7460c72014-01-21 16:38:14 -0500375 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400376 {
Jamie Madilld7460c72014-01-21 16:38:14 -0500377 case GL_TEXTURE_2D:
378 case GL_TEXTURE_CUBE_MAP:
379 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400380
Jamie Madilld7460c72014-01-21 16:38:14 -0500381 case GL_TEXTURE_3D:
382 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300383 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500384
385 default:
386 return false;
387 }
Jamie Madill35d15012013-10-07 10:46:37 -0400388}
389
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500390bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
391{
392 switch (target)
393 {
394 case GL_TEXTURE_2D:
395 case GL_TEXTURE_CUBE_MAP:
396 return true;
397
398 default:
399 return false;
400 }
401}
402
403bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
404{
405 switch (target)
406 {
407 case GL_TEXTURE_3D:
408 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300409 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500410
411 default:
412 return false;
413 }
414}
415
Ian Ewellbda75592016-04-18 17:25:54 -0400416// Most texture GL calls are not compatible with external textures, so we have a separate validation
417// function for use in the GL calls that do
418bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
419{
420 return (target == GL_TEXTURE_EXTERNAL_OES) &&
421 (context->getExtensions().eglImageExternal ||
422 context->getExtensions().eglStreamConsumerExternal);
423}
424
Shannon Woods4dfed832014-03-17 20:03:39 -0400425// This function differs from ValidTextureTarget in that the target must be
426// usable as the destination of a 2D operation-- so a cube face is valid, but
427// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400428// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500429bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400430{
431 switch (target)
432 {
433 case GL_TEXTURE_2D:
434 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
435 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
436 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
437 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
438 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
439 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
440 return true;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500441 default:
442 return false;
443 }
444}
445
446bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
447{
448 switch (target)
449 {
Shannon Woods4dfed832014-03-17 20:03:39 -0400450 case GL_TEXTURE_3D:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500451 case GL_TEXTURE_2D_ARRAY:
452 return true;
Shannon Woods4dfed832014-03-17 20:03:39 -0400453 default:
454 return false;
455 }
456}
457
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500458bool ValidFramebufferTarget(GLenum target)
459{
Geoff Langd4475812015-03-18 10:53:05 -0400460 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
461 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500462
463 switch (target)
464 {
465 case GL_FRAMEBUFFER: return true;
466 case GL_READ_FRAMEBUFFER: return true;
467 case GL_DRAW_FRAMEBUFFER: return true;
468 default: return false;
469 }
470}
471
Jamie Madill29639852016-09-02 15:00:09 -0400472bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -0500473{
474 switch (target)
475 {
476 case GL_ARRAY_BUFFER:
477 case GL_ELEMENT_ARRAY_BUFFER:
478 return true;
479
Jamie Madill8c96d582014-03-05 15:01:23 -0500480 case GL_PIXEL_PACK_BUFFER:
481 case GL_PIXEL_UNPACK_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +0300482 return (context->getExtensions().pixelBufferObject ||
483 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -0400484
Shannon Woodsb3801742014-03-27 14:59:19 -0400485 case GL_COPY_READ_BUFFER:
486 case GL_COPY_WRITE_BUFFER:
Jamie Madill8c96d582014-03-05 15:01:23 -0500487 case GL_TRANSFORM_FEEDBACK_BUFFER:
488 case GL_UNIFORM_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +0300489 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -0500490
491 default:
492 return false;
493 }
494}
495
Geoff Langff5b2d52016-09-07 11:32:23 -0400496bool ValidBufferParameter(const ValidationContext *context, GLenum pname, GLsizei *numParams)
Jamie Madill70656a62014-03-05 15:01:26 -0500497{
Geoff Langff5b2d52016-09-07 11:32:23 -0400498 // All buffer parameter queries return one value.
499 *numParams = 1;
500
Geoff Langcc6f55d2015-03-20 13:01:02 -0400501 const Extensions &extensions = context->getExtensions();
502
Jamie Madill70656a62014-03-05 15:01:26 -0500503 switch (pname)
504 {
505 case GL_BUFFER_USAGE:
506 case GL_BUFFER_SIZE:
507 return true;
508
Geoff Langcc6f55d2015-03-20 13:01:02 -0400509 case GL_BUFFER_ACCESS_OES:
510 return extensions.mapBuffer;
511
512 case GL_BUFFER_MAPPED:
513 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
Martin Radev1be913c2016-07-11 17:59:16 +0300514 return (context->getClientMajorVersion() >= 3) || extensions.mapBuffer ||
515 extensions.mapBufferRange;
Geoff Langcc6f55d2015-03-20 13:01:02 -0400516
Jamie Madill70656a62014-03-05 15:01:26 -0500517 // GL_BUFFER_MAP_POINTER is a special case, and may only be
518 // queried with GetBufferPointerv
519 case GL_BUFFER_ACCESS_FLAGS:
Jamie Madill70656a62014-03-05 15:01:26 -0500520 case GL_BUFFER_MAP_OFFSET:
521 case GL_BUFFER_MAP_LENGTH:
Martin Radev1be913c2016-07-11 17:59:16 +0300522 return (context->getClientMajorVersion() >= 3) || extensions.mapBufferRange;
Jamie Madill70656a62014-03-05 15:01:26 -0500523
524 default:
525 return false;
526 }
527}
528
Jamie Madillc29968b2016-01-20 11:17:23 -0500529bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400530{
Jamie Madillc29968b2016-01-20 11:17:23 -0500531 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400532 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400533 switch (target)
534 {
Jamie Madillc29968b2016-01-20 11:17:23 -0500535 case GL_TEXTURE_2D:
536 maxDimension = caps.max2DTextureSize;
537 break;
Geoff Langce635692013-09-24 13:56:32 -0400538 case GL_TEXTURE_CUBE_MAP:
539 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
540 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
541 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
542 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
543 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
Jamie Madillc29968b2016-01-20 11:17:23 -0500544 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
545 maxDimension = caps.maxCubeMapTextureSize;
546 break;
547 case GL_TEXTURE_3D:
548 maxDimension = caps.max3DTextureSize;
549 break;
550 case GL_TEXTURE_2D_ARRAY:
551 maxDimension = caps.max2DTextureSize;
552 break;
Geoff Langce635692013-09-24 13:56:32 -0400553 default: UNREACHABLE();
554 }
555
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700556 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -0400557}
558
Austin Kinross08528e12015-10-07 16:24:40 -0700559bool ValidImageSizeParameters(const Context *context,
560 GLenum target,
561 GLint level,
562 GLsizei width,
563 GLsizei height,
564 GLsizei depth,
565 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400566{
567 if (level < 0 || width < 0 || height < 0 || depth < 0)
568 {
569 return false;
570 }
571
Austin Kinross08528e12015-10-07 16:24:40 -0700572 // TexSubImage parameters can be NPOT without textureNPOT extension,
573 // as long as the destination texture is POT.
574 if (!isSubImage && !context->getExtensions().textureNPOT &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400575 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400576 {
577 return false;
578 }
579
580 if (!ValidMipLevel(context, target, level))
581 {
582 return false;
583 }
584
585 return true;
586}
587
Geoff Lang0d8b7242015-09-09 14:56:53 -0400588bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
589{
590 // List of compressed format that require that the texture size is smaller than or a multiple of
591 // the compressed block size.
592 switch (internalFormat)
593 {
594 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
595 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
596 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
597 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -0800598 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -0400599 return true;
600
601 default:
602 return false;
603 }
604}
605
Jamie Madillc29968b2016-01-20 11:17:23 -0500606bool ValidCompressedImageSize(const ValidationContext *context,
607 GLenum internalFormat,
608 GLsizei width,
609 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400610{
Geoff Lang5d601382014-07-22 15:14:06 -0400611 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
612 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400613 {
614 return false;
615 }
616
Geoff Lang0d8b7242015-09-09 14:56:53 -0400617 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400618 {
619 return false;
620 }
621
Geoff Lang0d8b7242015-09-09 14:56:53 -0400622 if (CompressedTextureFormatRequiresExactSize(internalFormat))
623 {
624 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
625 width % formatInfo.compressedBlockWidth != 0) ||
626 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
627 height % formatInfo.compressedBlockHeight != 0))
628 {
629 return false;
630 }
631 }
632
Geoff Langd4f180b2013-09-24 13:57:44 -0400633 return true;
634}
635
Geoff Langff5b2d52016-09-07 11:32:23 -0400636bool ValidImageDataSize(ValidationContext *context,
637 GLenum textureTarget,
638 GLsizei width,
639 GLsizei height,
640 GLsizei depth,
641 GLenum internalFormat,
642 GLenum type,
643 const GLvoid *pixels,
644 GLsizei imageSize)
645{
646 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
647 if (pixelUnpackBuffer == nullptr && imageSize < 0)
648 {
649 // Checks are not required
650 return true;
651 }
652
653 // ...the data would be unpacked from the buffer object such that the memory reads required
654 // would exceed the data store size.
655 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
656 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
657 const gl::Extents size(width, height, depth);
658 const auto &unpack = context->getGLState().getUnpackState();
659
660 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
661 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
662 if (endByteOrErr.isError())
663 {
664 context->handleError(endByteOrErr.getError());
665 return false;
666 }
667
668 GLuint endByte = endByteOrErr.getResult();
669
670 if (pixelUnpackBuffer)
671 {
672 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
673 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
674 checkedEndByte += checkedOffset;
675
676 if (!checkedEndByte.IsValid() ||
677 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
678 {
679 // Overflow past the end of the buffer
680 context->handleError(Error(GL_INVALID_OPERATION));
681 return false;
682 }
683 }
684 else
685 {
686 ASSERT(imageSize >= 0);
687 if (pixels == nullptr && imageSize != 0)
688 {
689 context->handleError(
690 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
691 }
692
693 if (endByte > static_cast<GLuint>(imageSize))
694 {
695 context->handleError(
696 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
697 return false;
698 }
699 }
700
701 return true;
702}
703
Geoff Lang37dde692014-01-31 16:34:54 -0500704bool ValidQueryType(const Context *context, GLenum queryType)
705{
Geoff Langd4475812015-03-18 10:53:05 -0400706 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT, "GL extension enums not equal.");
707 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 -0500708
709 switch (queryType)
710 {
711 case GL_ANY_SAMPLES_PASSED:
712 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
713 return true;
714 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
Martin Radev1be913c2016-07-11 17:59:16 +0300715 return (context->getClientMajorVersion() >= 3);
Ian Ewell3ffd78b2016-01-22 16:09:42 -0500716 case GL_TIME_ELAPSED_EXT:
717 return context->getExtensions().disjointTimerQuery;
Geoff Lang2b4ce802016-04-28 13:34:50 -0400718 case GL_COMMANDS_COMPLETED_CHROMIUM:
719 return context->getExtensions().syncQuery;
Geoff Lang37dde692014-01-31 16:34:54 -0500720 default:
721 return false;
722 }
723}
724
Dian Xiang769769a2015-09-09 15:20:08 -0700725Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -0500726{
727 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the
728 // error INVALID_VALUE if the provided name is not the name of either a shader or program object and
729 // INVALID_OPERATION if the provided name identifies an object that is not the expected type."
730
Dian Xiang769769a2015-09-09 15:20:08 -0700731 Program *validProgram = context->getProgram(id);
732
733 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -0500734 {
Dian Xiang769769a2015-09-09 15:20:08 -0700735 if (context->getShader(id))
736 {
Jamie Madill437fa652016-05-03 15:13:24 -0400737 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -0700738 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
739 }
740 else
741 {
Jamie Madill437fa652016-05-03 15:13:24 -0400742 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -0700743 }
Geoff Lang48dcae72014-02-05 16:28:24 -0500744 }
Dian Xiang769769a2015-09-09 15:20:08 -0700745
746 return validProgram;
747}
748
749Shader *GetValidShader(Context *context, GLuint id)
750{
751 // See ValidProgram for spec details.
752
753 Shader *validShader = context->getShader(id);
754
755 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -0500756 {
Dian Xiang769769a2015-09-09 15:20:08 -0700757 if (context->getProgram(id))
758 {
Jamie Madill437fa652016-05-03 15:13:24 -0400759 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -0700760 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
761 }
762 else
763 {
Jamie Madill437fa652016-05-03 15:13:24 -0400764 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -0700765 }
Geoff Lang48dcae72014-02-05 16:28:24 -0500766 }
Dian Xiang769769a2015-09-09 15:20:08 -0700767
768 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -0500769}
770
Geoff Langb1196682014-07-23 13:47:29 -0400771bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -0400772{
773 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
774 {
775 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
776
Geoff Langaae65a42014-05-26 12:43:44 -0400777 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -0400778 {
Jamie Madill437fa652016-05-03 15:13:24 -0400779 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400780 return false;
Jamie Madillb4472272014-07-03 10:38:55 -0400781 }
782 }
783 else
784 {
785 switch (attachment)
786 {
787 case GL_DEPTH_ATTACHMENT:
788 case GL_STENCIL_ATTACHMENT:
Martin Radev1be913c2016-07-11 17:59:16 +0300789 break;
Jamie Madillb4472272014-07-03 10:38:55 -0400790
791 case GL_DEPTH_STENCIL_ATTACHMENT:
Geoff Langc287ea62016-09-16 14:46:51 -0400792 if (!context->getExtensions().webglCompatibility &&
793 context->getClientMajorVersion() < 3)
Martin Radev1be913c2016-07-11 17:59:16 +0300794 {
795 context->handleError(Error(GL_INVALID_ENUM));
796 return false;
797 }
798 break;
Jamie Madillb4472272014-07-03 10:38:55 -0400799
800 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400801 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +0300802 return false;
Jamie Madillb4472272014-07-03 10:38:55 -0400803 }
804 }
805
806 return true;
807}
808
Corentin Walleze0902642014-11-04 12:32:15 -0800809bool ValidateRenderbufferStorageParametersBase(gl::Context *context, GLenum target, GLsizei samples,
810 GLenum internalformat, GLsizei width, GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400811{
812 switch (target)
813 {
814 case GL_RENDERBUFFER:
815 break;
816 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400817 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400818 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400819 }
820
821 if (width < 0 || height < 0 || samples < 0)
822 {
Jamie Madill437fa652016-05-03 15:13:24 -0400823 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400824 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400825 }
826
Geoff Langd87878e2014-09-19 15:42:59 -0400827 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
828 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400829 {
Jamie Madill437fa652016-05-03 15:13:24 -0400830 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400831 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400832 }
833
834 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
835 // 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 -0800836 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -0400837 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400838 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400839 {
Jamie Madill437fa652016-05-03 15:13:24 -0400840 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400841 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400842 }
843
Geoff Langaae65a42014-05-26 12:43:44 -0400844 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400845 {
Jamie Madill437fa652016-05-03 15:13:24 -0400846 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400847 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400848 }
849
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700850 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400851 if (handle == 0)
852 {
Jamie Madill437fa652016-05-03 15:13:24 -0400853 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400854 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400855 }
856
857 return true;
858}
859
Corentin Walleze0902642014-11-04 12:32:15 -0800860bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum target, GLsizei samples,
861 GLenum internalformat, GLsizei width, GLsizei height)
862{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -0800863 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -0800864
865 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -0400866 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -0800867 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -0400868 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -0800869 {
Jamie Madill437fa652016-05-03 15:13:24 -0400870 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -0800871 return false;
872 }
873
874 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
875 // the specified storage. This is different than ES 3.0 in which a sample number higher
876 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -0800877 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +0300878 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -0800879 {
Geoff Langa4903b72015-03-02 16:02:48 -0800880 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
881 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
882 {
Jamie Madill437fa652016-05-03 15:13:24 -0400883 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -0800884 return false;
885 }
Corentin Walleze0902642014-11-04 12:32:15 -0800886 }
887
888 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height);
889}
890
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500891bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
892 GLenum renderbuffertarget, GLuint renderbuffer)
893{
Shannon Woods1da3cf62014-06-27 15:32:23 -0400894 if (!ValidFramebufferTarget(target))
895 {
Jamie Madill437fa652016-05-03 15:13:24 -0400896 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400897 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -0400898 }
899
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700900 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500901
Jamie Madill84115c92015-04-23 15:00:07 -0400902 ASSERT(framebuffer);
903 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500904 {
Jamie Madill437fa652016-05-03 15:13:24 -0400905 context->handleError(
906 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -0400907 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500908 }
909
Jamie Madillb4472272014-07-03 10:38:55 -0400910 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500911 {
Jamie Madillb4472272014-07-03 10:38:55 -0400912 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500913 }
914
Jamie Madillab9d82c2014-01-21 16:38:14 -0500915 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
916 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
917 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
918 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
919 if (renderbuffer != 0)
920 {
921 if (!context->getRenderbuffer(renderbuffer))
922 {
Jamie Madill437fa652016-05-03 15:13:24 -0400923 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400924 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -0500925 }
926 }
927
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500928 return true;
929}
930
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700931bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500932 GLint srcX0,
933 GLint srcY0,
934 GLint srcX1,
935 GLint srcY1,
936 GLint dstX0,
937 GLint dstY0,
938 GLint dstX1,
939 GLint dstY1,
940 GLbitfield mask,
941 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400942{
943 switch (filter)
944 {
945 case GL_NEAREST:
946 break;
947 case GL_LINEAR:
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400948 break;
949 default:
Jamie Madill437fa652016-05-03 15:13:24 -0400950 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -0400951 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400952 }
953
954 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
955 {
Jamie Madill437fa652016-05-03 15:13:24 -0400956 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -0400957 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400958 }
959
960 if (mask == 0)
961 {
962 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
963 // buffers are copied.
964 return false;
965 }
966
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400967 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
968 // color buffer, leaving only nearest being unfiltered from above
969 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
970 {
Jamie Madill437fa652016-05-03 15:13:24 -0400971 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400972 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400973 }
974
Jamie Madill51f40ec2016-06-15 14:06:00 -0400975 const auto &glState = context->getGLState();
976 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
977 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -0500978
979 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400980 {
Jamie Madill437fa652016-05-03 15:13:24 -0400981 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -0400982 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400983 }
984
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700985 if (readFramebuffer->id() == drawFramebuffer->id())
986 {
987 context->handleError(Error(GL_INVALID_OPERATION));
988 return false;
989 }
990
Jamie Madill51f40ec2016-06-15 14:06:00 -0400991 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -0500992 {
Jamie Madill437fa652016-05-03 15:13:24 -0400993 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -0500994 return false;
995 }
996
Jamie Madill51f40ec2016-06-15 14:06:00 -0400997 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -0500998 {
Jamie Madill437fa652016-05-03 15:13:24 -0400999 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001000 return false;
1001 }
1002
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001003 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001004 {
Jamie Madill437fa652016-05-03 15:13:24 -04001005 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001006 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001007 }
1008
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001009 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1010
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001011 if (mask & GL_COLOR_BUFFER_BIT)
1012 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001013 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1014 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001015 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001016
1017 if (readColorBuffer && drawColorBuffer)
1018 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001019 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001020
Geoff Langa15472a2015-08-11 11:48:03 -04001021 for (size_t drawbufferIdx = 0;
1022 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001023 {
Geoff Langa15472a2015-08-11 11:48:03 -04001024 const FramebufferAttachment *attachment =
1025 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1026 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001027 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001028 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001029
Geoff Langb2f3d052013-08-13 12:49:27 -04001030 // The GL ES 3.0.2 spec (pg 193) states that:
1031 // 1) If the read buffer is fixed point format, the draw buffer must be as well
1032 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
1033 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
Jamie Madill6163c752015-12-07 16:32:59 -05001034 // Changes with EXT_color_buffer_float:
1035 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001036 GLenum readComponentType = readFormat.info->componentType;
1037 GLenum drawComponentType = drawFormat.info->componentType;
Jamie Madill6163c752015-12-07 16:32:59 -05001038 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
1039 readComponentType == GL_SIGNED_NORMALIZED);
1040 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1041 drawComponentType == GL_SIGNED_NORMALIZED);
1042
1043 if (extensions.colorBufferFloat)
1044 {
1045 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1046 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1047
1048 if (readFixedOrFloat != drawFixedOrFloat)
1049 {
Jamie Madill437fa652016-05-03 15:13:24 -04001050 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001051 "If the read buffer contains fixed-point or "
1052 "floating-point values, the draw buffer "
1053 "must as well."));
1054 return false;
1055 }
1056 }
1057 else if (readFixedPoint != drawFixedPoint)
1058 {
Jamie Madill437fa652016-05-03 15:13:24 -04001059 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001060 "If the read buffer contains fixed-point "
1061 "values, the draw buffer must as well."));
1062 return false;
1063 }
1064
1065 if (readComponentType == GL_UNSIGNED_INT &&
1066 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001067 {
Jamie Madill437fa652016-05-03 15:13:24 -04001068 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001069 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001070 }
1071
Jamie Madill6163c752015-12-07 16:32:59 -05001072 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001073 {
Jamie Madill437fa652016-05-03 15:13:24 -04001074 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001075 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001076 }
1077
Jamie Madilla3944d42016-07-22 22:13:26 -04001078 if (readColorBuffer->getSamples() > 0 &&
1079 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001080 {
Jamie Madill437fa652016-05-03 15:13:24 -04001081 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001082 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001083 }
1084 }
1085 }
1086
Jamie Madilla3944d42016-07-22 22:13:26 -04001087 if ((readFormat.info->componentType == GL_INT ||
1088 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1089 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001090 {
Jamie Madill437fa652016-05-03 15:13:24 -04001091 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001092 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001093 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001094 }
1095 }
1096
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001097 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1098 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1099 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001100 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001101 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001102 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001103 const gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]);
1104 const gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001105
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001106 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001107 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001108 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001109 {
Jamie Madill437fa652016-05-03 15:13:24 -04001110 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001111 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001112 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001113
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001114 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001115 {
Jamie Madill437fa652016-05-03 15:13:24 -04001116 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001117 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001118 }
1119 }
1120 }
1121 }
1122
1123 return true;
1124}
1125
Geoff Langb1196682014-07-23 13:47:29 -04001126bool ValidateGetVertexAttribParameters(Context *context, GLenum pname)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001127{
1128 switch (pname)
1129 {
1130 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1131 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1132 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1133 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1134 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1135 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1136 case GL_CURRENT_VERTEX_ATTRIB:
Martin Radev1be913c2016-07-11 17:59:16 +03001137 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001138
1139 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
Martin Radev1be913c2016-07-11 17:59:16 +03001140 // Don't verify ES3 context because GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE uses
1141 // the same constant.
1142 static_assert(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1143 "ANGLE extension enums not equal to GL enums.");
1144 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001145
1146 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Martin Radev1be913c2016-07-11 17:59:16 +03001147 if (context->getClientMajorVersion() < 3)
1148 {
1149 context->handleError(Error(GL_INVALID_ENUM));
1150 return false;
1151 }
1152 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001153
1154 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001155 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03001156 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001157 }
1158}
1159
Ian Ewellbda75592016-04-18 17:25:54 -04001160bool ValidateTexParamParameters(gl::Context *context, GLenum target, GLenum pname, GLint param)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001161{
1162 switch (pname)
1163 {
1164 case GL_TEXTURE_WRAP_R:
1165 case GL_TEXTURE_SWIZZLE_R:
1166 case GL_TEXTURE_SWIZZLE_G:
1167 case GL_TEXTURE_SWIZZLE_B:
1168 case GL_TEXTURE_SWIZZLE_A:
1169 case GL_TEXTURE_BASE_LEVEL:
1170 case GL_TEXTURE_MAX_LEVEL:
1171 case GL_TEXTURE_COMPARE_MODE:
1172 case GL_TEXTURE_COMPARE_FUNC:
1173 case GL_TEXTURE_MIN_LOD:
1174 case GL_TEXTURE_MAX_LOD:
Martin Radev1be913c2016-07-11 17:59:16 +03001175 if (context->getClientMajorVersion() < 3)
1176 {
1177 context->handleError(Error(GL_INVALID_ENUM));
1178 return false;
1179 }
1180 if (target == GL_TEXTURE_EXTERNAL_OES && !context->getExtensions().eglImageExternalEssl3)
1181 {
1182 context->handleError(Error(GL_INVALID_ENUM,
1183 "ES3 texture parameters are not available without "
1184 "GL_OES_EGL_image_external_essl3."));
1185 return false;
1186 }
1187 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001188
1189 default: break;
1190 }
1191
1192 switch (pname)
1193 {
1194 case GL_TEXTURE_WRAP_S:
1195 case GL_TEXTURE_WRAP_T:
1196 case GL_TEXTURE_WRAP_R:
1197 switch (param)
1198 {
Corentin Wallez9670b032016-04-29 09:47:47 +00001199 case GL_CLAMP_TO_EDGE:
Ian Ewellbda75592016-04-18 17:25:54 -04001200 return true;
1201 case GL_REPEAT:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001202 case GL_MIRRORED_REPEAT:
Olli Etuahobd329092016-04-29 12:51:42 +03001203 if (target == GL_TEXTURE_EXTERNAL_OES)
1204 {
1205 // OES_EGL_image_external specifies this error.
Jamie Madill437fa652016-05-03 15:13:24 -04001206 context->handleError(Error(
Olli Etuahobd329092016-04-29 12:51:42 +03001207 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
1208 return false;
1209 }
1210 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001211 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001212 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001213 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001214 }
1215
1216 case GL_TEXTURE_MIN_FILTER:
1217 switch (param)
1218 {
1219 case GL_NEAREST:
1220 case GL_LINEAR:
Ian Ewellbda75592016-04-18 17:25:54 -04001221 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001222 case GL_NEAREST_MIPMAP_NEAREST:
1223 case GL_LINEAR_MIPMAP_NEAREST:
1224 case GL_NEAREST_MIPMAP_LINEAR:
1225 case GL_LINEAR_MIPMAP_LINEAR:
Olli Etuahobd329092016-04-29 12:51:42 +03001226 if (target == GL_TEXTURE_EXTERNAL_OES)
1227 {
1228 // OES_EGL_image_external specifies this error.
Jamie Madill437fa652016-05-03 15:13:24 -04001229 context->handleError(
Olli Etuahobd329092016-04-29 12:51:42 +03001230 Error(GL_INVALID_ENUM,
1231 "external textures only support NEAREST and LINEAR filtering"));
1232 return false;
1233 }
1234 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001235 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_MAG_FILTER:
1242 switch (param)
1243 {
1244 case GL_NEAREST:
1245 case GL_LINEAR:
1246 return true;
1247 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001248 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001249 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001250 }
1251 break;
1252
1253 case GL_TEXTURE_USAGE_ANGLE:
1254 switch (param)
1255 {
1256 case GL_NONE:
1257 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
1258 return true;
1259 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001260 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001261 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001262 }
1263 break;
1264
1265 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001266 if (!context->getExtensions().textureFilterAnisotropic)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001267 {
Jamie Madill437fa652016-05-03 15:13:24 -04001268 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001269 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001270 }
1271
1272 // we assume the parameter passed to this validation method is truncated, not rounded
1273 if (param < 1)
1274 {
Jamie Madill437fa652016-05-03 15:13:24 -04001275 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001276 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001277 }
1278 return true;
1279
1280 case GL_TEXTURE_MIN_LOD:
1281 case GL_TEXTURE_MAX_LOD:
1282 // any value is permissible
1283 return true;
1284
1285 case GL_TEXTURE_COMPARE_MODE:
Geoff Lang63b5f1f2013-09-23 14:52:14 -04001286 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001287 switch (param)
1288 {
1289 case GL_NONE:
1290 case GL_COMPARE_REF_TO_TEXTURE:
1291 return true;
1292 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001293 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001294 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001295 }
1296 break;
1297
1298 case GL_TEXTURE_COMPARE_FUNC:
Geoff Lang63b5f1f2013-09-23 14:52:14 -04001299 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001300 switch (param)
1301 {
1302 case GL_LEQUAL:
1303 case GL_GEQUAL:
1304 case GL_LESS:
1305 case GL_GREATER:
1306 case GL_EQUAL:
1307 case GL_NOTEQUAL:
1308 case GL_ALWAYS:
1309 case GL_NEVER:
1310 return true;
1311 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001312 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001313 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001314 }
1315 break;
1316
1317 case GL_TEXTURE_SWIZZLE_R:
1318 case GL_TEXTURE_SWIZZLE_G:
1319 case GL_TEXTURE_SWIZZLE_B:
1320 case GL_TEXTURE_SWIZZLE_A:
Geoff Langbc90a482013-09-17 16:51:27 -04001321 switch (param)
1322 {
1323 case GL_RED:
1324 case GL_GREEN:
1325 case GL_BLUE:
1326 case GL_ALPHA:
1327 case GL_ZERO:
1328 case GL_ONE:
1329 return true;
1330 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001331 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001332 return false;
Geoff Langbc90a482013-09-17 16:51:27 -04001333 }
1334 break;
1335
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001336 case GL_TEXTURE_BASE_LEVEL:
Geoff Langb66a9092016-05-16 15:59:14 -04001337 if (param < 0)
Olli Etuahoa314b612016-03-10 16:43:00 +02001338 {
Geoff Langb66a9092016-05-16 15:59:14 -04001339 context->handleError(Error(GL_INVALID_VALUE));
Olli Etuahoa314b612016-03-10 16:43:00 +02001340 return false;
1341 }
Geoff Langb66a9092016-05-16 15:59:14 -04001342 if (target == GL_TEXTURE_EXTERNAL_OES && param != 0)
1343 {
1344 context->handleError(
1345 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
1346 return false;
1347 }
1348 return true;
1349
1350 case GL_TEXTURE_MAX_LEVEL:
Olli Etuahoa314b612016-03-10 16:43:00 +02001351 if (param < 0)
1352 {
1353 context->handleError(Error(GL_INVALID_VALUE));
1354 return false;
1355 }
1356 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001357 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001358 context->handleError(Error(GL_INVALID_ENUM));
Olli Etuahoa314b612016-03-10 16:43:00 +02001359 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001360 }
1361}
1362
Geoff Langb1196682014-07-23 13:47:29 -04001363bool ValidateSamplerObjectParameter(gl::Context *context, GLenum pname)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001364{
1365 switch (pname)
1366 {
1367 case GL_TEXTURE_MIN_FILTER:
1368 case GL_TEXTURE_MAG_FILTER:
1369 case GL_TEXTURE_WRAP_S:
1370 case GL_TEXTURE_WRAP_T:
1371 case GL_TEXTURE_WRAP_R:
1372 case GL_TEXTURE_MIN_LOD:
1373 case GL_TEXTURE_MAX_LOD:
1374 case GL_TEXTURE_COMPARE_MODE:
1375 case GL_TEXTURE_COMPARE_FUNC:
1376 return true;
1377
1378 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001379 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001380 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001381 }
1382}
1383
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001384bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001385 GLint x,
1386 GLint y,
1387 GLsizei width,
1388 GLsizei height,
1389 GLenum format,
1390 GLenum type,
1391 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05001392{
Geoff Lang62fce5b2016-09-30 10:46:35 -04001393 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
1394}
1395
1396bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
1397 GLint x,
1398 GLint y,
1399 GLsizei width,
1400 GLsizei height,
1401 GLenum format,
1402 GLenum type,
1403 GLsizei bufSize,
1404 GLsizei *length,
1405 GLvoid *pixels)
1406{
1407 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001408 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001409 return false;
1410 }
1411
Geoff Lang62fce5b2016-09-30 10:46:35 -04001412 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1413 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001414 {
Geoff Langb1196682014-07-23 13:47:29 -04001415 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001416 }
1417
Geoff Lang62fce5b2016-09-30 10:46:35 -04001418 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001419 {
Geoff Langb1196682014-07-23 13:47:29 -04001420 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001421 }
1422
Jamie Madillc29968b2016-01-20 11:17:23 -05001423 return true;
1424}
1425
1426bool ValidateReadnPixelsEXT(Context *context,
1427 GLint x,
1428 GLint y,
1429 GLsizei width,
1430 GLsizei height,
1431 GLenum format,
1432 GLenum type,
1433 GLsizei bufSize,
1434 GLvoid *pixels)
1435{
1436 if (bufSize < 0)
1437 {
Jamie Madill437fa652016-05-03 15:13:24 -04001438 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001439 return false;
1440 }
1441
Geoff Lang62fce5b2016-09-30 10:46:35 -04001442 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
1443 pixels);
1444}
Jamie Madill26e91952014-03-05 15:01:27 -05001445
Geoff Lang62fce5b2016-09-30 10:46:35 -04001446bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
1447 GLint x,
1448 GLint y,
1449 GLsizei width,
1450 GLsizei height,
1451 GLenum format,
1452 GLenum type,
1453 GLsizei bufSize,
1454 GLsizei *length,
1455 GLvoid *data)
1456{
1457 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001458 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001459 return false;
1460 }
1461
Geoff Lang62fce5b2016-09-30 10:46:35 -04001462 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001463 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001464 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001465 }
1466
Geoff Lang62fce5b2016-09-30 10:46:35 -04001467 if (!ValidateRobustBufferSize(context, bufSize, *length))
1468 {
1469 return false;
1470 }
1471
1472 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001473}
1474
Olli Etuaho41997e72016-03-10 13:38:39 +02001475bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001476{
1477 if (!context->getExtensions().occlusionQueryBoolean &&
1478 !context->getExtensions().disjointTimerQuery)
1479 {
Jamie Madill437fa652016-05-03 15:13:24 -04001480 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001481 return false;
1482 }
1483
Olli Etuaho41997e72016-03-10 13:38:39 +02001484 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001485}
1486
Olli Etuaho41997e72016-03-10 13:38:39 +02001487bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001488{
1489 if (!context->getExtensions().occlusionQueryBoolean &&
1490 !context->getExtensions().disjointTimerQuery)
1491 {
Jamie Madill437fa652016-05-03 15:13:24 -04001492 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001493 return false;
1494 }
1495
Olli Etuaho41997e72016-03-10 13:38:39 +02001496 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001497}
1498
1499bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001500{
1501 if (!ValidQueryType(context, target))
1502 {
Jamie Madill437fa652016-05-03 15:13:24 -04001503 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04001504 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001505 }
1506
1507 if (id == 0)
1508 {
Jamie Madill437fa652016-05-03 15:13:24 -04001509 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04001510 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001511 }
1512
1513 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1514 // of zero, if the active query object name for <target> is non-zero (for the
1515 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1516 // the active query for either target is non-zero), if <id> is the name of an
1517 // existing query object whose type does not match <target>, or if <id> is the
1518 // active query object name for any query type, the error INVALID_OPERATION is
1519 // generated.
1520
1521 // Ensure no other queries are active
1522 // NOTE: If other queries than occlusion are supported, we will need to check
1523 // separately that:
1524 // a) The query ID passed is not the current active query for any target/type
1525 // b) There are no active queries for the requested target (and in the case
1526 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1527 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001528
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001529 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001530 {
Jamie Madill437fa652016-05-03 15:13:24 -04001531 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04001532 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001533 }
1534
1535 Query *queryObject = context->getQuery(id, true, target);
1536
1537 // check that name was obtained with glGenQueries
1538 if (!queryObject)
1539 {
Jamie Madill437fa652016-05-03 15:13:24 -04001540 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04001541 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001542 }
1543
1544 // check for type mismatch
1545 if (queryObject->getType() != target)
1546 {
Jamie Madill437fa652016-05-03 15:13:24 -04001547 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04001548 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001549 }
1550
1551 return true;
1552}
1553
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001554bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1555{
1556 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001557 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001558 {
Jamie Madill437fa652016-05-03 15:13:24 -04001559 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001560 return false;
1561 }
1562
1563 return ValidateBeginQueryBase(context, target, id);
1564}
1565
1566bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001567{
1568 if (!ValidQueryType(context, target))
1569 {
Jamie Madill437fa652016-05-03 15:13:24 -04001570 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04001571 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001572 }
1573
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001574 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001575
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001576 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001577 {
Jamie Madill437fa652016-05-03 15:13:24 -04001578 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04001579 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001580 }
1581
Jamie Madill45c785d2014-05-13 14:09:34 -04001582 return true;
1583}
1584
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001585bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1586{
1587 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001588 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001589 {
Jamie Madill437fa652016-05-03 15:13:24 -04001590 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001591 return false;
1592 }
1593
1594 return ValidateEndQueryBase(context, target);
1595}
1596
1597bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1598{
1599 if (!context->getExtensions().disjointTimerQuery)
1600 {
Jamie Madill437fa652016-05-03 15:13:24 -04001601 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001602 return false;
1603 }
1604
1605 if (target != GL_TIMESTAMP_EXT)
1606 {
Jamie Madill437fa652016-05-03 15:13:24 -04001607 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001608 return false;
1609 }
1610
1611 Query *queryObject = context->getQuery(id, true, target);
1612 if (queryObject == nullptr)
1613 {
Jamie Madill437fa652016-05-03 15:13:24 -04001614 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001615 return false;
1616 }
1617
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001618 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001619 {
Jamie Madill437fa652016-05-03 15:13:24 -04001620 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001621 return false;
1622 }
1623
1624 return true;
1625}
1626
1627bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname)
1628{
1629 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1630 {
Jamie Madill437fa652016-05-03 15:13:24 -04001631 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001632 return false;
1633 }
1634
1635 switch (pname)
1636 {
1637 case GL_CURRENT_QUERY_EXT:
1638 if (target == GL_TIMESTAMP_EXT)
1639 {
Jamie Madill437fa652016-05-03 15:13:24 -04001640 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001641 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
1642 return false;
1643 }
1644 break;
1645 case GL_QUERY_COUNTER_BITS_EXT:
1646 if (!context->getExtensions().disjointTimerQuery ||
1647 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1648 {
Jamie Madill437fa652016-05-03 15:13:24 -04001649 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001650 return false;
1651 }
1652 break;
1653 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001654 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001655 return false;
1656 }
1657
1658 return true;
1659}
1660
1661bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1662{
1663 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001664 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001665 {
Jamie Madill437fa652016-05-03 15:13:24 -04001666 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001667 return false;
1668 }
1669
1670 return ValidateGetQueryivBase(context, target, pname);
1671}
1672
1673bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname)
1674{
1675 Query *queryObject = context->getQuery(id, false, GL_NONE);
1676
1677 if (!queryObject)
1678 {
Jamie Madill437fa652016-05-03 15:13:24 -04001679 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001680 return false;
1681 }
1682
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001683 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001684 {
Jamie Madill437fa652016-05-03 15:13:24 -04001685 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001686 return false;
1687 }
1688
1689 switch (pname)
1690 {
1691 case GL_QUERY_RESULT_EXT:
1692 case GL_QUERY_RESULT_AVAILABLE_EXT:
1693 break;
1694
1695 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001696 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001697 return false;
1698 }
1699
1700 return true;
1701}
1702
1703bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1704{
1705 if (!context->getExtensions().disjointTimerQuery)
1706 {
Jamie Madill437fa652016-05-03 15:13:24 -04001707 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001708 return false;
1709 }
1710 return ValidateGetQueryObjectValueBase(context, id, pname);
1711}
1712
1713bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1714{
1715 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001716 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001717 {
Jamie Madill437fa652016-05-03 15:13:24 -04001718 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001719 return false;
1720 }
1721 return ValidateGetQueryObjectValueBase(context, id, pname);
1722}
1723
1724bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1725{
1726 if (!context->getExtensions().disjointTimerQuery)
1727 {
Jamie Madill437fa652016-05-03 15:13:24 -04001728 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001729 return false;
1730 }
1731 return ValidateGetQueryObjectValueBase(context, id, pname);
1732}
1733
1734bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1735{
1736 if (!context->getExtensions().disjointTimerQuery)
1737 {
Jamie Madill437fa652016-05-03 15:13:24 -04001738 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001739 return false;
1740 }
1741 return ValidateGetQueryObjectValueBase(context, id, pname);
1742}
1743
Jamie Madill62d31cb2015-09-11 13:25:51 -04001744static bool ValidateUniformCommonBase(gl::Context *context,
1745 GLenum targetUniformType,
1746 GLint location,
1747 GLsizei count,
1748 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001749{
1750 if (count < 0)
1751 {
Jamie Madill437fa652016-05-03 15:13:24 -04001752 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001753 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001754 }
1755
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001756 gl::Program *program = context->getGLState().getProgram();
Geoff Lang7dd2e102014-11-10 15:19:26 -05001757 if (!program)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001758 {
Jamie Madill437fa652016-05-03 15:13:24 -04001759 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001760 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001761 }
1762
Geoff Langd8605522016-04-13 10:19:12 -04001763 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001764 {
1765 // Silently ignore the uniform command
1766 return false;
1767 }
1768
Geoff Lang7dd2e102014-11-10 15:19:26 -05001769 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04001770 {
Jamie Madill437fa652016-05-03 15:13:24 -04001771 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001772 return false;
Jamie Madill36398922014-05-20 14:51:53 -04001773 }
1774
Jamie Madill62d31cb2015-09-11 13:25:51 -04001775 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04001776
1777 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04001778 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04001779 {
Jamie Madill437fa652016-05-03 15:13:24 -04001780 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001781 return false;
Jamie Madill36398922014-05-20 14:51:53 -04001782 }
1783
Jamie Madill62d31cb2015-09-11 13:25:51 -04001784 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001785 return true;
1786}
1787
Jamie Madillaa981bd2014-05-20 10:55:55 -04001788bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
1789{
1790 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03001791 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
1792 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04001793 {
Jamie Madill437fa652016-05-03 15:13:24 -04001794 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001795 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001796 }
1797
Jamie Madill62d31cb2015-09-11 13:25:51 -04001798 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04001799 if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
1800 {
1801 return false;
1802 }
1803
Jamie Madillf2575982014-06-25 16:04:54 -04001804 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05001805 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04001806 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
1807 {
Jamie Madill437fa652016-05-03 15:13:24 -04001808 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001809 return false;
Jamie Madill36398922014-05-20 14:51:53 -04001810 }
1811
1812 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001813}
1814
1815bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count,
1816 GLboolean transpose)
1817{
1818 // Check for ES3 uniform entry points
1819 int rows = VariableRowCount(matrixType);
1820 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03001821 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04001822 {
Jamie Madill437fa652016-05-03 15:13:24 -04001823 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001824 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001825 }
1826
Martin Radev1be913c2016-07-11 17:59:16 +03001827 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04001828 {
Jamie Madill437fa652016-05-03 15:13:24 -04001829 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001830 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001831 }
1832
Jamie Madill62d31cb2015-09-11 13:25:51 -04001833 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04001834 if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
1835 {
1836 return false;
1837 }
1838
1839 if (uniform->type != matrixType)
1840 {
Jamie Madill437fa652016-05-03 15:13:24 -04001841 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001842 return false;
Jamie Madill36398922014-05-20 14:51:53 -04001843 }
1844
1845 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001846}
1847
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001848bool ValidateStateQuery(ValidationContext *context,
1849 GLenum pname,
1850 GLenum *nativeType,
1851 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04001852{
1853 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
1854 {
Jamie Madill437fa652016-05-03 15:13:24 -04001855 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001856 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001857 }
1858
Jamie Madill0af26e12015-03-05 19:54:33 -05001859 const Caps &caps = context->getCaps();
1860
Jamie Madill893ab082014-05-16 16:56:10 -04001861 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
1862 {
1863 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
1864
Jamie Madill0af26e12015-03-05 19:54:33 -05001865 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04001866 {
Jamie Madill437fa652016-05-03 15:13:24 -04001867 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001868 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001869 }
1870 }
1871
1872 switch (pname)
1873 {
1874 case GL_TEXTURE_BINDING_2D:
1875 case GL_TEXTURE_BINDING_CUBE_MAP:
1876 case GL_TEXTURE_BINDING_3D:
1877 case GL_TEXTURE_BINDING_2D_ARRAY:
Jamie Madill893ab082014-05-16 16:56:10 -04001878 break;
Ian Ewell54f87462016-03-10 13:47:21 -05001879 case GL_TEXTURE_BINDING_EXTERNAL_OES:
John Bauman18319182016-09-28 14:22:27 -07001880 if (!context->getExtensions().eglStreamConsumerExternal &&
1881 !context->getExtensions().eglImageExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05001882 {
John Bauman18319182016-09-28 14:22:27 -07001883 context->handleError(Error(GL_INVALID_ENUM,
1884 "Neither NV_EGL_stream_consumer_external nor "
1885 "GL_OES_EGL_image_external extensions enabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05001886 return false;
1887 }
1888 break;
Jamie Madill893ab082014-05-16 16:56:10 -04001889
1890 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1891 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1892 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04001893 if (context->getGLState().getReadFramebuffer()->checkStatus(
1894 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04001895 {
Jamie Madill437fa652016-05-03 15:13:24 -04001896 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001897 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001898 }
1899
Jamie Madill51f40ec2016-06-15 14:06:00 -04001900 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
1901 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03001902
1903 if (framebuffer->getReadBufferState() == GL_NONE)
1904 {
1905 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
1906 return false;
1907 }
1908
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001909 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04001910 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04001911 {
Jamie Madill437fa652016-05-03 15:13:24 -04001912 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001913 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001914 }
1915 }
1916 break;
1917
1918 default:
1919 break;
1920 }
1921
1922 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04001923 if (*numParams == 0)
1924 {
1925 return false;
1926 }
1927
1928 return true;
1929}
1930
1931bool ValidateRobustStateQuery(ValidationContext *context,
1932 GLenum pname,
1933 GLsizei bufSize,
1934 GLenum *nativeType,
1935 unsigned int *numParams)
1936{
1937 if (!ValidateRobustEntryPoint(context, bufSize))
1938 {
1939 return false;
1940 }
1941
1942 if (!ValidateStateQuery(context, pname, nativeType, numParams))
1943 {
1944 return false;
1945 }
1946
1947 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04001948 {
1949 return false;
1950 }
1951
1952 return true;
1953}
1954
Jamie Madillc29968b2016-01-20 11:17:23 -05001955bool ValidateCopyTexImageParametersBase(ValidationContext *context,
1956 GLenum target,
1957 GLint level,
1958 GLenum internalformat,
1959 bool isSubImage,
1960 GLint xoffset,
1961 GLint yoffset,
1962 GLint zoffset,
1963 GLint x,
1964 GLint y,
1965 GLsizei width,
1966 GLsizei height,
1967 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04001968 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04001969{
Jamie Madill560a8d82014-05-21 13:06:20 -04001970 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
1971 {
Jamie Madill437fa652016-05-03 15:13:24 -04001972 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001973 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001974 }
1975
1976 if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1977 {
Jamie Madill437fa652016-05-03 15:13:24 -04001978 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001979 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001980 }
1981
1982 if (border != 0)
1983 {
Jamie Madill437fa652016-05-03 15:13:24 -04001984 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001985 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001986 }
1987
1988 if (!ValidMipLevel(context, target, level))
1989 {
Jamie Madill437fa652016-05-03 15:13:24 -04001990 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001991 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001992 }
1993
Jamie Madill51f40ec2016-06-15 14:06:00 -04001994 const auto &state = context->getGLState();
1995 auto readFramebuffer = state.getReadFramebuffer();
1996 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04001997 {
Jamie Madill437fa652016-05-03 15:13:24 -04001998 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001999 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002000 }
2001
Jamie Madill51f40ec2016-06-15 14:06:00 -04002002 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002003 {
Jamie Madill437fa652016-05-03 15:13:24 -04002004 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002005 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002006 }
2007
Martin Radev138064f2016-07-15 12:03:41 +03002008 if (readFramebuffer->getReadBufferState() == GL_NONE)
2009 {
2010 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2011 return false;
2012 }
2013
Geoff Langaae65a42014-05-26 12:43:44 -04002014 const gl::Caps &caps = context->getCaps();
2015
Geoff Langaae65a42014-05-26 12:43:44 -04002016 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002017 switch (target)
2018 {
2019 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002020 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002021 break;
2022
2023 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2024 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2025 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2026 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2027 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2028 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002029 maxDimension = caps.maxCubeMapTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002030 break;
2031
2032 case GL_TEXTURE_2D_ARRAY:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002033 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002034 break;
2035
2036 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002037 maxDimension = caps.max3DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002038 break;
2039
2040 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002041 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002042 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002043 }
2044
Jamie Madillc29968b2016-01-20 11:17:23 -05002045 gl::Texture *texture =
2046 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002047 if (!texture)
2048 {
Jamie Madill437fa652016-05-03 15:13:24 -04002049 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002050 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002051 }
2052
Geoff Lang69cce582015-09-17 13:20:36 -04002053 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002054 {
Jamie Madill437fa652016-05-03 15:13:24 -04002055 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002056 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002057 }
2058
Geoff Lang5d601382014-07-22 15:14:06 -04002059 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
2060
2061 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002062 {
Jamie Madill437fa652016-05-03 15:13:24 -04002063 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002064 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002065 }
2066
Geoff Langa9be0dc2014-12-17 12:34:40 -05002067 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04002068 {
Jamie Madill437fa652016-05-03 15:13:24 -04002069 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002070 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002071 }
2072
2073 if (isSubImage)
2074 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002075 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2076 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2077 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002078 {
Jamie Madill437fa652016-05-03 15:13:24 -04002079 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002080 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002081 }
2082 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002083 else
2084 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002085 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002086 {
Jamie Madill437fa652016-05-03 15:13:24 -04002087 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002088 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002089 }
2090
Martin Radev1be913c2016-07-11 17:59:16 +03002091 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002092 {
Jamie Madill437fa652016-05-03 15:13:24 -04002093 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002094 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002095 }
2096
2097 int maxLevelDimension = (maxDimension >> level);
2098 if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension)
2099 {
Jamie Madill437fa652016-05-03 15:13:24 -04002100 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002101 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002102 }
2103 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002104
Jamie Madill0c8abca2016-07-22 20:21:26 -04002105 if (textureFormatOut)
2106 {
2107 *textureFormatOut = texture->getFormat(target, level);
2108 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002109 return true;
2110}
2111
Jamie Madillf25855c2015-11-03 11:06:18 -05002112static bool ValidateDrawBase(ValidationContext *context,
2113 GLenum mode,
2114 GLsizei count,
2115 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002116{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002117 switch (mode)
2118 {
2119 case GL_POINTS:
2120 case GL_LINES:
2121 case GL_LINE_LOOP:
2122 case GL_LINE_STRIP:
2123 case GL_TRIANGLES:
2124 case GL_TRIANGLE_STRIP:
2125 case GL_TRIANGLE_FAN:
2126 break;
2127 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002128 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002129 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002130 }
2131
Jamie Madill250d33f2014-06-06 17:09:03 -04002132 if (count < 0)
2133 {
Jamie Madill437fa652016-05-03 15:13:24 -04002134 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002135 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002136 }
2137
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002138 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002139
Jamie Madill250d33f2014-06-06 17:09:03 -04002140 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002141 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002142 {
Jamie Madill437fa652016-05-03 15:13:24 -04002143 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002144 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002145 }
2146
Jamie Madill51f40ec2016-06-15 14:06:00 -04002147 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04002148 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04002149 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04002150 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
2151 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
2152 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
2153 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2154 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2155 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04002156 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04002157 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2158 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04002159 {
2160 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2161 // Section 6.10 of the WebGL 1.0 spec
2162 ERR(
2163 "This ANGLE implementation does not support separate front/back stencil "
2164 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04002165 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04002166 return false;
2167 }
Jamie Madillac528012014-06-20 13:21:23 -04002168 }
2169
Jamie Madill51f40ec2016-06-15 14:06:00 -04002170 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002171 {
Jamie Madill437fa652016-05-03 15:13:24 -04002172 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002173 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002174 }
2175
Geoff Lang7dd2e102014-11-10 15:19:26 -05002176 gl::Program *program = state.getProgram();
2177 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002178 {
Jamie Madill437fa652016-05-03 15:13:24 -04002179 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002180 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002181 }
2182
Geoff Lang7dd2e102014-11-10 15:19:26 -05002183 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002184 {
Jamie Madill437fa652016-05-03 15:13:24 -04002185 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002186 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002187 }
2188
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002189 // Uniform buffer validation
2190 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2191 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002192 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002193 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002194 const OffsetBindingPointer<Buffer> &uniformBuffer =
2195 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002196
Geoff Lang5d124a62015-09-15 13:03:27 -04002197 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002198 {
2199 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002200 context->handleError(
2201 Error(GL_INVALID_OPERATION,
2202 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002203 return false;
2204 }
2205
Geoff Lang5d124a62015-09-15 13:03:27 -04002206 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002207 if (uniformBufferSize == 0)
2208 {
2209 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002210 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002211 }
2212
Jamie Madill62d31cb2015-09-11 13:25:51 -04002213 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002214 {
2215 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002216 context->handleError(
2217 Error(GL_INVALID_OPERATION,
2218 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002219 return false;
2220 }
2221 }
2222
Jamie Madill250d33f2014-06-06 17:09:03 -04002223 // No-op if zero count
2224 return (count > 0);
2225}
2226
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002227bool ValidateDrawArrays(ValidationContext *context,
2228 GLenum mode,
2229 GLint first,
2230 GLsizei count,
2231 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002232{
Jamie Madillfd716582014-06-06 17:09:04 -04002233 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002234 {
Jamie Madill437fa652016-05-03 15:13:24 -04002235 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002236 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002237 }
2238
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002239 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002240 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04002241 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused() &&
2242 curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002243 {
2244 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
2245 // that does not match the current transform feedback object's draw mode (if transform feedback
2246 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002247 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002248 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002249 }
2250
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002251 if (!ValidateDrawBase(context, mode, count, primcount))
2252 {
2253 return false;
2254 }
2255
2256 if (!ValidateDrawAttribs(context, primcount, count))
Jamie Madillfd716582014-06-06 17:09:04 -04002257 {
2258 return false;
2259 }
2260
2261 return true;
2262}
2263
Geoff Langb1196682014-07-23 13:47:29 -04002264bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002265{
2266 if (primcount < 0)
2267 {
Jamie Madill437fa652016-05-03 15:13:24 -04002268 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002269 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002270 }
2271
Jamie Madill2b976812014-08-25 15:47:49 -04002272 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04002273 {
2274 return false;
2275 }
2276
2277 // No-op if zero primitive count
2278 return (primcount > 0);
2279}
2280
Geoff Lang87a93302014-09-16 13:29:43 -04002281static bool ValidateDrawInstancedANGLE(Context *context)
2282{
2283 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002284 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04002285
Geoff Lang7dd2e102014-11-10 15:19:26 -05002286 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04002287
2288 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04002289 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04002290 {
2291 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04002292 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04002293 {
2294 return true;
2295 }
2296 }
2297
Jamie Madill437fa652016-05-03 15:13:24 -04002298 context->handleError(Error(GL_INVALID_OPERATION,
2299 "ANGLE_instanced_arrays requires that at least one active attribute"
2300 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04002301 return false;
2302}
2303
2304bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
2305{
2306 if (!ValidateDrawInstancedANGLE(context))
2307 {
2308 return false;
2309 }
2310
2311 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
2312}
2313
Jamie Madillf25855c2015-11-03 11:06:18 -05002314bool ValidateDrawElements(ValidationContext *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04002315 GLenum mode,
2316 GLsizei count,
2317 GLenum type,
2318 const GLvoid *indices,
2319 GLsizei primcount,
2320 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04002321{
Jamie Madill250d33f2014-06-06 17:09:03 -04002322 switch (type)
2323 {
2324 case GL_UNSIGNED_BYTE:
2325 case GL_UNSIGNED_SHORT:
Martin Radev1be913c2016-07-11 17:59:16 +03002326 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04002327 case GL_UNSIGNED_INT:
Martin Radev1be913c2016-07-11 17:59:16 +03002328 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2329 {
2330 context->handleError(Error(GL_INVALID_ENUM));
2331 return false;
2332 }
2333 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04002334 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002335 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03002336 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002337 }
2338
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002339 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002340
2341 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04002342 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002343 {
2344 // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
2345 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002346 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002347 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002348 }
2349
2350 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002351 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002352 {
Jamie Madill437fa652016-05-03 15:13:24 -04002353 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002354 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002355 }
2356
Jamie Madill2b976812014-08-25 15:47:49 -04002357 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002358 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madill2b976812014-08-25 15:47:49 -04002359 if (!indices && !elementArrayBuffer)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002360 {
Jamie Madill437fa652016-05-03 15:13:24 -04002361 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002362 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002363 }
2364
Jamie Madillae3000b2014-08-25 15:47:51 -04002365 if (elementArrayBuffer)
2366 {
2367 const gl::Type &typeInfo = gl::GetTypeInfo(type);
2368
2369 GLint64 offset = reinterpret_cast<GLint64>(indices);
2370 GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset;
2371
2372 // check for integer overflows
2373 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
2374 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
2375 {
Jamie Madill437fa652016-05-03 15:13:24 -04002376 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04002377 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002378 }
2379
2380 // Check for reading past the end of the bound buffer object
2381 if (byteCount > elementArrayBuffer->getSize())
2382 {
Jamie Madill437fa652016-05-03 15:13:24 -04002383 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002384 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002385 }
2386 }
2387 else if (!indices)
2388 {
2389 // Catch this programming error here
Jamie Madill437fa652016-05-03 15:13:24 -04002390 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002391 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002392 }
2393
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002394 if (!ValidateDrawBase(context, mode, count, primcount))
2395 {
2396 return false;
2397 }
2398
Jamie Madill2b976812014-08-25 15:47:49 -04002399 // Use max index to validate if our vertex buffers are large enough for the pull.
2400 // TODO: offer fast path, with disabled index validation.
2401 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
2402 if (elementArrayBuffer)
2403 {
Jacek Cabana5521de2014-10-01 17:23:46 +02002404 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04002405 Error error =
2406 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
2407 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04002408 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04002409 {
Jamie Madill437fa652016-05-03 15:13:24 -04002410 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04002411 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04002412 }
2413 }
2414 else
2415 {
Geoff Lang3edfe032015-09-04 16:38:24 -04002416 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04002417 }
2418
Jamie Madille79b1e12015-11-04 16:36:37 -05002419 // If we use an index greater than our maximum supported index range, return an error.
2420 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2421 // return an error if possible here.
2422 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
2423 {
Jamie Madill437fa652016-05-03 15:13:24 -04002424 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05002425 return false;
2426 }
2427
Jamie Madillbc4c4bc2016-03-23 21:04:43 -04002428 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04002429 {
2430 return false;
2431 }
2432
Geoff Lang3edfe032015-09-04 16:38:24 -04002433 // No op if there are no real indices in the index data (all are primitive restart).
2434 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04002435}
2436
Geoff Langb1196682014-07-23 13:47:29 -04002437bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04002438 GLenum mode,
2439 GLsizei count,
2440 GLenum type,
2441 const GLvoid *indices,
2442 GLsizei primcount,
2443 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04002444{
2445 if (primcount < 0)
2446 {
Jamie Madill437fa652016-05-03 15:13:24 -04002447 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002448 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002449 }
2450
Jamie Madill2b976812014-08-25 15:47:49 -04002451 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04002452 {
2453 return false;
2454 }
2455
2456 // No-op zero primitive count
2457 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04002458}
2459
Geoff Lang3edfe032015-09-04 16:38:24 -04002460bool ValidateDrawElementsInstancedANGLE(Context *context,
2461 GLenum mode,
2462 GLsizei count,
2463 GLenum type,
2464 const GLvoid *indices,
2465 GLsizei primcount,
2466 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04002467{
2468 if (!ValidateDrawInstancedANGLE(context))
2469 {
2470 return false;
2471 }
2472
2473 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut);
2474}
2475
Geoff Langb1196682014-07-23 13:47:29 -04002476bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04002477 GLuint texture, GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002478{
Jamie Madill55ec3b12014-07-03 10:38:57 -04002479 if (!ValidFramebufferTarget(target))
2480 {
Jamie Madill437fa652016-05-03 15:13:24 -04002481 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002482 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002483 }
2484
2485 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002486 {
2487 return false;
2488 }
2489
Jamie Madill55ec3b12014-07-03 10:38:57 -04002490 if (texture != 0)
2491 {
2492 gl::Texture *tex = context->getTexture(texture);
2493
2494 if (tex == NULL)
2495 {
Jamie Madill437fa652016-05-03 15:13:24 -04002496 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002497 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002498 }
2499
2500 if (level < 0)
2501 {
Jamie Madill437fa652016-05-03 15:13:24 -04002502 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002503 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002504 }
2505 }
2506
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002507 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002508 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002509
Jamie Madill84115c92015-04-23 15:00:07 -04002510 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002511 {
Jamie Madill437fa652016-05-03 15:13:24 -04002512 context->handleError(
2513 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002514 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002515 }
2516
2517 return true;
2518}
2519
Geoff Langb1196682014-07-23 13:47:29 -04002520bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04002521 GLenum textarget, GLuint texture, GLint level)
2522{
Geoff Lang95663912015-04-02 15:54:45 -04002523 // 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 +03002524 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
2525 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002526 {
Jamie Madill437fa652016-05-03 15:13:24 -04002527 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002528 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002529 }
2530
2531 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04002532 {
2533 return false;
2534 }
2535
Jamie Madill55ec3b12014-07-03 10:38:57 -04002536 if (texture != 0)
2537 {
2538 gl::Texture *tex = context->getTexture(texture);
2539 ASSERT(tex);
2540
Jamie Madill2a6564e2014-07-11 09:53:19 -04002541 const gl::Caps &caps = context->getCaps();
2542
Jamie Madill55ec3b12014-07-03 10:38:57 -04002543 switch (textarget)
2544 {
2545 case GL_TEXTURE_2D:
2546 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04002547 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002548 {
Jamie Madill437fa652016-05-03 15:13:24 -04002549 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002550 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002551 }
2552 if (tex->getTarget() != GL_TEXTURE_2D)
2553 {
Jamie Madill437fa652016-05-03 15:13:24 -04002554 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002555 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002556 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002557 }
2558 break;
2559
2560 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2561 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2562 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2563 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2564 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2565 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2566 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04002567 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002568 {
Jamie Madill437fa652016-05-03 15:13:24 -04002569 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002570 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002571 }
2572 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
2573 {
Jamie Madill437fa652016-05-03 15:13:24 -04002574 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002575 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002576 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002577 }
2578 break;
2579
2580 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002581 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002582 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002583 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05002584
Jamie Madilla3944d42016-07-22 22:13:26 -04002585 const Format &format = tex->getFormat(textarget, level);
2586 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05002587 {
Jamie Madill437fa652016-05-03 15:13:24 -04002588 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002589 return false;
2590 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002591 }
2592
Jamie Madill570f7c82014-07-03 10:38:54 -04002593 return true;
2594}
2595
Geoff Langb1196682014-07-23 13:47:29 -04002596bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04002597{
2598 if (program == 0)
2599 {
Jamie Madill437fa652016-05-03 15:13:24 -04002600 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002601 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002602 }
2603
Dian Xiang769769a2015-09-09 15:20:08 -07002604 gl::Program *programObject = GetValidProgram(context, program);
2605 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05002606 {
2607 return false;
2608 }
2609
Jamie Madill0063c512014-08-25 15:47:53 -04002610 if (!programObject || !programObject->isLinked())
2611 {
Jamie Madill437fa652016-05-03 15:13:24 -04002612 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002613 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002614 }
2615
Geoff Lang7dd2e102014-11-10 15:19:26 -05002616 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04002617 {
Jamie Madill437fa652016-05-03 15:13:24 -04002618 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002619 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04002620 }
2621
Jamie Madill0063c512014-08-25 15:47:53 -04002622 return true;
2623}
2624
Geoff Langb1196682014-07-23 13:47:29 -04002625bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params)
Jamie Madill78f41802014-08-25 15:47:55 -04002626{
2627 return ValidateGetUniformBase(context, program, location);
2628}
2629
Geoff Langb1196682014-07-23 13:47:29 -04002630bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04002631{
Jamie Madill78f41802014-08-25 15:47:55 -04002632 return ValidateGetUniformBase(context, program, location);
2633}
2634
Geoff Langb1196682014-07-23 13:47:29 -04002635static bool ValidateSizedGetUniform(Context *context, GLuint program, GLint location, GLsizei bufSize)
Jamie Madill78f41802014-08-25 15:47:55 -04002636{
2637 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04002638 {
Jamie Madill78f41802014-08-25 15:47:55 -04002639 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002640 }
2641
Jamie Madilla502c742014-08-28 17:19:13 -04002642 gl::Program *programObject = context->getProgram(program);
2643 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04002644
Jamie Madill78f41802014-08-25 15:47:55 -04002645 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04002646 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
2647 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04002648 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04002649 {
Jamie Madill437fa652016-05-03 15:13:24 -04002650 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002651 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002652 }
2653
2654 return true;
2655}
2656
Geoff Langb1196682014-07-23 13:47:29 -04002657bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
Jamie Madill0063c512014-08-25 15:47:53 -04002658{
Jamie Madill78f41802014-08-25 15:47:55 -04002659 return ValidateSizedGetUniform(context, program, location, bufSize);
Jamie Madill0063c512014-08-25 15:47:53 -04002660}
2661
Geoff Langb1196682014-07-23 13:47:29 -04002662bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04002663{
Jamie Madill78f41802014-08-25 15:47:55 -04002664 return ValidateSizedGetUniform(context, program, location, bufSize);
Jamie Madill0063c512014-08-25 15:47:53 -04002665}
2666
Austin Kinross08332632015-05-05 13:35:47 -07002667bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
2668 const GLenum *attachments, bool defaultFramebuffer)
2669{
2670 if (numAttachments < 0)
2671 {
Jamie Madill437fa652016-05-03 15:13:24 -04002672 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07002673 return false;
2674 }
2675
2676 for (GLsizei i = 0; i < numAttachments; ++i)
2677 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02002678 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07002679 {
2680 if (defaultFramebuffer)
2681 {
Jamie Madill437fa652016-05-03 15:13:24 -04002682 context->handleError(Error(
2683 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07002684 return false;
2685 }
2686
2687 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
2688 {
Jamie Madill437fa652016-05-03 15:13:24 -04002689 context->handleError(Error(GL_INVALID_OPERATION,
2690 "Requested color attachment is greater than the maximum "
2691 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07002692 return false;
2693 }
2694 }
2695 else
2696 {
2697 switch (attachments[i])
2698 {
2699 case GL_DEPTH_ATTACHMENT:
2700 case GL_STENCIL_ATTACHMENT:
2701 case GL_DEPTH_STENCIL_ATTACHMENT:
2702 if (defaultFramebuffer)
2703 {
Jamie Madill437fa652016-05-03 15:13:24 -04002704 context->handleError(
2705 Error(GL_INVALID_ENUM,
2706 "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07002707 return false;
2708 }
2709 break;
2710 case GL_COLOR:
2711 case GL_DEPTH:
2712 case GL_STENCIL:
2713 if (!defaultFramebuffer)
2714 {
Jamie Madill437fa652016-05-03 15:13:24 -04002715 context->handleError(
2716 Error(GL_INVALID_ENUM,
2717 "Invalid attachment when the default framebuffer is not bound"));
Austin Kinross08332632015-05-05 13:35:47 -07002718 return false;
2719 }
2720 break;
2721 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002722 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07002723 return false;
2724 }
2725 }
2726 }
2727
2728 return true;
2729}
2730
Austin Kinross6ee1e782015-05-29 17:05:37 -07002731bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
2732{
2733 // Note that debug marker calls must not set error state
2734
2735 if (length < 0)
2736 {
2737 return false;
2738 }
2739
2740 if (marker == nullptr)
2741 {
2742 return false;
2743 }
2744
2745 return true;
2746}
2747
2748bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
2749{
2750 // Note that debug marker calls must not set error state
2751
2752 if (length < 0)
2753 {
2754 return false;
2755 }
2756
2757 if (length > 0 && marker == nullptr)
2758 {
2759 return false;
2760 }
2761
2762 return true;
2763}
2764
Geoff Langdcab33b2015-07-21 13:03:16 -04002765bool ValidateEGLImageTargetTexture2DOES(Context *context,
2766 egl::Display *display,
2767 GLenum target,
2768 egl::Image *image)
2769{
Geoff Langa8406172015-07-21 16:53:39 -04002770 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
2771 {
Jamie Madill437fa652016-05-03 15:13:24 -04002772 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04002773 return false;
2774 }
2775
2776 switch (target)
2777 {
2778 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04002779 if (!context->getExtensions().eglImage)
2780 {
2781 context->handleError(Error(
2782 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
2783 }
2784 break;
2785
2786 case GL_TEXTURE_EXTERNAL_OES:
2787 if (!context->getExtensions().eglImageExternal)
2788 {
2789 context->handleError(Error(
2790 GL_INVALID_ENUM,
2791 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
2792 }
Geoff Langa8406172015-07-21 16:53:39 -04002793 break;
2794
2795 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002796 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04002797 return false;
2798 }
2799
2800 if (!display->isValidImage(image))
2801 {
Jamie Madill437fa652016-05-03 15:13:24 -04002802 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04002803 return false;
2804 }
2805
2806 if (image->getSamples() > 0)
2807 {
Jamie Madill437fa652016-05-03 15:13:24 -04002808 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04002809 "cannot create a 2D texture from a multisampled EGL image."));
2810 return false;
2811 }
2812
Jamie Madilla3944d42016-07-22 22:13:26 -04002813 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04002814 if (!textureCaps.texturable)
2815 {
Jamie Madill437fa652016-05-03 15:13:24 -04002816 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04002817 "EGL image internal format is not supported as a texture."));
2818 return false;
2819 }
2820
Geoff Langdcab33b2015-07-21 13:03:16 -04002821 return true;
2822}
2823
2824bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
2825 egl::Display *display,
2826 GLenum target,
2827 egl::Image *image)
2828{
Geoff Langa8406172015-07-21 16:53:39 -04002829 if (!context->getExtensions().eglImage)
2830 {
Jamie Madill437fa652016-05-03 15:13:24 -04002831 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04002832 return false;
2833 }
2834
2835 switch (target)
2836 {
2837 case GL_RENDERBUFFER:
2838 break;
2839
2840 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002841 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04002842 return false;
2843 }
2844
2845 if (!display->isValidImage(image))
2846 {
Jamie Madill437fa652016-05-03 15:13:24 -04002847 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04002848 return false;
2849 }
2850
Jamie Madilla3944d42016-07-22 22:13:26 -04002851 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04002852 if (!textureCaps.renderable)
2853 {
Jamie Madill437fa652016-05-03 15:13:24 -04002854 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04002855 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
2856 return false;
2857 }
2858
Geoff Langdcab33b2015-07-21 13:03:16 -04002859 return true;
2860}
Austin Kinrossbc781f32015-10-26 09:27:38 -07002861
2862bool ValidateBindVertexArrayBase(Context *context, GLuint array)
2863{
Geoff Lang36167ab2015-12-07 10:27:14 -05002864 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07002865 {
2866 // The default VAO should always exist
2867 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04002868 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07002869 return false;
2870 }
2871
2872 return true;
2873}
2874
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002875bool ValidateLinkProgram(Context *context, GLuint program)
2876{
2877 if (context->hasActiveTransformFeedback(program))
2878 {
2879 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04002880 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002881 "Cannot link program while program is associated with an active "
2882 "transform feedback object."));
2883 return false;
2884 }
2885 return true;
2886}
2887
Geoff Langc5629752015-12-07 16:29:04 -05002888bool ValidateProgramBinaryBase(Context *context,
2889 GLuint program,
2890 GLenum binaryFormat,
2891 const void *binary,
2892 GLint length)
2893{
2894 Program *programObject = GetValidProgram(context, program);
2895 if (programObject == nullptr)
2896 {
2897 return false;
2898 }
2899
2900 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
2901 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
2902 programBinaryFormats.end())
2903 {
Jamie Madill437fa652016-05-03 15:13:24 -04002904 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05002905 return false;
2906 }
2907
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002908 if (context->hasActiveTransformFeedback(program))
2909 {
2910 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04002911 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002912 "Cannot change program binary while program is associated with "
2913 "an active transform feedback object."));
2914 return false;
2915 }
2916
Geoff Langc5629752015-12-07 16:29:04 -05002917 return true;
2918}
2919
2920bool ValidateGetProgramBinaryBase(Context *context,
2921 GLuint program,
2922 GLsizei bufSize,
2923 GLsizei *length,
2924 GLenum *binaryFormat,
2925 void *binary)
2926{
2927 Program *programObject = GetValidProgram(context, program);
2928 if (programObject == nullptr)
2929 {
2930 return false;
2931 }
2932
2933 if (!programObject->isLinked())
2934 {
Jamie Madill437fa652016-05-03 15:13:24 -04002935 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05002936 return false;
2937 }
2938
2939 return true;
2940}
Jamie Madillc29968b2016-01-20 11:17:23 -05002941
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002942bool ValidateUseProgram(Context *context, GLuint program)
2943{
2944 if (program != 0)
2945 {
2946 Program *programObject = context->getProgram(program);
2947 if (!programObject)
2948 {
2949 // ES 3.1.0 section 7.3 page 72
2950 if (context->getShader(program))
2951 {
Jamie Madill437fa652016-05-03 15:13:24 -04002952 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002953 Error(GL_INVALID_OPERATION,
2954 "Attempted to use a single shader instead of a shader program."));
2955 return false;
2956 }
2957 else
2958 {
Jamie Madill437fa652016-05-03 15:13:24 -04002959 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002960 return false;
2961 }
2962 }
2963 if (!programObject->isLinked())
2964 {
Jamie Madill437fa652016-05-03 15:13:24 -04002965 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002966 return false;
2967 }
2968 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002969 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002970 {
2971 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04002972 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002973 Error(GL_INVALID_OPERATION,
2974 "Cannot change active program while transform feedback is unpaused."));
2975 return false;
2976 }
2977
2978 return true;
2979}
2980
Jamie Madillc29968b2016-01-20 11:17:23 -05002981bool ValidateCopyTexImage2D(ValidationContext *context,
2982 GLenum target,
2983 GLint level,
2984 GLenum internalformat,
2985 GLint x,
2986 GLint y,
2987 GLsizei width,
2988 GLsizei height,
2989 GLint border)
2990{
Martin Radev1be913c2016-07-11 17:59:16 +03002991 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05002992 {
2993 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
2994 0, x, y, width, height, border);
2995 }
2996
Martin Radev1be913c2016-07-11 17:59:16 +03002997 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05002998 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
2999 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003000}
Jamie Madillc29968b2016-01-20 11:17:23 -05003001
3002bool ValidateFramebufferRenderbuffer(Context *context,
3003 GLenum target,
3004 GLenum attachment,
3005 GLenum renderbuffertarget,
3006 GLuint renderbuffer)
3007{
3008 if (!ValidFramebufferTarget(target) ||
3009 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
3010 {
Jamie Madill437fa652016-05-03 15:13:24 -04003011 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05003012 return false;
3013 }
3014
3015 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
3016 renderbuffertarget, renderbuffer);
3017}
3018
3019bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3020{
3021 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3022 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3023 {
Jamie Madill437fa652016-05-03 15:13:24 -04003024 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003025 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
3026 return false;
3027 }
3028
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003029 ASSERT(context->getGLState().getDrawFramebuffer());
3030 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003031 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3032
3033 // This should come first before the check for the default frame buffer
3034 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3035 // rather than INVALID_OPERATION
3036 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3037 {
3038 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3039
3040 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003041 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3042 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003043 {
3044 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003045 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3046 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3047 // 3.1 is still a bit ambiguous about the error, but future specs are
3048 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04003049 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02003050 return false;
3051 }
3052 else if (bufs[colorAttachment] >= maxColorAttachment)
3053 {
Jamie Madill437fa652016-05-03 15:13:24 -04003054 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02003055 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05003056 return false;
3057 }
3058 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3059 frameBufferId != 0)
3060 {
3061 // INVALID_OPERATION-GL is bound to buffer and ith argument
3062 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04003063 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003064 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
3065 return false;
3066 }
3067 }
3068
3069 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3070 // and n is not 1 or bufs is bound to value other than BACK and NONE
3071 if (frameBufferId == 0)
3072 {
3073 if (n != 1)
3074 {
Jamie Madill437fa652016-05-03 15:13:24 -04003075 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05003076 "n must be 1 when GL is bound to the default framebuffer"));
3077 return false;
3078 }
3079
3080 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3081 {
Jamie Madill437fa652016-05-03 15:13:24 -04003082 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05003083 GL_INVALID_OPERATION,
3084 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
3085 return false;
3086 }
3087 }
3088
3089 return true;
3090}
3091
3092bool ValidateCopyTexSubImage2D(Context *context,
3093 GLenum target,
3094 GLint level,
3095 GLint xoffset,
3096 GLint yoffset,
3097 GLint x,
3098 GLint y,
3099 GLsizei width,
3100 GLsizei height)
3101{
Martin Radev1be913c2016-07-11 17:59:16 +03003102 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003103 {
3104 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
3105 yoffset, x, y, width, height, 0);
3106 }
3107
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003108 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
3109 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05003110}
3111
Olli Etuaho4f667482016-03-30 15:56:35 +03003112bool ValidateGetBufferPointervBase(Context *context, GLenum target, GLenum pname, void **params)
3113{
3114 if (!ValidBufferTarget(context, target))
3115 {
Jamie Madill437fa652016-05-03 15:13:24 -04003116 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03003117 return false;
3118 }
3119
3120 if (pname != GL_BUFFER_MAP_POINTER)
3121 {
Jamie Madill437fa652016-05-03 15:13:24 -04003122 context->handleError(Error(GL_INVALID_ENUM, "pname not valid: 0x%X", pname));
Olli Etuaho4f667482016-03-30 15:56:35 +03003123 return false;
3124 }
3125
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003126 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003127
3128 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3129 // target bound to zero generate an INVALID_OPERATION error."
3130 // GLES 3.1 section 6.6 explicitly specifies this error.
3131 if (!buffer)
3132 {
Jamie Madill437fa652016-05-03 15:13:24 -04003133 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003134 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
3135 return false;
3136 }
3137
3138 return true;
3139}
3140
3141bool ValidateUnmapBufferBase(Context *context, GLenum target)
3142{
3143 if (!ValidBufferTarget(context, target))
3144 {
Jamie Madill437fa652016-05-03 15:13:24 -04003145 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003146 return false;
3147 }
3148
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003149 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003150
3151 if (buffer == nullptr || !buffer->isMapped())
3152 {
Jamie Madill437fa652016-05-03 15:13:24 -04003153 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003154 return false;
3155 }
3156
3157 return true;
3158}
3159
3160bool ValidateMapBufferRangeBase(Context *context,
3161 GLenum target,
3162 GLintptr offset,
3163 GLsizeiptr length,
3164 GLbitfield access)
3165{
3166 if (!ValidBufferTarget(context, target))
3167 {
Jamie Madill437fa652016-05-03 15:13:24 -04003168 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003169 return false;
3170 }
3171
3172 if (offset < 0 || length < 0)
3173 {
Jamie Madill437fa652016-05-03 15:13:24 -04003174 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003175 return false;
3176 }
3177
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003178 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003179
3180 if (!buffer)
3181 {
Jamie Madill437fa652016-05-03 15:13:24 -04003182 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003183 return false;
3184 }
3185
3186 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003187 CheckedNumeric<size_t> checkedOffset(offset);
3188 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003189
Jamie Madille2e406c2016-06-02 13:04:10 -04003190 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003191 {
Jamie Madill437fa652016-05-03 15:13:24 -04003192 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003193 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
3194 return false;
3195 }
3196
3197 // Check for invalid bits in the mask
3198 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3199 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3200 GL_MAP_UNSYNCHRONIZED_BIT;
3201
3202 if (access & ~(allAccessBits))
3203 {
Jamie Madill437fa652016-05-03 15:13:24 -04003204 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03003205 return false;
3206 }
3207
3208 if (length == 0)
3209 {
Jamie Madill437fa652016-05-03 15:13:24 -04003210 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003211 return false;
3212 }
3213
3214 if (buffer->isMapped())
3215 {
Jamie Madill437fa652016-05-03 15:13:24 -04003216 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003217 return false;
3218 }
3219
3220 // Check for invalid bit combinations
3221 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3222 {
Jamie Madill437fa652016-05-03 15:13:24 -04003223 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003224 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
3225 return false;
3226 }
3227
3228 GLbitfield writeOnlyBits =
3229 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3230
3231 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3232 {
Jamie Madill437fa652016-05-03 15:13:24 -04003233 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03003234 "Invalid access bits when mapping buffer for reading: 0x%X.",
3235 access));
3236 return false;
3237 }
3238
3239 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3240 {
Jamie Madill437fa652016-05-03 15:13:24 -04003241 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003242 GL_INVALID_OPERATION,
3243 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
3244 return false;
3245 }
3246 return true;
3247}
3248
3249bool ValidateFlushMappedBufferRangeBase(Context *context,
3250 GLenum target,
3251 GLintptr offset,
3252 GLsizeiptr length)
3253{
3254 if (offset < 0 || length < 0)
3255 {
Jamie Madill437fa652016-05-03 15:13:24 -04003256 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003257 return false;
3258 }
3259
3260 if (!ValidBufferTarget(context, target))
3261 {
Jamie Madill437fa652016-05-03 15:13:24 -04003262 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003263 return false;
3264 }
3265
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003266 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003267
3268 if (buffer == nullptr)
3269 {
Jamie Madill437fa652016-05-03 15:13:24 -04003270 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003271 return false;
3272 }
3273
3274 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3275 {
Jamie Madill437fa652016-05-03 15:13:24 -04003276 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003277 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
3278 return false;
3279 }
3280
3281 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003282 CheckedNumeric<size_t> checkedOffset(offset);
3283 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003284
Jamie Madille2e406c2016-06-02 13:04:10 -04003285 if (!checkedSize.IsValid() ||
3286 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003287 {
Jamie Madill437fa652016-05-03 15:13:24 -04003288 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003289 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
3290 return false;
3291 }
3292
3293 return true;
3294}
3295
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003296bool ValidateGenerateMipmap(Context *context, GLenum target)
3297{
3298 if (!ValidTextureTarget(context, target))
3299 {
3300 context->handleError(Error(GL_INVALID_ENUM));
3301 return false;
3302 }
3303
3304 Texture *texture = context->getTargetTexture(target);
3305
3306 if (texture == nullptr)
3307 {
3308 context->handleError(Error(GL_INVALID_OPERATION));
3309 return false;
3310 }
3311
3312 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
3313
3314 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
3315 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
3316 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
3317 {
3318 context->handleError(Error(GL_INVALID_OPERATION));
3319 return false;
3320 }
3321
Jamie Madilla3944d42016-07-22 22:13:26 -04003322 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
3323 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
3324 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003325
3326 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
3327 // unsized formats or that are color renderable and filterable. Since we do not track if
3328 // the texture was created with sized or unsized format (only sized formats are stored),
3329 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
3330 // be able to) because they aren't color renderable. Simply do a special case for LUMA
3331 // textures since they're the only texture format that can be created with unsized formats
3332 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
3333 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04003334 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
3335 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003336 {
3337 context->handleError(Error(GL_INVALID_OPERATION));
3338 return false;
3339 }
3340
3341 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04003342 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003343 {
3344 context->handleError(Error(GL_INVALID_OPERATION));
3345 return false;
3346 }
3347
3348 // Non-power of 2 ES2 check
3349 if (!context->getExtensions().textureNPOT &&
3350 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
3351 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
3352 {
Martin Radev1be913c2016-07-11 17:59:16 +03003353 ASSERT(context->getClientMajorVersion() <= 2 &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003354 (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
3355 context->handleError(Error(GL_INVALID_OPERATION));
3356 return false;
3357 }
3358
3359 // Cube completeness check
3360 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
3361 {
3362 context->handleError(Error(GL_INVALID_OPERATION));
3363 return false;
3364 }
3365
3366 return true;
3367}
3368
Olli Etuaho41997e72016-03-10 13:38:39 +02003369bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
3370{
3371 return ValidateGenOrDelete(context, n);
3372}
3373
3374bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
3375{
3376 return ValidateGenOrDelete(context, n);
3377}
3378
3379bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
3380{
3381 return ValidateGenOrDelete(context, n);
3382}
3383
3384bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
3385{
3386 return ValidateGenOrDelete(context, n);
3387}
3388
3389bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
3390{
3391 return ValidateGenOrDelete(context, n);
3392}
3393
3394bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
3395{
3396 return ValidateGenOrDelete(context, n);
3397}
3398
3399bool ValidateGenTextures(Context *context, GLint n, GLuint *)
3400{
3401 return ValidateGenOrDelete(context, n);
3402}
3403
3404bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
3405{
3406 return ValidateGenOrDelete(context, n);
3407}
3408
3409bool ValidateGenOrDelete(Context *context, GLint n)
3410{
3411 if (n < 0)
3412 {
Jamie Madill437fa652016-05-03 15:13:24 -04003413 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02003414 return false;
3415 }
3416 return true;
3417}
3418
Geoff Langf41a7152016-09-19 15:11:17 -04003419bool ValidateEnable(Context *context, GLenum cap)
3420{
3421 if (!ValidCap(context, cap, false))
3422 {
3423 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
3424 return false;
3425 }
3426
3427 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
3428 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
3429 {
3430 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
3431 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
3432
3433 // We also output an error message to the debugger window if tracing is active, so that
3434 // developers can see the error message.
3435 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04003436 return false;
3437 }
3438
3439 return true;
3440}
3441
3442bool ValidateDisable(Context *context, GLenum cap)
3443{
3444 if (!ValidCap(context, cap, false))
3445 {
3446 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
3447 return false;
3448 }
3449
3450 return true;
3451}
3452
3453bool ValidateIsEnabled(Context *context, GLenum cap)
3454{
3455 if (!ValidCap(context, cap, true))
3456 {
3457 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
3458 return false;
3459 }
3460
3461 return true;
3462}
3463
Geoff Langff5b2d52016-09-07 11:32:23 -04003464bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3465{
3466 if (!context->getExtensions().robustClientMemory)
3467 {
3468 context->handleError(
3469 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
3470 return false;
3471 }
3472
3473 if (bufSize < 0)
3474 {
3475 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3476 return false;
3477 }
3478
3479 return true;
3480}
3481
3482bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
3483 GLenum target,
3484 GLenum attachment,
3485 GLenum pname,
3486 GLsizei *numParams)
3487{
3488 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
3489 *numParams = 1;
3490
3491 if (!ValidFramebufferTarget(target))
3492 {
3493 context->handleError(Error(GL_INVALID_ENUM));
3494 return false;
3495 }
3496
3497 int clientVersion = context->getClientMajorVersion();
3498
3499 switch (pname)
3500 {
3501 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3502 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3503 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3504 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3505 break;
3506
3507 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3508 if (clientVersion < 3 && !context->getExtensions().sRGB)
3509 {
3510 context->handleError(Error(GL_INVALID_ENUM));
3511 return false;
3512 }
3513 break;
3514
3515 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3516 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3517 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3518 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3519 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3520 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3521 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3522 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3523 if (clientVersion < 3)
3524 {
3525 context->handleError(Error(GL_INVALID_ENUM));
3526 return false;
3527 }
3528 break;
3529
3530 default:
3531 context->handleError(Error(GL_INVALID_ENUM));
3532 return false;
3533 }
3534
3535 // Determine if the attachment is a valid enum
3536 switch (attachment)
3537 {
3538 case GL_BACK:
3539 case GL_FRONT:
3540 case GL_DEPTH:
3541 case GL_STENCIL:
3542 case GL_DEPTH_STENCIL_ATTACHMENT:
3543 if (clientVersion < 3)
3544 {
3545 context->handleError(Error(GL_INVALID_ENUM));
3546 return false;
3547 }
3548 break;
3549
3550 case GL_DEPTH_ATTACHMENT:
3551 case GL_STENCIL_ATTACHMENT:
3552 break;
3553
3554 default:
3555 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
3556 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3557 {
3558 context->handleError(Error(GL_INVALID_ENUM));
3559 return false;
3560 }
3561 break;
3562 }
3563
3564 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3565 ASSERT(framebuffer);
3566
3567 if (framebuffer->id() == 0)
3568 {
3569 if (clientVersion < 3)
3570 {
3571 context->handleError(Error(GL_INVALID_OPERATION));
3572 return false;
3573 }
3574
3575 switch (attachment)
3576 {
3577 case GL_BACK:
3578 case GL_DEPTH:
3579 case GL_STENCIL:
3580 break;
3581
3582 default:
3583 context->handleError(Error(GL_INVALID_OPERATION));
3584 return false;
3585 }
3586 }
3587 else
3588 {
3589 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3590 {
3591 // Valid attachment query
3592 }
3593 else
3594 {
3595 switch (attachment)
3596 {
3597 case GL_DEPTH_ATTACHMENT:
3598 case GL_STENCIL_ATTACHMENT:
3599 break;
3600
3601 case GL_DEPTH_STENCIL_ATTACHMENT:
3602 if (!framebuffer->hasValidDepthStencil())
3603 {
3604 context->handleError(Error(GL_INVALID_OPERATION));
3605 return false;
3606 }
3607 break;
3608
3609 default:
3610 context->handleError(Error(GL_INVALID_OPERATION));
3611 return false;
3612 }
3613 }
3614 }
3615
3616 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3617 if (attachmentObject)
3618 {
3619 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3620 attachmentObject->type() == GL_TEXTURE ||
3621 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3622
3623 switch (pname)
3624 {
3625 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3626 if (attachmentObject->type() != GL_RENDERBUFFER &&
3627 attachmentObject->type() != GL_TEXTURE)
3628 {
3629 context->handleError(Error(GL_INVALID_ENUM));
3630 return false;
3631 }
3632 break;
3633
3634 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3635 if (attachmentObject->type() != GL_TEXTURE)
3636 {
3637 context->handleError(Error(GL_INVALID_ENUM));
3638 return false;
3639 }
3640 break;
3641
3642 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3643 if (attachmentObject->type() != GL_TEXTURE)
3644 {
3645 context->handleError(Error(GL_INVALID_ENUM));
3646 return false;
3647 }
3648 break;
3649
3650 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3651 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3652 {
3653 context->handleError(Error(GL_INVALID_OPERATION));
3654 return false;
3655 }
3656 break;
3657
3658 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3659 if (attachmentObject->type() != GL_TEXTURE)
3660 {
3661 context->handleError(Error(GL_INVALID_ENUM));
3662 return false;
3663 }
3664 break;
3665
3666 default:
3667 break;
3668 }
3669 }
3670 else
3671 {
3672 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3673 // is NONE, then querying any other pname will generate INVALID_ENUM.
3674
3675 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3676 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3677 // INVALID_OPERATION for all other pnames
3678
3679 switch (pname)
3680 {
3681 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3682 break;
3683
3684 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3685 if (clientVersion < 3)
3686 {
3687 context->handleError(Error(GL_INVALID_ENUM));
3688 return false;
3689 }
3690 break;
3691
3692 default:
3693 if (clientVersion < 3)
3694 {
3695 context->handleError(Error(GL_INVALID_ENUM));
3696 return false;
3697 }
3698 else
3699 {
3700 context->handleError(Error(GL_INVALID_OPERATION));
3701 return false;
3702 }
3703 }
3704 }
3705
3706 return true;
3707}
3708
3709bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
3710 GLenum target,
3711 GLenum attachment,
3712 GLenum pname,
3713 GLsizei bufSize,
3714 GLsizei *numParams)
3715{
3716 if (!ValidateRobustEntryPoint(context, bufSize))
3717 {
3718 return false;
3719 }
3720
3721 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
3722 {
3723 return false;
3724 }
3725
3726 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
3727 {
3728 return false;
3729 }
3730
3731 return true;
3732}
3733
3734bool ValidateGetBufferParameteriv(ValidationContext *context,
3735 GLenum target,
3736 GLenum pname,
3737 GLsizei *numParams)
3738{
3739 // Initialize result
3740 *numParams = 0;
3741
3742 if (!ValidBufferTarget(context, target))
3743 {
3744 context->handleError(Error(GL_INVALID_ENUM));
3745 return false;
3746 }
3747
3748 if (!ValidBufferParameter(context, pname, numParams))
3749 {
3750 context->handleError(Error(GL_INVALID_ENUM));
3751 return false;
3752 }
3753
3754 if (context->getGLState().getTargetBuffer(target) == nullptr)
3755 {
3756 // A null buffer means that "0" is bound to the requested buffer target
3757 context->handleError(Error(GL_INVALID_OPERATION));
3758 return false;
3759 }
3760
3761 return true;
3762}
3763
3764bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
3765 GLenum target,
3766 GLenum pname,
3767 GLsizei bufSize,
3768 GLsizei *numParams)
3769{
3770 if (!ValidateRobustEntryPoint(context, bufSize))
3771 {
3772 return false;
3773 }
3774
3775 if (!ValidateGetBufferParameteriv(context, target, pname, numParams))
3776 {
3777 return false;
3778 }
3779
3780 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
3781 {
3782 return false;
3783 }
3784
3785 return true;
3786}
3787
3788bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
3789{
3790 // Currently, all GetProgramiv queries return 1 parameter
3791 *numParams = 1;
3792
3793 Program *programObject = GetValidProgram(context, program);
3794 if (!programObject)
3795 {
3796 return false;
3797 }
3798
3799 switch (pname)
3800 {
3801 case GL_DELETE_STATUS:
3802 case GL_LINK_STATUS:
3803 case GL_VALIDATE_STATUS:
3804 case GL_INFO_LOG_LENGTH:
3805 case GL_ATTACHED_SHADERS:
3806 case GL_ACTIVE_ATTRIBUTES:
3807 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
3808 case GL_ACTIVE_UNIFORMS:
3809 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
3810 break;
3811
3812 case GL_PROGRAM_BINARY_LENGTH:
3813 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
3814 {
3815 context->handleError(Error(GL_INVALID_ENUM,
3816 "Querying GL_PROGRAM_BINARY_LENGTH requires "
3817 "GL_OES_get_program_binary or ES 3.0."));
3818 return false;
3819 }
3820 break;
3821
3822 case GL_ACTIVE_UNIFORM_BLOCKS:
3823 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
3824 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
3825 case GL_TRANSFORM_FEEDBACK_VARYINGS:
3826 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
3827 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
3828 if (context->getClientMajorVersion() < 3)
3829 {
3830 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
3831 return false;
3832 }
3833 break;
3834
3835 default:
3836 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
3837 return false;
3838 }
3839
3840 return true;
3841}
3842
3843bool ValidateGetProgramivRobustANGLE(Context *context,
3844 GLuint program,
3845 GLenum pname,
3846 GLsizei bufSize,
3847 GLsizei *numParams)
3848{
3849 if (!ValidateRobustEntryPoint(context, bufSize))
3850 {
3851 return false;
3852 }
3853
3854 if (!ValidateGetProgramiv(context, program, pname, numParams))
3855 {
3856 return false;
3857 }
3858
3859 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
3860 {
3861 return false;
3862 }
3863
3864 return true;
3865}
3866
Geoff Lang740d9022016-10-07 11:20:52 -04003867bool ValidateGetRenderbufferParameteriv(Context *context,
3868 GLenum target,
3869 GLenum pname,
3870 GLint *params)
3871{
3872 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
3873}
3874
3875bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
3876 GLenum target,
3877 GLenum pname,
3878 GLsizei bufSize,
3879 GLsizei *length,
3880 GLint *params)
3881{
3882 if (!ValidateRobustEntryPoint(context, bufSize))
3883 {
3884 return false;
3885 }
3886
3887 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
3888 {
3889 return false;
3890 }
3891
3892 if (!ValidateRobustBufferSize(context, bufSize, *length))
3893 {
3894 return false;
3895 }
3896
3897 return true;
3898}
3899
Jamie Madillc29968b2016-01-20 11:17:23 -05003900} // namespace gl