blob: 20413f6c4cd0afa75e5c2c39d37998b350fbd267 [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{
Corentin Wallez92db6942016-12-09 13:10:36 -050037bool ValidateDrawAttribs(ValidationContext *context,
38 GLint primcount,
39 GLint maxVertex,
40 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040041{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070042 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040043 const gl::Program *program = state.getProgram();
44
Corentin Wallez327411e2016-12-09 11:09:17 -050045 bool webglCompatibility = context->getExtensions().webglCompatibility;
46
He Yunchaoced53ae2016-11-29 15:00:51 +080047 const VertexArray *vao = state.getVertexArray();
48 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080049 const auto &vertexBindings = vao->getVertexBindings();
He Yunchaoced53ae2016-11-29 15:00:51 +080050 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040051 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
52 {
53 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallezfd456442016-12-21 17:57:00 -050054 if (!program->isAttribLocationActive(attributeIndex) || !attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040055 {
Corentin Wallezfd456442016-12-21 17:57:00 -050056 continue;
57 }
Jamie Madill1ca74672015-07-21 15:14:11 -040058
Jiawei-Shao2597fb62016-12-09 16:38:02 +080059 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
Corentin Wallezfd456442016-12-21 17:57:00 -050060 // If we have no buffer, then we either get an error, or there are no more checks to be done.
Jiawei-Shao2597fb62016-12-09 16:38:02 +080061 gl::Buffer *buffer = binding.buffer.get();
Corentin Wallezfd456442016-12-21 17:57:00 -050062 if (!buffer)
63 {
Geoff Langfeb8c682017-02-13 16:07:35 -050064 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050065 {
66 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050067 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
68 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
69 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
70 // error.
Corentin Wallez327411e2016-12-09 11:09:17 -050071 context->handleError(
72 Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer."));
Corentin Wallezfd456442016-12-21 17:57:00 -050073 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050074 }
Corentin Wallezfd456442016-12-21 17:57:00 -050075 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040076 {
77 // This is an application error that would normally result in a crash,
78 // but we catch it and return an error
Corentin Wallezfd456442016-12-21 17:57:00 -050079 context->handleError(
80 Error(GL_INVALID_OPERATION,
81 "An enabled vertex array has no buffer and no pointer."));
Jamie Madill1ca74672015-07-21 15:14:11 -040082 return false;
83 }
Corentin Wallezfd456442016-12-21 17:57:00 -050084 continue;
85 }
86
87 // If we're drawing zero vertices, we have enough data.
88 if (vertexCount <= 0 || primcount <= 0)
89 {
90 continue;
91 }
92
93 GLint maxVertexElement = 0;
Jiawei-Shao2597fb62016-12-09 16:38:02 +080094 if (binding.divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -050095 {
96 maxVertexElement = maxVertex;
97 }
98 else
99 {
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800100 maxVertexElement = (primcount - 1) / binding.divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500101 }
102
103 // We do manual overflow checks here instead of using safe_math.h because it was
104 // a bottleneck. Thanks to some properties of GL we know inequalities that can
105 // help us make the overflow checks faster.
106
107 // The max possible attribSize is 16 for a vector of 4 32 bit values.
108 constexpr uint64_t kMaxAttribSize = 16;
109 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
110 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
111
112 // We know attribStride is given as a GLsizei which is typedefed to int.
113 // We also know an upper bound for attribSize.
114 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800115 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500116 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
117 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
118
119 // Computing the max offset using uint64_t without attrib.offset is overflow
120 // safe. Note: Last vertex element does not take the full stride!
121 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
122 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
123
124 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800125 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
126 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500127 {
128 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
129 return false;
130 }
131 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
132
133 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
134 // We can return INVALID_OPERATION if our vertex attribute does not have
135 // enough backing data.
136 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
137 {
138 context->handleError(Error(GL_INVALID_OPERATION,
139 "Vertex buffer is not big enough for the draw call"));
140 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400141 }
142 }
143
144 return true;
145}
146
Geoff Langf607c602016-09-21 11:46:48 -0400147bool ValidReadPixelsFormatType(ValidationContext *context,
148 GLenum framebufferComponentType,
149 GLenum format,
150 GLenum type)
151{
152 switch (framebufferComponentType)
153 {
154 case GL_UNSIGNED_NORMALIZED:
155 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
156 // ReadPixels with BGRA even if the extension is not present
157 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
158 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
159 type == GL_UNSIGNED_BYTE);
160
161 case GL_SIGNED_NORMALIZED:
162 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
163
164 case GL_INT:
165 return (format == GL_RGBA_INTEGER && type == GL_INT);
166
167 case GL_UNSIGNED_INT:
168 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
169
170 case GL_FLOAT:
171 return (format == GL_RGBA && type == GL_FLOAT);
172
173 default:
174 UNREACHABLE();
175 return false;
176 }
177}
178
Geoff Langf41a7152016-09-19 15:11:17 -0400179bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
Geoff Lang0550d032014-01-30 11:29:07 -0500180{
181 switch (cap)
182 {
Geoff Langf41a7152016-09-19 15:11:17 -0400183 // EXT_multisample_compatibility
184 case GL_MULTISAMPLE_EXT:
185 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
186 return context->getExtensions().multisampleCompatibility;
Sami Väisänen74c23472016-05-09 17:30:30 +0300187
Geoff Langf41a7152016-09-19 15:11:17 -0400188 case GL_CULL_FACE:
189 case GL_POLYGON_OFFSET_FILL:
190 case GL_SAMPLE_ALPHA_TO_COVERAGE:
191 case GL_SAMPLE_COVERAGE:
192 case GL_SCISSOR_TEST:
193 case GL_STENCIL_TEST:
194 case GL_DEPTH_TEST:
195 case GL_BLEND:
196 case GL_DITHER:
197 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -0500198
Geoff Langf41a7152016-09-19 15:11:17 -0400199 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
200 case GL_RASTERIZER_DISCARD:
201 return (context->getClientMajorVersion() >= 3);
Geoff Lang70d0f492015-12-10 17:45:46 -0500202
Geoff Langf41a7152016-09-19 15:11:17 -0400203 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
204 case GL_DEBUG_OUTPUT:
205 return context->getExtensions().debug;
Geoff Lang70d0f492015-12-10 17:45:46 -0500206
Geoff Langf41a7152016-09-19 15:11:17 -0400207 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
208 return queryOnly && context->getExtensions().bindGeneratesResource;
209
Geoff Langfeb8c682017-02-13 16:07:35 -0500210 case GL_CLIENT_ARRAYS_ANGLE:
211 return queryOnly && context->getExtensions().clientArrays;
212
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700213 case GL_FRAMEBUFFER_SRGB_EXT:
214 return context->getExtensions().sRGBWriteControl;
215
Geoff Lang3b573612016-10-31 14:08:10 -0400216 case GL_SAMPLE_MASK:
Geoff Lang3b573612016-10-31 14:08:10 -0400217 return context->getClientVersion() >= Version(3, 1);
218
Geoff Langf41a7152016-09-19 15:11:17 -0400219 default:
220 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500221 }
222}
223
Geoff Lang62fce5b2016-09-30 10:46:35 -0400224bool ValidateReadPixelsBase(ValidationContext *context,
225 GLint x,
226 GLint y,
227 GLsizei width,
228 GLsizei height,
229 GLenum format,
230 GLenum type,
231 GLsizei bufSize,
232 GLsizei *length,
233 GLvoid *pixels)
234{
235 if (length != nullptr)
236 {
237 *length = 0;
238 }
239
240 if (width < 0 || height < 0)
241 {
242 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
243 return false;
244 }
245
246 auto readFramebuffer = context->getGLState().getReadFramebuffer();
247
248 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
249 {
250 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
251 return false;
252 }
253
254 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
255 {
256 context->handleError(Error(GL_INVALID_OPERATION));
257 return false;
258 }
259
260 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
261 ASSERT(framebuffer);
262
263 if (framebuffer->getReadBufferState() == GL_NONE)
264 {
265 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
266 return false;
267 }
268
269 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500270 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
271 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
272 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
273 // situation is an application error that would lead to a crash in ANGLE.
274 if (readBuffer == nullptr)
Geoff Lang62fce5b2016-09-30 10:46:35 -0400275 {
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500276 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
Geoff Lang62fce5b2016-09-30 10:46:35 -0400277 return false;
278 }
279
280 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
281 GLenum currentType = framebuffer->getImplementationColorReadType();
282 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
283
284 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
285 bool validFormatTypeCombination =
286 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
287
288 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
289 {
290 context->handleError(Error(GL_INVALID_OPERATION));
291 return false;
292 }
293
294 // Check for pixel pack buffer related API errors
295 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
296 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
297 {
298 // ...the buffer object's data store is currently mapped.
299 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
300 return false;
301 }
302
303 // .. the data would be packed to the buffer object such that the memory writes required
304 // would exceed the data store size.
305 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
306 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
307 const gl::Extents size(width, height, 1);
308 const auto &pack = context->getGLState().getPackState();
309
310 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
311 if (endByteOrErr.isError())
312 {
313 context->handleError(endByteOrErr.getError());
314 return false;
315 }
316
317 size_t endByte = endByteOrErr.getResult();
318 if (bufSize >= 0)
319 {
320
321 if (static_cast<size_t>(bufSize) < endByte)
322 {
323 context->handleError(
324 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
325 return false;
326 }
327 }
328
329 if (pixelPackBuffer != nullptr)
330 {
331 CheckedNumeric<size_t> checkedEndByte(endByte);
332 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
333 checkedEndByte += checkedOffset;
334
335 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
336 {
337 // Overflow past the end of the buffer
338 context->handleError(
339 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
340 return false;
341 }
342 }
343
344 if (length != nullptr)
345 {
346 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
347 {
348 context->handleError(
349 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
350 return false;
351 }
352
353 *length = static_cast<GLsizei>(endByte);
354 }
355
356 return true;
357}
358
Geoff Lang740d9022016-10-07 11:20:52 -0400359bool ValidateGetRenderbufferParameterivBase(Context *context,
360 GLenum target,
361 GLenum pname,
362 GLsizei *length)
363{
364 if (length)
365 {
366 *length = 0;
367 }
368
369 if (target != GL_RENDERBUFFER)
370 {
371 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
372 return false;
373 }
374
375 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
376 if (renderbuffer == nullptr)
377 {
378 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
379 return false;
380 }
381
382 switch (pname)
383 {
384 case GL_RENDERBUFFER_WIDTH:
385 case GL_RENDERBUFFER_HEIGHT:
386 case GL_RENDERBUFFER_INTERNAL_FORMAT:
387 case GL_RENDERBUFFER_RED_SIZE:
388 case GL_RENDERBUFFER_GREEN_SIZE:
389 case GL_RENDERBUFFER_BLUE_SIZE:
390 case GL_RENDERBUFFER_ALPHA_SIZE:
391 case GL_RENDERBUFFER_DEPTH_SIZE:
392 case GL_RENDERBUFFER_STENCIL_SIZE:
393 break;
394
395 case GL_RENDERBUFFER_SAMPLES_ANGLE:
396 if (!context->getExtensions().framebufferMultisample)
397 {
398 context->handleError(
399 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
400 return false;
401 }
402 break;
403
404 default:
405 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
406 return false;
407 }
408
409 if (length)
410 {
411 *length = 1;
412 }
413 return true;
414}
415
Geoff Langd7d0ed32016-10-07 11:33:51 -0400416bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
417{
418 if (length)
419 {
420 *length = 0;
421 }
422
423 if (GetValidShader(context, shader) == nullptr)
424 {
425 return false;
426 }
427
428 switch (pname)
429 {
430 case GL_SHADER_TYPE:
431 case GL_DELETE_STATUS:
432 case GL_COMPILE_STATUS:
433 case GL_INFO_LOG_LENGTH:
434 case GL_SHADER_SOURCE_LENGTH:
435 break;
436
437 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
438 if (!context->getExtensions().translatedShaderSource)
439 {
440 context->handleError(
441 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
442 return false;
443 }
444 break;
445
446 default:
447 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
448 return false;
449 }
450
451 if (length)
452 {
453 *length = 1;
454 }
455 return true;
456}
457
Geoff Langc1984ed2016-10-07 12:41:00 -0400458bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
459{
460 if (length)
461 {
462 *length = 0;
463 }
464
465 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
466 {
467 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
468 return false;
469 }
470
471 if (context->getTargetTexture(target) == nullptr)
472 {
473 // Should only be possible for external textures
474 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
475 return false;
476 }
477
478 switch (pname)
479 {
480 case GL_TEXTURE_MAG_FILTER:
481 case GL_TEXTURE_MIN_FILTER:
482 case GL_TEXTURE_WRAP_S:
483 case GL_TEXTURE_WRAP_T:
484 break;
485
486 case GL_TEXTURE_USAGE_ANGLE:
487 if (!context->getExtensions().textureUsage)
488 {
489 context->handleError(
490 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
491 return false;
492 }
493 break;
494
495 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
496 if (!context->getExtensions().textureFilterAnisotropic)
497 {
498 context->handleError(
499 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
500 return false;
501 }
502 break;
503
504 case GL_TEXTURE_IMMUTABLE_FORMAT:
505 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
506 {
507 context->handleError(
508 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
509 return false;
510 }
511 break;
512
513 case GL_TEXTURE_WRAP_R:
514 case GL_TEXTURE_IMMUTABLE_LEVELS:
515 case GL_TEXTURE_SWIZZLE_R:
516 case GL_TEXTURE_SWIZZLE_G:
517 case GL_TEXTURE_SWIZZLE_B:
518 case GL_TEXTURE_SWIZZLE_A:
519 case GL_TEXTURE_BASE_LEVEL:
520 case GL_TEXTURE_MAX_LEVEL:
521 case GL_TEXTURE_MIN_LOD:
522 case GL_TEXTURE_MAX_LOD:
523 case GL_TEXTURE_COMPARE_MODE:
524 case GL_TEXTURE_COMPARE_FUNC:
525 if (context->getClientMajorVersion() < 3)
526 {
527 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
528 return false;
529 }
530 break;
531
Geoff Lang81c6b572016-10-19 14:07:52 -0700532 case GL_TEXTURE_SRGB_DECODE_EXT:
533 if (!context->getExtensions().textureSRGBDecode)
534 {
535 context->handleError(
536 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
537 return false;
538 }
539 break;
540
Geoff Langc1984ed2016-10-07 12:41:00 -0400541 default:
542 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
543 return false;
544 }
545
546 if (length)
547 {
548 *length = 1;
549 }
550 return true;
551}
552
553template <typename ParamType>
554bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
555{
556 switch (ConvertToGLenum(params[0]))
557 {
558 case GL_CLAMP_TO_EDGE:
559 break;
560
561 case GL_REPEAT:
562 case GL_MIRRORED_REPEAT:
563 if (isExternalTextureTarget)
564 {
565 // OES_EGL_image_external specifies this error.
566 context->handleError(Error(
567 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
568 return false;
569 }
570 break;
571
572 default:
573 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
574 return false;
575 }
576
577 return true;
578}
579
580template <typename ParamType>
581bool ValidateTextureMinFilterValue(Context *context,
582 ParamType *params,
583 bool isExternalTextureTarget)
584{
585 switch (ConvertToGLenum(params[0]))
586 {
587 case GL_NEAREST:
588 case GL_LINEAR:
589 break;
590
591 case GL_NEAREST_MIPMAP_NEAREST:
592 case GL_LINEAR_MIPMAP_NEAREST:
593 case GL_NEAREST_MIPMAP_LINEAR:
594 case GL_LINEAR_MIPMAP_LINEAR:
595 if (isExternalTextureTarget)
596 {
597 // OES_EGL_image_external specifies this error.
598 context->handleError(
599 Error(GL_INVALID_ENUM,
600 "external textures only support NEAREST and LINEAR filtering"));
601 return false;
602 }
603 break;
604
605 default:
606 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
607 return false;
608 }
609
610 return true;
611}
612
613template <typename ParamType>
614bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
615{
616 switch (ConvertToGLenum(params[0]))
617 {
618 case GL_NEAREST:
619 case GL_LINEAR:
620 break;
621
622 default:
623 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
624 return false;
625 }
626
627 return true;
628}
629
630template <typename ParamType>
631bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
632{
633 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
634 switch (ConvertToGLenum(params[0]))
635 {
636 case GL_NONE:
637 case GL_COMPARE_REF_TO_TEXTURE:
638 break;
639
640 default:
641 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
642 return false;
643 }
644
645 return true;
646}
647
648template <typename ParamType>
649bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
650{
651 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
652 switch (ConvertToGLenum(params[0]))
653 {
654 case GL_LEQUAL:
655 case GL_GEQUAL:
656 case GL_LESS:
657 case GL_GREATER:
658 case GL_EQUAL:
659 case GL_NOTEQUAL:
660 case GL_ALWAYS:
661 case GL_NEVER:
662 break;
663
664 default:
665 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
666 return false;
667 }
668
669 return true;
670}
671
672template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700673bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
674{
675 if (!context->getExtensions().textureSRGBDecode)
676 {
677 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
678 return false;
679 }
680
681 switch (ConvertToGLenum(params[0]))
682 {
683 case GL_DECODE_EXT:
684 case GL_SKIP_DECODE_EXT:
685 break;
686
687 default:
688 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
689 return false;
690 }
691
692 return true;
693}
694
695template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400696bool ValidateTexParameterBase(Context *context,
697 GLenum target,
698 GLenum pname,
699 GLsizei bufSize,
700 ParamType *params)
701{
702 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
703 {
704 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
705 return false;
706 }
707
708 if (context->getTargetTexture(target) == nullptr)
709 {
710 // Should only be possible for external textures
711 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
712 return false;
713 }
714
715 const GLsizei minBufSize = 1;
716 if (bufSize >= 0 && bufSize < minBufSize)
717 {
718 context->handleError(
719 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
720 return false;
721 }
722
723 switch (pname)
724 {
725 case GL_TEXTURE_WRAP_R:
726 case GL_TEXTURE_SWIZZLE_R:
727 case GL_TEXTURE_SWIZZLE_G:
728 case GL_TEXTURE_SWIZZLE_B:
729 case GL_TEXTURE_SWIZZLE_A:
730 case GL_TEXTURE_BASE_LEVEL:
731 case GL_TEXTURE_MAX_LEVEL:
732 case GL_TEXTURE_COMPARE_MODE:
733 case GL_TEXTURE_COMPARE_FUNC:
734 case GL_TEXTURE_MIN_LOD:
735 case GL_TEXTURE_MAX_LOD:
736 if (context->getClientMajorVersion() < 3)
737 {
738 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
739 return false;
740 }
741 if (target == GL_TEXTURE_EXTERNAL_OES &&
742 !context->getExtensions().eglImageExternalEssl3)
743 {
744 context->handleError(Error(GL_INVALID_ENUM,
745 "ES3 texture parameters are not available without "
746 "GL_OES_EGL_image_external_essl3."));
747 return false;
748 }
749 break;
750
751 default:
752 break;
753 }
754
755 switch (pname)
756 {
757 case GL_TEXTURE_WRAP_S:
758 case GL_TEXTURE_WRAP_T:
759 case GL_TEXTURE_WRAP_R:
760 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
761 {
762 return false;
763 }
764 break;
765
766 case GL_TEXTURE_MIN_FILTER:
767 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
768 {
769 return false;
770 }
771 break;
772
773 case GL_TEXTURE_MAG_FILTER:
774 if (!ValidateTextureMagFilterValue(context, params))
775 {
776 return false;
777 }
778 break;
779
780 case GL_TEXTURE_USAGE_ANGLE:
781 switch (ConvertToGLenum(params[0]))
782 {
783 case GL_NONE:
784 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
785 break;
786
787 default:
788 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
789 return false;
790 }
791 break;
792
793 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
794 if (!context->getExtensions().textureFilterAnisotropic)
795 {
796 context->handleError(
797 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
798 return false;
799 }
800
801 // we assume the parameter passed to this validation method is truncated, not rounded
802 if (params[0] < 1)
803 {
804 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
805 return false;
806 }
807 break;
808
809 case GL_TEXTURE_MIN_LOD:
810 case GL_TEXTURE_MAX_LOD:
811 // any value is permissible
812 break;
813
814 case GL_TEXTURE_COMPARE_MODE:
815 if (!ValidateTextureCompareModeValue(context, params))
816 {
817 return false;
818 }
819 break;
820
821 case GL_TEXTURE_COMPARE_FUNC:
822 if (!ValidateTextureCompareFuncValue(context, params))
823 {
824 return false;
825 }
826 break;
827
828 case GL_TEXTURE_SWIZZLE_R:
829 case GL_TEXTURE_SWIZZLE_G:
830 case GL_TEXTURE_SWIZZLE_B:
831 case GL_TEXTURE_SWIZZLE_A:
832 switch (ConvertToGLenum(params[0]))
833 {
834 case GL_RED:
835 case GL_GREEN:
836 case GL_BLUE:
837 case GL_ALPHA:
838 case GL_ZERO:
839 case GL_ONE:
840 break;
841
842 default:
843 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
844 return false;
845 }
846 break;
847
848 case GL_TEXTURE_BASE_LEVEL:
849 if (params[0] < 0)
850 {
851 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
852 return false;
853 }
854 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
855 {
856 context->handleError(
857 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
858 return false;
859 }
860 break;
861
862 case GL_TEXTURE_MAX_LEVEL:
863 if (params[0] < 0)
864 {
865 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
866 return false;
867 }
868 break;
869
Geoff Lang3b573612016-10-31 14:08:10 -0400870 case GL_DEPTH_STENCIL_TEXTURE_MODE:
871 if (context->getClientVersion() < Version(3, 1))
872 {
873 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
874 return false;
875 }
Geoff Lang9f090372016-12-02 10:20:43 -0500876 switch (ConvertToGLenum(params[0]))
877 {
878 case GL_DEPTH_COMPONENT:
879 case GL_STENCIL_INDEX:
880 break;
881
882 default:
883 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
884 return false;
885 }
Geoff Lang3b573612016-10-31 14:08:10 -0400886 break;
887
Geoff Lang81c6b572016-10-19 14:07:52 -0700888 case GL_TEXTURE_SRGB_DECODE_EXT:
889 if (!ValidateTextureSRGBDecodeValue(context, params))
890 {
891 return false;
892 }
893 break;
894
Geoff Langc1984ed2016-10-07 12:41:00 -0400895 default:
896 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
897 return false;
898 }
899
900 return true;
901}
902
903template <typename ParamType>
904bool ValidateSamplerParameterBase(Context *context,
905 GLuint sampler,
906 GLenum pname,
907 GLsizei bufSize,
908 ParamType *params)
909{
910 if (context->getClientMajorVersion() < 3)
911 {
912 context->handleError(
913 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
914 return false;
915 }
916
917 if (!context->isSampler(sampler))
918 {
919 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
920 return false;
921 }
922
923 const GLsizei minBufSize = 1;
924 if (bufSize >= 0 && bufSize < minBufSize)
925 {
926 context->handleError(
927 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
928 return false;
929 }
930
931 switch (pname)
932 {
933 case GL_TEXTURE_WRAP_S:
934 case GL_TEXTURE_WRAP_T:
935 case GL_TEXTURE_WRAP_R:
936 if (!ValidateTextureWrapModeValue(context, params, false))
937 {
938 return false;
939 }
940 break;
941
942 case GL_TEXTURE_MIN_FILTER:
943 if (!ValidateTextureMinFilterValue(context, params, false))
944 {
945 return false;
946 }
947 break;
948
949 case GL_TEXTURE_MAG_FILTER:
950 if (!ValidateTextureMagFilterValue(context, params))
951 {
952 return false;
953 }
954 break;
955
956 case GL_TEXTURE_MIN_LOD:
957 case GL_TEXTURE_MAX_LOD:
958 // any value is permissible
959 break;
960
961 case GL_TEXTURE_COMPARE_MODE:
962 if (!ValidateTextureCompareModeValue(context, params))
963 {
964 return false;
965 }
966 break;
967
968 case GL_TEXTURE_COMPARE_FUNC:
969 if (!ValidateTextureCompareFuncValue(context, params))
970 {
971 return false;
972 }
973 break;
974
Geoff Lang81c6b572016-10-19 14:07:52 -0700975 case GL_TEXTURE_SRGB_DECODE_EXT:
976 if (!ValidateTextureSRGBDecodeValue(context, params))
977 {
978 return false;
979 }
980 break;
981
Geoff Langc1984ed2016-10-07 12:41:00 -0400982 default:
983 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
984 return false;
985 }
986
987 return true;
988}
989
990bool ValidateGetSamplerParameterBase(Context *context,
991 GLuint sampler,
992 GLenum pname,
993 GLsizei *length)
994{
995 if (length)
996 {
997 *length = 0;
998 }
999
1000 if (context->getClientMajorVersion() < 3)
1001 {
1002 context->handleError(
1003 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1004 return false;
1005 }
1006
1007 if (!context->isSampler(sampler))
1008 {
1009 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
1010 return false;
1011 }
1012
1013 switch (pname)
1014 {
1015 case GL_TEXTURE_WRAP_S:
1016 case GL_TEXTURE_WRAP_T:
1017 case GL_TEXTURE_WRAP_R:
1018 case GL_TEXTURE_MIN_FILTER:
1019 case GL_TEXTURE_MAG_FILTER:
1020 case GL_TEXTURE_MIN_LOD:
1021 case GL_TEXTURE_MAX_LOD:
1022 case GL_TEXTURE_COMPARE_MODE:
1023 case GL_TEXTURE_COMPARE_FUNC:
1024 break;
1025
Geoff Lang81c6b572016-10-19 14:07:52 -07001026 case GL_TEXTURE_SRGB_DECODE_EXT:
1027 if (!context->getExtensions().textureSRGBDecode)
1028 {
1029 context->handleError(
1030 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
1031 return false;
1032 }
1033 break;
1034
Geoff Langc1984ed2016-10-07 12:41:00 -04001035 default:
1036 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1037 return false;
1038 }
1039
1040 if (length)
1041 {
1042 *length = 1;
1043 }
1044 return true;
1045}
1046
Geoff Lang0b031062016-10-13 14:30:04 -04001047bool ValidateGetVertexAttribBase(Context *context,
1048 GLuint index,
1049 GLenum pname,
1050 GLsizei *length,
1051 bool pointer,
1052 bool pureIntegerEntryPoint)
1053{
1054 if (length)
1055 {
1056 *length = 0;
1057 }
1058
1059 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
1060 {
1061 context->handleError(
1062 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1063 return false;
1064 }
1065
1066 if (index >= context->getCaps().maxVertexAttributes)
1067 {
1068 context->handleError(Error(
1069 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
1070 return false;
1071 }
1072
1073 if (pointer)
1074 {
1075 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1076 {
1077 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1078 return false;
1079 }
1080 }
1081 else
1082 {
1083 switch (pname)
1084 {
1085 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1086 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1087 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1088 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1089 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1090 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1091 case GL_CURRENT_VERTEX_ATTRIB:
1092 break;
1093
1094 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1095 static_assert(
1096 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1097 "ANGLE extension enums not equal to GL enums.");
1098 if (context->getClientMajorVersion() < 3 &&
1099 !context->getExtensions().instancedArrays)
1100 {
1101 context->handleError(Error(GL_INVALID_ENUM,
1102 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1103 "3.0 or GL_ANGLE_instanced_arrays."));
1104 return false;
1105 }
1106 break;
1107
1108 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1109 if (context->getClientMajorVersion() < 3)
1110 {
1111 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
1112 return false;
1113 }
1114 break;
1115
1116 default:
1117 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1118 return false;
1119 }
1120 }
1121
1122 if (length)
1123 {
1124 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1125 {
1126 *length = 4;
1127 }
1128 else
1129 {
1130 *length = 1;
1131 }
1132 }
1133
1134 return true;
1135}
1136
Geoff Lang6899b872016-10-14 11:30:13 -04001137bool ValidateGetActiveUniformBlockivBase(Context *context,
1138 GLuint program,
1139 GLuint uniformBlockIndex,
1140 GLenum pname,
1141 GLsizei *length)
1142{
1143 if (length)
1144 {
1145 *length = 0;
1146 }
1147
1148 if (context->getClientMajorVersion() < 3)
1149 {
1150 context->handleError(
1151 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1152 return false;
1153 }
1154
1155 Program *programObject = GetValidProgram(context, program);
1156 if (!programObject)
1157 {
1158 return false;
1159 }
1160
1161 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1162 {
1163 context->handleError(
1164 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1165 return false;
1166 }
1167
1168 switch (pname)
1169 {
1170 case GL_UNIFORM_BLOCK_BINDING:
1171 case GL_UNIFORM_BLOCK_DATA_SIZE:
1172 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1173 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1174 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1175 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1176 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1177 break;
1178
1179 default:
1180 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1181 return false;
1182 }
1183
1184 if (length)
1185 {
1186 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1187 {
1188 const UniformBlock &uniformBlock =
1189 programObject->getUniformBlockByIndex(uniformBlockIndex);
1190 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1191 }
1192 else
1193 {
1194 *length = 1;
1195 }
1196 }
1197
1198 return true;
1199}
1200
Geoff Langebebe1c2016-10-14 12:01:31 -04001201bool ValidateGetBufferParameterBase(ValidationContext *context,
1202 GLenum target,
1203 GLenum pname,
1204 bool pointerVersion,
1205 GLsizei *numParams)
1206{
1207 if (numParams)
1208 {
1209 *numParams = 0;
1210 }
1211
1212 if (!ValidBufferTarget(context, target))
1213 {
1214 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1215 return false;
1216 }
1217
1218 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1219 if (!buffer)
1220 {
1221 // A null buffer means that "0" is bound to the requested buffer target
1222 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1223 return false;
1224 }
1225
1226 const Extensions &extensions = context->getExtensions();
1227
1228 switch (pname)
1229 {
1230 case GL_BUFFER_USAGE:
1231 case GL_BUFFER_SIZE:
1232 break;
1233
1234 case GL_BUFFER_ACCESS_OES:
1235 if (!extensions.mapBuffer)
1236 {
1237 context->handleError(
Jamie Madillcc6ac252017-01-25 12:57:21 -08001238 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer."));
Geoff Langebebe1c2016-10-14 12:01:31 -04001239 return false;
1240 }
1241 break;
1242
1243 case GL_BUFFER_MAPPED:
1244 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1245 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1246 !extensions.mapBufferRange)
1247 {
1248 context->handleError(Error(
1249 GL_INVALID_ENUM,
Jamie Madillcc6ac252017-01-25 12:57:21 -08001250 "pname requires OpenGL ES 3.0, GL_OES_mapbuffer or GL_EXT_map_buffer_range."));
Geoff Langebebe1c2016-10-14 12:01:31 -04001251 return false;
1252 }
1253 break;
1254
1255 case GL_BUFFER_MAP_POINTER:
1256 if (!pointerVersion)
1257 {
1258 context->handleError(
1259 Error(GL_INVALID_ENUM,
1260 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1261 return false;
1262 }
1263 break;
1264
1265 case GL_BUFFER_ACCESS_FLAGS:
1266 case GL_BUFFER_MAP_OFFSET:
1267 case GL_BUFFER_MAP_LENGTH:
1268 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1269 {
1270 context->handleError(Error(
1271 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1272 return false;
1273 }
1274 break;
1275
1276 default:
1277 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1278 return false;
1279 }
1280
1281 // All buffer parameter queries return one value.
1282 if (numParams)
1283 {
1284 *numParams = 1;
1285 }
1286
1287 return true;
1288}
1289
Geoff Lang0a9661f2016-10-20 10:59:20 -07001290bool ValidateGetInternalFormativBase(Context *context,
1291 GLenum target,
1292 GLenum internalformat,
1293 GLenum pname,
1294 GLsizei bufSize,
1295 GLsizei *numParams)
1296{
1297 if (numParams)
1298 {
1299 *numParams = 0;
1300 }
1301
1302 if (context->getClientMajorVersion() < 3)
1303 {
1304 context->handleError(
1305 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1306 return false;
1307 }
1308
1309 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1310 if (!formatCaps.renderable)
1311 {
1312 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1313 return false;
1314 }
1315
1316 switch (target)
1317 {
1318 case GL_RENDERBUFFER:
1319 break;
1320
JiangYizhoubddc46b2016-12-09 09:50:51 +08001321 case GL_TEXTURE_2D_MULTISAMPLE:
1322 if (context->getClientVersion() < ES_3_1)
1323 {
1324 context->handleError(
1325 Error(GL_INVALID_OPERATION, "Texture target requires at least OpenGL ES 3.1."));
1326 return false;
1327 }
1328 break;
1329
Geoff Lang0a9661f2016-10-20 10:59:20 -07001330 default:
1331 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1332 return false;
1333 }
1334
1335 if (bufSize < 0)
1336 {
1337 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1338 return false;
1339 }
1340
1341 GLsizei maxWriteParams = 0;
1342 switch (pname)
1343 {
1344 case GL_NUM_SAMPLE_COUNTS:
1345 maxWriteParams = 1;
1346 break;
1347
1348 case GL_SAMPLES:
1349 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1350 break;
1351
1352 default:
1353 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1354 return false;
1355 }
1356
1357 if (numParams)
1358 {
1359 // glGetInternalFormativ will not overflow bufSize
1360 *numParams = std::min(bufSize, maxWriteParams);
1361 }
1362
1363 return true;
1364}
1365
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001366bool ValidateUniformCommonBase(gl::Context *context,
1367 gl::Program *program,
1368 GLint location,
1369 GLsizei count,
1370 const LinkedUniform **uniformOut)
1371{
1372 // TODO(Jiajia): Add image uniform check in future.
1373 if (count < 0)
1374 {
1375 context->handleError(Error(GL_INVALID_VALUE));
1376 return false;
1377 }
1378
1379 if (!program || !program->isLinked())
1380 {
1381 context->handleError(Error(GL_INVALID_OPERATION));
1382 return false;
1383 }
1384
1385 if (location == -1)
1386 {
1387 // Silently ignore the uniform command
1388 return false;
1389 }
1390
1391 const auto &uniformLocations = program->getUniformLocations();
1392 size_t castedLocation = static_cast<size_t>(location);
1393 if (castedLocation >= uniformLocations.size())
1394 {
1395 context->handleError(Error(GL_INVALID_OPERATION, "Invalid uniform location"));
1396 return false;
1397 }
1398
1399 const auto &uniformLocation = uniformLocations[castedLocation];
1400 if (uniformLocation.ignored)
1401 {
1402 // Silently ignore the uniform command
1403 return false;
1404 }
1405
1406 if (!uniformLocation.used)
1407 {
1408 context->handleError(Error(GL_INVALID_OPERATION));
1409 return false;
1410 }
1411
1412 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
1413
1414 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
1415 if (!uniform.isArray() && count > 1)
1416 {
1417 context->handleError(Error(GL_INVALID_OPERATION));
1418 return false;
1419 }
1420
1421 *uniformOut = &uniform;
1422 return true;
1423}
1424
Frank Henigman999b0fd2017-02-02 21:45:55 -05001425bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -05001426 GLenum uniformType,
1427 GLsizei count,
1428 const GLint *value)
1429{
1430 // Value type is GL_INT, because we only get here from glUniform1i{v}.
1431 // It is compatible with INT or BOOL.
1432 // Do these cheap tests first, for a little extra speed.
1433 if (GL_INT == uniformType || GL_BOOL == uniformType)
1434 {
1435 return true;
1436 }
1437
1438 if (IsSamplerType(uniformType))
1439 {
Frank Henigman999b0fd2017-02-02 21:45:55 -05001440 // Check that the values are in range.
1441 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
1442 for (GLsizei i = 0; i < count; ++i)
1443 {
1444 if (value[i] < 0 || value[i] >= max)
1445 {
1446 context->handleError(Error(GL_INVALID_VALUE, "sampler uniform value out of range"));
1447 return false;
1448 }
1449 }
Frank Henigmana98a6472017-02-02 21:38:32 -05001450 return true;
1451 }
1452
1453 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1454 return false;
1455}
1456
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001457bool ValidateUniformValue(gl::Context *context, GLenum valueType, GLenum uniformType)
1458{
1459 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -05001460 // Do the cheaper test first, for a little extra speed.
1461 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001462 {
1463 return true;
1464 }
1465
1466 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1467 return false;
1468}
1469
1470bool ValidateUniformMatrixValue(gl::Context *context, GLenum valueType, GLenum uniformType)
1471{
1472 // Check that the value type is compatible with uniform type.
1473 if (valueType == uniformType)
1474 {
1475 return true;
1476 }
1477
1478 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1479 return false;
1480}
1481
Geoff Langf41a7152016-09-19 15:11:17 -04001482} // anonymous namespace
1483
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001484bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001485{
Jamie Madilld7460c72014-01-21 16:38:14 -05001486 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001487 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001488 case GL_TEXTURE_2D:
1489 case GL_TEXTURE_CUBE_MAP:
1490 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001491
He Yunchaoced53ae2016-11-29 15:00:51 +08001492 case GL_TEXTURE_3D:
1493 case GL_TEXTURE_2D_ARRAY:
1494 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001495
He Yunchaoced53ae2016-11-29 15:00:51 +08001496 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001497 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001498
He Yunchaoced53ae2016-11-29 15:00:51 +08001499 default:
1500 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001501 }
Jamie Madill35d15012013-10-07 10:46:37 -04001502}
1503
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001504bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1505{
1506 switch (target)
1507 {
1508 case GL_TEXTURE_2D:
1509 case GL_TEXTURE_CUBE_MAP:
1510 return true;
1511
1512 default:
1513 return false;
1514 }
1515}
1516
1517bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1518{
1519 switch (target)
1520 {
1521 case GL_TEXTURE_3D:
1522 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001523 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001524
1525 default:
1526 return false;
1527 }
1528}
1529
Ian Ewellbda75592016-04-18 17:25:54 -04001530// Most texture GL calls are not compatible with external textures, so we have a separate validation
1531// function for use in the GL calls that do
1532bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1533{
1534 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1535 (context->getExtensions().eglImageExternal ||
1536 context->getExtensions().eglStreamConsumerExternal);
1537}
1538
Shannon Woods4dfed832014-03-17 20:03:39 -04001539// This function differs from ValidTextureTarget in that the target must be
1540// usable as the destination of a 2D operation-- so a cube face is valid, but
1541// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001542// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001543bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001544{
1545 switch (target)
1546 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001547 case GL_TEXTURE_2D:
1548 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1549 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1550 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1551 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1552 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1553 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1554 return true;
1555 default:
1556 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001557 }
1558}
1559
1560bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1561{
1562 switch (target)
1563 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001564 case GL_TEXTURE_3D:
1565 case GL_TEXTURE_2D_ARRAY:
1566 return true;
1567 default:
1568 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001569 }
1570}
1571
He Yunchao11b038b2016-11-22 21:24:04 +08001572bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
1573{
1574 switch (target)
1575 {
1576 case GL_TEXTURE_2D:
1577 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1578 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1579 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1580 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1581 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1582 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1583 case GL_TEXTURE_3D:
1584 case GL_TEXTURE_2D_ARRAY:
1585 case GL_TEXTURE_2D_MULTISAMPLE:
1586 return true;
1587 default:
1588 return false;
1589 }
1590}
1591
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001592bool ValidFramebufferTarget(GLenum target)
1593{
He Yunchaoced53ae2016-11-29 15:00:51 +08001594 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1595 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001596 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001597
1598 switch (target)
1599 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001600 case GL_FRAMEBUFFER:
1601 return true;
1602 case GL_READ_FRAMEBUFFER:
1603 return true;
1604 case GL_DRAW_FRAMEBUFFER:
1605 return true;
1606 default:
1607 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001608 }
1609}
1610
Jamie Madill29639852016-09-02 15:00:09 -04001611bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001612{
1613 switch (target)
1614 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001615 case GL_ARRAY_BUFFER:
1616 case GL_ELEMENT_ARRAY_BUFFER:
1617 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001618
He Yunchaoced53ae2016-11-29 15:00:51 +08001619 case GL_PIXEL_PACK_BUFFER:
1620 case GL_PIXEL_UNPACK_BUFFER:
1621 return (context->getExtensions().pixelBufferObject ||
1622 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001623
He Yunchaoced53ae2016-11-29 15:00:51 +08001624 case GL_COPY_READ_BUFFER:
1625 case GL_COPY_WRITE_BUFFER:
1626 case GL_TRANSFORM_FEEDBACK_BUFFER:
1627 case GL_UNIFORM_BUFFER:
1628 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001629
He Yunchaoced53ae2016-11-29 15:00:51 +08001630 case GL_ATOMIC_COUNTER_BUFFER:
1631 case GL_SHADER_STORAGE_BUFFER:
1632 case GL_DRAW_INDIRECT_BUFFER:
1633 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001634 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001635
He Yunchaoced53ae2016-11-29 15:00:51 +08001636 default:
1637 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001638 }
1639}
1640
Jamie Madillc29968b2016-01-20 11:17:23 -05001641bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001642{
Jamie Madillc29968b2016-01-20 11:17:23 -05001643 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001644 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001645 switch (target)
1646 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001647 case GL_TEXTURE_2D:
1648 maxDimension = caps.max2DTextureSize;
1649 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001650 case GL_TEXTURE_CUBE_MAP:
1651 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1652 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1653 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1654 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1655 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1656 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1657 maxDimension = caps.maxCubeMapTextureSize;
1658 break;
1659 case GL_TEXTURE_3D:
1660 maxDimension = caps.max3DTextureSize;
1661 break;
1662 case GL_TEXTURE_2D_ARRAY:
1663 maxDimension = caps.max2DTextureSize;
1664 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001665 case GL_TEXTURE_2D_MULTISAMPLE:
1666 maxDimension = caps.max2DTextureSize;
1667 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001668 default:
1669 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001670 }
1671
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001672 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001673}
1674
Geoff Langcc507aa2016-12-12 10:09:52 -05001675bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001676 GLenum target,
1677 GLint level,
1678 GLsizei width,
1679 GLsizei height,
1680 GLsizei depth,
1681 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001682{
1683 if (level < 0 || width < 0 || height < 0 || depth < 0)
1684 {
1685 return false;
1686 }
1687
Austin Kinross08528e12015-10-07 16:24:40 -07001688 // TexSubImage parameters can be NPOT without textureNPOT extension,
1689 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001690 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001691 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001692 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001693 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001694 {
1695 return false;
1696 }
1697
1698 if (!ValidMipLevel(context, target, level))
1699 {
1700 return false;
1701 }
1702
1703 return true;
1704}
1705
Geoff Lang0d8b7242015-09-09 14:56:53 -04001706bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1707{
1708 // List of compressed format that require that the texture size is smaller than or a multiple of
1709 // the compressed block size.
1710 switch (internalFormat)
1711 {
1712 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1713 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1714 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1715 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001716 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001717 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1718 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1719 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1720 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1721 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
1722 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001723 return true;
1724
1725 default:
1726 return false;
1727 }
1728}
1729
Jamie Madillc29968b2016-01-20 11:17:23 -05001730bool ValidCompressedImageSize(const ValidationContext *context,
1731 GLenum internalFormat,
Geoff Lang44ff5a72017-02-03 15:15:43 -05001732 GLint xoffset,
1733 GLint yoffset,
Jamie Madillc29968b2016-01-20 11:17:23 -05001734 GLsizei width,
1735 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001736{
Geoff Lang5d601382014-07-22 15:14:06 -04001737 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1738 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001739 {
1740 return false;
1741 }
1742
Geoff Lang44ff5a72017-02-03 15:15:43 -05001743 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001744 {
1745 return false;
1746 }
1747
Geoff Lang0d8b7242015-09-09 14:56:53 -04001748 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1749 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05001750 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
1751 yoffset % formatInfo.compressedBlockHeight != 0 ||
1752 (static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
Geoff Lang0d8b7242015-09-09 14:56:53 -04001753 width % formatInfo.compressedBlockWidth != 0) ||
1754 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1755 height % formatInfo.compressedBlockHeight != 0))
1756 {
1757 return false;
1758 }
1759 }
1760
Geoff Langd4f180b2013-09-24 13:57:44 -04001761 return true;
1762}
1763
Geoff Langff5b2d52016-09-07 11:32:23 -04001764bool ValidImageDataSize(ValidationContext *context,
1765 GLenum textureTarget,
1766 GLsizei width,
1767 GLsizei height,
1768 GLsizei depth,
1769 GLenum internalFormat,
1770 GLenum type,
1771 const GLvoid *pixels,
1772 GLsizei imageSize)
1773{
1774 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1775 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1776 {
1777 // Checks are not required
1778 return true;
1779 }
1780
1781 // ...the data would be unpacked from the buffer object such that the memory reads required
1782 // would exceed the data store size.
1783 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1784 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1785 const gl::Extents size(width, height, depth);
1786 const auto &unpack = context->getGLState().getUnpackState();
1787
1788 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1789 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1790 if (endByteOrErr.isError())
1791 {
1792 context->handleError(endByteOrErr.getError());
1793 return false;
1794 }
1795
1796 GLuint endByte = endByteOrErr.getResult();
1797
1798 if (pixelUnpackBuffer)
1799 {
1800 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1801 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1802 checkedEndByte += checkedOffset;
1803
1804 if (!checkedEndByte.IsValid() ||
1805 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1806 {
1807 // Overflow past the end of the buffer
1808 context->handleError(Error(GL_INVALID_OPERATION));
1809 return false;
1810 }
1811 }
1812 else
1813 {
1814 ASSERT(imageSize >= 0);
1815 if (pixels == nullptr && imageSize != 0)
1816 {
1817 context->handleError(
1818 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001819 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001820 }
1821
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001822 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001823 {
1824 context->handleError(
1825 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1826 return false;
1827 }
1828 }
1829
1830 return true;
1831}
1832
Geoff Lang37dde692014-01-31 16:34:54 -05001833bool ValidQueryType(const Context *context, GLenum queryType)
1834{
He Yunchaoced53ae2016-11-29 15:00:51 +08001835 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1836 "GL extension enums not equal.");
1837 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1838 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001839
1840 switch (queryType)
1841 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001842 case GL_ANY_SAMPLES_PASSED:
1843 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1844 return true;
1845 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1846 return (context->getClientMajorVersion() >= 3);
1847 case GL_TIME_ELAPSED_EXT:
1848 return context->getExtensions().disjointTimerQuery;
1849 case GL_COMMANDS_COMPLETED_CHROMIUM:
1850 return context->getExtensions().syncQuery;
1851 default:
1852 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001853 }
1854}
1855
Jamie Madillef300b12016-10-07 15:12:09 -04001856Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001857{
He Yunchaoced53ae2016-11-29 15:00:51 +08001858 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1859 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1860 // or program object and INVALID_OPERATION if the provided name identifies an object
1861 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001862
Dian Xiang769769a2015-09-09 15:20:08 -07001863 Program *validProgram = context->getProgram(id);
1864
1865 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001866 {
Dian Xiang769769a2015-09-09 15:20:08 -07001867 if (context->getShader(id))
1868 {
Jamie Madill437fa652016-05-03 15:13:24 -04001869 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001870 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1871 }
1872 else
1873 {
Jamie Madill437fa652016-05-03 15:13:24 -04001874 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001875 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001876 }
Dian Xiang769769a2015-09-09 15:20:08 -07001877
1878 return validProgram;
1879}
1880
Jamie Madillef300b12016-10-07 15:12:09 -04001881Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001882{
1883 // See ValidProgram for spec details.
1884
1885 Shader *validShader = context->getShader(id);
1886
1887 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001888 {
Dian Xiang769769a2015-09-09 15:20:08 -07001889 if (context->getProgram(id))
1890 {
Jamie Madill437fa652016-05-03 15:13:24 -04001891 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001892 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1893 }
1894 else
1895 {
Jamie Madill437fa652016-05-03 15:13:24 -04001896 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001897 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001898 }
Dian Xiang769769a2015-09-09 15:20:08 -07001899
1900 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001901}
1902
Geoff Langb1196682014-07-23 13:47:29 -04001903bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001904{
1905 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1906 {
1907 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1908
Geoff Langaae65a42014-05-26 12:43:44 -04001909 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001910 {
Jamie Madill437fa652016-05-03 15:13:24 -04001911 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001912 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001913 }
1914 }
1915 else
1916 {
1917 switch (attachment)
1918 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001919 case GL_DEPTH_ATTACHMENT:
1920 case GL_STENCIL_ATTACHMENT:
1921 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001922
He Yunchaoced53ae2016-11-29 15:00:51 +08001923 case GL_DEPTH_STENCIL_ATTACHMENT:
1924 if (!context->getExtensions().webglCompatibility &&
1925 context->getClientMajorVersion() < 3)
1926 {
1927 context->handleError(Error(GL_INVALID_ENUM));
1928 return false;
1929 }
1930 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001931
He Yunchaoced53ae2016-11-29 15:00:51 +08001932 default:
1933 context->handleError(Error(GL_INVALID_ENUM));
1934 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001935 }
1936 }
1937
1938 return true;
1939}
1940
Jamie Madille8fb6402017-02-14 17:56:40 -05001941bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001942 GLenum target,
1943 GLsizei samples,
1944 GLenum internalformat,
1945 GLsizei width,
1946 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001947{
1948 switch (target)
1949 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001950 case GL_RENDERBUFFER:
1951 break;
1952 default:
1953 context->handleError(Error(GL_INVALID_ENUM));
1954 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001955 }
1956
1957 if (width < 0 || height < 0 || samples < 0)
1958 {
Jamie Madill437fa652016-05-03 15:13:24 -04001959 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001960 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001961 }
1962
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001963 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1964 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1965
1966 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001967 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001968 {
Jamie Madill437fa652016-05-03 15:13:24 -04001969 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001970 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001971 }
1972
1973 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1974 // 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 -08001975 // only sized internal formats.
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001976 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(convertedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -04001977 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001978 {
Jamie Madill437fa652016-05-03 15:13:24 -04001979 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001980 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001981 }
1982
Geoff Langaae65a42014-05-26 12:43:44 -04001983 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001984 {
Jamie Madill437fa652016-05-03 15:13:24 -04001985 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001986 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001987 }
1988
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001989 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001990 if (handle == 0)
1991 {
Jamie Madill437fa652016-05-03 15:13:24 -04001992 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001993 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001994 }
1995
1996 return true;
1997}
1998
He Yunchaoced53ae2016-11-29 15:00:51 +08001999bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
2000 GLenum target,
2001 GLenum attachment,
2002 GLenum renderbuffertarget,
2003 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002004{
Shannon Woods1da3cf62014-06-27 15:32:23 -04002005 if (!ValidFramebufferTarget(target))
2006 {
Jamie Madill437fa652016-05-03 15:13:24 -04002007 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002008 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04002009 }
2010
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002011 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002012
Jamie Madill84115c92015-04-23 15:00:07 -04002013 ASSERT(framebuffer);
2014 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002015 {
Jamie Madill437fa652016-05-03 15:13:24 -04002016 context->handleError(
2017 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002018 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002019 }
2020
Jamie Madillb4472272014-07-03 10:38:55 -04002021 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002022 {
Jamie Madillb4472272014-07-03 10:38:55 -04002023 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002024 }
2025
Jamie Madillab9d82c2014-01-21 16:38:14 -05002026 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
2027 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
2028 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
2029 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
2030 if (renderbuffer != 0)
2031 {
2032 if (!context->getRenderbuffer(renderbuffer))
2033 {
Jamie Madill437fa652016-05-03 15:13:24 -04002034 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002035 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05002036 }
2037 }
2038
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002039 return true;
2040}
2041
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002042bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002043 GLint srcX0,
2044 GLint srcY0,
2045 GLint srcX1,
2046 GLint srcY1,
2047 GLint dstX0,
2048 GLint dstY0,
2049 GLint dstX1,
2050 GLint dstY1,
2051 GLbitfield mask,
2052 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002053{
2054 switch (filter)
2055 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002056 case GL_NEAREST:
2057 break;
2058 case GL_LINEAR:
2059 break;
2060 default:
2061 context->handleError(Error(GL_INVALID_ENUM));
2062 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002063 }
2064
2065 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
2066 {
Jamie Madill437fa652016-05-03 15:13:24 -04002067 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002068 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002069 }
2070
2071 if (mask == 0)
2072 {
2073 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
2074 // buffers are copied.
2075 return false;
2076 }
2077
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002078 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
2079 // color buffer, leaving only nearest being unfiltered from above
2080 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
2081 {
Jamie Madill437fa652016-05-03 15:13:24 -04002082 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002083 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002084 }
2085
Jamie Madill51f40ec2016-06-15 14:06:00 -04002086 const auto &glState = context->getGLState();
2087 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
2088 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05002089
2090 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002091 {
Jamie Madill437fa652016-05-03 15:13:24 -04002092 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002093 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002094 }
2095
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002096 if (readFramebuffer->id() == drawFramebuffer->id())
2097 {
2098 context->handleError(Error(GL_INVALID_OPERATION));
2099 return false;
2100 }
2101
Jamie Madill51f40ec2016-06-15 14:06:00 -04002102 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002103 {
Jamie Madill437fa652016-05-03 15:13:24 -04002104 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002105 return false;
2106 }
2107
Jamie Madill51f40ec2016-06-15 14:06:00 -04002108 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002109 {
Jamie Madill437fa652016-05-03 15:13:24 -04002110 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002111 return false;
2112 }
2113
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002114 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002115 {
Jamie Madill437fa652016-05-03 15:13:24 -04002116 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002117 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002118 }
2119
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002120 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
2121
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002122 if (mask & GL_COLOR_BUFFER_BIT)
2123 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002124 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05002125 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002126
He Yunchao66a41a22016-12-15 16:45:05 +08002127 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002128 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002129 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002130
Geoff Langa15472a2015-08-11 11:48:03 -04002131 for (size_t drawbufferIdx = 0;
2132 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002133 {
Geoff Langa15472a2015-08-11 11:48:03 -04002134 const FramebufferAttachment *attachment =
2135 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2136 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002137 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002138 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002139
Geoff Langb2f3d052013-08-13 12:49:27 -04002140 // The GL ES 3.0.2 spec (pg 193) states that:
2141 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08002142 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
2143 // as well
2144 // 3) If the read buffer is a signed integer format, the draw buffer must be as
2145 // well
Jamie Madill6163c752015-12-07 16:32:59 -05002146 // Changes with EXT_color_buffer_float:
2147 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04002148 GLenum readComponentType = readFormat.info->componentType;
2149 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002150 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002151 readComponentType == GL_SIGNED_NORMALIZED);
2152 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2153 drawComponentType == GL_SIGNED_NORMALIZED);
2154
2155 if (extensions.colorBufferFloat)
2156 {
2157 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2158 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2159
2160 if (readFixedOrFloat != drawFixedOrFloat)
2161 {
Jamie Madill437fa652016-05-03 15:13:24 -04002162 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002163 "If the read buffer contains fixed-point or "
2164 "floating-point values, the draw buffer "
2165 "must as well."));
2166 return false;
2167 }
2168 }
2169 else if (readFixedPoint != drawFixedPoint)
2170 {
Jamie Madill437fa652016-05-03 15:13:24 -04002171 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002172 "If the read buffer contains fixed-point "
2173 "values, the draw buffer must as well."));
2174 return false;
2175 }
2176
2177 if (readComponentType == GL_UNSIGNED_INT &&
2178 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002179 {
Jamie Madill437fa652016-05-03 15:13:24 -04002180 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002181 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002182 }
2183
Jamie Madill6163c752015-12-07 16:32:59 -05002184 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002185 {
Jamie Madill437fa652016-05-03 15:13:24 -04002186 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002187 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002188 }
2189
Jamie Madilla3944d42016-07-22 22:13:26 -04002190 if (readColorBuffer->getSamples() > 0 &&
2191 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002192 {
Jamie Madill437fa652016-05-03 15:13:24 -04002193 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002194 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002195 }
2196 }
2197 }
2198
Jamie Madilla3944d42016-07-22 22:13:26 -04002199 if ((readFormat.info->componentType == GL_INT ||
2200 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2201 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002202 {
Jamie Madill437fa652016-05-03 15:13:24 -04002203 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002204 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002205 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002206 }
He Yunchao66a41a22016-12-15 16:45:05 +08002207 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2208 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
2209 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2210 // situation is an application error that would lead to a crash in ANGLE.
2211 else if (drawFramebuffer->hasEnabledDrawBuffer())
2212 {
2213 context->handleError(Error(
2214 GL_INVALID_OPERATION,
2215 "Attempt to read from a missing color attachment of a complete framebuffer."));
2216 return false;
2217 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002218 }
2219
He Yunchaoced53ae2016-11-29 15:00:51 +08002220 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002221 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2222 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002223 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002224 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002225 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002226 const gl::FramebufferAttachment *readBuffer =
2227 readFramebuffer->getAttachment(attachments[i]);
2228 const gl::FramebufferAttachment *drawBuffer =
2229 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002230
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002231 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002232 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002233 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002234 {
Jamie Madill437fa652016-05-03 15:13:24 -04002235 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002236 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002237 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002238
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002239 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002240 {
Jamie Madill437fa652016-05-03 15:13:24 -04002241 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002242 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002243 }
2244 }
He Yunchao66a41a22016-12-15 16:45:05 +08002245 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2246 else if (drawBuffer)
2247 {
2248 context->handleError(Error(GL_INVALID_OPERATION,
2249 "Attempt to read from a missing depth/stencil "
2250 "attachment of a complete framebuffer."));
2251 return false;
2252 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002253 }
2254 }
2255
2256 return true;
2257}
2258
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002259bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002260 GLint x,
2261 GLint y,
2262 GLsizei width,
2263 GLsizei height,
2264 GLenum format,
2265 GLenum type,
2266 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002267{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002268 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2269}
2270
2271bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2272 GLint x,
2273 GLint y,
2274 GLsizei width,
2275 GLsizei height,
2276 GLenum format,
2277 GLenum type,
2278 GLsizei bufSize,
2279 GLsizei *length,
2280 GLvoid *pixels)
2281{
2282 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002283 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002284 return false;
2285 }
2286
Geoff Lang62fce5b2016-09-30 10:46:35 -04002287 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2288 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002289 {
Geoff Langb1196682014-07-23 13:47:29 -04002290 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002291 }
2292
Geoff Lang62fce5b2016-09-30 10:46:35 -04002293 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002294 {
Geoff Langb1196682014-07-23 13:47:29 -04002295 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002296 }
2297
Jamie Madillc29968b2016-01-20 11:17:23 -05002298 return true;
2299}
2300
2301bool ValidateReadnPixelsEXT(Context *context,
2302 GLint x,
2303 GLint y,
2304 GLsizei width,
2305 GLsizei height,
2306 GLenum format,
2307 GLenum type,
2308 GLsizei bufSize,
2309 GLvoid *pixels)
2310{
2311 if (bufSize < 0)
2312 {
Jamie Madill437fa652016-05-03 15:13:24 -04002313 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002314 return false;
2315 }
2316
Geoff Lang62fce5b2016-09-30 10:46:35 -04002317 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2318 pixels);
2319}
Jamie Madill26e91952014-03-05 15:01:27 -05002320
Geoff Lang62fce5b2016-09-30 10:46:35 -04002321bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2322 GLint x,
2323 GLint y,
2324 GLsizei width,
2325 GLsizei height,
2326 GLenum format,
2327 GLenum type,
2328 GLsizei bufSize,
2329 GLsizei *length,
2330 GLvoid *data)
2331{
2332 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002333 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002334 return false;
2335 }
2336
Geoff Lang62fce5b2016-09-30 10:46:35 -04002337 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002338 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002339 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002340 }
2341
Geoff Lang62fce5b2016-09-30 10:46:35 -04002342 if (!ValidateRobustBufferSize(context, bufSize, *length))
2343 {
2344 return false;
2345 }
2346
2347 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002348}
2349
Olli Etuaho41997e72016-03-10 13:38:39 +02002350bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002351{
2352 if (!context->getExtensions().occlusionQueryBoolean &&
2353 !context->getExtensions().disjointTimerQuery)
2354 {
Jamie Madill437fa652016-05-03 15:13:24 -04002355 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002356 return false;
2357 }
2358
Olli Etuaho41997e72016-03-10 13:38:39 +02002359 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002360}
2361
Olli Etuaho41997e72016-03-10 13:38:39 +02002362bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002363{
2364 if (!context->getExtensions().occlusionQueryBoolean &&
2365 !context->getExtensions().disjointTimerQuery)
2366 {
Jamie Madill437fa652016-05-03 15:13:24 -04002367 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002368 return false;
2369 }
2370
Olli Etuaho41997e72016-03-10 13:38:39 +02002371 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002372}
2373
2374bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002375{
2376 if (!ValidQueryType(context, target))
2377 {
Jamie Madill437fa652016-05-03 15:13:24 -04002378 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002379 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002380 }
2381
2382 if (id == 0)
2383 {
Jamie Madill437fa652016-05-03 15:13:24 -04002384 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002385 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002386 }
2387
2388 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2389 // of zero, if the active query object name for <target> is non-zero (for the
2390 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2391 // the active query for either target is non-zero), if <id> is the name of an
2392 // existing query object whose type does not match <target>, or if <id> is the
2393 // active query object name for any query type, the error INVALID_OPERATION is
2394 // generated.
2395
2396 // Ensure no other queries are active
2397 // NOTE: If other queries than occlusion are supported, we will need to check
2398 // separately that:
2399 // a) The query ID passed is not the current active query for any target/type
2400 // b) There are no active queries for the requested target (and in the case
2401 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2402 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002403
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002404 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002405 {
Jamie Madill437fa652016-05-03 15:13:24 -04002406 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002407 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002408 }
2409
2410 Query *queryObject = context->getQuery(id, true, target);
2411
2412 // check that name was obtained with glGenQueries
2413 if (!queryObject)
2414 {
Jamie Madill437fa652016-05-03 15:13:24 -04002415 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002416 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002417 }
2418
2419 // check for type mismatch
2420 if (queryObject->getType() != target)
2421 {
Jamie Madill437fa652016-05-03 15:13:24 -04002422 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002423 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002424 }
2425
2426 return true;
2427}
2428
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002429bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2430{
2431 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002432 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002433 {
Jamie Madill437fa652016-05-03 15:13:24 -04002434 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002435 return false;
2436 }
2437
2438 return ValidateBeginQueryBase(context, target, id);
2439}
2440
2441bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002442{
2443 if (!ValidQueryType(context, target))
2444 {
Jamie Madill437fa652016-05-03 15:13:24 -04002445 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002446 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002447 }
2448
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002449 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002450
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002451 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002452 {
Jamie Madill437fa652016-05-03 15:13:24 -04002453 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002454 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002455 }
2456
Jamie Madill45c785d2014-05-13 14:09:34 -04002457 return true;
2458}
2459
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002460bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2461{
2462 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002463 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002464 {
Jamie Madill437fa652016-05-03 15:13:24 -04002465 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002466 return false;
2467 }
2468
2469 return ValidateEndQueryBase(context, target);
2470}
2471
2472bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2473{
2474 if (!context->getExtensions().disjointTimerQuery)
2475 {
Jamie Madill437fa652016-05-03 15:13:24 -04002476 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002477 return false;
2478 }
2479
2480 if (target != GL_TIMESTAMP_EXT)
2481 {
Jamie Madill437fa652016-05-03 15:13:24 -04002482 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002483 return false;
2484 }
2485
2486 Query *queryObject = context->getQuery(id, true, target);
2487 if (queryObject == nullptr)
2488 {
Jamie Madill437fa652016-05-03 15:13:24 -04002489 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002490 return false;
2491 }
2492
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002493 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002494 {
Jamie Madill437fa652016-05-03 15:13:24 -04002495 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002496 return false;
2497 }
2498
2499 return true;
2500}
2501
Geoff Lang2186c382016-10-14 10:54:54 -04002502bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002503{
Geoff Lang2186c382016-10-14 10:54:54 -04002504 if (numParams)
2505 {
2506 *numParams = 0;
2507 }
2508
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002509 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2510 {
Jamie Madill437fa652016-05-03 15:13:24 -04002511 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002512 return false;
2513 }
2514
2515 switch (pname)
2516 {
2517 case GL_CURRENT_QUERY_EXT:
2518 if (target == GL_TIMESTAMP_EXT)
2519 {
Jamie Madill437fa652016-05-03 15:13:24 -04002520 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002521 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2522 return false;
2523 }
2524 break;
2525 case GL_QUERY_COUNTER_BITS_EXT:
2526 if (!context->getExtensions().disjointTimerQuery ||
2527 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2528 {
Jamie Madill437fa652016-05-03 15:13:24 -04002529 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002530 return false;
2531 }
2532 break;
2533 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002534 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002535 return false;
2536 }
2537
Geoff Lang2186c382016-10-14 10:54:54 -04002538 if (numParams)
2539 {
2540 // All queries return only one value
2541 *numParams = 1;
2542 }
2543
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002544 return true;
2545}
2546
2547bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2548{
2549 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002550 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002551 {
Jamie Madill437fa652016-05-03 15:13:24 -04002552 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002553 return false;
2554 }
2555
Geoff Lang2186c382016-10-14 10:54:54 -04002556 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002557}
2558
Geoff Lang2186c382016-10-14 10:54:54 -04002559bool ValidateGetQueryivRobustANGLE(Context *context,
2560 GLenum target,
2561 GLenum pname,
2562 GLsizei bufSize,
2563 GLsizei *length,
2564 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002565{
Geoff Lang2186c382016-10-14 10:54:54 -04002566 if (!ValidateRobustEntryPoint(context, bufSize))
2567 {
2568 return false;
2569 }
2570
2571 if (!ValidateGetQueryivBase(context, target, pname, length))
2572 {
2573 return false;
2574 }
2575
2576 if (!ValidateRobustBufferSize(context, bufSize, *length))
2577 {
2578 return false;
2579 }
2580
2581 return true;
2582}
2583
2584bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2585{
2586 if (numParams)
2587 {
2588 *numParams = 0;
2589 }
2590
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002591 Query *queryObject = context->getQuery(id, false, GL_NONE);
2592
2593 if (!queryObject)
2594 {
Jamie Madill437fa652016-05-03 15:13:24 -04002595 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002596 return false;
2597 }
2598
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002599 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002600 {
Jamie Madill437fa652016-05-03 15:13:24 -04002601 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002602 return false;
2603 }
2604
2605 switch (pname)
2606 {
2607 case GL_QUERY_RESULT_EXT:
2608 case GL_QUERY_RESULT_AVAILABLE_EXT:
2609 break;
2610
2611 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002612 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002613 return false;
2614 }
2615
Geoff Lang2186c382016-10-14 10:54:54 -04002616 if (numParams)
2617 {
2618 *numParams = 1;
2619 }
2620
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002621 return true;
2622}
2623
2624bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2625{
2626 if (!context->getExtensions().disjointTimerQuery)
2627 {
Jamie Madill437fa652016-05-03 15:13:24 -04002628 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002629 return false;
2630 }
Geoff Lang2186c382016-10-14 10:54:54 -04002631 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2632}
2633
2634bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2635 GLuint id,
2636 GLenum pname,
2637 GLsizei bufSize,
2638 GLsizei *length,
2639 GLint *params)
2640{
2641 if (!context->getExtensions().disjointTimerQuery)
2642 {
2643 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2644 return false;
2645 }
2646
2647 if (!ValidateRobustEntryPoint(context, bufSize))
2648 {
2649 return false;
2650 }
2651
2652 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2653 {
2654 return false;
2655 }
2656
2657 if (!ValidateRobustBufferSize(context, bufSize, *length))
2658 {
2659 return false;
2660 }
2661
2662 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002663}
2664
2665bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2666{
2667 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002668 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002669 {
Jamie Madill437fa652016-05-03 15:13:24 -04002670 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002671 return false;
2672 }
Geoff Lang2186c382016-10-14 10:54:54 -04002673 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2674}
2675
2676bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2677 GLuint id,
2678 GLenum pname,
2679 GLsizei bufSize,
2680 GLsizei *length,
2681 GLuint *params)
2682{
2683 if (!context->getExtensions().disjointTimerQuery &&
2684 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2685 {
2686 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2687 return false;
2688 }
2689
2690 if (!ValidateRobustEntryPoint(context, bufSize))
2691 {
2692 return false;
2693 }
2694
2695 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2696 {
2697 return false;
2698 }
2699
2700 if (!ValidateRobustBufferSize(context, bufSize, *length))
2701 {
2702 return false;
2703 }
2704
2705 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002706}
2707
2708bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2709{
2710 if (!context->getExtensions().disjointTimerQuery)
2711 {
Jamie Madill437fa652016-05-03 15:13:24 -04002712 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002713 return false;
2714 }
Geoff Lang2186c382016-10-14 10:54:54 -04002715 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2716}
2717
2718bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2719 GLuint id,
2720 GLenum pname,
2721 GLsizei bufSize,
2722 GLsizei *length,
2723 GLint64 *params)
2724{
2725 if (!context->getExtensions().disjointTimerQuery)
2726 {
2727 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2728 return false;
2729 }
2730
2731 if (!ValidateRobustEntryPoint(context, bufSize))
2732 {
2733 return false;
2734 }
2735
2736 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2737 {
2738 return false;
2739 }
2740
2741 if (!ValidateRobustBufferSize(context, bufSize, *length))
2742 {
2743 return false;
2744 }
2745
2746 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002747}
2748
2749bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2750{
2751 if (!context->getExtensions().disjointTimerQuery)
2752 {
Jamie Madill437fa652016-05-03 15:13:24 -04002753 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002754 return false;
2755 }
Geoff Lang2186c382016-10-14 10:54:54 -04002756 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2757}
2758
2759bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2760 GLuint id,
2761 GLenum pname,
2762 GLsizei bufSize,
2763 GLsizei *length,
2764 GLuint64 *params)
2765{
2766 if (!context->getExtensions().disjointTimerQuery)
2767 {
2768 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2769 return false;
2770 }
2771
2772 if (!ValidateRobustEntryPoint(context, bufSize))
2773 {
2774 return false;
2775 }
2776
2777 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2778 {
2779 return false;
2780 }
2781
2782 if (!ValidateRobustBufferSize(context, bufSize, *length))
2783 {
2784 return false;
2785 }
2786
2787 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002788}
2789
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002790bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002791 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002792 GLuint program,
2793 GLint location,
2794 GLsizei count)
2795{
2796 // Check for ES31 program uniform entry points
2797 if (context->getClientVersion() < Version(3, 1))
2798 {
2799 context->handleError(Error(GL_INVALID_OPERATION));
2800 return false;
2801 }
2802
2803 const LinkedUniform *uniform = nullptr;
2804 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002805 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2806 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002807}
2808
Frank Henigmana98a6472017-02-02 21:38:32 -05002809bool ValidateProgramUniform1iv(gl::Context *context,
2810 GLuint program,
2811 GLint location,
2812 GLsizei count,
2813 const GLint *value)
2814{
2815 // Check for ES31 program uniform entry points
2816 if (context->getClientVersion() < Version(3, 1))
2817 {
2818 context->handleError(Error(GL_INVALID_OPERATION));
2819 return false;
2820 }
2821
2822 const LinkedUniform *uniform = nullptr;
2823 gl::Program *programObject = GetValidProgram(context, program);
2824 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2825 ValidateUniform1ivValue(context, uniform->type, count, value);
2826}
2827
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002828bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002829 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002830 GLuint program,
2831 GLint location,
2832 GLsizei count,
2833 GLboolean transpose)
2834{
2835 // Check for ES31 program uniform entry points
2836 if (context->getClientVersion() < Version(3, 1))
2837 {
2838 context->handleError(Error(GL_INVALID_OPERATION));
2839 return false;
2840 }
2841
2842 const LinkedUniform *uniform = nullptr;
2843 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002844 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2845 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002846}
2847
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002848bool ValidateUniform(gl::Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002849{
2850 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002851 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002852 {
Jamie Madill437fa652016-05-03 15:13:24 -04002853 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002854 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002855 }
2856
Jamie Madill62d31cb2015-09-11 13:25:51 -04002857 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002858 gl::Program *programObject = context->getGLState().getProgram();
2859 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2860 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002861}
2862
Frank Henigmana98a6472017-02-02 21:38:32 -05002863bool ValidateUniform1iv(gl::Context *context, GLint location, GLsizei count, const GLint *value)
2864{
2865 const LinkedUniform *uniform = nullptr;
2866 gl::Program *programObject = context->getGLState().getProgram();
2867 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2868 ValidateUniform1ivValue(context, uniform->type, count, value);
2869}
2870
He Yunchaoced53ae2016-11-29 15:00:51 +08002871bool ValidateUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002872 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002873 GLint location,
2874 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002875 GLboolean transpose)
2876{
2877 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002878 int rows = VariableRowCount(valueType);
2879 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002880 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002881 {
Jamie Madill437fa652016-05-03 15:13:24 -04002882 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002883 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002884 }
2885
Martin Radev1be913c2016-07-11 17:59:16 +03002886 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002887 {
Jamie Madill437fa652016-05-03 15:13:24 -04002888 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002889 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002890 }
2891
Jamie Madill62d31cb2015-09-11 13:25:51 -04002892 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002893 gl::Program *programObject = context->getGLState().getProgram();
2894 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2895 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002896}
2897
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002898bool ValidateStateQuery(ValidationContext *context,
2899 GLenum pname,
2900 GLenum *nativeType,
2901 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002902{
2903 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2904 {
Jamie Madill437fa652016-05-03 15:13:24 -04002905 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002906 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002907 }
2908
Jamie Madill0af26e12015-03-05 19:54:33 -05002909 const Caps &caps = context->getCaps();
2910
Jamie Madill893ab082014-05-16 16:56:10 -04002911 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2912 {
2913 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2914
Jamie Madill0af26e12015-03-05 19:54:33 -05002915 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002916 {
Jamie Madill437fa652016-05-03 15:13:24 -04002917 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002918 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002919 }
2920 }
2921
2922 switch (pname)
2923 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002924 case GL_TEXTURE_BINDING_2D:
2925 case GL_TEXTURE_BINDING_CUBE_MAP:
2926 case GL_TEXTURE_BINDING_3D:
2927 case GL_TEXTURE_BINDING_2D_ARRAY:
2928 break;
2929 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2930 if (!context->getExtensions().eglStreamConsumerExternal &&
2931 !context->getExtensions().eglImageExternal)
2932 {
2933 context->handleError(Error(GL_INVALID_ENUM,
2934 "Neither NV_EGL_stream_consumer_external nor "
2935 "GL_OES_EGL_image_external extensions enabled"));
2936 return false;
2937 }
2938 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002939
He Yunchaoced53ae2016-11-29 15:00:51 +08002940 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2941 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002942 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002943 if (context->getGLState().getReadFramebuffer()->checkStatus(
2944 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002945 {
Jamie Madill437fa652016-05-03 15:13:24 -04002946 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002947 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002948 }
2949
Jamie Madill51f40ec2016-06-15 14:06:00 -04002950 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2951 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002952
2953 if (framebuffer->getReadBufferState() == GL_NONE)
2954 {
2955 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2956 return false;
2957 }
2958
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002959 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002960 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002961 {
Jamie Madill437fa652016-05-03 15:13:24 -04002962 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002963 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002964 }
2965 }
2966 break;
2967
He Yunchaoced53ae2016-11-29 15:00:51 +08002968 default:
2969 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002970 }
2971
2972 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002973 if (*numParams == 0)
2974 {
2975 return false;
2976 }
2977
2978 return true;
2979}
2980
2981bool ValidateRobustStateQuery(ValidationContext *context,
2982 GLenum pname,
2983 GLsizei bufSize,
2984 GLenum *nativeType,
2985 unsigned int *numParams)
2986{
2987 if (!ValidateRobustEntryPoint(context, bufSize))
2988 {
2989 return false;
2990 }
2991
2992 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2993 {
2994 return false;
2995 }
2996
2997 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002998 {
2999 return false;
3000 }
3001
3002 return true;
3003}
3004
Jamie Madillc29968b2016-01-20 11:17:23 -05003005bool ValidateCopyTexImageParametersBase(ValidationContext *context,
3006 GLenum target,
3007 GLint level,
3008 GLenum internalformat,
3009 bool isSubImage,
3010 GLint xoffset,
3011 GLint yoffset,
3012 GLint zoffset,
3013 GLint x,
3014 GLint y,
3015 GLsizei width,
3016 GLsizei height,
3017 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04003018 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04003019{
Jamie Madill560a8d82014-05-21 13:06:20 -04003020 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
3021 {
Jamie Madill437fa652016-05-03 15:13:24 -04003022 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003023 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003024 }
3025
He Yunchaoced53ae2016-11-29 15:00:51 +08003026 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
3027 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04003028 {
Jamie Madill437fa652016-05-03 15:13:24 -04003029 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003030 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003031 }
3032
3033 if (border != 0)
3034 {
Jamie Madill437fa652016-05-03 15:13:24 -04003035 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003036 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003037 }
3038
3039 if (!ValidMipLevel(context, target, level))
3040 {
Jamie Madill437fa652016-05-03 15:13:24 -04003041 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003042 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003043 }
3044
Jamie Madill51f40ec2016-06-15 14:06:00 -04003045 const auto &state = context->getGLState();
3046 auto readFramebuffer = state.getReadFramebuffer();
3047 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04003048 {
Jamie Madill437fa652016-05-03 15:13:24 -04003049 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003050 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003051 }
3052
Jamie Madill51f40ec2016-06-15 14:06:00 -04003053 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003054 {
Jamie Madill437fa652016-05-03 15:13:24 -04003055 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003056 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003057 }
3058
Martin Radev138064f2016-07-15 12:03:41 +03003059 if (readFramebuffer->getReadBufferState() == GL_NONE)
3060 {
3061 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3062 return false;
3063 }
3064
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003065 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
3066 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08003067 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003068 // situation is an application error that would lead to a crash in ANGLE.
3069 if (readFramebuffer->getReadColorbuffer() == nullptr)
3070 {
3071 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
3072 return false;
3073 }
3074
Geoff Langaae65a42014-05-26 12:43:44 -04003075 const gl::Caps &caps = context->getCaps();
3076
Geoff Langaae65a42014-05-26 12:43:44 -04003077 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04003078 switch (target)
3079 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003080 case GL_TEXTURE_2D:
3081 maxDimension = caps.max2DTextureSize;
3082 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003083
He Yunchaoced53ae2016-11-29 15:00:51 +08003084 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3085 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3086 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3087 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3088 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3089 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3090 maxDimension = caps.maxCubeMapTextureSize;
3091 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003092
He Yunchaoced53ae2016-11-29 15:00:51 +08003093 case GL_TEXTURE_2D_ARRAY:
3094 maxDimension = caps.max2DTextureSize;
3095 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003096
He Yunchaoced53ae2016-11-29 15:00:51 +08003097 case GL_TEXTURE_3D:
3098 maxDimension = caps.max3DTextureSize;
3099 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003100
He Yunchaoced53ae2016-11-29 15:00:51 +08003101 default:
3102 context->handleError(Error(GL_INVALID_ENUM));
3103 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003104 }
3105
Jamie Madillc29968b2016-01-20 11:17:23 -05003106 gl::Texture *texture =
3107 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003108 if (!texture)
3109 {
Jamie Madill437fa652016-05-03 15:13:24 -04003110 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003111 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003112 }
3113
Geoff Lang69cce582015-09-17 13:20:36 -04003114 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003115 {
Jamie Madill437fa652016-05-03 15:13:24 -04003116 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003117 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003118 }
3119
Geoff Lang5d601382014-07-22 15:14:06 -04003120 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
3121
3122 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003123 {
Jamie Madill437fa652016-05-03 15:13:24 -04003124 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003125 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003126 }
3127
Geoff Lang44ff5a72017-02-03 15:15:43 -05003128 if (formatInfo.compressed &&
3129 !ValidCompressedImageSize(context, internalformat, xoffset, yoffset, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003130 {
Jamie Madill437fa652016-05-03 15:13:24 -04003131 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003132 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003133 }
3134
3135 if (isSubImage)
3136 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003137 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3138 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3139 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003140 {
Jamie Madill437fa652016-05-03 15:13:24 -04003141 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003142 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003143 }
3144 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003145 else
3146 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003147 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003148 {
Jamie Madill437fa652016-05-03 15:13:24 -04003149 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003150 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003151 }
3152
Geoff Langeb66a6e2016-10-31 13:06:12 -04003153 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003154 {
Jamie Madill437fa652016-05-03 15:13:24 -04003155 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003156 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003157 }
3158
3159 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003160 if (static_cast<int>(width) > maxLevelDimension ||
3161 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003162 {
Jamie Madill437fa652016-05-03 15:13:24 -04003163 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003164 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003165 }
3166 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003167
Jamie Madill0c8abca2016-07-22 20:21:26 -04003168 if (textureFormatOut)
3169 {
3170 *textureFormatOut = texture->getFormat(target, level);
3171 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05003172
3173 // Detect texture copying feedback loops for WebGL.
3174 if (context->getExtensions().webglCompatibility)
3175 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05003176 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05003177 {
3178 context->handleError(Error(GL_INVALID_OPERATION,
3179 "Texture copying feedback loop formed between Framebuffer "
3180 "and specified Texture level."));
3181 return false;
3182 }
3183 }
3184
Jamie Madill560a8d82014-05-21 13:06:20 -04003185 return true;
3186}
3187
Jiajia Qind9671222016-11-29 16:30:31 +08003188bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003189{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003190 switch (mode)
3191 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003192 case GL_POINTS:
3193 case GL_LINES:
3194 case GL_LINE_LOOP:
3195 case GL_LINE_STRIP:
3196 case GL_TRIANGLES:
3197 case GL_TRIANGLE_STRIP:
3198 case GL_TRIANGLE_FAN:
3199 break;
3200 default:
3201 context->handleError(Error(GL_INVALID_ENUM));
3202 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003203 }
3204
Jamie Madill250d33f2014-06-06 17:09:03 -04003205 if (count < 0)
3206 {
Jamie Madill437fa652016-05-03 15:13:24 -04003207 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003208 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003209 }
3210
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003211 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003212
Jamie Madill250d33f2014-06-06 17:09:03 -04003213 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003214 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003215 {
Jamie Madill437fa652016-05-03 15:13:24 -04003216 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003217 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003218 }
3219
Jamie Madillcbcde722017-01-06 14:50:00 -05003220 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3221 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04003222 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003223 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3224 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003225 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003226 const FramebufferAttachment *dsAttachment =
3227 framebuffer->getStencilOrDepthStencilAttachment();
3228 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003229 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003230 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003231
3232 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3233 bool differentWritemasks =
3234 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3235 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3236 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3237 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3238
3239 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003240 {
Jamie Madillcbcde722017-01-06 14:50:00 -05003241 if (!context->getExtensions().webglCompatibility)
3242 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05003243 ERR() << "This ANGLE implementation does not support separate front/back stencil "
3244 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05003245 }
Jamie Madill437fa652016-05-03 15:13:24 -04003246 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003247 return false;
3248 }
Jamie Madillac528012014-06-20 13:21:23 -04003249 }
3250
Jamie Madill51f40ec2016-06-15 14:06:00 -04003251 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003252 {
Jamie Madill437fa652016-05-03 15:13:24 -04003253 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003254 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003255 }
3256
Geoff Lang7dd2e102014-11-10 15:19:26 -05003257 gl::Program *program = state.getProgram();
3258 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003259 {
Jamie Madill437fa652016-05-03 15:13:24 -04003260 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003261 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003262 }
3263
Geoff Lang7dd2e102014-11-10 15:19:26 -05003264 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003265 {
Jamie Madill437fa652016-05-03 15:13:24 -04003266 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003267 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003268 }
3269
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003270 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003271 for (unsigned int uniformBlockIndex = 0;
3272 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003273 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003274 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003275 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003276 const OffsetBindingPointer<Buffer> &uniformBuffer =
3277 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003278
Geoff Lang5d124a62015-09-15 13:03:27 -04003279 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003280 {
3281 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003282 context->handleError(
3283 Error(GL_INVALID_OPERATION,
3284 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003285 return false;
3286 }
3287
Geoff Lang5d124a62015-09-15 13:03:27 -04003288 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003289 if (uniformBufferSize == 0)
3290 {
3291 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003292 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003293 }
3294
Jamie Madill62d31cb2015-09-11 13:25:51 -04003295 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003296 {
3297 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003298 context->handleError(
3299 Error(GL_INVALID_OPERATION,
3300 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003301 return false;
3302 }
3303 }
3304
Jamie Madilla4595b82017-01-11 17:36:34 -05003305 // Detect rendering feedback loops for WebGL.
3306 if (context->getExtensions().webglCompatibility)
3307 {
3308 if (framebuffer->formsRenderingFeedbackLoopWith(state))
3309 {
3310 context->handleError(
3311 Error(GL_INVALID_OPERATION,
3312 "Rendering feedback loop formed between Framebuffer and active Texture."));
3313 return false;
3314 }
3315 }
3316
Jamie Madill250d33f2014-06-06 17:09:03 -04003317 // No-op if zero count
3318 return (count > 0);
3319}
3320
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003321bool ValidateDrawArrays(ValidationContext *context,
3322 GLenum mode,
3323 GLint first,
3324 GLsizei count,
3325 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003326{
Jamie Madillfd716582014-06-06 17:09:04 -04003327 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003328 {
Jamie Madill437fa652016-05-03 15:13:24 -04003329 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003330 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003331 }
3332
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003333 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003334 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003335 if (curTransformFeedback && curTransformFeedback->isActive() &&
3336 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003337 {
3338 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003339 // that does not match the current transform feedback object's draw mode (if transform
3340 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003341 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003342 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003343 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003344 }
3345
Jiajia Qind9671222016-11-29 16:30:31 +08003346 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003347 {
3348 return false;
3349 }
3350
Corentin Wallez71168a02016-12-19 15:11:18 -08003351 // Check the computation of maxVertex doesn't overflow.
3352 // - first < 0 or count < 0 have been checked as an error condition
3353 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3354 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3355 ASSERT(count > 0 && first >= 0);
3356 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3357 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003358 {
3359 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3360 return false;
3361 }
3362
Corentin Wallez71168a02016-12-19 15:11:18 -08003363 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003364 {
3365 return false;
3366 }
3367
3368 return true;
3369}
3370
He Yunchaoced53ae2016-11-29 15:00:51 +08003371bool ValidateDrawArraysInstanced(Context *context,
3372 GLenum mode,
3373 GLint first,
3374 GLsizei count,
3375 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003376{
3377 if (primcount < 0)
3378 {
Jamie Madill437fa652016-05-03 15:13:24 -04003379 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003380 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003381 }
3382
Jamie Madill2b976812014-08-25 15:47:49 -04003383 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003384 {
3385 return false;
3386 }
3387
3388 // No-op if zero primitive count
3389 return (primcount > 0);
3390}
3391
Geoff Lang87a93302014-09-16 13:29:43 -04003392static bool ValidateDrawInstancedANGLE(Context *context)
3393{
3394 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003395 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003396
Geoff Lang7dd2e102014-11-10 15:19:26 -05003397 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003398
Jiawei-Shao2597fb62016-12-09 16:38:02 +08003399 const auto &attribs = state.getVertexArray()->getVertexAttributes();
3400 const auto &bindings = state.getVertexArray()->getVertexBindings();
Jamie Madill63805b42015-08-25 13:17:39 -04003401 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003402 {
Jiawei-Shao2597fb62016-12-09 16:38:02 +08003403 const VertexAttribute &attrib = attribs[attributeIndex];
3404 const VertexBinding &binding = bindings[attrib.bindingIndex];
3405 if (program->isAttribLocationActive(attributeIndex) && binding.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003406 {
3407 return true;
3408 }
3409 }
3410
Jamie Madill437fa652016-05-03 15:13:24 -04003411 context->handleError(Error(GL_INVALID_OPERATION,
3412 "ANGLE_instanced_arrays requires that at least one active attribute"
3413 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003414 return false;
3415}
3416
He Yunchaoced53ae2016-11-29 15:00:51 +08003417bool ValidateDrawArraysInstancedANGLE(Context *context,
3418 GLenum mode,
3419 GLint first,
3420 GLsizei count,
3421 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003422{
3423 if (!ValidateDrawInstancedANGLE(context))
3424 {
3425 return false;
3426 }
3427
3428 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3429}
3430
Jiajia Qind9671222016-11-29 16:30:31 +08003431bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003432{
Jamie Madill250d33f2014-06-06 17:09:03 -04003433 switch (type)
3434 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003435 case GL_UNSIGNED_BYTE:
3436 case GL_UNSIGNED_SHORT:
3437 break;
3438 case GL_UNSIGNED_INT:
3439 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3440 {
3441 context->handleError(Error(GL_INVALID_ENUM));
3442 return false;
3443 }
3444 break;
3445 default:
3446 context->handleError(Error(GL_INVALID_ENUM));
3447 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003448 }
3449
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003450 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003451
3452 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003453 if (curTransformFeedback && curTransformFeedback->isActive() &&
3454 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003455 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003456 // It is an invalid operation to call DrawElements, DrawRangeElements or
3457 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003458 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003459 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003460 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003461 }
3462
Jiajia Qind9671222016-11-29 16:30:31 +08003463 return true;
3464}
3465
3466bool ValidateDrawElements(ValidationContext *context,
3467 GLenum mode,
3468 GLsizei count,
3469 GLenum type,
3470 const GLvoid *indices,
3471 GLsizei primcount,
3472 IndexRange *indexRangeOut)
3473{
3474 if (!ValidateDrawElementsBase(context, type))
3475 return false;
3476
3477 const State &state = context->getGLState();
3478
Jamie Madill250d33f2014-06-06 17:09:03 -04003479 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003480 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003481 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003482 context->handleError(Error(GL_INVALID_OPERATION, "Index buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -04003483 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003484 }
3485
He Yunchaoced53ae2016-11-29 15:00:51 +08003486 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003487 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003488
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003489 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3490
3491 if (context->getExtensions().webglCompatibility)
3492 {
3493 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3494 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3495 {
3496 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3497 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3498 // data type passed to the call, or an INVALID_OPERATION error is generated.
3499 context->handleError(Error(GL_INVALID_OPERATION,
3500 "indices must be a multiple of the element type size."));
3501 return false;
3502 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003503 }
3504
3505 if (context->getExtensions().webglCompatibility ||
3506 !context->getGLState().areClientArraysEnabled())
3507 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003508 if (!elementArrayBuffer && count > 0)
3509 {
3510 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3511 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3512 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3513 context->handleError(Error(GL_INVALID_OPERATION,
3514 "There is no element array buffer bound and count > 0."));
3515 return false;
3516 }
3517 }
3518
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003519 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003520 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003521 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003522 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003523 GLint64 offset = reinterpret_cast<GLint64>(indices);
3524 GLint64 byteCount =
3525 static_cast<GLint64>(typeBytes) * static_cast<GLint64>(count) + offset;
3526
3527 // check for integer overflows
3528 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeBytes) ||
3529 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3530 {
3531 context->handleError(Error(GL_OUT_OF_MEMORY, "Integer overflow."));
3532 return false;
3533 }
3534
3535 // Check for reading past the end of the bound buffer object
3536 if (byteCount > elementArrayBuffer->getSize())
3537 {
3538 context->handleError(
3539 Error(GL_INVALID_OPERATION, "Index buffer is not big enough for the draw."));
3540 return false;
3541 }
3542 }
3543 else if (!indices)
3544 {
3545 // This is an application error that would normally result in a crash,
3546 // but we catch it and return an error
3547 context->handleError(
3548 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003549 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003550 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003551 }
3552
Jiajia Qind9671222016-11-29 16:30:31 +08003553 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003554 {
3555 return false;
3556 }
3557
Jamie Madill2b976812014-08-25 15:47:49 -04003558 // Use max index to validate if our vertex buffers are large enough for the pull.
3559 // TODO: offer fast path, with disabled index validation.
3560 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3561 if (elementArrayBuffer)
3562 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003563 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003564 Error error =
3565 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3566 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003567 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003568 {
Jamie Madill437fa652016-05-03 15:13:24 -04003569 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003570 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003571 }
3572 }
3573 else
3574 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003575 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003576 }
3577
Jamie Madille79b1e12015-11-04 16:36:37 -05003578 // If we use an index greater than our maximum supported index range, return an error.
3579 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3580 // return an error if possible here.
3581 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3582 {
Jamie Madill437fa652016-05-03 15:13:24 -04003583 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003584 return false;
3585 }
3586
Corentin Wallez92db6942016-12-09 13:10:36 -05003587 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3588 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003589 {
3590 return false;
3591 }
3592
Geoff Lang3edfe032015-09-04 16:38:24 -04003593 // No op if there are no real indices in the index data (all are primitive restart).
3594 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003595}
3596
Geoff Langb1196682014-07-23 13:47:29 -04003597bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003598 GLenum mode,
3599 GLsizei count,
3600 GLenum type,
3601 const GLvoid *indices,
3602 GLsizei primcount,
3603 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003604{
3605 if (primcount < 0)
3606 {
Jamie Madill437fa652016-05-03 15:13:24 -04003607 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003608 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003609 }
3610
Jamie Madill2b976812014-08-25 15:47:49 -04003611 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003612 {
3613 return false;
3614 }
3615
3616 // No-op zero primitive count
3617 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003618}
3619
Geoff Lang3edfe032015-09-04 16:38:24 -04003620bool ValidateDrawElementsInstancedANGLE(Context *context,
3621 GLenum mode,
3622 GLsizei count,
3623 GLenum type,
3624 const GLvoid *indices,
3625 GLsizei primcount,
3626 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003627{
3628 if (!ValidateDrawInstancedANGLE(context))
3629 {
3630 return false;
3631 }
3632
He Yunchaoced53ae2016-11-29 15:00:51 +08003633 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3634 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003635}
3636
He Yunchaoced53ae2016-11-29 15:00:51 +08003637bool ValidateFramebufferTextureBase(Context *context,
3638 GLenum target,
3639 GLenum attachment,
3640 GLuint texture,
3641 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003642{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003643 if (!ValidFramebufferTarget(target))
3644 {
Jamie Madill437fa652016-05-03 15:13:24 -04003645 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003646 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003647 }
3648
3649 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003650 {
3651 return false;
3652 }
3653
Jamie Madill55ec3b12014-07-03 10:38:57 -04003654 if (texture != 0)
3655 {
3656 gl::Texture *tex = context->getTexture(texture);
3657
3658 if (tex == NULL)
3659 {
Jamie Madill437fa652016-05-03 15:13:24 -04003660 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003661 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003662 }
3663
3664 if (level < 0)
3665 {
Jamie Madill437fa652016-05-03 15:13:24 -04003666 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003667 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003668 }
3669 }
3670
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003671 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003672 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003673
Jamie Madill84115c92015-04-23 15:00:07 -04003674 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003675 {
Jamie Madill437fa652016-05-03 15:13:24 -04003676 context->handleError(
3677 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003678 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003679 }
3680
3681 return true;
3682}
3683
He Yunchaoced53ae2016-11-29 15:00:51 +08003684bool ValidateFramebufferTexture2D(Context *context,
3685 GLenum target,
3686 GLenum attachment,
3687 GLenum textarget,
3688 GLuint texture,
3689 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003690{
He Yunchaoced53ae2016-11-29 15:00:51 +08003691 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3692 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003693 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3694 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003695 {
Jamie Madill437fa652016-05-03 15:13:24 -04003696 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003697 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003698 }
3699
3700 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003701 {
3702 return false;
3703 }
3704
Jamie Madill55ec3b12014-07-03 10:38:57 -04003705 if (texture != 0)
3706 {
3707 gl::Texture *tex = context->getTexture(texture);
3708 ASSERT(tex);
3709
Jamie Madill2a6564e2014-07-11 09:53:19 -04003710 const gl::Caps &caps = context->getCaps();
3711
Jamie Madill55ec3b12014-07-03 10:38:57 -04003712 switch (textarget)
3713 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003714 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003715 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003716 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003717 {
Jamie Madill437fa652016-05-03 15:13:24 -04003718 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003719 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003720 }
3721 if (tex->getTarget() != GL_TEXTURE_2D)
3722 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003723 context->handleError(Error(GL_INVALID_OPERATION,
3724 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003725 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003726 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003727 }
3728 break;
3729
He Yunchaoced53ae2016-11-29 15:00:51 +08003730 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3731 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3732 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3733 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3734 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3735 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003736 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003737 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003738 {
Jamie Madill437fa652016-05-03 15:13:24 -04003739 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003740 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003741 }
3742 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3743 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003744 context->handleError(Error(GL_INVALID_OPERATION,
3745 "Textarget must match the texture target type."));
3746 return false;
3747 }
3748 }
3749 break;
3750
3751 case GL_TEXTURE_2D_MULTISAMPLE:
3752 {
3753 if (context->getClientVersion() < ES_3_1)
3754 {
3755 context->handleError(Error(GL_INVALID_OPERATION,
3756 "Texture target requires at least OpenGL ES 3.1."));
3757 return false;
3758 }
3759
3760 if (level != 0)
3761 {
3762 context->handleError(
3763 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
3764 return false;
3765 }
3766 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
3767 {
3768 context->handleError(Error(GL_INVALID_OPERATION,
3769 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003770 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003771 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003772 }
3773 break;
3774
He Yunchaoced53ae2016-11-29 15:00:51 +08003775 default:
3776 context->handleError(Error(GL_INVALID_ENUM));
3777 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003778 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003779
Jamie Madilla3944d42016-07-22 22:13:26 -04003780 const Format &format = tex->getFormat(textarget, level);
3781 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003782 {
Jamie Madill437fa652016-05-03 15:13:24 -04003783 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003784 return false;
3785 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003786 }
3787
Jamie Madill570f7c82014-07-03 10:38:54 -04003788 return true;
3789}
3790
Geoff Langb1196682014-07-23 13:47:29 -04003791bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003792{
3793 if (program == 0)
3794 {
Jamie Madill437fa652016-05-03 15:13:24 -04003795 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003796 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003797 }
3798
Dian Xiang769769a2015-09-09 15:20:08 -07003799 gl::Program *programObject = GetValidProgram(context, program);
3800 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003801 {
3802 return false;
3803 }
3804
Jamie Madill0063c512014-08-25 15:47:53 -04003805 if (!programObject || !programObject->isLinked())
3806 {
Jamie Madill437fa652016-05-03 15:13:24 -04003807 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003808 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003809 }
3810
Geoff Lang7dd2e102014-11-10 15:19:26 -05003811 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003812 {
Jamie Madill437fa652016-05-03 15:13:24 -04003813 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003814 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003815 }
3816
Jamie Madill0063c512014-08-25 15:47:53 -04003817 return true;
3818}
3819
He Yunchaoced53ae2016-11-29 15:00:51 +08003820bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003821{
3822 return ValidateGetUniformBase(context, program, location);
3823}
3824
He Yunchaoced53ae2016-11-29 15:00:51 +08003825bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003826{
Jamie Madill78f41802014-08-25 15:47:55 -04003827 return ValidateGetUniformBase(context, program, location);
3828}
3829
Geoff Langf41d0ee2016-10-07 13:04:23 -04003830static bool ValidateSizedGetUniform(Context *context,
3831 GLuint program,
3832 GLint location,
3833 GLsizei bufSize,
3834 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003835{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003836 if (length)
3837 {
3838 *length = 0;
3839 }
3840
Jamie Madill78f41802014-08-25 15:47:55 -04003841 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003842 {
Jamie Madill78f41802014-08-25 15:47:55 -04003843 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003844 }
3845
Geoff Langf41d0ee2016-10-07 13:04:23 -04003846 if (bufSize < 0)
3847 {
3848 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3849 return false;
3850 }
3851
Jamie Madilla502c742014-08-28 17:19:13 -04003852 gl::Program *programObject = context->getProgram(program);
3853 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003854
Jamie Madill78f41802014-08-25 15:47:55 -04003855 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003856 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003857 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003858 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003859 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003860 context->handleError(
3861 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003862 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003863 }
3864
Geoff Langf41d0ee2016-10-07 13:04:23 -04003865 if (length)
3866 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003867 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003868 }
3869
Jamie Madill0063c512014-08-25 15:47:53 -04003870 return true;
3871}
3872
He Yunchaoced53ae2016-11-29 15:00:51 +08003873bool ValidateGetnUniformfvEXT(Context *context,
3874 GLuint program,
3875 GLint location,
3876 GLsizei bufSize,
3877 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003878{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003879 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003880}
3881
He Yunchaoced53ae2016-11-29 15:00:51 +08003882bool ValidateGetnUniformivEXT(Context *context,
3883 GLuint program,
3884 GLint location,
3885 GLsizei bufSize,
3886 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003887{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003888 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3889}
3890
3891bool ValidateGetUniformfvRobustANGLE(Context *context,
3892 GLuint program,
3893 GLint location,
3894 GLsizei bufSize,
3895 GLsizei *length,
3896 GLfloat *params)
3897{
3898 if (!ValidateRobustEntryPoint(context, bufSize))
3899 {
3900 return false;
3901 }
3902
3903 // bufSize is validated in ValidateSizedGetUniform
3904 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3905}
3906
3907bool ValidateGetUniformivRobustANGLE(Context *context,
3908 GLuint program,
3909 GLint location,
3910 GLsizei bufSize,
3911 GLsizei *length,
3912 GLint *params)
3913{
3914 if (!ValidateRobustEntryPoint(context, bufSize))
3915 {
3916 return false;
3917 }
3918
3919 // bufSize is validated in ValidateSizedGetUniform
3920 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3921}
3922
3923bool ValidateGetUniformuivRobustANGLE(Context *context,
3924 GLuint program,
3925 GLint location,
3926 GLsizei bufSize,
3927 GLsizei *length,
3928 GLuint *params)
3929{
3930 if (!ValidateRobustEntryPoint(context, bufSize))
3931 {
3932 return false;
3933 }
3934
3935 if (context->getClientMajorVersion() < 3)
3936 {
3937 context->handleError(
3938 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3939 return false;
3940 }
3941
3942 // bufSize is validated in ValidateSizedGetUniform
3943 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003944}
3945
He Yunchaoced53ae2016-11-29 15:00:51 +08003946bool ValidateDiscardFramebufferBase(Context *context,
3947 GLenum target,
3948 GLsizei numAttachments,
3949 const GLenum *attachments,
3950 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003951{
3952 if (numAttachments < 0)
3953 {
Jamie Madill437fa652016-05-03 15:13:24 -04003954 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003955 return false;
3956 }
3957
3958 for (GLsizei i = 0; i < numAttachments; ++i)
3959 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003960 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003961 {
3962 if (defaultFramebuffer)
3963 {
Jamie Madill437fa652016-05-03 15:13:24 -04003964 context->handleError(Error(
3965 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003966 return false;
3967 }
3968
3969 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3970 {
Jamie Madill437fa652016-05-03 15:13:24 -04003971 context->handleError(Error(GL_INVALID_OPERATION,
3972 "Requested color attachment is greater than the maximum "
3973 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003974 return false;
3975 }
3976 }
3977 else
3978 {
3979 switch (attachments[i])
3980 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003981 case GL_DEPTH_ATTACHMENT:
3982 case GL_STENCIL_ATTACHMENT:
3983 case GL_DEPTH_STENCIL_ATTACHMENT:
3984 if (defaultFramebuffer)
3985 {
3986 context->handleError(
3987 Error(GL_INVALID_ENUM,
3988 "Invalid attachment when the default framebuffer is bound"));
3989 return false;
3990 }
3991 break;
3992 case GL_COLOR:
3993 case GL_DEPTH:
3994 case GL_STENCIL:
3995 if (!defaultFramebuffer)
3996 {
3997 context->handleError(
3998 Error(GL_INVALID_ENUM,
3999 "Invalid attachment when the default framebuffer is not bound"));
4000 return false;
4001 }
4002 break;
4003 default:
4004 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07004005 return false;
Austin Kinross08332632015-05-05 13:35:47 -07004006 }
4007 }
4008 }
4009
4010 return true;
4011}
4012
Austin Kinross6ee1e782015-05-29 17:05:37 -07004013bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
4014{
4015 // Note that debug marker calls must not set error state
4016
4017 if (length < 0)
4018 {
4019 return false;
4020 }
4021
4022 if (marker == nullptr)
4023 {
4024 return false;
4025 }
4026
4027 return true;
4028}
4029
4030bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
4031{
4032 // Note that debug marker calls must not set error state
4033
4034 if (length < 0)
4035 {
4036 return false;
4037 }
4038
4039 if (length > 0 && marker == nullptr)
4040 {
4041 return false;
4042 }
4043
4044 return true;
4045}
4046
Geoff Langdcab33b2015-07-21 13:03:16 -04004047bool ValidateEGLImageTargetTexture2DOES(Context *context,
4048 egl::Display *display,
4049 GLenum target,
4050 egl::Image *image)
4051{
Geoff Langa8406172015-07-21 16:53:39 -04004052 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
4053 {
Jamie Madill437fa652016-05-03 15:13:24 -04004054 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004055 return false;
4056 }
4057
4058 switch (target)
4059 {
4060 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04004061 if (!context->getExtensions().eglImage)
4062 {
4063 context->handleError(Error(
4064 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
4065 }
4066 break;
4067
4068 case GL_TEXTURE_EXTERNAL_OES:
4069 if (!context->getExtensions().eglImageExternal)
4070 {
4071 context->handleError(Error(
4072 GL_INVALID_ENUM,
4073 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
4074 }
Geoff Langa8406172015-07-21 16:53:39 -04004075 break;
4076
4077 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004078 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04004079 return false;
4080 }
4081
4082 if (!display->isValidImage(image))
4083 {
Jamie Madill437fa652016-05-03 15:13:24 -04004084 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004085 return false;
4086 }
4087
4088 if (image->getSamples() > 0)
4089 {
Jamie Madill437fa652016-05-03 15:13:24 -04004090 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004091 "cannot create a 2D texture from a multisampled EGL image."));
4092 return false;
4093 }
4094
Jamie Madilla3944d42016-07-22 22:13:26 -04004095 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004096 if (!textureCaps.texturable)
4097 {
Jamie Madill437fa652016-05-03 15:13:24 -04004098 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004099 "EGL image internal format is not supported as a texture."));
4100 return false;
4101 }
4102
Geoff Langdcab33b2015-07-21 13:03:16 -04004103 return true;
4104}
4105
4106bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
4107 egl::Display *display,
4108 GLenum target,
4109 egl::Image *image)
4110{
Geoff Langa8406172015-07-21 16:53:39 -04004111 if (!context->getExtensions().eglImage)
4112 {
Jamie Madill437fa652016-05-03 15:13:24 -04004113 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004114 return false;
4115 }
4116
4117 switch (target)
4118 {
4119 case GL_RENDERBUFFER:
4120 break;
4121
4122 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004123 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04004124 return false;
4125 }
4126
4127 if (!display->isValidImage(image))
4128 {
Jamie Madill437fa652016-05-03 15:13:24 -04004129 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004130 return false;
4131 }
4132
Jamie Madilla3944d42016-07-22 22:13:26 -04004133 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004134 if (!textureCaps.renderable)
4135 {
Jamie Madill437fa652016-05-03 15:13:24 -04004136 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04004137 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
4138 return false;
4139 }
4140
Geoff Langdcab33b2015-07-21 13:03:16 -04004141 return true;
4142}
Austin Kinrossbc781f32015-10-26 09:27:38 -07004143
4144bool ValidateBindVertexArrayBase(Context *context, GLuint array)
4145{
Geoff Lang36167ab2015-12-07 10:27:14 -05004146 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07004147 {
4148 // The default VAO should always exist
4149 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004150 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004151 return false;
4152 }
4153
4154 return true;
4155}
4156
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004157bool ValidateLinkProgram(Context *context, GLuint program)
4158{
4159 if (context->hasActiveTransformFeedback(program))
4160 {
4161 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004162 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004163 "Cannot link program while program is associated with an active "
4164 "transform feedback object."));
4165 return false;
4166 }
4167 return true;
4168}
4169
Geoff Langc5629752015-12-07 16:29:04 -05004170bool ValidateProgramBinaryBase(Context *context,
4171 GLuint program,
4172 GLenum binaryFormat,
4173 const void *binary,
4174 GLint length)
4175{
4176 Program *programObject = GetValidProgram(context, program);
4177 if (programObject == nullptr)
4178 {
4179 return false;
4180 }
4181
4182 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4183 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4184 programBinaryFormats.end())
4185 {
Jamie Madill437fa652016-05-03 15:13:24 -04004186 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004187 return false;
4188 }
4189
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004190 if (context->hasActiveTransformFeedback(program))
4191 {
4192 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004193 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004194 "Cannot change program binary while program is associated with "
4195 "an active transform feedback object."));
4196 return false;
4197 }
4198
Geoff Langc5629752015-12-07 16:29:04 -05004199 return true;
4200}
4201
4202bool ValidateGetProgramBinaryBase(Context *context,
4203 GLuint program,
4204 GLsizei bufSize,
4205 GLsizei *length,
4206 GLenum *binaryFormat,
4207 void *binary)
4208{
4209 Program *programObject = GetValidProgram(context, program);
4210 if (programObject == nullptr)
4211 {
4212 return false;
4213 }
4214
4215 if (!programObject->isLinked())
4216 {
Jamie Madill437fa652016-05-03 15:13:24 -04004217 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004218 return false;
4219 }
4220
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004221 if (context->getCaps().programBinaryFormats.empty())
4222 {
4223 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4224 return false;
4225 }
4226
Geoff Langc5629752015-12-07 16:29:04 -05004227 return true;
4228}
Jamie Madillc29968b2016-01-20 11:17:23 -05004229
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004230bool ValidateUseProgram(Context *context, GLuint program)
4231{
4232 if (program != 0)
4233 {
4234 Program *programObject = context->getProgram(program);
4235 if (!programObject)
4236 {
4237 // ES 3.1.0 section 7.3 page 72
4238 if (context->getShader(program))
4239 {
Jamie Madill437fa652016-05-03 15:13:24 -04004240 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004241 Error(GL_INVALID_OPERATION,
4242 "Attempted to use a single shader instead of a shader program."));
4243 return false;
4244 }
4245 else
4246 {
Jamie Madill437fa652016-05-03 15:13:24 -04004247 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004248 return false;
4249 }
4250 }
4251 if (!programObject->isLinked())
4252 {
Jamie Madill437fa652016-05-03 15:13:24 -04004253 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004254 return false;
4255 }
4256 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004257 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004258 {
4259 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004260 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004261 Error(GL_INVALID_OPERATION,
4262 "Cannot change active program while transform feedback is unpaused."));
4263 return false;
4264 }
4265
4266 return true;
4267}
4268
Jamie Madillc29968b2016-01-20 11:17:23 -05004269bool ValidateCopyTexImage2D(ValidationContext *context,
4270 GLenum target,
4271 GLint level,
4272 GLenum internalformat,
4273 GLint x,
4274 GLint y,
4275 GLsizei width,
4276 GLsizei height,
4277 GLint border)
4278{
Martin Radev1be913c2016-07-11 17:59:16 +03004279 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004280 {
4281 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4282 0, x, y, width, height, border);
4283 }
4284
Martin Radev1be913c2016-07-11 17:59:16 +03004285 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004286 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4287 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004288}
Jamie Madillc29968b2016-01-20 11:17:23 -05004289
4290bool ValidateFramebufferRenderbuffer(Context *context,
4291 GLenum target,
4292 GLenum attachment,
4293 GLenum renderbuffertarget,
4294 GLuint renderbuffer)
4295{
4296 if (!ValidFramebufferTarget(target) ||
4297 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4298 {
Jamie Madill437fa652016-05-03 15:13:24 -04004299 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004300 return false;
4301 }
4302
4303 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4304 renderbuffertarget, renderbuffer);
4305}
4306
4307bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4308{
4309 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4310 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4311 {
Jamie Madill437fa652016-05-03 15:13:24 -04004312 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004313 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4314 return false;
4315 }
4316
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004317 ASSERT(context->getGLState().getDrawFramebuffer());
4318 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004319 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4320
4321 // This should come first before the check for the default frame buffer
4322 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4323 // rather than INVALID_OPERATION
4324 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4325 {
4326 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4327
4328 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004329 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4330 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004331 {
4332 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004333 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4334 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4335 // 3.1 is still a bit ambiguous about the error, but future specs are
4336 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004337 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004338 return false;
4339 }
4340 else if (bufs[colorAttachment] >= maxColorAttachment)
4341 {
Jamie Madill437fa652016-05-03 15:13:24 -04004342 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004343 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004344 return false;
4345 }
4346 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4347 frameBufferId != 0)
4348 {
4349 // INVALID_OPERATION-GL is bound to buffer and ith argument
4350 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004351 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004352 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4353 return false;
4354 }
4355 }
4356
4357 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4358 // and n is not 1 or bufs is bound to value other than BACK and NONE
4359 if (frameBufferId == 0)
4360 {
4361 if (n != 1)
4362 {
Jamie Madill437fa652016-05-03 15:13:24 -04004363 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004364 "n must be 1 when GL is bound to the default framebuffer"));
4365 return false;
4366 }
4367
4368 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4369 {
Jamie Madill437fa652016-05-03 15:13:24 -04004370 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004371 GL_INVALID_OPERATION,
4372 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4373 return false;
4374 }
4375 }
4376
4377 return true;
4378}
4379
4380bool ValidateCopyTexSubImage2D(Context *context,
4381 GLenum target,
4382 GLint level,
4383 GLint xoffset,
4384 GLint yoffset,
4385 GLint x,
4386 GLint y,
4387 GLsizei width,
4388 GLsizei height)
4389{
Martin Radev1be913c2016-07-11 17:59:16 +03004390 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004391 {
4392 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4393 yoffset, x, y, width, height, 0);
4394 }
4395
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004396 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4397 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004398}
4399
Geoff Lang496c02d2016-10-20 11:38:11 -07004400bool ValidateGetBufferPointervBase(Context *context,
4401 GLenum target,
4402 GLenum pname,
4403 GLsizei *length,
4404 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004405{
Geoff Lang496c02d2016-10-20 11:38:11 -07004406 if (length)
4407 {
4408 *length = 0;
4409 }
4410
4411 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4412 {
4413 context->handleError(
4414 Error(GL_INVALID_OPERATION,
Jamie Madillcc6ac252017-01-25 12:57:21 -08004415 "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
Geoff Lang496c02d2016-10-20 11:38:11 -07004416 return false;
4417 }
4418
Olli Etuaho4f667482016-03-30 15:56:35 +03004419 if (!ValidBufferTarget(context, target))
4420 {
Jamie Madill437fa652016-05-03 15:13:24 -04004421 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004422 return false;
4423 }
4424
Geoff Lang496c02d2016-10-20 11:38:11 -07004425 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004426 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004427 case GL_BUFFER_MAP_POINTER:
4428 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004429
Geoff Lang496c02d2016-10-20 11:38:11 -07004430 default:
4431 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4432 return false;
4433 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004434
4435 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4436 // target bound to zero generate an INVALID_OPERATION error."
4437 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004438 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004439 {
Jamie Madill437fa652016-05-03 15:13:24 -04004440 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004441 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4442 return false;
4443 }
4444
Geoff Lang496c02d2016-10-20 11:38:11 -07004445 if (length)
4446 {
4447 *length = 1;
4448 }
4449
Olli Etuaho4f667482016-03-30 15:56:35 +03004450 return true;
4451}
4452
4453bool ValidateUnmapBufferBase(Context *context, GLenum target)
4454{
4455 if (!ValidBufferTarget(context, target))
4456 {
Jamie Madill437fa652016-05-03 15:13:24 -04004457 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004458 return false;
4459 }
4460
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004461 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004462
4463 if (buffer == nullptr || !buffer->isMapped())
4464 {
Jamie Madill437fa652016-05-03 15:13:24 -04004465 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004466 return false;
4467 }
4468
4469 return true;
4470}
4471
4472bool ValidateMapBufferRangeBase(Context *context,
4473 GLenum target,
4474 GLintptr offset,
4475 GLsizeiptr length,
4476 GLbitfield access)
4477{
4478 if (!ValidBufferTarget(context, target))
4479 {
Jamie Madill437fa652016-05-03 15:13:24 -04004480 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004481 return false;
4482 }
4483
4484 if (offset < 0 || length < 0)
4485 {
Jamie Madill437fa652016-05-03 15:13:24 -04004486 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004487 return false;
4488 }
4489
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004490 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004491
4492 if (!buffer)
4493 {
Jamie Madill437fa652016-05-03 15:13:24 -04004494 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004495 return false;
4496 }
4497
4498 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004499 CheckedNumeric<size_t> checkedOffset(offset);
4500 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004501
Jamie Madille2e406c2016-06-02 13:04:10 -04004502 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004503 {
Jamie Madill437fa652016-05-03 15:13:24 -04004504 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004505 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4506 return false;
4507 }
4508
4509 // Check for invalid bits in the mask
4510 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4511 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4512 GL_MAP_UNSYNCHRONIZED_BIT;
4513
4514 if (access & ~(allAccessBits))
4515 {
Jamie Madill437fa652016-05-03 15:13:24 -04004516 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004517 return false;
4518 }
4519
4520 if (length == 0)
4521 {
Jamie Madill437fa652016-05-03 15:13:24 -04004522 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004523 return false;
4524 }
4525
4526 if (buffer->isMapped())
4527 {
Jamie Madill437fa652016-05-03 15:13:24 -04004528 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004529 return false;
4530 }
4531
4532 // Check for invalid bit combinations
4533 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4534 {
Jamie Madill437fa652016-05-03 15:13:24 -04004535 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004536 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4537 return false;
4538 }
4539
4540 GLbitfield writeOnlyBits =
4541 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4542
4543 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4544 {
Jamie Madill437fa652016-05-03 15:13:24 -04004545 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004546 "Invalid access bits when mapping buffer for reading: 0x%X.",
4547 access));
4548 return false;
4549 }
4550
4551 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4552 {
Jamie Madill437fa652016-05-03 15:13:24 -04004553 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004554 GL_INVALID_OPERATION,
4555 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4556 return false;
4557 }
4558 return true;
4559}
4560
4561bool ValidateFlushMappedBufferRangeBase(Context *context,
4562 GLenum target,
4563 GLintptr offset,
4564 GLsizeiptr length)
4565{
4566 if (offset < 0 || length < 0)
4567 {
Jamie Madill437fa652016-05-03 15:13:24 -04004568 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004569 return false;
4570 }
4571
4572 if (!ValidBufferTarget(context, target))
4573 {
Jamie Madill437fa652016-05-03 15:13:24 -04004574 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004575 return false;
4576 }
4577
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004578 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004579
4580 if (buffer == nullptr)
4581 {
Jamie Madill437fa652016-05-03 15:13:24 -04004582 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004583 return false;
4584 }
4585
4586 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4587 {
Jamie Madill437fa652016-05-03 15:13:24 -04004588 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004589 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4590 return false;
4591 }
4592
4593 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004594 CheckedNumeric<size_t> checkedOffset(offset);
4595 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004596
Jamie Madille2e406c2016-06-02 13:04:10 -04004597 if (!checkedSize.IsValid() ||
4598 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004599 {
Jamie Madill437fa652016-05-03 15:13:24 -04004600 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004601 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4602 return false;
4603 }
4604
4605 return true;
4606}
4607
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004608bool ValidateGenerateMipmap(Context *context, GLenum target)
4609{
4610 if (!ValidTextureTarget(context, target))
4611 {
4612 context->handleError(Error(GL_INVALID_ENUM));
4613 return false;
4614 }
4615
4616 Texture *texture = context->getTargetTexture(target);
4617
4618 if (texture == nullptr)
4619 {
4620 context->handleError(Error(GL_INVALID_OPERATION));
4621 return false;
4622 }
4623
4624 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4625
4626 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4627 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4628 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4629 {
4630 context->handleError(Error(GL_INVALID_OPERATION));
4631 return false;
4632 }
4633
Jamie Madilla3944d42016-07-22 22:13:26 -04004634 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4635 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4636 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004637
4638 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4639 // unsized formats or that are color renderable and filterable. Since we do not track if
4640 // the texture was created with sized or unsized format (only sized formats are stored),
4641 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4642 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4643 // textures since they're the only texture format that can be created with unsized formats
4644 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4645 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004646 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4647 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004648 {
4649 context->handleError(Error(GL_INVALID_OPERATION));
4650 return false;
4651 }
4652
4653 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004654 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004655 {
4656 context->handleError(Error(GL_INVALID_OPERATION));
4657 return false;
4658 }
4659
4660 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004661 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004662 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4663 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4664 {
Geoff Lang55482a12016-11-21 16:54:01 -05004665 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004666 context->handleError(Error(GL_INVALID_OPERATION));
4667 return false;
4668 }
4669
4670 // Cube completeness check
4671 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4672 {
4673 context->handleError(Error(GL_INVALID_OPERATION));
4674 return false;
4675 }
4676
4677 return true;
4678}
4679
Olli Etuaho41997e72016-03-10 13:38:39 +02004680bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4681{
4682 return ValidateGenOrDelete(context, n);
4683}
4684
4685bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4686{
4687 return ValidateGenOrDelete(context, n);
4688}
4689
4690bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4691{
4692 return ValidateGenOrDelete(context, n);
4693}
4694
4695bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4696{
4697 return ValidateGenOrDelete(context, n);
4698}
4699
4700bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4701{
4702 return ValidateGenOrDelete(context, n);
4703}
4704
4705bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4706{
4707 return ValidateGenOrDelete(context, n);
4708}
4709
4710bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4711{
4712 return ValidateGenOrDelete(context, n);
4713}
4714
4715bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4716{
4717 return ValidateGenOrDelete(context, n);
4718}
4719
4720bool ValidateGenOrDelete(Context *context, GLint n)
4721{
4722 if (n < 0)
4723 {
Jamie Madill437fa652016-05-03 15:13:24 -04004724 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004725 return false;
4726 }
4727 return true;
4728}
4729
Geoff Langf41a7152016-09-19 15:11:17 -04004730bool ValidateEnable(Context *context, GLenum cap)
4731{
4732 if (!ValidCap(context, cap, false))
4733 {
4734 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4735 return false;
4736 }
4737
4738 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4739 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4740 {
4741 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4742 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4743
4744 // We also output an error message to the debugger window if tracing is active, so that
4745 // developers can see the error message.
Yuly Novikovd73f8522017-01-13 17:48:57 -05004746 ERR() << errorMessage;
Geoff Langf41a7152016-09-19 15:11:17 -04004747 return false;
4748 }
4749
4750 return true;
4751}
4752
4753bool ValidateDisable(Context *context, GLenum cap)
4754{
4755 if (!ValidCap(context, cap, false))
4756 {
4757 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4758 return false;
4759 }
4760
4761 return true;
4762}
4763
4764bool ValidateIsEnabled(Context *context, GLenum cap)
4765{
4766 if (!ValidCap(context, cap, true))
4767 {
4768 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4769 return false;
4770 }
4771
4772 return true;
4773}
4774
Geoff Langff5b2d52016-09-07 11:32:23 -04004775bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4776{
4777 if (!context->getExtensions().robustClientMemory)
4778 {
4779 context->handleError(
4780 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4781 return false;
4782 }
4783
4784 if (bufSize < 0)
4785 {
4786 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4787 return false;
4788 }
4789
4790 return true;
4791}
4792
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004793bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4794{
4795 if (bufSize < numParams)
4796 {
4797 context->handleError(Error(GL_INVALID_OPERATION,
4798 "%u parameters are required but %i were provided.", numParams,
4799 bufSize));
4800 return false;
4801 }
4802
4803 return true;
4804}
4805
Geoff Langff5b2d52016-09-07 11:32:23 -04004806bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4807 GLenum target,
4808 GLenum attachment,
4809 GLenum pname,
4810 GLsizei *numParams)
4811{
4812 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4813 *numParams = 1;
4814
4815 if (!ValidFramebufferTarget(target))
4816 {
4817 context->handleError(Error(GL_INVALID_ENUM));
4818 return false;
4819 }
4820
4821 int clientVersion = context->getClientMajorVersion();
4822
4823 switch (pname)
4824 {
4825 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4826 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4827 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4828 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4829 break;
4830
4831 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4832 if (clientVersion < 3 && !context->getExtensions().sRGB)
4833 {
4834 context->handleError(Error(GL_INVALID_ENUM));
4835 return false;
4836 }
4837 break;
4838
4839 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4840 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4841 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4842 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4843 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4844 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4845 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4846 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4847 if (clientVersion < 3)
4848 {
4849 context->handleError(Error(GL_INVALID_ENUM));
4850 return false;
4851 }
4852 break;
4853
4854 default:
4855 context->handleError(Error(GL_INVALID_ENUM));
4856 return false;
4857 }
4858
4859 // Determine if the attachment is a valid enum
4860 switch (attachment)
4861 {
4862 case GL_BACK:
4863 case GL_FRONT:
4864 case GL_DEPTH:
4865 case GL_STENCIL:
4866 case GL_DEPTH_STENCIL_ATTACHMENT:
4867 if (clientVersion < 3)
4868 {
4869 context->handleError(Error(GL_INVALID_ENUM));
4870 return false;
4871 }
4872 break;
4873
4874 case GL_DEPTH_ATTACHMENT:
4875 case GL_STENCIL_ATTACHMENT:
4876 break;
4877
4878 default:
4879 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4880 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4881 {
4882 context->handleError(Error(GL_INVALID_ENUM));
4883 return false;
4884 }
4885 break;
4886 }
4887
4888 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4889 ASSERT(framebuffer);
4890
4891 if (framebuffer->id() == 0)
4892 {
4893 if (clientVersion < 3)
4894 {
4895 context->handleError(Error(GL_INVALID_OPERATION));
4896 return false;
4897 }
4898
4899 switch (attachment)
4900 {
4901 case GL_BACK:
4902 case GL_DEPTH:
4903 case GL_STENCIL:
4904 break;
4905
4906 default:
4907 context->handleError(Error(GL_INVALID_OPERATION));
4908 return false;
4909 }
4910 }
4911 else
4912 {
4913 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4914 {
4915 // Valid attachment query
4916 }
4917 else
4918 {
4919 switch (attachment)
4920 {
4921 case GL_DEPTH_ATTACHMENT:
4922 case GL_STENCIL_ATTACHMENT:
4923 break;
4924
4925 case GL_DEPTH_STENCIL_ATTACHMENT:
4926 if (!framebuffer->hasValidDepthStencil())
4927 {
4928 context->handleError(Error(GL_INVALID_OPERATION));
4929 return false;
4930 }
4931 break;
4932
4933 default:
4934 context->handleError(Error(GL_INVALID_OPERATION));
4935 return false;
4936 }
4937 }
4938 }
4939
4940 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4941 if (attachmentObject)
4942 {
4943 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4944 attachmentObject->type() == GL_TEXTURE ||
4945 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4946
4947 switch (pname)
4948 {
4949 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4950 if (attachmentObject->type() != GL_RENDERBUFFER &&
4951 attachmentObject->type() != GL_TEXTURE)
4952 {
4953 context->handleError(Error(GL_INVALID_ENUM));
4954 return false;
4955 }
4956 break;
4957
4958 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4959 if (attachmentObject->type() != GL_TEXTURE)
4960 {
4961 context->handleError(Error(GL_INVALID_ENUM));
4962 return false;
4963 }
4964 break;
4965
4966 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4967 if (attachmentObject->type() != GL_TEXTURE)
4968 {
4969 context->handleError(Error(GL_INVALID_ENUM));
4970 return false;
4971 }
4972 break;
4973
4974 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4975 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4976 {
4977 context->handleError(Error(GL_INVALID_OPERATION));
4978 return false;
4979 }
4980 break;
4981
4982 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4983 if (attachmentObject->type() != GL_TEXTURE)
4984 {
4985 context->handleError(Error(GL_INVALID_ENUM));
4986 return false;
4987 }
4988 break;
4989
4990 default:
4991 break;
4992 }
4993 }
4994 else
4995 {
4996 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4997 // is NONE, then querying any other pname will generate INVALID_ENUM.
4998
4999 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
5000 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
5001 // INVALID_OPERATION for all other pnames
5002
5003 switch (pname)
5004 {
5005 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
5006 break;
5007
5008 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5009 if (clientVersion < 3)
5010 {
5011 context->handleError(Error(GL_INVALID_ENUM));
5012 return false;
5013 }
5014 break;
5015
5016 default:
5017 if (clientVersion < 3)
5018 {
5019 context->handleError(Error(GL_INVALID_ENUM));
5020 return false;
5021 }
5022 else
5023 {
5024 context->handleError(Error(GL_INVALID_OPERATION));
5025 return false;
5026 }
5027 }
5028 }
5029
5030 return true;
5031}
5032
5033bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
5034 GLenum target,
5035 GLenum attachment,
5036 GLenum pname,
5037 GLsizei bufSize,
5038 GLsizei *numParams)
5039{
5040 if (!ValidateRobustEntryPoint(context, bufSize))
5041 {
5042 return false;
5043 }
5044
5045 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
5046 {
5047 return false;
5048 }
5049
5050 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5051 {
5052 return false;
5053 }
5054
5055 return true;
5056}
5057
5058bool ValidateGetBufferParameteriv(ValidationContext *context,
5059 GLenum target,
5060 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04005061 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005062{
Geoff Langebebe1c2016-10-14 12:01:31 -04005063 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04005064}
5065
5066bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
5067 GLenum target,
5068 GLenum pname,
5069 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04005070 GLsizei *length,
5071 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005072{
5073 if (!ValidateRobustEntryPoint(context, bufSize))
5074 {
5075 return false;
5076 }
5077
Geoff Langebebe1c2016-10-14 12:01:31 -04005078 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005079 {
5080 return false;
5081 }
5082
Geoff Langebebe1c2016-10-14 12:01:31 -04005083 if (!ValidateRobustBufferSize(context, bufSize, *length))
5084 {
5085 return false;
5086 }
5087
5088 return true;
5089}
5090
5091bool ValidateGetBufferParameteri64v(ValidationContext *context,
5092 GLenum target,
5093 GLenum pname,
5094 GLint64 *params)
5095{
5096 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5097}
5098
5099bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
5100 GLenum target,
5101 GLenum pname,
5102 GLsizei bufSize,
5103 GLsizei *length,
5104 GLint64 *params)
5105{
5106 if (!ValidateRobustEntryPoint(context, bufSize))
5107 {
5108 return false;
5109 }
5110
5111 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
5112 {
5113 return false;
5114 }
5115
5116 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005117 {
5118 return false;
5119 }
5120
5121 return true;
5122}
5123
5124bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
5125{
5126 // Currently, all GetProgramiv queries return 1 parameter
5127 *numParams = 1;
5128
5129 Program *programObject = GetValidProgram(context, program);
5130 if (!programObject)
5131 {
5132 return false;
5133 }
5134
5135 switch (pname)
5136 {
5137 case GL_DELETE_STATUS:
5138 case GL_LINK_STATUS:
5139 case GL_VALIDATE_STATUS:
5140 case GL_INFO_LOG_LENGTH:
5141 case GL_ATTACHED_SHADERS:
5142 case GL_ACTIVE_ATTRIBUTES:
5143 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
5144 case GL_ACTIVE_UNIFORMS:
5145 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
5146 break;
5147
5148 case GL_PROGRAM_BINARY_LENGTH:
5149 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5150 {
5151 context->handleError(Error(GL_INVALID_ENUM,
5152 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5153 "GL_OES_get_program_binary or ES 3.0."));
5154 return false;
5155 }
5156 break;
5157
5158 case GL_ACTIVE_UNIFORM_BLOCKS:
5159 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5160 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5161 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5162 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5163 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5164 if (context->getClientMajorVersion() < 3)
5165 {
5166 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5167 return false;
5168 }
5169 break;
5170
5171 default:
5172 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5173 return false;
5174 }
5175
5176 return true;
5177}
5178
5179bool ValidateGetProgramivRobustANGLE(Context *context,
5180 GLuint program,
5181 GLenum pname,
5182 GLsizei bufSize,
5183 GLsizei *numParams)
5184{
5185 if (!ValidateRobustEntryPoint(context, bufSize))
5186 {
5187 return false;
5188 }
5189
5190 if (!ValidateGetProgramiv(context, program, pname, numParams))
5191 {
5192 return false;
5193 }
5194
5195 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5196 {
5197 return false;
5198 }
5199
5200 return true;
5201}
5202
Geoff Lang740d9022016-10-07 11:20:52 -04005203bool ValidateGetRenderbufferParameteriv(Context *context,
5204 GLenum target,
5205 GLenum pname,
5206 GLint *params)
5207{
5208 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5209}
5210
5211bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5212 GLenum target,
5213 GLenum pname,
5214 GLsizei bufSize,
5215 GLsizei *length,
5216 GLint *params)
5217{
5218 if (!ValidateRobustEntryPoint(context, bufSize))
5219 {
5220 return false;
5221 }
5222
5223 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5224 {
5225 return false;
5226 }
5227
5228 if (!ValidateRobustBufferSize(context, bufSize, *length))
5229 {
5230 return false;
5231 }
5232
5233 return true;
5234}
5235
Geoff Langd7d0ed32016-10-07 11:33:51 -04005236bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5237{
5238 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5239}
5240
5241bool ValidateGetShaderivRobustANGLE(Context *context,
5242 GLuint shader,
5243 GLenum pname,
5244 GLsizei bufSize,
5245 GLsizei *length,
5246 GLint *params)
5247{
5248 if (!ValidateRobustEntryPoint(context, bufSize))
5249 {
5250 return false;
5251 }
5252
5253 if (!ValidateGetShaderivBase(context, shader, pname, length))
5254 {
5255 return false;
5256 }
5257
5258 if (!ValidateRobustBufferSize(context, bufSize, *length))
5259 {
5260 return false;
5261 }
5262
5263 return true;
5264}
5265
Geoff Langc1984ed2016-10-07 12:41:00 -04005266bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5267{
5268 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5269}
5270
5271bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5272 GLenum target,
5273 GLenum pname,
5274 GLsizei bufSize,
5275 GLsizei *length,
5276 GLfloat *params)
5277{
5278 if (!ValidateRobustEntryPoint(context, bufSize))
5279 {
5280 return false;
5281 }
5282
5283 if (!ValidateGetTexParameterBase(context, target, pname, length))
5284 {
5285 return false;
5286 }
5287
5288 if (!ValidateRobustBufferSize(context, bufSize, *length))
5289 {
5290 return false;
5291 }
5292
5293 return true;
5294}
5295
5296bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5297{
5298 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5299}
5300
5301bool ValidateGetTexParameterivRobustANGLE(Context *context,
5302 GLenum target,
5303 GLenum pname,
5304 GLsizei bufSize,
5305 GLsizei *length,
5306 GLint *params)
5307{
5308 if (!ValidateRobustEntryPoint(context, bufSize))
5309 {
5310 return false;
5311 }
5312
5313 if (!ValidateGetTexParameterBase(context, target, pname, length))
5314 {
5315 return false;
5316 }
5317
5318 if (!ValidateRobustBufferSize(context, bufSize, *length))
5319 {
5320 return false;
5321 }
5322
5323 return true;
5324}
5325
5326bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5327{
5328 return ValidateTexParameterBase(context, target, pname, -1, &param);
5329}
5330
5331bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5332{
5333 return ValidateTexParameterBase(context, target, pname, -1, params);
5334}
5335
5336bool ValidateTexParameterfvRobustANGLE(Context *context,
5337 GLenum target,
5338 GLenum pname,
5339 GLsizei bufSize,
5340 const GLfloat *params)
5341{
5342 if (!ValidateRobustEntryPoint(context, bufSize))
5343 {
5344 return false;
5345 }
5346
5347 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5348}
5349
5350bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5351{
5352 return ValidateTexParameterBase(context, target, pname, -1, &param);
5353}
5354
5355bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5356{
5357 return ValidateTexParameterBase(context, target, pname, -1, params);
5358}
5359
5360bool ValidateTexParameterivRobustANGLE(Context *context,
5361 GLenum target,
5362 GLenum pname,
5363 GLsizei bufSize,
5364 const GLint *params)
5365{
5366 if (!ValidateRobustEntryPoint(context, bufSize))
5367 {
5368 return false;
5369 }
5370
5371 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5372}
5373
5374bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5375{
5376 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5377}
5378
5379bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5380 GLuint sampler,
5381 GLenum pname,
5382 GLuint bufSize,
5383 GLsizei *length,
5384 GLfloat *params)
5385{
5386 if (!ValidateRobustEntryPoint(context, bufSize))
5387 {
5388 return false;
5389 }
5390
5391 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5392 {
5393 return false;
5394 }
5395
5396 if (!ValidateRobustBufferSize(context, bufSize, *length))
5397 {
5398 return false;
5399 }
5400
5401 return true;
5402}
5403
5404bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5405{
5406 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5407}
5408
5409bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5410 GLuint sampler,
5411 GLenum pname,
5412 GLuint bufSize,
5413 GLsizei *length,
5414 GLint *params)
5415{
5416 if (!ValidateRobustEntryPoint(context, bufSize))
5417 {
5418 return false;
5419 }
5420
5421 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5422 {
5423 return false;
5424 }
5425
5426 if (!ValidateRobustBufferSize(context, bufSize, *length))
5427 {
5428 return false;
5429 }
5430
5431 return true;
5432}
5433
5434bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5435{
5436 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5437}
5438
5439bool ValidateSamplerParameterfv(Context *context,
5440 GLuint sampler,
5441 GLenum pname,
5442 const GLfloat *params)
5443{
5444 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5445}
5446
5447bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5448 GLuint sampler,
5449 GLenum pname,
5450 GLsizei bufSize,
5451 const GLfloat *params)
5452{
5453 if (!ValidateRobustEntryPoint(context, bufSize))
5454 {
5455 return false;
5456 }
5457
5458 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5459}
5460
5461bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5462{
5463 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5464}
5465
5466bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5467{
5468 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5469}
5470
5471bool ValidateSamplerParameterivRobustANGLE(Context *context,
5472 GLuint sampler,
5473 GLenum pname,
5474 GLsizei bufSize,
5475 const GLint *params)
5476{
5477 if (!ValidateRobustEntryPoint(context, bufSize))
5478 {
5479 return false;
5480 }
5481
5482 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5483}
5484
Geoff Lang0b031062016-10-13 14:30:04 -04005485bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5486{
5487 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5488}
5489
5490bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5491 GLuint index,
5492 GLenum pname,
5493 GLsizei bufSize,
5494 GLsizei *length,
5495 GLfloat *params)
5496{
5497 if (!ValidateRobustEntryPoint(context, bufSize))
5498 {
5499 return false;
5500 }
5501
5502 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5503 {
5504 return false;
5505 }
5506
5507 if (!ValidateRobustBufferSize(context, bufSize, *length))
5508 {
5509 return false;
5510 }
5511
5512 return true;
5513}
5514
5515bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5516{
5517 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5518}
5519
5520bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5521 GLuint index,
5522 GLenum pname,
5523 GLsizei bufSize,
5524 GLsizei *length,
5525 GLint *params)
5526{
5527 if (!ValidateRobustEntryPoint(context, bufSize))
5528 {
5529 return false;
5530 }
5531
5532 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5533 {
5534 return false;
5535 }
5536
5537 if (!ValidateRobustBufferSize(context, bufSize, *length))
5538 {
5539 return false;
5540 }
5541
5542 return true;
5543}
5544
5545bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5546{
5547 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5548}
5549
5550bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5551 GLuint index,
5552 GLenum pname,
5553 GLsizei bufSize,
5554 GLsizei *length,
5555 void **pointer)
5556{
5557 if (!ValidateRobustEntryPoint(context, bufSize))
5558 {
5559 return false;
5560 }
5561
5562 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5563 {
5564 return false;
5565 }
5566
5567 if (!ValidateRobustBufferSize(context, bufSize, *length))
5568 {
5569 return false;
5570 }
5571
5572 return true;
5573}
5574
5575bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5576{
5577 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5578}
5579
5580bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5581 GLuint index,
5582 GLenum pname,
5583 GLsizei bufSize,
5584 GLsizei *length,
5585 GLint *params)
5586{
5587 if (!ValidateRobustEntryPoint(context, bufSize))
5588 {
5589 return false;
5590 }
5591
5592 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5593 {
5594 return false;
5595 }
5596
5597 if (!ValidateRobustBufferSize(context, bufSize, *length))
5598 {
5599 return false;
5600 }
5601
5602 return true;
5603}
5604
5605bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5606{
5607 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5608}
5609
5610bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5611 GLuint index,
5612 GLenum pname,
5613 GLsizei bufSize,
5614 GLsizei *length,
5615 GLuint *params)
5616{
5617 if (!ValidateRobustEntryPoint(context, bufSize))
5618 {
5619 return false;
5620 }
5621
5622 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5623 {
5624 return false;
5625 }
5626
5627 if (!ValidateRobustBufferSize(context, bufSize, *length))
5628 {
5629 return false;
5630 }
5631
5632 return true;
5633}
5634
Geoff Lang6899b872016-10-14 11:30:13 -04005635bool ValidateGetActiveUniformBlockiv(Context *context,
5636 GLuint program,
5637 GLuint uniformBlockIndex,
5638 GLenum pname,
5639 GLint *params)
5640{
5641 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5642}
5643
5644bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5645 GLuint program,
5646 GLuint uniformBlockIndex,
5647 GLenum pname,
5648 GLsizei bufSize,
5649 GLsizei *length,
5650 GLint *params)
5651{
5652 if (!ValidateRobustEntryPoint(context, bufSize))
5653 {
5654 return false;
5655 }
5656
5657 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5658 {
5659 return false;
5660 }
5661
5662 if (!ValidateRobustBufferSize(context, bufSize, *length))
5663 {
5664 return false;
5665 }
5666
5667 return true;
5668}
5669
Geoff Lang0a9661f2016-10-20 10:59:20 -07005670bool ValidateGetInternalFormativ(Context *context,
5671 GLenum target,
5672 GLenum internalformat,
5673 GLenum pname,
5674 GLsizei bufSize,
5675 GLint *params)
5676{
5677 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5678 nullptr);
5679}
5680
5681bool ValidateGetInternalFormativRobustANGLE(Context *context,
5682 GLenum target,
5683 GLenum internalformat,
5684 GLenum pname,
5685 GLsizei bufSize,
5686 GLsizei *length,
5687 GLint *params)
5688{
5689 if (!ValidateRobustEntryPoint(context, bufSize))
5690 {
5691 return false;
5692 }
5693
5694 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5695 {
5696 return false;
5697 }
5698
5699 if (!ValidateRobustBufferSize(context, bufSize, *length))
5700 {
5701 return false;
5702 }
5703
5704 return true;
5705}
5706
Jamie Madillc29968b2016-01-20 11:17:23 -05005707} // namespace gl