blob: 2a911a7eea042ef2f6011e038c37608a9dea665c [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:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001717 return true;
1718
1719 default:
1720 return false;
1721 }
1722}
1723
Jamie Madillc29968b2016-01-20 11:17:23 -05001724bool ValidCompressedImageSize(const ValidationContext *context,
1725 GLenum internalFormat,
Geoff Lang44ff5a72017-02-03 15:15:43 -05001726 GLint xoffset,
1727 GLint yoffset,
Jamie Madillc29968b2016-01-20 11:17:23 -05001728 GLsizei width,
1729 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001730{
Geoff Lang5d601382014-07-22 15:14:06 -04001731 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1732 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001733 {
1734 return false;
1735 }
1736
Geoff Lang44ff5a72017-02-03 15:15:43 -05001737 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001738 {
1739 return false;
1740 }
1741
Geoff Lang0d8b7242015-09-09 14:56:53 -04001742 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1743 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05001744 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
1745 yoffset % formatInfo.compressedBlockHeight != 0 ||
1746 (static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
Geoff Lang0d8b7242015-09-09 14:56:53 -04001747 width % formatInfo.compressedBlockWidth != 0) ||
1748 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1749 height % formatInfo.compressedBlockHeight != 0))
1750 {
1751 return false;
1752 }
1753 }
1754
Geoff Langd4f180b2013-09-24 13:57:44 -04001755 return true;
1756}
1757
Geoff Langff5b2d52016-09-07 11:32:23 -04001758bool ValidImageDataSize(ValidationContext *context,
1759 GLenum textureTarget,
1760 GLsizei width,
1761 GLsizei height,
1762 GLsizei depth,
1763 GLenum internalFormat,
1764 GLenum type,
1765 const GLvoid *pixels,
1766 GLsizei imageSize)
1767{
1768 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1769 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1770 {
1771 // Checks are not required
1772 return true;
1773 }
1774
1775 // ...the data would be unpacked from the buffer object such that the memory reads required
1776 // would exceed the data store size.
1777 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1778 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1779 const gl::Extents size(width, height, depth);
1780 const auto &unpack = context->getGLState().getUnpackState();
1781
1782 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1783 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1784 if (endByteOrErr.isError())
1785 {
1786 context->handleError(endByteOrErr.getError());
1787 return false;
1788 }
1789
1790 GLuint endByte = endByteOrErr.getResult();
1791
1792 if (pixelUnpackBuffer)
1793 {
1794 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1795 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1796 checkedEndByte += checkedOffset;
1797
1798 if (!checkedEndByte.IsValid() ||
1799 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1800 {
1801 // Overflow past the end of the buffer
1802 context->handleError(Error(GL_INVALID_OPERATION));
1803 return false;
1804 }
1805 }
1806 else
1807 {
1808 ASSERT(imageSize >= 0);
1809 if (pixels == nullptr && imageSize != 0)
1810 {
1811 context->handleError(
1812 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001813 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001814 }
1815
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001816 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001817 {
1818 context->handleError(
1819 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1820 return false;
1821 }
1822 }
1823
1824 return true;
1825}
1826
Geoff Lang37dde692014-01-31 16:34:54 -05001827bool ValidQueryType(const Context *context, GLenum queryType)
1828{
He Yunchaoced53ae2016-11-29 15:00:51 +08001829 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1830 "GL extension enums not equal.");
1831 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1832 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001833
1834 switch (queryType)
1835 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001836 case GL_ANY_SAMPLES_PASSED:
1837 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1838 return true;
1839 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1840 return (context->getClientMajorVersion() >= 3);
1841 case GL_TIME_ELAPSED_EXT:
1842 return context->getExtensions().disjointTimerQuery;
1843 case GL_COMMANDS_COMPLETED_CHROMIUM:
1844 return context->getExtensions().syncQuery;
1845 default:
1846 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001847 }
1848}
1849
Jamie Madillef300b12016-10-07 15:12:09 -04001850Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001851{
He Yunchaoced53ae2016-11-29 15:00:51 +08001852 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1853 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1854 // or program object and INVALID_OPERATION if the provided name identifies an object
1855 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001856
Dian Xiang769769a2015-09-09 15:20:08 -07001857 Program *validProgram = context->getProgram(id);
1858
1859 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001860 {
Dian Xiang769769a2015-09-09 15:20:08 -07001861 if (context->getShader(id))
1862 {
Jamie Madill437fa652016-05-03 15:13:24 -04001863 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001864 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1865 }
1866 else
1867 {
Jamie Madill437fa652016-05-03 15:13:24 -04001868 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001869 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001870 }
Dian Xiang769769a2015-09-09 15:20:08 -07001871
1872 return validProgram;
1873}
1874
Jamie Madillef300b12016-10-07 15:12:09 -04001875Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001876{
1877 // See ValidProgram for spec details.
1878
1879 Shader *validShader = context->getShader(id);
1880
1881 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001882 {
Dian Xiang769769a2015-09-09 15:20:08 -07001883 if (context->getProgram(id))
1884 {
Jamie Madill437fa652016-05-03 15:13:24 -04001885 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001886 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1887 }
1888 else
1889 {
Jamie Madill437fa652016-05-03 15:13:24 -04001890 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001891 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001892 }
Dian Xiang769769a2015-09-09 15:20:08 -07001893
1894 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001895}
1896
Geoff Langb1196682014-07-23 13:47:29 -04001897bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001898{
1899 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1900 {
1901 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1902
Geoff Langaae65a42014-05-26 12:43:44 -04001903 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001904 {
Jamie Madill437fa652016-05-03 15:13:24 -04001905 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001906 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001907 }
1908 }
1909 else
1910 {
1911 switch (attachment)
1912 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001913 case GL_DEPTH_ATTACHMENT:
1914 case GL_STENCIL_ATTACHMENT:
1915 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001916
He Yunchaoced53ae2016-11-29 15:00:51 +08001917 case GL_DEPTH_STENCIL_ATTACHMENT:
1918 if (!context->getExtensions().webglCompatibility &&
1919 context->getClientMajorVersion() < 3)
1920 {
1921 context->handleError(Error(GL_INVALID_ENUM));
1922 return false;
1923 }
1924 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001925
He Yunchaoced53ae2016-11-29 15:00:51 +08001926 default:
1927 context->handleError(Error(GL_INVALID_ENUM));
1928 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001929 }
1930 }
1931
1932 return true;
1933}
1934
Jamie Madille8fb6402017-02-14 17:56:40 -05001935bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001936 GLenum target,
1937 GLsizei samples,
1938 GLenum internalformat,
1939 GLsizei width,
1940 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001941{
1942 switch (target)
1943 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001944 case GL_RENDERBUFFER:
1945 break;
1946 default:
1947 context->handleError(Error(GL_INVALID_ENUM));
1948 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001949 }
1950
1951 if (width < 0 || height < 0 || samples < 0)
1952 {
Jamie Madill437fa652016-05-03 15:13:24 -04001953 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001954 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001955 }
1956
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001957 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1958 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1959
1960 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001961 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001962 {
Jamie Madill437fa652016-05-03 15:13:24 -04001963 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001964 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001965 }
1966
1967 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1968 // 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 -08001969 // only sized internal formats.
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001970 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(convertedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -04001971 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001972 {
Jamie Madill437fa652016-05-03 15:13:24 -04001973 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001974 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001975 }
1976
Geoff Langaae65a42014-05-26 12:43:44 -04001977 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001978 {
Jamie Madill437fa652016-05-03 15:13:24 -04001979 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001980 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001981 }
1982
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001983 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001984 if (handle == 0)
1985 {
Jamie Madill437fa652016-05-03 15:13:24 -04001986 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001987 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001988 }
1989
1990 return true;
1991}
1992
He Yunchaoced53ae2016-11-29 15:00:51 +08001993bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1994 GLenum target,
1995 GLenum attachment,
1996 GLenum renderbuffertarget,
1997 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001998{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001999 if (!ValidFramebufferTarget(target))
2000 {
Jamie Madill437fa652016-05-03 15:13:24 -04002001 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002002 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04002003 }
2004
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002005 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002006
Jamie Madill84115c92015-04-23 15:00:07 -04002007 ASSERT(framebuffer);
2008 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002009 {
Jamie Madill437fa652016-05-03 15:13:24 -04002010 context->handleError(
2011 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002012 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002013 }
2014
Jamie Madillb4472272014-07-03 10:38:55 -04002015 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002016 {
Jamie Madillb4472272014-07-03 10:38:55 -04002017 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002018 }
2019
Jamie Madillab9d82c2014-01-21 16:38:14 -05002020 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
2021 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
2022 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
2023 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
2024 if (renderbuffer != 0)
2025 {
2026 if (!context->getRenderbuffer(renderbuffer))
2027 {
Jamie Madill437fa652016-05-03 15:13:24 -04002028 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002029 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05002030 }
2031 }
2032
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002033 return true;
2034}
2035
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002036bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002037 GLint srcX0,
2038 GLint srcY0,
2039 GLint srcX1,
2040 GLint srcY1,
2041 GLint dstX0,
2042 GLint dstY0,
2043 GLint dstX1,
2044 GLint dstY1,
2045 GLbitfield mask,
2046 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002047{
2048 switch (filter)
2049 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002050 case GL_NEAREST:
2051 break;
2052 case GL_LINEAR:
2053 break;
2054 default:
2055 context->handleError(Error(GL_INVALID_ENUM));
2056 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002057 }
2058
2059 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
2060 {
Jamie Madill437fa652016-05-03 15:13:24 -04002061 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002062 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002063 }
2064
2065 if (mask == 0)
2066 {
2067 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
2068 // buffers are copied.
2069 return false;
2070 }
2071
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002072 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
2073 // color buffer, leaving only nearest being unfiltered from above
2074 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
2075 {
Jamie Madill437fa652016-05-03 15:13:24 -04002076 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002077 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002078 }
2079
Jamie Madill51f40ec2016-06-15 14:06:00 -04002080 const auto &glState = context->getGLState();
2081 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
2082 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05002083
2084 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002085 {
Jamie Madill437fa652016-05-03 15:13:24 -04002086 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002087 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002088 }
2089
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002090 if (readFramebuffer->id() == drawFramebuffer->id())
2091 {
2092 context->handleError(Error(GL_INVALID_OPERATION));
2093 return false;
2094 }
2095
Jamie Madill51f40ec2016-06-15 14:06:00 -04002096 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002097 {
Jamie Madill437fa652016-05-03 15:13:24 -04002098 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002099 return false;
2100 }
2101
Jamie Madill51f40ec2016-06-15 14:06:00 -04002102 if (drawFramebuffer->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 Madilldfde6ab2016-06-09 07:07:18 -07002108 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002109 {
Jamie Madill437fa652016-05-03 15:13:24 -04002110 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002111 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002112 }
2113
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002114 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
2115
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002116 if (mask & GL_COLOR_BUFFER_BIT)
2117 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002118 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05002119 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002120
He Yunchao66a41a22016-12-15 16:45:05 +08002121 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002122 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002123 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002124
Geoff Langa15472a2015-08-11 11:48:03 -04002125 for (size_t drawbufferIdx = 0;
2126 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002127 {
Geoff Langa15472a2015-08-11 11:48:03 -04002128 const FramebufferAttachment *attachment =
2129 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2130 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002131 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002132 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002133
Geoff Langb2f3d052013-08-13 12:49:27 -04002134 // The GL ES 3.0.2 spec (pg 193) states that:
2135 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08002136 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
2137 // as well
2138 // 3) If the read buffer is a signed integer format, the draw buffer must be as
2139 // well
Jamie Madill6163c752015-12-07 16:32:59 -05002140 // Changes with EXT_color_buffer_float:
2141 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04002142 GLenum readComponentType = readFormat.info->componentType;
2143 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002144 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002145 readComponentType == GL_SIGNED_NORMALIZED);
2146 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2147 drawComponentType == GL_SIGNED_NORMALIZED);
2148
2149 if (extensions.colorBufferFloat)
2150 {
2151 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2152 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2153
2154 if (readFixedOrFloat != drawFixedOrFloat)
2155 {
Jamie Madill437fa652016-05-03 15:13:24 -04002156 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002157 "If the read buffer contains fixed-point or "
2158 "floating-point values, the draw buffer "
2159 "must as well."));
2160 return false;
2161 }
2162 }
2163 else if (readFixedPoint != drawFixedPoint)
2164 {
Jamie Madill437fa652016-05-03 15:13:24 -04002165 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002166 "If the read buffer contains fixed-point "
2167 "values, the draw buffer must as well."));
2168 return false;
2169 }
2170
2171 if (readComponentType == GL_UNSIGNED_INT &&
2172 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002173 {
Jamie Madill437fa652016-05-03 15:13:24 -04002174 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002175 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002176 }
2177
Jamie Madill6163c752015-12-07 16:32:59 -05002178 if (readComponentType == GL_INT && drawComponentType != GL_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 Madilla3944d42016-07-22 22:13:26 -04002184 if (readColorBuffer->getSamples() > 0 &&
2185 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002186 {
Jamie Madill437fa652016-05-03 15:13:24 -04002187 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002188 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002189 }
2190 }
2191 }
2192
Jamie Madilla3944d42016-07-22 22:13:26 -04002193 if ((readFormat.info->componentType == GL_INT ||
2194 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2195 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002196 {
Jamie Madill437fa652016-05-03 15:13:24 -04002197 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002198 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002199 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002200 }
He Yunchao66a41a22016-12-15 16:45:05 +08002201 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2202 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
2203 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2204 // situation is an application error that would lead to a crash in ANGLE.
2205 else if (drawFramebuffer->hasEnabledDrawBuffer())
2206 {
2207 context->handleError(Error(
2208 GL_INVALID_OPERATION,
2209 "Attempt to read from a missing color attachment of a complete framebuffer."));
2210 return false;
2211 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002212 }
2213
He Yunchaoced53ae2016-11-29 15:00:51 +08002214 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002215 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2216 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002217 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002218 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002219 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002220 const gl::FramebufferAttachment *readBuffer =
2221 readFramebuffer->getAttachment(attachments[i]);
2222 const gl::FramebufferAttachment *drawBuffer =
2223 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002224
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002225 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002226 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002227 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002228 {
Jamie Madill437fa652016-05-03 15:13:24 -04002229 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002230 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002231 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002232
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002233 if (readBuffer->getSamples() > 0 && !sameBounds)
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 }
2238 }
He Yunchao66a41a22016-12-15 16:45:05 +08002239 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2240 else if (drawBuffer)
2241 {
2242 context->handleError(Error(GL_INVALID_OPERATION,
2243 "Attempt to read from a missing depth/stencil "
2244 "attachment of a complete framebuffer."));
2245 return false;
2246 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002247 }
2248 }
2249
2250 return true;
2251}
2252
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002253bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002254 GLint x,
2255 GLint y,
2256 GLsizei width,
2257 GLsizei height,
2258 GLenum format,
2259 GLenum type,
2260 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002261{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002262 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2263}
2264
2265bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2266 GLint x,
2267 GLint y,
2268 GLsizei width,
2269 GLsizei height,
2270 GLenum format,
2271 GLenum type,
2272 GLsizei bufSize,
2273 GLsizei *length,
2274 GLvoid *pixels)
2275{
2276 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002277 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002278 return false;
2279 }
2280
Geoff Lang62fce5b2016-09-30 10:46:35 -04002281 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2282 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002283 {
Geoff Langb1196682014-07-23 13:47:29 -04002284 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002285 }
2286
Geoff Lang62fce5b2016-09-30 10:46:35 -04002287 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002288 {
Geoff Langb1196682014-07-23 13:47:29 -04002289 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002290 }
2291
Jamie Madillc29968b2016-01-20 11:17:23 -05002292 return true;
2293}
2294
2295bool ValidateReadnPixelsEXT(Context *context,
2296 GLint x,
2297 GLint y,
2298 GLsizei width,
2299 GLsizei height,
2300 GLenum format,
2301 GLenum type,
2302 GLsizei bufSize,
2303 GLvoid *pixels)
2304{
2305 if (bufSize < 0)
2306 {
Jamie Madill437fa652016-05-03 15:13:24 -04002307 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002308 return false;
2309 }
2310
Geoff Lang62fce5b2016-09-30 10:46:35 -04002311 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2312 pixels);
2313}
Jamie Madill26e91952014-03-05 15:01:27 -05002314
Geoff Lang62fce5b2016-09-30 10:46:35 -04002315bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2316 GLint x,
2317 GLint y,
2318 GLsizei width,
2319 GLsizei height,
2320 GLenum format,
2321 GLenum type,
2322 GLsizei bufSize,
2323 GLsizei *length,
2324 GLvoid *data)
2325{
2326 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002327 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002328 return false;
2329 }
2330
Geoff Lang62fce5b2016-09-30 10:46:35 -04002331 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002332 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002333 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002334 }
2335
Geoff Lang62fce5b2016-09-30 10:46:35 -04002336 if (!ValidateRobustBufferSize(context, bufSize, *length))
2337 {
2338 return false;
2339 }
2340
2341 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002342}
2343
Olli Etuaho41997e72016-03-10 13:38:39 +02002344bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002345{
2346 if (!context->getExtensions().occlusionQueryBoolean &&
2347 !context->getExtensions().disjointTimerQuery)
2348 {
Jamie Madill437fa652016-05-03 15:13:24 -04002349 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002350 return false;
2351 }
2352
Olli Etuaho41997e72016-03-10 13:38:39 +02002353 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002354}
2355
Olli Etuaho41997e72016-03-10 13:38:39 +02002356bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002357{
2358 if (!context->getExtensions().occlusionQueryBoolean &&
2359 !context->getExtensions().disjointTimerQuery)
2360 {
Jamie Madill437fa652016-05-03 15:13:24 -04002361 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002362 return false;
2363 }
2364
Olli Etuaho41997e72016-03-10 13:38:39 +02002365 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002366}
2367
2368bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002369{
2370 if (!ValidQueryType(context, target))
2371 {
Jamie Madill437fa652016-05-03 15:13:24 -04002372 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002373 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002374 }
2375
2376 if (id == 0)
2377 {
Jamie Madill437fa652016-05-03 15:13:24 -04002378 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002379 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002380 }
2381
2382 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2383 // of zero, if the active query object name for <target> is non-zero (for the
2384 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2385 // the active query for either target is non-zero), if <id> is the name of an
2386 // existing query object whose type does not match <target>, or if <id> is the
2387 // active query object name for any query type, the error INVALID_OPERATION is
2388 // generated.
2389
2390 // Ensure no other queries are active
2391 // NOTE: If other queries than occlusion are supported, we will need to check
2392 // separately that:
2393 // a) The query ID passed is not the current active query for any target/type
2394 // b) There are no active queries for the requested target (and in the case
2395 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2396 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002397
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002398 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002399 {
Jamie Madill437fa652016-05-03 15:13:24 -04002400 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002401 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002402 }
2403
2404 Query *queryObject = context->getQuery(id, true, target);
2405
2406 // check that name was obtained with glGenQueries
2407 if (!queryObject)
2408 {
Jamie Madill437fa652016-05-03 15:13:24 -04002409 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002410 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002411 }
2412
2413 // check for type mismatch
2414 if (queryObject->getType() != target)
2415 {
Jamie Madill437fa652016-05-03 15:13:24 -04002416 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002417 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002418 }
2419
2420 return true;
2421}
2422
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002423bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2424{
2425 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002426 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002427 {
Jamie Madill437fa652016-05-03 15:13:24 -04002428 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002429 return false;
2430 }
2431
2432 return ValidateBeginQueryBase(context, target, id);
2433}
2434
2435bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002436{
2437 if (!ValidQueryType(context, target))
2438 {
Jamie Madill437fa652016-05-03 15:13:24 -04002439 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002440 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002441 }
2442
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002443 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002444
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002445 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002446 {
Jamie Madill437fa652016-05-03 15:13:24 -04002447 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002448 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002449 }
2450
Jamie Madill45c785d2014-05-13 14:09:34 -04002451 return true;
2452}
2453
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002454bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2455{
2456 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002457 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002458 {
Jamie Madill437fa652016-05-03 15:13:24 -04002459 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002460 return false;
2461 }
2462
2463 return ValidateEndQueryBase(context, target);
2464}
2465
2466bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2467{
2468 if (!context->getExtensions().disjointTimerQuery)
2469 {
Jamie Madill437fa652016-05-03 15:13:24 -04002470 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002471 return false;
2472 }
2473
2474 if (target != GL_TIMESTAMP_EXT)
2475 {
Jamie Madill437fa652016-05-03 15:13:24 -04002476 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002477 return false;
2478 }
2479
2480 Query *queryObject = context->getQuery(id, true, target);
2481 if (queryObject == nullptr)
2482 {
Jamie Madill437fa652016-05-03 15:13:24 -04002483 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002484 return false;
2485 }
2486
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002487 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002488 {
Jamie Madill437fa652016-05-03 15:13:24 -04002489 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002490 return false;
2491 }
2492
2493 return true;
2494}
2495
Geoff Lang2186c382016-10-14 10:54:54 -04002496bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002497{
Geoff Lang2186c382016-10-14 10:54:54 -04002498 if (numParams)
2499 {
2500 *numParams = 0;
2501 }
2502
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002503 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2504 {
Jamie Madill437fa652016-05-03 15:13:24 -04002505 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002506 return false;
2507 }
2508
2509 switch (pname)
2510 {
2511 case GL_CURRENT_QUERY_EXT:
2512 if (target == GL_TIMESTAMP_EXT)
2513 {
Jamie Madill437fa652016-05-03 15:13:24 -04002514 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002515 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2516 return false;
2517 }
2518 break;
2519 case GL_QUERY_COUNTER_BITS_EXT:
2520 if (!context->getExtensions().disjointTimerQuery ||
2521 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2522 {
Jamie Madill437fa652016-05-03 15:13:24 -04002523 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002524 return false;
2525 }
2526 break;
2527 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002528 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002529 return false;
2530 }
2531
Geoff Lang2186c382016-10-14 10:54:54 -04002532 if (numParams)
2533 {
2534 // All queries return only one value
2535 *numParams = 1;
2536 }
2537
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002538 return true;
2539}
2540
2541bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2542{
2543 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002544 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002545 {
Jamie Madill437fa652016-05-03 15:13:24 -04002546 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002547 return false;
2548 }
2549
Geoff Lang2186c382016-10-14 10:54:54 -04002550 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002551}
2552
Geoff Lang2186c382016-10-14 10:54:54 -04002553bool ValidateGetQueryivRobustANGLE(Context *context,
2554 GLenum target,
2555 GLenum pname,
2556 GLsizei bufSize,
2557 GLsizei *length,
2558 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002559{
Geoff Lang2186c382016-10-14 10:54:54 -04002560 if (!ValidateRobustEntryPoint(context, bufSize))
2561 {
2562 return false;
2563 }
2564
2565 if (!ValidateGetQueryivBase(context, target, pname, length))
2566 {
2567 return false;
2568 }
2569
2570 if (!ValidateRobustBufferSize(context, bufSize, *length))
2571 {
2572 return false;
2573 }
2574
2575 return true;
2576}
2577
2578bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2579{
2580 if (numParams)
2581 {
2582 *numParams = 0;
2583 }
2584
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002585 Query *queryObject = context->getQuery(id, false, GL_NONE);
2586
2587 if (!queryObject)
2588 {
Jamie Madill437fa652016-05-03 15:13:24 -04002589 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002590 return false;
2591 }
2592
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002593 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002594 {
Jamie Madill437fa652016-05-03 15:13:24 -04002595 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002596 return false;
2597 }
2598
2599 switch (pname)
2600 {
2601 case GL_QUERY_RESULT_EXT:
2602 case GL_QUERY_RESULT_AVAILABLE_EXT:
2603 break;
2604
2605 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002606 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002607 return false;
2608 }
2609
Geoff Lang2186c382016-10-14 10:54:54 -04002610 if (numParams)
2611 {
2612 *numParams = 1;
2613 }
2614
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002615 return true;
2616}
2617
2618bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2619{
2620 if (!context->getExtensions().disjointTimerQuery)
2621 {
Jamie Madill437fa652016-05-03 15:13:24 -04002622 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002623 return false;
2624 }
Geoff Lang2186c382016-10-14 10:54:54 -04002625 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2626}
2627
2628bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2629 GLuint id,
2630 GLenum pname,
2631 GLsizei bufSize,
2632 GLsizei *length,
2633 GLint *params)
2634{
2635 if (!context->getExtensions().disjointTimerQuery)
2636 {
2637 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2638 return false;
2639 }
2640
2641 if (!ValidateRobustEntryPoint(context, bufSize))
2642 {
2643 return false;
2644 }
2645
2646 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2647 {
2648 return false;
2649 }
2650
2651 if (!ValidateRobustBufferSize(context, bufSize, *length))
2652 {
2653 return false;
2654 }
2655
2656 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002657}
2658
2659bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2660{
2661 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002662 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002663 {
Jamie Madill437fa652016-05-03 15:13:24 -04002664 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002665 return false;
2666 }
Geoff Lang2186c382016-10-14 10:54:54 -04002667 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2668}
2669
2670bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2671 GLuint id,
2672 GLenum pname,
2673 GLsizei bufSize,
2674 GLsizei *length,
2675 GLuint *params)
2676{
2677 if (!context->getExtensions().disjointTimerQuery &&
2678 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2679 {
2680 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2681 return false;
2682 }
2683
2684 if (!ValidateRobustEntryPoint(context, bufSize))
2685 {
2686 return false;
2687 }
2688
2689 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2690 {
2691 return false;
2692 }
2693
2694 if (!ValidateRobustBufferSize(context, bufSize, *length))
2695 {
2696 return false;
2697 }
2698
2699 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002700}
2701
2702bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2703{
2704 if (!context->getExtensions().disjointTimerQuery)
2705 {
Jamie Madill437fa652016-05-03 15:13:24 -04002706 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002707 return false;
2708 }
Geoff Lang2186c382016-10-14 10:54:54 -04002709 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2710}
2711
2712bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2713 GLuint id,
2714 GLenum pname,
2715 GLsizei bufSize,
2716 GLsizei *length,
2717 GLint64 *params)
2718{
2719 if (!context->getExtensions().disjointTimerQuery)
2720 {
2721 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2722 return false;
2723 }
2724
2725 if (!ValidateRobustEntryPoint(context, bufSize))
2726 {
2727 return false;
2728 }
2729
2730 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2731 {
2732 return false;
2733 }
2734
2735 if (!ValidateRobustBufferSize(context, bufSize, *length))
2736 {
2737 return false;
2738 }
2739
2740 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002741}
2742
2743bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2744{
2745 if (!context->getExtensions().disjointTimerQuery)
2746 {
Jamie Madill437fa652016-05-03 15:13:24 -04002747 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002748 return false;
2749 }
Geoff Lang2186c382016-10-14 10:54:54 -04002750 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2751}
2752
2753bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2754 GLuint id,
2755 GLenum pname,
2756 GLsizei bufSize,
2757 GLsizei *length,
2758 GLuint64 *params)
2759{
2760 if (!context->getExtensions().disjointTimerQuery)
2761 {
2762 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2763 return false;
2764 }
2765
2766 if (!ValidateRobustEntryPoint(context, bufSize))
2767 {
2768 return false;
2769 }
2770
2771 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2772 {
2773 return false;
2774 }
2775
2776 if (!ValidateRobustBufferSize(context, bufSize, *length))
2777 {
2778 return false;
2779 }
2780
2781 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002782}
2783
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002784bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002785 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002786 GLuint program,
2787 GLint location,
2788 GLsizei count)
2789{
2790 // Check for ES31 program uniform entry points
2791 if (context->getClientVersion() < Version(3, 1))
2792 {
2793 context->handleError(Error(GL_INVALID_OPERATION));
2794 return false;
2795 }
2796
2797 const LinkedUniform *uniform = nullptr;
2798 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002799 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2800 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002801}
2802
Frank Henigmana98a6472017-02-02 21:38:32 -05002803bool ValidateProgramUniform1iv(gl::Context *context,
2804 GLuint program,
2805 GLint location,
2806 GLsizei count,
2807 const GLint *value)
2808{
2809 // Check for ES31 program uniform entry points
2810 if (context->getClientVersion() < Version(3, 1))
2811 {
2812 context->handleError(Error(GL_INVALID_OPERATION));
2813 return false;
2814 }
2815
2816 const LinkedUniform *uniform = nullptr;
2817 gl::Program *programObject = GetValidProgram(context, program);
2818 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2819 ValidateUniform1ivValue(context, uniform->type, count, value);
2820}
2821
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002822bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002823 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002824 GLuint program,
2825 GLint location,
2826 GLsizei count,
2827 GLboolean transpose)
2828{
2829 // Check for ES31 program uniform entry points
2830 if (context->getClientVersion() < Version(3, 1))
2831 {
2832 context->handleError(Error(GL_INVALID_OPERATION));
2833 return false;
2834 }
2835
2836 const LinkedUniform *uniform = nullptr;
2837 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002838 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2839 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002840}
2841
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002842bool ValidateUniform(gl::Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002843{
2844 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002845 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002846 {
Jamie Madill437fa652016-05-03 15:13:24 -04002847 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002848 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002849 }
2850
Jamie Madill62d31cb2015-09-11 13:25:51 -04002851 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002852 gl::Program *programObject = context->getGLState().getProgram();
2853 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2854 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002855}
2856
Frank Henigmana98a6472017-02-02 21:38:32 -05002857bool ValidateUniform1iv(gl::Context *context, GLint location, GLsizei count, const GLint *value)
2858{
2859 const LinkedUniform *uniform = nullptr;
2860 gl::Program *programObject = context->getGLState().getProgram();
2861 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2862 ValidateUniform1ivValue(context, uniform->type, count, value);
2863}
2864
He Yunchaoced53ae2016-11-29 15:00:51 +08002865bool ValidateUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002866 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002867 GLint location,
2868 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002869 GLboolean transpose)
2870{
2871 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002872 int rows = VariableRowCount(valueType);
2873 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002874 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002875 {
Jamie Madill437fa652016-05-03 15:13:24 -04002876 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002877 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002878 }
2879
Martin Radev1be913c2016-07-11 17:59:16 +03002880 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002881 {
Jamie Madill437fa652016-05-03 15:13:24 -04002882 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002883 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002884 }
2885
Jamie Madill62d31cb2015-09-11 13:25:51 -04002886 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002887 gl::Program *programObject = context->getGLState().getProgram();
2888 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2889 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002890}
2891
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002892bool ValidateStateQuery(ValidationContext *context,
2893 GLenum pname,
2894 GLenum *nativeType,
2895 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002896{
2897 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2898 {
Jamie Madill437fa652016-05-03 15:13:24 -04002899 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002900 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002901 }
2902
Jamie Madill0af26e12015-03-05 19:54:33 -05002903 const Caps &caps = context->getCaps();
2904
Jamie Madill893ab082014-05-16 16:56:10 -04002905 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2906 {
2907 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2908
Jamie Madill0af26e12015-03-05 19:54:33 -05002909 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002910 {
Jamie Madill437fa652016-05-03 15:13:24 -04002911 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002912 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002913 }
2914 }
2915
2916 switch (pname)
2917 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002918 case GL_TEXTURE_BINDING_2D:
2919 case GL_TEXTURE_BINDING_CUBE_MAP:
2920 case GL_TEXTURE_BINDING_3D:
2921 case GL_TEXTURE_BINDING_2D_ARRAY:
2922 break;
2923 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2924 if (!context->getExtensions().eglStreamConsumerExternal &&
2925 !context->getExtensions().eglImageExternal)
2926 {
2927 context->handleError(Error(GL_INVALID_ENUM,
2928 "Neither NV_EGL_stream_consumer_external nor "
2929 "GL_OES_EGL_image_external extensions enabled"));
2930 return false;
2931 }
2932 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002933
He Yunchaoced53ae2016-11-29 15:00:51 +08002934 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2935 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002936 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002937 if (context->getGLState().getReadFramebuffer()->checkStatus(
2938 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002939 {
Jamie Madill437fa652016-05-03 15:13:24 -04002940 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002941 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002942 }
2943
Jamie Madill51f40ec2016-06-15 14:06:00 -04002944 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2945 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002946
2947 if (framebuffer->getReadBufferState() == GL_NONE)
2948 {
2949 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2950 return false;
2951 }
2952
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002953 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002954 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002955 {
Jamie Madill437fa652016-05-03 15:13:24 -04002956 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002957 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002958 }
2959 }
2960 break;
2961
He Yunchaoced53ae2016-11-29 15:00:51 +08002962 default:
2963 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002964 }
2965
2966 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002967 if (*numParams == 0)
2968 {
2969 return false;
2970 }
2971
2972 return true;
2973}
2974
2975bool ValidateRobustStateQuery(ValidationContext *context,
2976 GLenum pname,
2977 GLsizei bufSize,
2978 GLenum *nativeType,
2979 unsigned int *numParams)
2980{
2981 if (!ValidateRobustEntryPoint(context, bufSize))
2982 {
2983 return false;
2984 }
2985
2986 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2987 {
2988 return false;
2989 }
2990
2991 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002992 {
2993 return false;
2994 }
2995
2996 return true;
2997}
2998
Jamie Madillc29968b2016-01-20 11:17:23 -05002999bool ValidateCopyTexImageParametersBase(ValidationContext *context,
3000 GLenum target,
3001 GLint level,
3002 GLenum internalformat,
3003 bool isSubImage,
3004 GLint xoffset,
3005 GLint yoffset,
3006 GLint zoffset,
3007 GLint x,
3008 GLint y,
3009 GLsizei width,
3010 GLsizei height,
3011 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04003012 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04003013{
Jamie Madill560a8d82014-05-21 13:06:20 -04003014 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
3015 {
Jamie Madill437fa652016-05-03 15:13:24 -04003016 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003017 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003018 }
3019
He Yunchaoced53ae2016-11-29 15:00:51 +08003020 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
3021 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04003022 {
Jamie Madill437fa652016-05-03 15:13:24 -04003023 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003024 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003025 }
3026
3027 if (border != 0)
3028 {
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 (!ValidMipLevel(context, target, level))
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
Jamie Madill51f40ec2016-06-15 14:06:00 -04003039 const auto &state = context->getGLState();
3040 auto readFramebuffer = state.getReadFramebuffer();
3041 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04003042 {
Jamie Madill437fa652016-05-03 15:13:24 -04003043 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003044 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003045 }
3046
Jamie Madill51f40ec2016-06-15 14:06:00 -04003047 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003048 {
Jamie Madill437fa652016-05-03 15:13:24 -04003049 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003050 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003051 }
3052
Martin Radev138064f2016-07-15 12:03:41 +03003053 if (readFramebuffer->getReadBufferState() == GL_NONE)
3054 {
3055 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3056 return false;
3057 }
3058
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003059 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
3060 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08003061 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003062 // situation is an application error that would lead to a crash in ANGLE.
3063 if (readFramebuffer->getReadColorbuffer() == nullptr)
3064 {
3065 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
3066 return false;
3067 }
3068
Geoff Langaae65a42014-05-26 12:43:44 -04003069 const gl::Caps &caps = context->getCaps();
3070
Geoff Langaae65a42014-05-26 12:43:44 -04003071 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04003072 switch (target)
3073 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003074 case GL_TEXTURE_2D:
3075 maxDimension = caps.max2DTextureSize;
3076 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003077
He Yunchaoced53ae2016-11-29 15:00:51 +08003078 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3079 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3080 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3081 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3082 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3083 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3084 maxDimension = caps.maxCubeMapTextureSize;
3085 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003086
He Yunchaoced53ae2016-11-29 15:00:51 +08003087 case GL_TEXTURE_2D_ARRAY:
3088 maxDimension = caps.max2DTextureSize;
3089 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003090
He Yunchaoced53ae2016-11-29 15:00:51 +08003091 case GL_TEXTURE_3D:
3092 maxDimension = caps.max3DTextureSize;
3093 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003094
He Yunchaoced53ae2016-11-29 15:00:51 +08003095 default:
3096 context->handleError(Error(GL_INVALID_ENUM));
3097 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003098 }
3099
Jamie Madillc29968b2016-01-20 11:17:23 -05003100 gl::Texture *texture =
3101 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003102 if (!texture)
3103 {
Jamie Madill437fa652016-05-03 15:13:24 -04003104 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003105 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003106 }
3107
Geoff Lang69cce582015-09-17 13:20:36 -04003108 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003109 {
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 Lang5d601382014-07-22 15:14:06 -04003114 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
3115
3116 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003117 {
Jamie Madill437fa652016-05-03 15:13:24 -04003118 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003119 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003120 }
3121
Geoff Lang44ff5a72017-02-03 15:15:43 -05003122 if (formatInfo.compressed &&
3123 !ValidCompressedImageSize(context, internalformat, xoffset, yoffset, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003124 {
Jamie Madill437fa652016-05-03 15:13:24 -04003125 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003126 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003127 }
3128
3129 if (isSubImage)
3130 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003131 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3132 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3133 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003134 {
Jamie Madill437fa652016-05-03 15:13:24 -04003135 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003136 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003137 }
3138 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003139 else
3140 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003141 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003142 {
Jamie Madill437fa652016-05-03 15:13:24 -04003143 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003144 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003145 }
3146
Geoff Langeb66a6e2016-10-31 13:06:12 -04003147 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003148 {
Jamie Madill437fa652016-05-03 15:13:24 -04003149 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003150 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003151 }
3152
3153 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003154 if (static_cast<int>(width) > maxLevelDimension ||
3155 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003156 {
Jamie Madill437fa652016-05-03 15:13:24 -04003157 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003158 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003159 }
3160 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003161
Jamie Madill0c8abca2016-07-22 20:21:26 -04003162 if (textureFormatOut)
3163 {
3164 *textureFormatOut = texture->getFormat(target, level);
3165 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05003166
3167 // Detect texture copying feedback loops for WebGL.
3168 if (context->getExtensions().webglCompatibility)
3169 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05003170 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05003171 {
3172 context->handleError(Error(GL_INVALID_OPERATION,
3173 "Texture copying feedback loop formed between Framebuffer "
3174 "and specified Texture level."));
3175 return false;
3176 }
3177 }
3178
Jamie Madill560a8d82014-05-21 13:06:20 -04003179 return true;
3180}
3181
Jiajia Qind9671222016-11-29 16:30:31 +08003182bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003183{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003184 switch (mode)
3185 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003186 case GL_POINTS:
3187 case GL_LINES:
3188 case GL_LINE_LOOP:
3189 case GL_LINE_STRIP:
3190 case GL_TRIANGLES:
3191 case GL_TRIANGLE_STRIP:
3192 case GL_TRIANGLE_FAN:
3193 break;
3194 default:
3195 context->handleError(Error(GL_INVALID_ENUM));
3196 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003197 }
3198
Jamie Madill250d33f2014-06-06 17:09:03 -04003199 if (count < 0)
3200 {
Jamie Madill437fa652016-05-03 15:13:24 -04003201 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003202 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003203 }
3204
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003205 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003206
Jamie Madill250d33f2014-06-06 17:09:03 -04003207 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003208 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003209 {
Jamie Madill437fa652016-05-03 15:13:24 -04003210 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003211 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003212 }
3213
Jamie Madillcbcde722017-01-06 14:50:00 -05003214 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3215 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04003216 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003217 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3218 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003219 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003220 const FramebufferAttachment *dsAttachment =
3221 framebuffer->getStencilOrDepthStencilAttachment();
3222 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003223 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003224 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003225
3226 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3227 bool differentWritemasks =
3228 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3229 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3230 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3231 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3232
3233 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003234 {
Jamie Madillcbcde722017-01-06 14:50:00 -05003235 if (!context->getExtensions().webglCompatibility)
3236 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05003237 ERR() << "This ANGLE implementation does not support separate front/back stencil "
3238 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05003239 }
Jamie Madill437fa652016-05-03 15:13:24 -04003240 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003241 return false;
3242 }
Jamie Madillac528012014-06-20 13:21:23 -04003243 }
3244
Jamie Madill51f40ec2016-06-15 14:06:00 -04003245 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003246 {
Jamie Madill437fa652016-05-03 15:13:24 -04003247 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003248 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003249 }
3250
Geoff Lang7dd2e102014-11-10 15:19:26 -05003251 gl::Program *program = state.getProgram();
3252 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003253 {
Jamie Madill437fa652016-05-03 15:13:24 -04003254 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003255 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003256 }
3257
Geoff Lang7dd2e102014-11-10 15:19:26 -05003258 if (!program->validateSamplers(NULL, context->getCaps()))
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
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003264 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003265 for (unsigned int uniformBlockIndex = 0;
3266 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003267 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003268 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003269 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003270 const OffsetBindingPointer<Buffer> &uniformBuffer =
3271 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003272
Geoff Lang5d124a62015-09-15 13:03:27 -04003273 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003274 {
3275 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003276 context->handleError(
3277 Error(GL_INVALID_OPERATION,
3278 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003279 return false;
3280 }
3281
Geoff Lang5d124a62015-09-15 13:03:27 -04003282 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003283 if (uniformBufferSize == 0)
3284 {
3285 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003286 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003287 }
3288
Jamie Madill62d31cb2015-09-11 13:25:51 -04003289 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003290 {
3291 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003292 context->handleError(
3293 Error(GL_INVALID_OPERATION,
3294 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003295 return false;
3296 }
3297 }
3298
Jamie Madilla4595b82017-01-11 17:36:34 -05003299 // Detect rendering feedback loops for WebGL.
3300 if (context->getExtensions().webglCompatibility)
3301 {
3302 if (framebuffer->formsRenderingFeedbackLoopWith(state))
3303 {
3304 context->handleError(
3305 Error(GL_INVALID_OPERATION,
3306 "Rendering feedback loop formed between Framebuffer and active Texture."));
3307 return false;
3308 }
3309 }
3310
Jamie Madill250d33f2014-06-06 17:09:03 -04003311 // No-op if zero count
3312 return (count > 0);
3313}
3314
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003315bool ValidateDrawArrays(ValidationContext *context,
3316 GLenum mode,
3317 GLint first,
3318 GLsizei count,
3319 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003320{
Jamie Madillfd716582014-06-06 17:09:04 -04003321 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003322 {
Jamie Madill437fa652016-05-03 15:13:24 -04003323 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003324 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003325 }
3326
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003327 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003328 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003329 if (curTransformFeedback && curTransformFeedback->isActive() &&
3330 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003331 {
3332 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003333 // that does not match the current transform feedback object's draw mode (if transform
3334 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003335 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003336 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003337 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003338 }
3339
Jiajia Qind9671222016-11-29 16:30:31 +08003340 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003341 {
3342 return false;
3343 }
3344
Corentin Wallez71168a02016-12-19 15:11:18 -08003345 // Check the computation of maxVertex doesn't overflow.
3346 // - first < 0 or count < 0 have been checked as an error condition
3347 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3348 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3349 ASSERT(count > 0 && first >= 0);
3350 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3351 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003352 {
3353 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3354 return false;
3355 }
3356
Corentin Wallez71168a02016-12-19 15:11:18 -08003357 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003358 {
3359 return false;
3360 }
3361
3362 return true;
3363}
3364
He Yunchaoced53ae2016-11-29 15:00:51 +08003365bool ValidateDrawArraysInstanced(Context *context,
3366 GLenum mode,
3367 GLint first,
3368 GLsizei count,
3369 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003370{
3371 if (primcount < 0)
3372 {
Jamie Madill437fa652016-05-03 15:13:24 -04003373 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003374 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003375 }
3376
Jamie Madill2b976812014-08-25 15:47:49 -04003377 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003378 {
3379 return false;
3380 }
3381
3382 // No-op if zero primitive count
3383 return (primcount > 0);
3384}
3385
Geoff Lang87a93302014-09-16 13:29:43 -04003386static bool ValidateDrawInstancedANGLE(Context *context)
3387{
3388 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003389 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003390
Geoff Lang7dd2e102014-11-10 15:19:26 -05003391 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003392
Jiawei-Shao2597fb62016-12-09 16:38:02 +08003393 const auto &attribs = state.getVertexArray()->getVertexAttributes();
3394 const auto &bindings = state.getVertexArray()->getVertexBindings();
Jamie Madill63805b42015-08-25 13:17:39 -04003395 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003396 {
Jiawei-Shao2597fb62016-12-09 16:38:02 +08003397 const VertexAttribute &attrib = attribs[attributeIndex];
3398 const VertexBinding &binding = bindings[attrib.bindingIndex];
3399 if (program->isAttribLocationActive(attributeIndex) && binding.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003400 {
3401 return true;
3402 }
3403 }
3404
Jamie Madill437fa652016-05-03 15:13:24 -04003405 context->handleError(Error(GL_INVALID_OPERATION,
3406 "ANGLE_instanced_arrays requires that at least one active attribute"
3407 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003408 return false;
3409}
3410
He Yunchaoced53ae2016-11-29 15:00:51 +08003411bool ValidateDrawArraysInstancedANGLE(Context *context,
3412 GLenum mode,
3413 GLint first,
3414 GLsizei count,
3415 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003416{
3417 if (!ValidateDrawInstancedANGLE(context))
3418 {
3419 return false;
3420 }
3421
3422 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3423}
3424
Jiajia Qind9671222016-11-29 16:30:31 +08003425bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003426{
Jamie Madill250d33f2014-06-06 17:09:03 -04003427 switch (type)
3428 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003429 case GL_UNSIGNED_BYTE:
3430 case GL_UNSIGNED_SHORT:
3431 break;
3432 case GL_UNSIGNED_INT:
3433 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3434 {
3435 context->handleError(Error(GL_INVALID_ENUM));
3436 return false;
3437 }
3438 break;
3439 default:
3440 context->handleError(Error(GL_INVALID_ENUM));
3441 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003442 }
3443
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003444 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003445
3446 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003447 if (curTransformFeedback && curTransformFeedback->isActive() &&
3448 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003449 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003450 // It is an invalid operation to call DrawElements, DrawRangeElements or
3451 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003452 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003453 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003454 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003455 }
3456
Jiajia Qind9671222016-11-29 16:30:31 +08003457 return true;
3458}
3459
3460bool ValidateDrawElements(ValidationContext *context,
3461 GLenum mode,
3462 GLsizei count,
3463 GLenum type,
3464 const GLvoid *indices,
3465 GLsizei primcount,
3466 IndexRange *indexRangeOut)
3467{
3468 if (!ValidateDrawElementsBase(context, type))
3469 return false;
3470
3471 const State &state = context->getGLState();
3472
Jamie Madill250d33f2014-06-06 17:09:03 -04003473 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003474 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003475 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003476 context->handleError(Error(GL_INVALID_OPERATION, "Index buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -04003477 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003478 }
3479
He Yunchaoced53ae2016-11-29 15:00:51 +08003480 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003481 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003482
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003483 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3484
3485 if (context->getExtensions().webglCompatibility)
3486 {
3487 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3488 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3489 {
3490 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3491 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3492 // data type passed to the call, or an INVALID_OPERATION error is generated.
3493 context->handleError(Error(GL_INVALID_OPERATION,
3494 "indices must be a multiple of the element type size."));
3495 return false;
3496 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003497 }
3498
3499 if (context->getExtensions().webglCompatibility ||
3500 !context->getGLState().areClientArraysEnabled())
3501 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003502 if (!elementArrayBuffer && count > 0)
3503 {
3504 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3505 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3506 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3507 context->handleError(Error(GL_INVALID_OPERATION,
3508 "There is no element array buffer bound and count > 0."));
3509 return false;
3510 }
3511 }
3512
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003513 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003514 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003515 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003516 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003517 GLint64 offset = reinterpret_cast<GLint64>(indices);
3518 GLint64 byteCount =
3519 static_cast<GLint64>(typeBytes) * static_cast<GLint64>(count) + offset;
3520
3521 // check for integer overflows
3522 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeBytes) ||
3523 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3524 {
3525 context->handleError(Error(GL_OUT_OF_MEMORY, "Integer overflow."));
3526 return false;
3527 }
3528
3529 // Check for reading past the end of the bound buffer object
3530 if (byteCount > elementArrayBuffer->getSize())
3531 {
3532 context->handleError(
3533 Error(GL_INVALID_OPERATION, "Index buffer is not big enough for the draw."));
3534 return false;
3535 }
3536 }
3537 else if (!indices)
3538 {
3539 // This is an application error that would normally result in a crash,
3540 // but we catch it and return an error
3541 context->handleError(
3542 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003543 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003544 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003545 }
3546
Jiajia Qind9671222016-11-29 16:30:31 +08003547 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003548 {
3549 return false;
3550 }
3551
Jamie Madill2b976812014-08-25 15:47:49 -04003552 // Use max index to validate if our vertex buffers are large enough for the pull.
3553 // TODO: offer fast path, with disabled index validation.
3554 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3555 if (elementArrayBuffer)
3556 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003557 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003558 Error error =
3559 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3560 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003561 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003562 {
Jamie Madill437fa652016-05-03 15:13:24 -04003563 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003564 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003565 }
3566 }
3567 else
3568 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003569 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003570 }
3571
Jamie Madille79b1e12015-11-04 16:36:37 -05003572 // If we use an index greater than our maximum supported index range, return an error.
3573 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3574 // return an error if possible here.
3575 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3576 {
Jamie Madill437fa652016-05-03 15:13:24 -04003577 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003578 return false;
3579 }
3580
Corentin Wallez92db6942016-12-09 13:10:36 -05003581 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3582 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003583 {
3584 return false;
3585 }
3586
Geoff Lang3edfe032015-09-04 16:38:24 -04003587 // No op if there are no real indices in the index data (all are primitive restart).
3588 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003589}
3590
Geoff Langb1196682014-07-23 13:47:29 -04003591bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003592 GLenum mode,
3593 GLsizei count,
3594 GLenum type,
3595 const GLvoid *indices,
3596 GLsizei primcount,
3597 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003598{
3599 if (primcount < 0)
3600 {
Jamie Madill437fa652016-05-03 15:13:24 -04003601 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003602 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003603 }
3604
Jamie Madill2b976812014-08-25 15:47:49 -04003605 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003606 {
3607 return false;
3608 }
3609
3610 // No-op zero primitive count
3611 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003612}
3613
Geoff Lang3edfe032015-09-04 16:38:24 -04003614bool ValidateDrawElementsInstancedANGLE(Context *context,
3615 GLenum mode,
3616 GLsizei count,
3617 GLenum type,
3618 const GLvoid *indices,
3619 GLsizei primcount,
3620 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003621{
3622 if (!ValidateDrawInstancedANGLE(context))
3623 {
3624 return false;
3625 }
3626
He Yunchaoced53ae2016-11-29 15:00:51 +08003627 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3628 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003629}
3630
He Yunchaoced53ae2016-11-29 15:00:51 +08003631bool ValidateFramebufferTextureBase(Context *context,
3632 GLenum target,
3633 GLenum attachment,
3634 GLuint texture,
3635 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003636{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003637 if (!ValidFramebufferTarget(target))
3638 {
Jamie Madill437fa652016-05-03 15:13:24 -04003639 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003640 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003641 }
3642
3643 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003644 {
3645 return false;
3646 }
3647
Jamie Madill55ec3b12014-07-03 10:38:57 -04003648 if (texture != 0)
3649 {
3650 gl::Texture *tex = context->getTexture(texture);
3651
3652 if (tex == NULL)
3653 {
Jamie Madill437fa652016-05-03 15:13:24 -04003654 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003655 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003656 }
3657
3658 if (level < 0)
3659 {
Jamie Madill437fa652016-05-03 15:13:24 -04003660 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003661 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003662 }
3663 }
3664
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003665 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003666 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003667
Jamie Madill84115c92015-04-23 15:00:07 -04003668 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003669 {
Jamie Madill437fa652016-05-03 15:13:24 -04003670 context->handleError(
3671 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003672 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003673 }
3674
3675 return true;
3676}
3677
He Yunchaoced53ae2016-11-29 15:00:51 +08003678bool ValidateFramebufferTexture2D(Context *context,
3679 GLenum target,
3680 GLenum attachment,
3681 GLenum textarget,
3682 GLuint texture,
3683 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003684{
He Yunchaoced53ae2016-11-29 15:00:51 +08003685 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3686 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003687 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3688 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003689 {
Jamie Madill437fa652016-05-03 15:13:24 -04003690 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003691 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003692 }
3693
3694 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003695 {
3696 return false;
3697 }
3698
Jamie Madill55ec3b12014-07-03 10:38:57 -04003699 if (texture != 0)
3700 {
3701 gl::Texture *tex = context->getTexture(texture);
3702 ASSERT(tex);
3703
Jamie Madill2a6564e2014-07-11 09:53:19 -04003704 const gl::Caps &caps = context->getCaps();
3705
Jamie Madill55ec3b12014-07-03 10:38:57 -04003706 switch (textarget)
3707 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003708 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003709 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003710 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003711 {
Jamie Madill437fa652016-05-03 15:13:24 -04003712 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003713 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003714 }
3715 if (tex->getTarget() != GL_TEXTURE_2D)
3716 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003717 context->handleError(Error(GL_INVALID_OPERATION,
3718 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003719 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003720 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003721 }
3722 break;
3723
He Yunchaoced53ae2016-11-29 15:00:51 +08003724 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3725 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3726 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3727 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3728 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3729 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003730 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003731 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003732 {
Jamie Madill437fa652016-05-03 15:13:24 -04003733 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003734 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003735 }
3736 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3737 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003738 context->handleError(Error(GL_INVALID_OPERATION,
3739 "Textarget must match the texture target type."));
3740 return false;
3741 }
3742 }
3743 break;
3744
3745 case GL_TEXTURE_2D_MULTISAMPLE:
3746 {
3747 if (context->getClientVersion() < ES_3_1)
3748 {
3749 context->handleError(Error(GL_INVALID_OPERATION,
3750 "Texture target requires at least OpenGL ES 3.1."));
3751 return false;
3752 }
3753
3754 if (level != 0)
3755 {
3756 context->handleError(
3757 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
3758 return false;
3759 }
3760 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
3761 {
3762 context->handleError(Error(GL_INVALID_OPERATION,
3763 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003764 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003765 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003766 }
3767 break;
3768
He Yunchaoced53ae2016-11-29 15:00:51 +08003769 default:
3770 context->handleError(Error(GL_INVALID_ENUM));
3771 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003772 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003773
Jamie Madilla3944d42016-07-22 22:13:26 -04003774 const Format &format = tex->getFormat(textarget, level);
3775 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003776 {
Jamie Madill437fa652016-05-03 15:13:24 -04003777 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003778 return false;
3779 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003780 }
3781
Jamie Madill570f7c82014-07-03 10:38:54 -04003782 return true;
3783}
3784
Geoff Langb1196682014-07-23 13:47:29 -04003785bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003786{
3787 if (program == 0)
3788 {
Jamie Madill437fa652016-05-03 15:13:24 -04003789 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003790 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003791 }
3792
Dian Xiang769769a2015-09-09 15:20:08 -07003793 gl::Program *programObject = GetValidProgram(context, program);
3794 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003795 {
3796 return false;
3797 }
3798
Jamie Madill0063c512014-08-25 15:47:53 -04003799 if (!programObject || !programObject->isLinked())
3800 {
Jamie Madill437fa652016-05-03 15:13:24 -04003801 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003802 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003803 }
3804
Geoff Lang7dd2e102014-11-10 15:19:26 -05003805 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003806 {
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 Madill549c7fd2014-08-25 15:47:56 -04003809 }
3810
Jamie Madill0063c512014-08-25 15:47:53 -04003811 return true;
3812}
3813
He Yunchaoced53ae2016-11-29 15:00:51 +08003814bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003815{
3816 return ValidateGetUniformBase(context, program, location);
3817}
3818
He Yunchaoced53ae2016-11-29 15:00:51 +08003819bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003820{
Jamie Madill78f41802014-08-25 15:47:55 -04003821 return ValidateGetUniformBase(context, program, location);
3822}
3823
Geoff Langf41d0ee2016-10-07 13:04:23 -04003824static bool ValidateSizedGetUniform(Context *context,
3825 GLuint program,
3826 GLint location,
3827 GLsizei bufSize,
3828 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003829{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003830 if (length)
3831 {
3832 *length = 0;
3833 }
3834
Jamie Madill78f41802014-08-25 15:47:55 -04003835 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003836 {
Jamie Madill78f41802014-08-25 15:47:55 -04003837 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003838 }
3839
Geoff Langf41d0ee2016-10-07 13:04:23 -04003840 if (bufSize < 0)
3841 {
3842 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3843 return false;
3844 }
3845
Jamie Madilla502c742014-08-28 17:19:13 -04003846 gl::Program *programObject = context->getProgram(program);
3847 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003848
Jamie Madill78f41802014-08-25 15:47:55 -04003849 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003850 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003851 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003852 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003853 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003854 context->handleError(
3855 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003856 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003857 }
3858
Geoff Langf41d0ee2016-10-07 13:04:23 -04003859 if (length)
3860 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003861 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003862 }
3863
Jamie Madill0063c512014-08-25 15:47:53 -04003864 return true;
3865}
3866
He Yunchaoced53ae2016-11-29 15:00:51 +08003867bool ValidateGetnUniformfvEXT(Context *context,
3868 GLuint program,
3869 GLint location,
3870 GLsizei bufSize,
3871 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003872{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003873 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003874}
3875
He Yunchaoced53ae2016-11-29 15:00:51 +08003876bool ValidateGetnUniformivEXT(Context *context,
3877 GLuint program,
3878 GLint location,
3879 GLsizei bufSize,
3880 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003881{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003882 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3883}
3884
3885bool ValidateGetUniformfvRobustANGLE(Context *context,
3886 GLuint program,
3887 GLint location,
3888 GLsizei bufSize,
3889 GLsizei *length,
3890 GLfloat *params)
3891{
3892 if (!ValidateRobustEntryPoint(context, bufSize))
3893 {
3894 return false;
3895 }
3896
3897 // bufSize is validated in ValidateSizedGetUniform
3898 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3899}
3900
3901bool ValidateGetUniformivRobustANGLE(Context *context,
3902 GLuint program,
3903 GLint location,
3904 GLsizei bufSize,
3905 GLsizei *length,
3906 GLint *params)
3907{
3908 if (!ValidateRobustEntryPoint(context, bufSize))
3909 {
3910 return false;
3911 }
3912
3913 // bufSize is validated in ValidateSizedGetUniform
3914 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3915}
3916
3917bool ValidateGetUniformuivRobustANGLE(Context *context,
3918 GLuint program,
3919 GLint location,
3920 GLsizei bufSize,
3921 GLsizei *length,
3922 GLuint *params)
3923{
3924 if (!ValidateRobustEntryPoint(context, bufSize))
3925 {
3926 return false;
3927 }
3928
3929 if (context->getClientMajorVersion() < 3)
3930 {
3931 context->handleError(
3932 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3933 return false;
3934 }
3935
3936 // bufSize is validated in ValidateSizedGetUniform
3937 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003938}
3939
He Yunchaoced53ae2016-11-29 15:00:51 +08003940bool ValidateDiscardFramebufferBase(Context *context,
3941 GLenum target,
3942 GLsizei numAttachments,
3943 const GLenum *attachments,
3944 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003945{
3946 if (numAttachments < 0)
3947 {
Jamie Madill437fa652016-05-03 15:13:24 -04003948 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003949 return false;
3950 }
3951
3952 for (GLsizei i = 0; i < numAttachments; ++i)
3953 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003954 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003955 {
3956 if (defaultFramebuffer)
3957 {
Jamie Madill437fa652016-05-03 15:13:24 -04003958 context->handleError(Error(
3959 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003960 return false;
3961 }
3962
3963 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3964 {
Jamie Madill437fa652016-05-03 15:13:24 -04003965 context->handleError(Error(GL_INVALID_OPERATION,
3966 "Requested color attachment is greater than the maximum "
3967 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003968 return false;
3969 }
3970 }
3971 else
3972 {
3973 switch (attachments[i])
3974 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003975 case GL_DEPTH_ATTACHMENT:
3976 case GL_STENCIL_ATTACHMENT:
3977 case GL_DEPTH_STENCIL_ATTACHMENT:
3978 if (defaultFramebuffer)
3979 {
3980 context->handleError(
3981 Error(GL_INVALID_ENUM,
3982 "Invalid attachment when the default framebuffer is bound"));
3983 return false;
3984 }
3985 break;
3986 case GL_COLOR:
3987 case GL_DEPTH:
3988 case GL_STENCIL:
3989 if (!defaultFramebuffer)
3990 {
3991 context->handleError(
3992 Error(GL_INVALID_ENUM,
3993 "Invalid attachment when the default framebuffer is not bound"));
3994 return false;
3995 }
3996 break;
3997 default:
3998 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003999 return false;
Austin Kinross08332632015-05-05 13:35:47 -07004000 }
4001 }
4002 }
4003
4004 return true;
4005}
4006
Austin Kinross6ee1e782015-05-29 17:05:37 -07004007bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
4008{
4009 // Note that debug marker calls must not set error state
4010
4011 if (length < 0)
4012 {
4013 return false;
4014 }
4015
4016 if (marker == nullptr)
4017 {
4018 return false;
4019 }
4020
4021 return true;
4022}
4023
4024bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
4025{
4026 // Note that debug marker calls must not set error state
4027
4028 if (length < 0)
4029 {
4030 return false;
4031 }
4032
4033 if (length > 0 && marker == nullptr)
4034 {
4035 return false;
4036 }
4037
4038 return true;
4039}
4040
Geoff Langdcab33b2015-07-21 13:03:16 -04004041bool ValidateEGLImageTargetTexture2DOES(Context *context,
4042 egl::Display *display,
4043 GLenum target,
4044 egl::Image *image)
4045{
Geoff Langa8406172015-07-21 16:53:39 -04004046 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
4047 {
Jamie Madill437fa652016-05-03 15:13:24 -04004048 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004049 return false;
4050 }
4051
4052 switch (target)
4053 {
4054 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04004055 if (!context->getExtensions().eglImage)
4056 {
4057 context->handleError(Error(
4058 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
4059 }
4060 break;
4061
4062 case GL_TEXTURE_EXTERNAL_OES:
4063 if (!context->getExtensions().eglImageExternal)
4064 {
4065 context->handleError(Error(
4066 GL_INVALID_ENUM,
4067 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
4068 }
Geoff Langa8406172015-07-21 16:53:39 -04004069 break;
4070
4071 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004072 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04004073 return false;
4074 }
4075
4076 if (!display->isValidImage(image))
4077 {
Jamie Madill437fa652016-05-03 15:13:24 -04004078 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004079 return false;
4080 }
4081
4082 if (image->getSamples() > 0)
4083 {
Jamie Madill437fa652016-05-03 15:13:24 -04004084 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004085 "cannot create a 2D texture from a multisampled EGL image."));
4086 return false;
4087 }
4088
Jamie Madilla3944d42016-07-22 22:13:26 -04004089 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004090 if (!textureCaps.texturable)
4091 {
Jamie Madill437fa652016-05-03 15:13:24 -04004092 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004093 "EGL image internal format is not supported as a texture."));
4094 return false;
4095 }
4096
Geoff Langdcab33b2015-07-21 13:03:16 -04004097 return true;
4098}
4099
4100bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
4101 egl::Display *display,
4102 GLenum target,
4103 egl::Image *image)
4104{
Geoff Langa8406172015-07-21 16:53:39 -04004105 if (!context->getExtensions().eglImage)
4106 {
Jamie Madill437fa652016-05-03 15:13:24 -04004107 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004108 return false;
4109 }
4110
4111 switch (target)
4112 {
4113 case GL_RENDERBUFFER:
4114 break;
4115
4116 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004117 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04004118 return false;
4119 }
4120
4121 if (!display->isValidImage(image))
4122 {
Jamie Madill437fa652016-05-03 15:13:24 -04004123 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004124 return false;
4125 }
4126
Jamie Madilla3944d42016-07-22 22:13:26 -04004127 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004128 if (!textureCaps.renderable)
4129 {
Jamie Madill437fa652016-05-03 15:13:24 -04004130 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04004131 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
4132 return false;
4133 }
4134
Geoff Langdcab33b2015-07-21 13:03:16 -04004135 return true;
4136}
Austin Kinrossbc781f32015-10-26 09:27:38 -07004137
4138bool ValidateBindVertexArrayBase(Context *context, GLuint array)
4139{
Geoff Lang36167ab2015-12-07 10:27:14 -05004140 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07004141 {
4142 // The default VAO should always exist
4143 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004144 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004145 return false;
4146 }
4147
4148 return true;
4149}
4150
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004151bool ValidateLinkProgram(Context *context, GLuint program)
4152{
4153 if (context->hasActiveTransformFeedback(program))
4154 {
4155 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004156 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004157 "Cannot link program while program is associated with an active "
4158 "transform feedback object."));
4159 return false;
4160 }
4161 return true;
4162}
4163
Geoff Langc5629752015-12-07 16:29:04 -05004164bool ValidateProgramBinaryBase(Context *context,
4165 GLuint program,
4166 GLenum binaryFormat,
4167 const void *binary,
4168 GLint length)
4169{
4170 Program *programObject = GetValidProgram(context, program);
4171 if (programObject == nullptr)
4172 {
4173 return false;
4174 }
4175
4176 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4177 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4178 programBinaryFormats.end())
4179 {
Jamie Madill437fa652016-05-03 15:13:24 -04004180 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004181 return false;
4182 }
4183
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004184 if (context->hasActiveTransformFeedback(program))
4185 {
4186 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004187 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004188 "Cannot change program binary while program is associated with "
4189 "an active transform feedback object."));
4190 return false;
4191 }
4192
Geoff Langc5629752015-12-07 16:29:04 -05004193 return true;
4194}
4195
4196bool ValidateGetProgramBinaryBase(Context *context,
4197 GLuint program,
4198 GLsizei bufSize,
4199 GLsizei *length,
4200 GLenum *binaryFormat,
4201 void *binary)
4202{
4203 Program *programObject = GetValidProgram(context, program);
4204 if (programObject == nullptr)
4205 {
4206 return false;
4207 }
4208
4209 if (!programObject->isLinked())
4210 {
Jamie Madill437fa652016-05-03 15:13:24 -04004211 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004212 return false;
4213 }
4214
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004215 if (context->getCaps().programBinaryFormats.empty())
4216 {
4217 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4218 return false;
4219 }
4220
Geoff Langc5629752015-12-07 16:29:04 -05004221 return true;
4222}
Jamie Madillc29968b2016-01-20 11:17:23 -05004223
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004224bool ValidateUseProgram(Context *context, GLuint program)
4225{
4226 if (program != 0)
4227 {
4228 Program *programObject = context->getProgram(program);
4229 if (!programObject)
4230 {
4231 // ES 3.1.0 section 7.3 page 72
4232 if (context->getShader(program))
4233 {
Jamie Madill437fa652016-05-03 15:13:24 -04004234 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004235 Error(GL_INVALID_OPERATION,
4236 "Attempted to use a single shader instead of a shader program."));
4237 return false;
4238 }
4239 else
4240 {
Jamie Madill437fa652016-05-03 15:13:24 -04004241 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004242 return false;
4243 }
4244 }
4245 if (!programObject->isLinked())
4246 {
Jamie Madill437fa652016-05-03 15:13:24 -04004247 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004248 return false;
4249 }
4250 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004251 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004252 {
4253 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004254 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004255 Error(GL_INVALID_OPERATION,
4256 "Cannot change active program while transform feedback is unpaused."));
4257 return false;
4258 }
4259
4260 return true;
4261}
4262
Jamie Madillc29968b2016-01-20 11:17:23 -05004263bool ValidateCopyTexImage2D(ValidationContext *context,
4264 GLenum target,
4265 GLint level,
4266 GLenum internalformat,
4267 GLint x,
4268 GLint y,
4269 GLsizei width,
4270 GLsizei height,
4271 GLint border)
4272{
Martin Radev1be913c2016-07-11 17:59:16 +03004273 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004274 {
4275 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4276 0, x, y, width, height, border);
4277 }
4278
Martin Radev1be913c2016-07-11 17:59:16 +03004279 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004280 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4281 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004282}
Jamie Madillc29968b2016-01-20 11:17:23 -05004283
4284bool ValidateFramebufferRenderbuffer(Context *context,
4285 GLenum target,
4286 GLenum attachment,
4287 GLenum renderbuffertarget,
4288 GLuint renderbuffer)
4289{
4290 if (!ValidFramebufferTarget(target) ||
4291 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4292 {
Jamie Madill437fa652016-05-03 15:13:24 -04004293 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004294 return false;
4295 }
4296
4297 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4298 renderbuffertarget, renderbuffer);
4299}
4300
4301bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4302{
4303 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4304 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4305 {
Jamie Madill437fa652016-05-03 15:13:24 -04004306 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004307 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4308 return false;
4309 }
4310
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004311 ASSERT(context->getGLState().getDrawFramebuffer());
4312 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004313 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4314
4315 // This should come first before the check for the default frame buffer
4316 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4317 // rather than INVALID_OPERATION
4318 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4319 {
4320 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4321
4322 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004323 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4324 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004325 {
4326 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004327 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4328 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4329 // 3.1 is still a bit ambiguous about the error, but future specs are
4330 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004331 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004332 return false;
4333 }
4334 else if (bufs[colorAttachment] >= maxColorAttachment)
4335 {
Jamie Madill437fa652016-05-03 15:13:24 -04004336 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004337 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004338 return false;
4339 }
4340 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4341 frameBufferId != 0)
4342 {
4343 // INVALID_OPERATION-GL is bound to buffer and ith argument
4344 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004345 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004346 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4347 return false;
4348 }
4349 }
4350
4351 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4352 // and n is not 1 or bufs is bound to value other than BACK and NONE
4353 if (frameBufferId == 0)
4354 {
4355 if (n != 1)
4356 {
Jamie Madill437fa652016-05-03 15:13:24 -04004357 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004358 "n must be 1 when GL is bound to the default framebuffer"));
4359 return false;
4360 }
4361
4362 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4363 {
Jamie Madill437fa652016-05-03 15:13:24 -04004364 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004365 GL_INVALID_OPERATION,
4366 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4367 return false;
4368 }
4369 }
4370
4371 return true;
4372}
4373
4374bool ValidateCopyTexSubImage2D(Context *context,
4375 GLenum target,
4376 GLint level,
4377 GLint xoffset,
4378 GLint yoffset,
4379 GLint x,
4380 GLint y,
4381 GLsizei width,
4382 GLsizei height)
4383{
Martin Radev1be913c2016-07-11 17:59:16 +03004384 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004385 {
4386 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4387 yoffset, x, y, width, height, 0);
4388 }
4389
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004390 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4391 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004392}
4393
Geoff Lang496c02d2016-10-20 11:38:11 -07004394bool ValidateGetBufferPointervBase(Context *context,
4395 GLenum target,
4396 GLenum pname,
4397 GLsizei *length,
4398 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004399{
Geoff Lang496c02d2016-10-20 11:38:11 -07004400 if (length)
4401 {
4402 *length = 0;
4403 }
4404
4405 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4406 {
4407 context->handleError(
4408 Error(GL_INVALID_OPERATION,
Jamie Madillcc6ac252017-01-25 12:57:21 -08004409 "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
Geoff Lang496c02d2016-10-20 11:38:11 -07004410 return false;
4411 }
4412
Olli Etuaho4f667482016-03-30 15:56:35 +03004413 if (!ValidBufferTarget(context, target))
4414 {
Jamie Madill437fa652016-05-03 15:13:24 -04004415 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004416 return false;
4417 }
4418
Geoff Lang496c02d2016-10-20 11:38:11 -07004419 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004420 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004421 case GL_BUFFER_MAP_POINTER:
4422 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004423
Geoff Lang496c02d2016-10-20 11:38:11 -07004424 default:
4425 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4426 return false;
4427 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004428
4429 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4430 // target bound to zero generate an INVALID_OPERATION error."
4431 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004432 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004433 {
Jamie Madill437fa652016-05-03 15:13:24 -04004434 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004435 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4436 return false;
4437 }
4438
Geoff Lang496c02d2016-10-20 11:38:11 -07004439 if (length)
4440 {
4441 *length = 1;
4442 }
4443
Olli Etuaho4f667482016-03-30 15:56:35 +03004444 return true;
4445}
4446
4447bool ValidateUnmapBufferBase(Context *context, GLenum target)
4448{
4449 if (!ValidBufferTarget(context, target))
4450 {
Jamie Madill437fa652016-05-03 15:13:24 -04004451 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004452 return false;
4453 }
4454
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004455 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004456
4457 if (buffer == nullptr || !buffer->isMapped())
4458 {
Jamie Madill437fa652016-05-03 15:13:24 -04004459 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004460 return false;
4461 }
4462
4463 return true;
4464}
4465
4466bool ValidateMapBufferRangeBase(Context *context,
4467 GLenum target,
4468 GLintptr offset,
4469 GLsizeiptr length,
4470 GLbitfield access)
4471{
4472 if (!ValidBufferTarget(context, target))
4473 {
Jamie Madill437fa652016-05-03 15:13:24 -04004474 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004475 return false;
4476 }
4477
4478 if (offset < 0 || length < 0)
4479 {
Jamie Madill437fa652016-05-03 15:13:24 -04004480 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004481 return false;
4482 }
4483
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004484 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004485
4486 if (!buffer)
4487 {
Jamie Madill437fa652016-05-03 15:13:24 -04004488 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004489 return false;
4490 }
4491
4492 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004493 CheckedNumeric<size_t> checkedOffset(offset);
4494 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004495
Jamie Madille2e406c2016-06-02 13:04:10 -04004496 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004497 {
Jamie Madill437fa652016-05-03 15:13:24 -04004498 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004499 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4500 return false;
4501 }
4502
4503 // Check for invalid bits in the mask
4504 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4505 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4506 GL_MAP_UNSYNCHRONIZED_BIT;
4507
4508 if (access & ~(allAccessBits))
4509 {
Jamie Madill437fa652016-05-03 15:13:24 -04004510 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004511 return false;
4512 }
4513
4514 if (length == 0)
4515 {
Jamie Madill437fa652016-05-03 15:13:24 -04004516 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004517 return false;
4518 }
4519
4520 if (buffer->isMapped())
4521 {
Jamie Madill437fa652016-05-03 15:13:24 -04004522 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004523 return false;
4524 }
4525
4526 // Check for invalid bit combinations
4527 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4528 {
Jamie Madill437fa652016-05-03 15:13:24 -04004529 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004530 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4531 return false;
4532 }
4533
4534 GLbitfield writeOnlyBits =
4535 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4536
4537 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4538 {
Jamie Madill437fa652016-05-03 15:13:24 -04004539 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004540 "Invalid access bits when mapping buffer for reading: 0x%X.",
4541 access));
4542 return false;
4543 }
4544
4545 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4546 {
Jamie Madill437fa652016-05-03 15:13:24 -04004547 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004548 GL_INVALID_OPERATION,
4549 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4550 return false;
4551 }
4552 return true;
4553}
4554
4555bool ValidateFlushMappedBufferRangeBase(Context *context,
4556 GLenum target,
4557 GLintptr offset,
4558 GLsizeiptr length)
4559{
4560 if (offset < 0 || length < 0)
4561 {
Jamie Madill437fa652016-05-03 15:13:24 -04004562 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004563 return false;
4564 }
4565
4566 if (!ValidBufferTarget(context, target))
4567 {
Jamie Madill437fa652016-05-03 15:13:24 -04004568 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004569 return false;
4570 }
4571
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004572 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004573
4574 if (buffer == nullptr)
4575 {
Jamie Madill437fa652016-05-03 15:13:24 -04004576 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004577 return false;
4578 }
4579
4580 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4581 {
Jamie Madill437fa652016-05-03 15:13:24 -04004582 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004583 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4584 return false;
4585 }
4586
4587 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004588 CheckedNumeric<size_t> checkedOffset(offset);
4589 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004590
Jamie Madille2e406c2016-06-02 13:04:10 -04004591 if (!checkedSize.IsValid() ||
4592 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004593 {
Jamie Madill437fa652016-05-03 15:13:24 -04004594 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004595 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4596 return false;
4597 }
4598
4599 return true;
4600}
4601
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004602bool ValidateGenerateMipmap(Context *context, GLenum target)
4603{
4604 if (!ValidTextureTarget(context, target))
4605 {
4606 context->handleError(Error(GL_INVALID_ENUM));
4607 return false;
4608 }
4609
4610 Texture *texture = context->getTargetTexture(target);
4611
4612 if (texture == nullptr)
4613 {
4614 context->handleError(Error(GL_INVALID_OPERATION));
4615 return false;
4616 }
4617
4618 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4619
4620 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4621 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4622 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4623 {
4624 context->handleError(Error(GL_INVALID_OPERATION));
4625 return false;
4626 }
4627
Jamie Madilla3944d42016-07-22 22:13:26 -04004628 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4629 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4630 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004631
4632 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4633 // unsized formats or that are color renderable and filterable. Since we do not track if
4634 // the texture was created with sized or unsized format (only sized formats are stored),
4635 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4636 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4637 // textures since they're the only texture format that can be created with unsized formats
4638 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4639 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004640 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4641 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004642 {
4643 context->handleError(Error(GL_INVALID_OPERATION));
4644 return false;
4645 }
4646
4647 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004648 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004649 {
4650 context->handleError(Error(GL_INVALID_OPERATION));
4651 return false;
4652 }
4653
4654 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004655 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004656 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4657 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4658 {
Geoff Lang55482a12016-11-21 16:54:01 -05004659 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004660 context->handleError(Error(GL_INVALID_OPERATION));
4661 return false;
4662 }
4663
4664 // Cube completeness check
4665 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4666 {
4667 context->handleError(Error(GL_INVALID_OPERATION));
4668 return false;
4669 }
4670
4671 return true;
4672}
4673
Olli Etuaho41997e72016-03-10 13:38:39 +02004674bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4675{
4676 return ValidateGenOrDelete(context, n);
4677}
4678
4679bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4680{
4681 return ValidateGenOrDelete(context, n);
4682}
4683
4684bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4685{
4686 return ValidateGenOrDelete(context, n);
4687}
4688
4689bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4690{
4691 return ValidateGenOrDelete(context, n);
4692}
4693
4694bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4695{
4696 return ValidateGenOrDelete(context, n);
4697}
4698
4699bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4700{
4701 return ValidateGenOrDelete(context, n);
4702}
4703
4704bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4705{
4706 return ValidateGenOrDelete(context, n);
4707}
4708
4709bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4710{
4711 return ValidateGenOrDelete(context, n);
4712}
4713
4714bool ValidateGenOrDelete(Context *context, GLint n)
4715{
4716 if (n < 0)
4717 {
Jamie Madill437fa652016-05-03 15:13:24 -04004718 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004719 return false;
4720 }
4721 return true;
4722}
4723
Geoff Langf41a7152016-09-19 15:11:17 -04004724bool ValidateEnable(Context *context, GLenum cap)
4725{
4726 if (!ValidCap(context, cap, false))
4727 {
4728 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4729 return false;
4730 }
4731
4732 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4733 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4734 {
4735 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4736 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4737
4738 // We also output an error message to the debugger window if tracing is active, so that
4739 // developers can see the error message.
Yuly Novikovd73f8522017-01-13 17:48:57 -05004740 ERR() << errorMessage;
Geoff Langf41a7152016-09-19 15:11:17 -04004741 return false;
4742 }
4743
4744 return true;
4745}
4746
4747bool ValidateDisable(Context *context, GLenum cap)
4748{
4749 if (!ValidCap(context, cap, false))
4750 {
4751 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4752 return false;
4753 }
4754
4755 return true;
4756}
4757
4758bool ValidateIsEnabled(Context *context, GLenum cap)
4759{
4760 if (!ValidCap(context, cap, true))
4761 {
4762 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4763 return false;
4764 }
4765
4766 return true;
4767}
4768
Geoff Langff5b2d52016-09-07 11:32:23 -04004769bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4770{
4771 if (!context->getExtensions().robustClientMemory)
4772 {
4773 context->handleError(
4774 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4775 return false;
4776 }
4777
4778 if (bufSize < 0)
4779 {
4780 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4781 return false;
4782 }
4783
4784 return true;
4785}
4786
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004787bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4788{
4789 if (bufSize < numParams)
4790 {
4791 context->handleError(Error(GL_INVALID_OPERATION,
4792 "%u parameters are required but %i were provided.", numParams,
4793 bufSize));
4794 return false;
4795 }
4796
4797 return true;
4798}
4799
Geoff Langff5b2d52016-09-07 11:32:23 -04004800bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4801 GLenum target,
4802 GLenum attachment,
4803 GLenum pname,
4804 GLsizei *numParams)
4805{
4806 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4807 *numParams = 1;
4808
4809 if (!ValidFramebufferTarget(target))
4810 {
4811 context->handleError(Error(GL_INVALID_ENUM));
4812 return false;
4813 }
4814
4815 int clientVersion = context->getClientMajorVersion();
4816
4817 switch (pname)
4818 {
4819 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4820 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4821 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4822 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4823 break;
4824
4825 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4826 if (clientVersion < 3 && !context->getExtensions().sRGB)
4827 {
4828 context->handleError(Error(GL_INVALID_ENUM));
4829 return false;
4830 }
4831 break;
4832
4833 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4834 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4835 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4836 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4837 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4838 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4839 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4840 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4841 if (clientVersion < 3)
4842 {
4843 context->handleError(Error(GL_INVALID_ENUM));
4844 return false;
4845 }
4846 break;
4847
4848 default:
4849 context->handleError(Error(GL_INVALID_ENUM));
4850 return false;
4851 }
4852
4853 // Determine if the attachment is a valid enum
4854 switch (attachment)
4855 {
4856 case GL_BACK:
4857 case GL_FRONT:
4858 case GL_DEPTH:
4859 case GL_STENCIL:
4860 case GL_DEPTH_STENCIL_ATTACHMENT:
4861 if (clientVersion < 3)
4862 {
4863 context->handleError(Error(GL_INVALID_ENUM));
4864 return false;
4865 }
4866 break;
4867
4868 case GL_DEPTH_ATTACHMENT:
4869 case GL_STENCIL_ATTACHMENT:
4870 break;
4871
4872 default:
4873 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4874 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4875 {
4876 context->handleError(Error(GL_INVALID_ENUM));
4877 return false;
4878 }
4879 break;
4880 }
4881
4882 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4883 ASSERT(framebuffer);
4884
4885 if (framebuffer->id() == 0)
4886 {
4887 if (clientVersion < 3)
4888 {
4889 context->handleError(Error(GL_INVALID_OPERATION));
4890 return false;
4891 }
4892
4893 switch (attachment)
4894 {
4895 case GL_BACK:
4896 case GL_DEPTH:
4897 case GL_STENCIL:
4898 break;
4899
4900 default:
4901 context->handleError(Error(GL_INVALID_OPERATION));
4902 return false;
4903 }
4904 }
4905 else
4906 {
4907 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4908 {
4909 // Valid attachment query
4910 }
4911 else
4912 {
4913 switch (attachment)
4914 {
4915 case GL_DEPTH_ATTACHMENT:
4916 case GL_STENCIL_ATTACHMENT:
4917 break;
4918
4919 case GL_DEPTH_STENCIL_ATTACHMENT:
4920 if (!framebuffer->hasValidDepthStencil())
4921 {
4922 context->handleError(Error(GL_INVALID_OPERATION));
4923 return false;
4924 }
4925 break;
4926
4927 default:
4928 context->handleError(Error(GL_INVALID_OPERATION));
4929 return false;
4930 }
4931 }
4932 }
4933
4934 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4935 if (attachmentObject)
4936 {
4937 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4938 attachmentObject->type() == GL_TEXTURE ||
4939 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4940
4941 switch (pname)
4942 {
4943 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4944 if (attachmentObject->type() != GL_RENDERBUFFER &&
4945 attachmentObject->type() != GL_TEXTURE)
4946 {
4947 context->handleError(Error(GL_INVALID_ENUM));
4948 return false;
4949 }
4950 break;
4951
4952 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4953 if (attachmentObject->type() != GL_TEXTURE)
4954 {
4955 context->handleError(Error(GL_INVALID_ENUM));
4956 return false;
4957 }
4958 break;
4959
4960 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4961 if (attachmentObject->type() != GL_TEXTURE)
4962 {
4963 context->handleError(Error(GL_INVALID_ENUM));
4964 return false;
4965 }
4966 break;
4967
4968 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4969 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4970 {
4971 context->handleError(Error(GL_INVALID_OPERATION));
4972 return false;
4973 }
4974 break;
4975
4976 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4977 if (attachmentObject->type() != GL_TEXTURE)
4978 {
4979 context->handleError(Error(GL_INVALID_ENUM));
4980 return false;
4981 }
4982 break;
4983
4984 default:
4985 break;
4986 }
4987 }
4988 else
4989 {
4990 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4991 // is NONE, then querying any other pname will generate INVALID_ENUM.
4992
4993 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4994 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4995 // INVALID_OPERATION for all other pnames
4996
4997 switch (pname)
4998 {
4999 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
5000 break;
5001
5002 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5003 if (clientVersion < 3)
5004 {
5005 context->handleError(Error(GL_INVALID_ENUM));
5006 return false;
5007 }
5008 break;
5009
5010 default:
5011 if (clientVersion < 3)
5012 {
5013 context->handleError(Error(GL_INVALID_ENUM));
5014 return false;
5015 }
5016 else
5017 {
5018 context->handleError(Error(GL_INVALID_OPERATION));
5019 return false;
5020 }
5021 }
5022 }
5023
5024 return true;
5025}
5026
5027bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
5028 GLenum target,
5029 GLenum attachment,
5030 GLenum pname,
5031 GLsizei bufSize,
5032 GLsizei *numParams)
5033{
5034 if (!ValidateRobustEntryPoint(context, bufSize))
5035 {
5036 return false;
5037 }
5038
5039 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
5040 {
5041 return false;
5042 }
5043
5044 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5045 {
5046 return false;
5047 }
5048
5049 return true;
5050}
5051
5052bool ValidateGetBufferParameteriv(ValidationContext *context,
5053 GLenum target,
5054 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04005055 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005056{
Geoff Langebebe1c2016-10-14 12:01:31 -04005057 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04005058}
5059
5060bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
5061 GLenum target,
5062 GLenum pname,
5063 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04005064 GLsizei *length,
5065 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005066{
5067 if (!ValidateRobustEntryPoint(context, bufSize))
5068 {
5069 return false;
5070 }
5071
Geoff Langebebe1c2016-10-14 12:01:31 -04005072 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005073 {
5074 return false;
5075 }
5076
Geoff Langebebe1c2016-10-14 12:01:31 -04005077 if (!ValidateRobustBufferSize(context, bufSize, *length))
5078 {
5079 return false;
5080 }
5081
5082 return true;
5083}
5084
5085bool ValidateGetBufferParameteri64v(ValidationContext *context,
5086 GLenum target,
5087 GLenum pname,
5088 GLint64 *params)
5089{
5090 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5091}
5092
5093bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
5094 GLenum target,
5095 GLenum pname,
5096 GLsizei bufSize,
5097 GLsizei *length,
5098 GLint64 *params)
5099{
5100 if (!ValidateRobustEntryPoint(context, bufSize))
5101 {
5102 return false;
5103 }
5104
5105 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
5106 {
5107 return false;
5108 }
5109
5110 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005111 {
5112 return false;
5113 }
5114
5115 return true;
5116}
5117
5118bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
5119{
5120 // Currently, all GetProgramiv queries return 1 parameter
5121 *numParams = 1;
5122
5123 Program *programObject = GetValidProgram(context, program);
5124 if (!programObject)
5125 {
5126 return false;
5127 }
5128
5129 switch (pname)
5130 {
5131 case GL_DELETE_STATUS:
5132 case GL_LINK_STATUS:
5133 case GL_VALIDATE_STATUS:
5134 case GL_INFO_LOG_LENGTH:
5135 case GL_ATTACHED_SHADERS:
5136 case GL_ACTIVE_ATTRIBUTES:
5137 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
5138 case GL_ACTIVE_UNIFORMS:
5139 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
5140 break;
5141
5142 case GL_PROGRAM_BINARY_LENGTH:
5143 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5144 {
5145 context->handleError(Error(GL_INVALID_ENUM,
5146 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5147 "GL_OES_get_program_binary or ES 3.0."));
5148 return false;
5149 }
5150 break;
5151
5152 case GL_ACTIVE_UNIFORM_BLOCKS:
5153 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5154 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5155 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5156 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5157 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5158 if (context->getClientMajorVersion() < 3)
5159 {
5160 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5161 return false;
5162 }
5163 break;
5164
5165 default:
5166 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5167 return false;
5168 }
5169
5170 return true;
5171}
5172
5173bool ValidateGetProgramivRobustANGLE(Context *context,
5174 GLuint program,
5175 GLenum pname,
5176 GLsizei bufSize,
5177 GLsizei *numParams)
5178{
5179 if (!ValidateRobustEntryPoint(context, bufSize))
5180 {
5181 return false;
5182 }
5183
5184 if (!ValidateGetProgramiv(context, program, pname, numParams))
5185 {
5186 return false;
5187 }
5188
5189 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5190 {
5191 return false;
5192 }
5193
5194 return true;
5195}
5196
Geoff Lang740d9022016-10-07 11:20:52 -04005197bool ValidateGetRenderbufferParameteriv(Context *context,
5198 GLenum target,
5199 GLenum pname,
5200 GLint *params)
5201{
5202 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5203}
5204
5205bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5206 GLenum target,
5207 GLenum pname,
5208 GLsizei bufSize,
5209 GLsizei *length,
5210 GLint *params)
5211{
5212 if (!ValidateRobustEntryPoint(context, bufSize))
5213 {
5214 return false;
5215 }
5216
5217 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5218 {
5219 return false;
5220 }
5221
5222 if (!ValidateRobustBufferSize(context, bufSize, *length))
5223 {
5224 return false;
5225 }
5226
5227 return true;
5228}
5229
Geoff Langd7d0ed32016-10-07 11:33:51 -04005230bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5231{
5232 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5233}
5234
5235bool ValidateGetShaderivRobustANGLE(Context *context,
5236 GLuint shader,
5237 GLenum pname,
5238 GLsizei bufSize,
5239 GLsizei *length,
5240 GLint *params)
5241{
5242 if (!ValidateRobustEntryPoint(context, bufSize))
5243 {
5244 return false;
5245 }
5246
5247 if (!ValidateGetShaderivBase(context, shader, pname, length))
5248 {
5249 return false;
5250 }
5251
5252 if (!ValidateRobustBufferSize(context, bufSize, *length))
5253 {
5254 return false;
5255 }
5256
5257 return true;
5258}
5259
Geoff Langc1984ed2016-10-07 12:41:00 -04005260bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5261{
5262 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5263}
5264
5265bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5266 GLenum target,
5267 GLenum pname,
5268 GLsizei bufSize,
5269 GLsizei *length,
5270 GLfloat *params)
5271{
5272 if (!ValidateRobustEntryPoint(context, bufSize))
5273 {
5274 return false;
5275 }
5276
5277 if (!ValidateGetTexParameterBase(context, target, pname, length))
5278 {
5279 return false;
5280 }
5281
5282 if (!ValidateRobustBufferSize(context, bufSize, *length))
5283 {
5284 return false;
5285 }
5286
5287 return true;
5288}
5289
5290bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5291{
5292 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5293}
5294
5295bool ValidateGetTexParameterivRobustANGLE(Context *context,
5296 GLenum target,
5297 GLenum pname,
5298 GLsizei bufSize,
5299 GLsizei *length,
5300 GLint *params)
5301{
5302 if (!ValidateRobustEntryPoint(context, bufSize))
5303 {
5304 return false;
5305 }
5306
5307 if (!ValidateGetTexParameterBase(context, target, pname, length))
5308 {
5309 return false;
5310 }
5311
5312 if (!ValidateRobustBufferSize(context, bufSize, *length))
5313 {
5314 return false;
5315 }
5316
5317 return true;
5318}
5319
5320bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5321{
5322 return ValidateTexParameterBase(context, target, pname, -1, &param);
5323}
5324
5325bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5326{
5327 return ValidateTexParameterBase(context, target, pname, -1, params);
5328}
5329
5330bool ValidateTexParameterfvRobustANGLE(Context *context,
5331 GLenum target,
5332 GLenum pname,
5333 GLsizei bufSize,
5334 const GLfloat *params)
5335{
5336 if (!ValidateRobustEntryPoint(context, bufSize))
5337 {
5338 return false;
5339 }
5340
5341 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5342}
5343
5344bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5345{
5346 return ValidateTexParameterBase(context, target, pname, -1, &param);
5347}
5348
5349bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5350{
5351 return ValidateTexParameterBase(context, target, pname, -1, params);
5352}
5353
5354bool ValidateTexParameterivRobustANGLE(Context *context,
5355 GLenum target,
5356 GLenum pname,
5357 GLsizei bufSize,
5358 const GLint *params)
5359{
5360 if (!ValidateRobustEntryPoint(context, bufSize))
5361 {
5362 return false;
5363 }
5364
5365 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5366}
5367
5368bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5369{
5370 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5371}
5372
5373bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5374 GLuint sampler,
5375 GLenum pname,
5376 GLuint bufSize,
5377 GLsizei *length,
5378 GLfloat *params)
5379{
5380 if (!ValidateRobustEntryPoint(context, bufSize))
5381 {
5382 return false;
5383 }
5384
5385 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5386 {
5387 return false;
5388 }
5389
5390 if (!ValidateRobustBufferSize(context, bufSize, *length))
5391 {
5392 return false;
5393 }
5394
5395 return true;
5396}
5397
5398bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5399{
5400 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5401}
5402
5403bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5404 GLuint sampler,
5405 GLenum pname,
5406 GLuint bufSize,
5407 GLsizei *length,
5408 GLint *params)
5409{
5410 if (!ValidateRobustEntryPoint(context, bufSize))
5411 {
5412 return false;
5413 }
5414
5415 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5416 {
5417 return false;
5418 }
5419
5420 if (!ValidateRobustBufferSize(context, bufSize, *length))
5421 {
5422 return false;
5423 }
5424
5425 return true;
5426}
5427
5428bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5429{
5430 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5431}
5432
5433bool ValidateSamplerParameterfv(Context *context,
5434 GLuint sampler,
5435 GLenum pname,
5436 const GLfloat *params)
5437{
5438 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5439}
5440
5441bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5442 GLuint sampler,
5443 GLenum pname,
5444 GLsizei bufSize,
5445 const GLfloat *params)
5446{
5447 if (!ValidateRobustEntryPoint(context, bufSize))
5448 {
5449 return false;
5450 }
5451
5452 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5453}
5454
5455bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5456{
5457 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5458}
5459
5460bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5461{
5462 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5463}
5464
5465bool ValidateSamplerParameterivRobustANGLE(Context *context,
5466 GLuint sampler,
5467 GLenum pname,
5468 GLsizei bufSize,
5469 const GLint *params)
5470{
5471 if (!ValidateRobustEntryPoint(context, bufSize))
5472 {
5473 return false;
5474 }
5475
5476 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5477}
5478
Geoff Lang0b031062016-10-13 14:30:04 -04005479bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5480{
5481 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5482}
5483
5484bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5485 GLuint index,
5486 GLenum pname,
5487 GLsizei bufSize,
5488 GLsizei *length,
5489 GLfloat *params)
5490{
5491 if (!ValidateRobustEntryPoint(context, bufSize))
5492 {
5493 return false;
5494 }
5495
5496 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5497 {
5498 return false;
5499 }
5500
5501 if (!ValidateRobustBufferSize(context, bufSize, *length))
5502 {
5503 return false;
5504 }
5505
5506 return true;
5507}
5508
5509bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5510{
5511 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5512}
5513
5514bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5515 GLuint index,
5516 GLenum pname,
5517 GLsizei bufSize,
5518 GLsizei *length,
5519 GLint *params)
5520{
5521 if (!ValidateRobustEntryPoint(context, bufSize))
5522 {
5523 return false;
5524 }
5525
5526 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5527 {
5528 return false;
5529 }
5530
5531 if (!ValidateRobustBufferSize(context, bufSize, *length))
5532 {
5533 return false;
5534 }
5535
5536 return true;
5537}
5538
5539bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5540{
5541 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5542}
5543
5544bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5545 GLuint index,
5546 GLenum pname,
5547 GLsizei bufSize,
5548 GLsizei *length,
5549 void **pointer)
5550{
5551 if (!ValidateRobustEntryPoint(context, bufSize))
5552 {
5553 return false;
5554 }
5555
5556 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5557 {
5558 return false;
5559 }
5560
5561 if (!ValidateRobustBufferSize(context, bufSize, *length))
5562 {
5563 return false;
5564 }
5565
5566 return true;
5567}
5568
5569bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5570{
5571 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5572}
5573
5574bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5575 GLuint index,
5576 GLenum pname,
5577 GLsizei bufSize,
5578 GLsizei *length,
5579 GLint *params)
5580{
5581 if (!ValidateRobustEntryPoint(context, bufSize))
5582 {
5583 return false;
5584 }
5585
5586 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5587 {
5588 return false;
5589 }
5590
5591 if (!ValidateRobustBufferSize(context, bufSize, *length))
5592 {
5593 return false;
5594 }
5595
5596 return true;
5597}
5598
5599bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5600{
5601 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5602}
5603
5604bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5605 GLuint index,
5606 GLenum pname,
5607 GLsizei bufSize,
5608 GLsizei *length,
5609 GLuint *params)
5610{
5611 if (!ValidateRobustEntryPoint(context, bufSize))
5612 {
5613 return false;
5614 }
5615
5616 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5617 {
5618 return false;
5619 }
5620
5621 if (!ValidateRobustBufferSize(context, bufSize, *length))
5622 {
5623 return false;
5624 }
5625
5626 return true;
5627}
5628
Geoff Lang6899b872016-10-14 11:30:13 -04005629bool ValidateGetActiveUniformBlockiv(Context *context,
5630 GLuint program,
5631 GLuint uniformBlockIndex,
5632 GLenum pname,
5633 GLint *params)
5634{
5635 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5636}
5637
5638bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5639 GLuint program,
5640 GLuint uniformBlockIndex,
5641 GLenum pname,
5642 GLsizei bufSize,
5643 GLsizei *length,
5644 GLint *params)
5645{
5646 if (!ValidateRobustEntryPoint(context, bufSize))
5647 {
5648 return false;
5649 }
5650
5651 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5652 {
5653 return false;
5654 }
5655
5656 if (!ValidateRobustBufferSize(context, bufSize, *length))
5657 {
5658 return false;
5659 }
5660
5661 return true;
5662}
5663
Geoff Lang0a9661f2016-10-20 10:59:20 -07005664bool ValidateGetInternalFormativ(Context *context,
5665 GLenum target,
5666 GLenum internalformat,
5667 GLenum pname,
5668 GLsizei bufSize,
5669 GLint *params)
5670{
5671 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5672 nullptr);
5673}
5674
5675bool ValidateGetInternalFormativRobustANGLE(Context *context,
5676 GLenum target,
5677 GLenum internalformat,
5678 GLenum pname,
5679 GLsizei bufSize,
5680 GLsizei *length,
5681 GLint *params)
5682{
5683 if (!ValidateRobustEntryPoint(context, bufSize))
5684 {
5685 return false;
5686 }
5687
5688 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5689 {
5690 return false;
5691 }
5692
5693 if (!ValidateRobustBufferSize(context, bufSize, *length))
5694 {
5695 return false;
5696 }
5697
5698 return true;
5699}
5700
Jamie Madillc29968b2016-01-20 11:17:23 -05005701} // namespace gl