blob: d367250871a4b7be807b8e2c3aca10758232f520 [file] [log] [blame]
Martin Radev66fb8202016-07-28 11:45:20 +03001//
2// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES31.cpp: Validation functions for OpenGL ES 3.1 entry point parameters
8
Martin Radev66fb8202016-07-28 11:45:20 +03009#include "libANGLE/validationES31.h"
10
11#include "libANGLE/Context.h"
JiangYizhouf7bbc8a2016-11-16 09:57:22 +080012#include "libANGLE/Framebuffer.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040013#include "libANGLE/VertexArray.h"
Geoff Lang2e43dbb2016-10-14 12:27:35 -040014#include "libANGLE/validationES.h"
15#include "libANGLE/validationES3.h"
Martin Radev66fb8202016-07-28 11:45:20 +030016
He Yunchao11b038b2016-11-22 21:24:04 +080017#include "common/utilities.h"
18
Martin Radev66fb8202016-07-28 11:45:20 +030019using namespace angle;
20
21namespace gl
22{
23
jchen1015015f72017-03-16 13:54:21 +080024namespace
25{
26
27bool ValidateNamedProgramInterface(GLenum programInterface)
28{
29 switch (programInterface)
30 {
31 case GL_UNIFORM:
32 case GL_UNIFORM_BLOCK:
33 case GL_PROGRAM_INPUT:
34 case GL_PROGRAM_OUTPUT:
35 case GL_TRANSFORM_FEEDBACK_VARYING:
36 case GL_BUFFER_VARIABLE:
37 case GL_SHADER_STORAGE_BLOCK:
38 return true;
39 default:
40 return false;
41 }
42}
43
jchen10191381f2017-04-11 13:59:04 +080044bool ValidateLocationProgramInterface(GLenum programInterface)
45{
46 switch (programInterface)
47 {
48 case GL_UNIFORM:
49 case GL_PROGRAM_INPUT:
50 case GL_PROGRAM_OUTPUT:
51 return true;
52 default:
53 return false;
54 }
55}
56
jchen10fd7c3b52017-03-21 15:36:03 +080057bool ValidateProgramResourceIndex(const Program *programObject,
58 GLenum programInterface,
59 GLuint index)
60{
61 switch (programInterface)
62 {
63 case GL_PROGRAM_INPUT:
64 return (index < static_cast<GLuint>(programObject->getActiveAttributeCount()));
65
66 case GL_PROGRAM_OUTPUT:
67 return (index < static_cast<GLuint>(programObject->getOutputResourceCount()));
68
69 // TODO(Jie): more interfaces.
70 case GL_UNIFORM:
71 case GL_UNIFORM_BLOCK:
72 case GL_TRANSFORM_FEEDBACK_VARYING:
73 case GL_BUFFER_VARIABLE:
74 case GL_SHADER_STORAGE_BLOCK:
75 UNIMPLEMENTED();
76 return false;
77
78 default:
79 UNREACHABLE();
80 return false;
81 }
82}
83
jchen1015015f72017-03-16 13:54:21 +080084} // anonymous namespace
85
Martin Radev66fb8202016-07-28 11:45:20 +030086bool ValidateGetBooleani_v(Context *context, GLenum target, GLuint index, GLboolean *data)
87{
Geoff Langeb66a6e2016-10-31 13:06:12 -040088 if (context->getClientVersion() < ES_3_1)
Martin Radev66fb8202016-07-28 11:45:20 +030089 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050090 context->handleError(InvalidOperation() << "Context does not support GLES3.1");
Martin Radev66fb8202016-07-28 11:45:20 +030091 return false;
92 }
93
Geoff Lang2e43dbb2016-10-14 12:27:35 -040094 if (!ValidateIndexedStateQuery(context, target, index, nullptr))
95 {
96 return false;
97 }
98
99 return true;
100}
101
102bool ValidateGetBooleani_vRobustANGLE(Context *context,
103 GLenum target,
104 GLuint index,
105 GLsizei bufSize,
106 GLsizei *length,
107 GLboolean *data)
108{
Geoff Langeb66a6e2016-10-31 13:06:12 -0400109 if (context->getClientVersion() < ES_3_1)
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400110 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500111 context->handleError(InvalidOperation() << "Context does not support GLES3.1");
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400112 return false;
113 }
114
115 if (!ValidateRobustEntryPoint(context, bufSize))
116 {
117 return false;
118 }
119
120 if (!ValidateIndexedStateQuery(context, target, index, length))
121 {
122 return false;
123 }
124
125 if (!ValidateRobustBufferSize(context, bufSize, *length))
Martin Radev66fb8202016-07-28 11:45:20 +0300126 {
127 return false;
128 }
129
130 return true;
131}
132
Jamie Madill876429b2017-04-20 15:46:24 -0400133bool ValidateDrawIndirectBase(Context *context, GLenum mode, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800134{
135 if (context->getClientVersion() < ES_3_1)
136 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500137 context->handleError(InvalidOperation() << "Context does not support GLES3.1");
Jiajia Qind9671222016-11-29 16:30:31 +0800138 return false;
139 }
140
141 // Here the third parameter 1 is only to pass the count validation.
142 if (!ValidateDrawBase(context, mode, 1))
143 {
144 return false;
145 }
146
147 const State &state = context->getGLState();
148
149 // An INVALID_OPERATION error is generated if zero is bound to VERTEX_ARRAY_BINDING,
150 // DRAW_INDIRECT_BUFFER or to any enabled vertex array.
151 if (!state.getVertexArrayId())
152 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500153 context->handleError(InvalidOperation() << "zero is bound to VERTEX_ARRAY_BINDING");
Jiajia Qind9671222016-11-29 16:30:31 +0800154 return false;
155 }
156
157 gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
158 if (!drawIndirectBuffer)
159 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500160 context->handleError(InvalidOperation() << "zero is bound to DRAW_INDIRECT_BUFFER");
Jiajia Qind9671222016-11-29 16:30:31 +0800161 return false;
162 }
163
164 // An INVALID_VALUE error is generated if indirect is not a multiple of the size, in basic
165 // machine units, of uint.
166 GLint64 offset = reinterpret_cast<GLint64>(indirect);
167 if ((static_cast<GLuint>(offset) % sizeof(GLuint)) != 0)
168 {
169 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500170 InvalidValue()
171 << "indirect is not a multiple of the size, in basic machine units, of uint");
Jiajia Qind9671222016-11-29 16:30:31 +0800172 return false;
173 }
174
Martin Radev14a26ae2017-07-24 15:56:29 +0300175 // ANGLE_multiview spec, revision 1:
176 // An INVALID_OPERATION is generated by DrawArraysIndirect and DrawElementsIndirect if the
177 // number of views in the draw framebuffer is greater than 1.
178 const Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
179 ASSERT(drawFramebuffer != nullptr);
180 if (drawFramebuffer->getNumViews() > 1)
181 {
182 context->handleError(
183 InvalidOperation()
184 << "The number of views in the active draw framebuffer is greater than 1.");
185 return false;
186 }
187
Jiajia Qind9671222016-11-29 16:30:31 +0800188 return true;
189}
190
Jamie Madill876429b2017-04-20 15:46:24 -0400191bool ValidateDrawArraysIndirect(Context *context, GLenum mode, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800192{
193 const State &state = context->getGLState();
194 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
195 if (curTransformFeedback && curTransformFeedback->isActive() &&
196 !curTransformFeedback->isPaused())
197 {
198 // An INVALID_OPERATION error is generated if transform feedback is active and not paused.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500199 context->handleError(InvalidOperation() << "transform feedback is active and not paused.");
Jiajia Qind9671222016-11-29 16:30:31 +0800200 return false;
201 }
202
203 if (!ValidateDrawIndirectBase(context, mode, indirect))
204 return false;
205
206 gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
207 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
208 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawArraysIndirectCommand
209 // which's size is 4 * sizeof(uint).
210 auto checkedSum = checkedOffset + 4 * sizeof(GLuint);
211 if (!checkedSum.IsValid() ||
212 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
213 {
214 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500215 InvalidOperation()
216 << "the command would source data beyond the end of the buffer object.");
Jiajia Qind9671222016-11-29 16:30:31 +0800217 return false;
218 }
219
220 return true;
221}
222
Jamie Madill876429b2017-04-20 15:46:24 -0400223bool ValidateDrawElementsIndirect(Context *context, GLenum mode, GLenum type, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800224{
225 if (!ValidateDrawElementsBase(context, type))
226 return false;
227
228 const State &state = context->getGLState();
229 const VertexArray *vao = state.getVertexArray();
230 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
231 if (!elementArrayBuffer)
232 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500233 context->handleError(InvalidOperation() << "zero is bound to ELEMENT_ARRAY_BUFFER");
Jiajia Qind9671222016-11-29 16:30:31 +0800234 return false;
235 }
236
237 if (!ValidateDrawIndirectBase(context, mode, indirect))
238 return false;
239
240 gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
241 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
242 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawElementsIndirectCommand
243 // which's size is 5 * sizeof(uint).
244 auto checkedSum = checkedOffset + 5 * sizeof(GLuint);
245 if (!checkedSum.IsValid() ||
246 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
247 {
248 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500249 InvalidOperation()
250 << "the command would source data beyond the end of the buffer object.");
Jiajia Qind9671222016-11-29 16:30:31 +0800251 return false;
252 }
253
254 return true;
255}
256
He Yunchao11b038b2016-11-22 21:24:04 +0800257bool ValidateGetTexLevelParameterBase(Context *context,
258 GLenum target,
259 GLint level,
260 GLenum pname,
261 GLsizei *length)
262{
263 if (context->getClientVersion() < ES_3_1)
264 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500265 context->handleError(InvalidOperation() << "Context does not support GLES3.1");
He Yunchao11b038b2016-11-22 21:24:04 +0800266 return false;
267 }
268
269 if (length)
270 {
271 *length = 0;
272 }
273
274 if (!ValidTexLevelDestinationTarget(context, target))
275 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500276 context->handleError(InvalidEnum() << "Invalid texture target");
He Yunchao11b038b2016-11-22 21:24:04 +0800277 return false;
278 }
279
280 if (context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target) ==
281 nullptr)
282 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500283 context->handleError(InvalidEnum() << "No texture bound.");
He Yunchao11b038b2016-11-22 21:24:04 +0800284 return false;
285 }
286
287 if (!ValidMipLevel(context, target, level))
288 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500289 context->handleError(InvalidValue());
He Yunchao11b038b2016-11-22 21:24:04 +0800290 return false;
291 }
292
293 switch (pname)
294 {
295 case GL_TEXTURE_RED_TYPE:
296 case GL_TEXTURE_GREEN_TYPE:
297 case GL_TEXTURE_BLUE_TYPE:
298 case GL_TEXTURE_ALPHA_TYPE:
299 case GL_TEXTURE_DEPTH_TYPE:
300 break;
301 case GL_TEXTURE_RED_SIZE:
302 case GL_TEXTURE_GREEN_SIZE:
303 case GL_TEXTURE_BLUE_SIZE:
304 case GL_TEXTURE_ALPHA_SIZE:
305 case GL_TEXTURE_DEPTH_SIZE:
306 case GL_TEXTURE_STENCIL_SIZE:
307 case GL_TEXTURE_SHARED_SIZE:
308 break;
309 case GL_TEXTURE_INTERNAL_FORMAT:
310 case GL_TEXTURE_WIDTH:
311 case GL_TEXTURE_HEIGHT:
312 case GL_TEXTURE_DEPTH:
313 break;
314 case GL_TEXTURE_SAMPLES:
315 case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
316 break;
317 case GL_TEXTURE_COMPRESSED:
318 break;
319 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500320 context->handleError(InvalidEnum() << "Unknown pname.");
He Yunchao11b038b2016-11-22 21:24:04 +0800321 return false;
322 }
323
324 if (length)
325 {
326 *length = 1;
327 }
328 return true;
329}
330
331bool ValidateGetTexLevelParameterfv(Context *context,
332 GLenum target,
333 GLint level,
334 GLenum pname,
335 GLfloat *params)
336{
337 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
338}
339
340bool ValidateGetTexLevelParameteriv(Context *context,
341 GLenum target,
342 GLint level,
343 GLenum pname,
344 GLint *params)
345{
346 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
347}
348
JiangYizhoubddc46b2016-12-09 09:50:51 +0800349bool ValidateTexStorage2DMultiSample(Context *context,
350 GLenum target,
351 GLsizei samples,
352 GLint internalFormat,
353 GLsizei width,
354 GLsizei height,
355 GLboolean fixedSampleLocations)
356{
357 if (context->getClientVersion() < ES_3_1)
358 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500359 context->handleError(InvalidOperation() << "Context does not support GLES3.1.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800360 return false;
361 }
362
363 if (target != GL_TEXTURE_2D_MULTISAMPLE)
364 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500365 context->handleError(InvalidEnum() << "Target must be TEXTURE_2D_MULTISAMPLE.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800366 return false;
367 }
368
369 if (width < 1 || height < 1)
370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500371 context->handleError(InvalidValue() << "Width and height must be positive.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800372 return false;
373 }
374
375 const Caps &caps = context->getCaps();
376 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
377 static_cast<GLuint>(height) > caps.max2DTextureSize)
378 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500379 context
380 ->handleError(InvalidValue()
381 << "Width and height must be less than or equal to GL_MAX_TEXTURE_SIZE.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800382 return false;
383 }
384
385 if (samples == 0)
386 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500387 context->handleError(InvalidValue() << "Samples may not be zero.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800388 return false;
389 }
390
391 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
392 if (!formatCaps.renderable)
393 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500394 context->handleError(InvalidEnum() << "SizedInternalformat must be color-renderable, "
395 "depth-renderable, or stencil-renderable.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800396 return false;
397 }
398
399 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
400 // is one of the unsized base internalformats listed in table 8.11.
Geoff Langca271392017-04-05 12:30:00 -0400401 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
402 if (formatInfo.internalFormat == GL_NONE)
JiangYizhoubddc46b2016-12-09 09:50:51 +0800403 {
404 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500405 InvalidEnum()
406 << "Internalformat is one of the unsupported unsized base internalformats.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800407 return false;
408 }
409
410 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
411 {
412 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500413 InvalidOperation()
414 << "Samples must not be greater than maximum supported value for the format.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800415 return false;
416 }
417
418 Texture *texture = context->getTargetTexture(target);
419 if (!texture || texture->id() == 0)
420 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500421 context->handleError(InvalidOperation() << "Zero is bound to target.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800422 return false;
423 }
424
425 if (texture->getImmutableFormat())
426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500427 context->handleError(InvalidOperation() << "The value of TEXTURE_IMMUTABLE_FORMAT for "
428 "the texture currently bound to target on "
429 "the active texture unit is true.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800430 return false;
431 }
432
433 return true;
434}
435
436bool ValidateGetMultisamplefv(Context *context, GLenum pname, GLuint index, GLfloat *val)
437{
438 if (context->getClientVersion() < ES_3_1)
439 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500440 context->handleError(InvalidOperation() << "Context does not support GLES3.1.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800441 return false;
442 }
443
444 if (pname != GL_SAMPLE_POSITION)
445 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500446 context->handleError(InvalidEnum() << "Pname must be SAMPLE_POSITION.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800447 return false;
448 }
449
450 GLint maxSamples = context->getCaps().maxSamples;
451 if (index >= static_cast<GLuint>(maxSamples))
452 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500453 context->handleError(InvalidValue() << "Index must be less than the value of SAMPLES.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800454 return false;
455 }
456
457 return true;
458}
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800459
460bool ValidationFramebufferParameteri(Context *context, GLenum target, GLenum pname, GLint param)
461{
462 if (context->getClientVersion() < ES_3_1)
463 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500464 context->handleError(InvalidOperation() << "Context does not support GLES3.1.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800465 return false;
466 }
467
468 if (!ValidFramebufferTarget(target))
469 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500470 context->handleError(InvalidEnum() << "Invalid framebuffer target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800471 return false;
472 }
473
474 switch (pname)
475 {
476 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
477 {
478 GLint maxWidth = context->getCaps().maxFramebufferWidth;
479 if (param < 0 || param > maxWidth)
480 {
481 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500482 InvalidValue()
483 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_WIDTH.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800484 return false;
485 }
486 break;
487 }
488 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
489 {
490 GLint maxHeight = context->getCaps().maxFramebufferHeight;
491 if (param < 0 || param > maxHeight)
492 {
493 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500494 InvalidValue()
495 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_HEIGHT.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800496 return false;
497 }
498 break;
499 }
500 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
501 {
502 GLint maxSamples = context->getCaps().maxFramebufferSamples;
503 if (param < 0 || param > maxSamples)
504 {
505 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500506 InvalidValue()
507 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_SAMPLES.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800508 return false;
509 }
510 break;
511 }
512 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
513 {
514 break;
515 }
516 default:
517 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500518 context->handleError(InvalidEnum()
519 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800520 return false;
521 }
522 }
523
524 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
525 ASSERT(framebuffer);
526 if (framebuffer->id() == 0)
527 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500528 context->handleError(InvalidOperation() << "Default framebuffer is bound to target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800529 return false;
530 }
531 return true;
532}
533
534bool ValidationGetFramebufferParameteri(Context *context,
535 GLenum target,
536 GLenum pname,
537 GLint *params)
538{
539 if (context->getClientVersion() < ES_3_1)
540 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500541 context->handleError(InvalidOperation() << "Context does not support GLES3.1.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800542 return false;
543 }
544
545 if (!ValidFramebufferTarget(target))
546 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500547 context->handleError(InvalidEnum() << "Invalid framebuffer target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800548 return false;
549 }
550
551 switch (pname)
552 {
553 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
554 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
555 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
556 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
557 break;
558 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500559 context->handleError(InvalidEnum()
560 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800561 return false;
562 }
563
564 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
565 ASSERT(framebuffer);
566
567 if (framebuffer->id() == 0)
568 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500569 context->handleError(InvalidOperation() << "Default framebuffer is bound to target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800570 return false;
571 }
572 return true;
573}
574
jchen1015015f72017-03-16 13:54:21 +0800575bool ValidateGetProgramResourceIndex(Context *context,
576 GLuint program,
577 GLenum programInterface,
578 const GLchar *name)
579{
580 if (context->getClientVersion() < ES_3_1)
581 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500582 context->handleError(InvalidOperation() << "Context does not support GLES 3.1.");
jchen1015015f72017-03-16 13:54:21 +0800583 return false;
584 }
585
586 Program *programObject = GetValidProgram(context, program);
587 if (programObject == nullptr)
588 {
589 return false;
590 }
591
592 if (!ValidateNamedProgramInterface(programInterface))
593 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500594 context->handleError(InvalidEnum() << "Invalid program interface: 0x" << std::hex
595 << std::uppercase << programInterface);
jchen1015015f72017-03-16 13:54:21 +0800596 return false;
597 }
Shao80957d92017-02-20 21:25:59 +0800598
599 return true;
600}
601
602bool ValidateBindVertexBuffer(ValidationContext *context,
603 GLuint bindingIndex,
604 GLuint buffer,
605 GLintptr offset,
606 GLsizei stride)
607{
608 if (context->getClientVersion() < ES_3_1)
609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500610 context->handleError(InvalidOperation() << "Context does not support GLES3.1.");
Shao80957d92017-02-20 21:25:59 +0800611 return false;
612 }
613
614 if (!context->isBufferGenerated(buffer))
615 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500616 context->handleError(InvalidOperation() << "Buffer is not generated.");
Shao80957d92017-02-20 21:25:59 +0800617 return false;
618 }
619
620 const Caps &caps = context->getCaps();
621 if (bindingIndex >= caps.maxVertexAttribBindings)
622 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500623 context->handleError(InvalidValue()
624 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +0800625 return false;
626 }
627
628 if (offset < 0)
629 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500630 context->handleError(InvalidValue() << "offset cannot be negative.");
Shao80957d92017-02-20 21:25:59 +0800631 return false;
632 }
633
634 if (stride < 0 || stride > caps.maxVertexAttribStride)
635 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500636 context->handleError(InvalidValue()
637 << "stride must be between 0 and MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +0800638 return false;
639 }
640
641 // [OpenGL ES 3.1] Section 10.3.1 page 244:
642 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
643 if (context->getGLState().getVertexArrayId() == 0)
644 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500645 context->handleError(InvalidOperation() << "Default vertex array buffer is bound.");
Shao80957d92017-02-20 21:25:59 +0800646 return false;
647 }
648
649 return true;
650}
651
652bool ValidateVertexBindingDivisor(ValidationContext *context, GLuint bindingIndex, GLuint divisor)
653{
654 if (context->getClientVersion() < ES_3_1)
655 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500656 context->handleError(InvalidOperation() << "Context does not support GLES3.1.");
Shao80957d92017-02-20 21:25:59 +0800657 return false;
658 }
659
660 const Caps &caps = context->getCaps();
661 if (bindingIndex >= caps.maxVertexAttribBindings)
662 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500663 context->handleError(InvalidValue()
664 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +0800665 return false;
666 }
667
668 // [OpenGL ES 3.1] Section 10.3.1 page 243:
669 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
670 if (context->getGLState().getVertexArrayId() == 0)
671 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500672 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +0800673 return false;
674 }
675
676 return true;
677}
678
679bool ValidateVertexAttribFormat(ValidationContext *context,
680 GLuint attribIndex,
681 GLint size,
682 GLenum type,
683 GLuint relativeOffset,
684 GLboolean pureInteger)
685{
686 if (context->getClientVersion() < ES_3_1)
687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500688 context->handleError(InvalidOperation() << "Context does not support GLES3.1.");
Shao80957d92017-02-20 21:25:59 +0800689 return false;
690 }
691
692 const Caps &caps = context->getCaps();
693 if (relativeOffset > static_cast<GLuint>(caps.maxVertexAttribRelativeOffset))
694 {
695 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500696 InvalidValue()
697 << "relativeOffset cannot be greater than MAX_VERTEX_ATTRIB_RELATIVE_OFFSET.");
Shao80957d92017-02-20 21:25:59 +0800698 return false;
699 }
700
701 // [OpenGL ES 3.1] Section 10.3.1 page 243:
702 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
703 if (context->getGLState().getVertexArrayId() == 0)
704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500705 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +0800706 return false;
707 }
708
709 return ValidateVertexFormatBase(context, attribIndex, size, type, pureInteger);
710}
711
712bool ValidateVertexAttribBinding(ValidationContext *context,
713 GLuint attribIndex,
714 GLuint bindingIndex)
715{
716 if (context->getClientVersion() < ES_3_1)
717 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500718 context->handleError(InvalidOperation() << "Context does not support GLES3.1.");
Shao80957d92017-02-20 21:25:59 +0800719 return false;
720 }
721
722 // [OpenGL ES 3.1] Section 10.3.1 page 243:
723 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
724 if (context->getGLState().getVertexArrayId() == 0)
725 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500726 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +0800727 return false;
728 }
729
730 const Caps &caps = context->getCaps();
731 if (attribIndex >= caps.maxVertexAttributes)
732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500733 context->handleError(InvalidValue()
734 << "attribindex must be smaller than MAX_VERTEX_ATTRIBS.");
Shao80957d92017-02-20 21:25:59 +0800735 return false;
736 }
737
738 if (bindingIndex >= caps.maxVertexAttribBindings)
739 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500740 context->handleError(InvalidValue()
741 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS");
Shao80957d92017-02-20 21:25:59 +0800742 return false;
743 }
744
jchen1015015f72017-03-16 13:54:21 +0800745 return true;
746}
747
jchen10fd7c3b52017-03-21 15:36:03 +0800748bool ValidateGetProgramResourceName(Context *context,
749 GLuint program,
750 GLenum programInterface,
751 GLuint index,
752 GLsizei bufSize,
753 GLsizei *length,
754 GLchar *name)
755{
756 if (context->getClientVersion() < ES_3_1)
757 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500758 context->handleError(InvalidOperation() << "Context does not support GLES3.1.");
jchen10fd7c3b52017-03-21 15:36:03 +0800759 return false;
760 }
761
762 Program *programObject = GetValidProgram(context, program);
763 if (programObject == nullptr)
764 {
765 return false;
766 }
767
768 if (!ValidateNamedProgramInterface(programInterface))
769 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500770 context->handleError(InvalidEnum() << "Invalid program interface: 0x" << std::hex
771 << std::uppercase << programInterface);
jchen10fd7c3b52017-03-21 15:36:03 +0800772 return false;
773 }
774
775 if (!ValidateProgramResourceIndex(programObject, programInterface, index))
776 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500777 context->handleError(InvalidValue() << "Invalid index: " << index);
jchen10fd7c3b52017-03-21 15:36:03 +0800778 return false;
779 }
780
781 if (bufSize < 0)
782 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500783 context->handleError(InvalidValue() << "Invalid bufSize: " << bufSize);
jchen10fd7c3b52017-03-21 15:36:03 +0800784 return false;
785 }
786
787 return true;
788}
789
Xinghua Cao2b396592017-03-29 15:36:04 +0800790bool ValidateDispatchCompute(Context *context,
791 GLuint numGroupsX,
792 GLuint numGroupsY,
793 GLuint numGroupsZ)
794{
795 if (context->getClientVersion() < ES_3_1)
796 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500797 context->handleError(InvalidOperation() << "Context does not support GLES3.1.");
Xinghua Cao2b396592017-03-29 15:36:04 +0800798 return false;
799 }
800
801 const State &state = context->getGLState();
802 Program *program = state.getProgram();
803
804 if (program == nullptr)
805 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500806 context->handleError(InvalidOperation()
807 << "No active program object for the compute shader stage.");
Xinghua Cao2b396592017-03-29 15:36:04 +0800808 return false;
809 }
810
811 if (program->isLinked() == false || program->getAttachedComputeShader() == nullptr)
812 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500813 context->handleError(
814 InvalidOperation()
815 << "Program has not been successfully linked, or program contains no compute shaders.");
Xinghua Cao2b396592017-03-29 15:36:04 +0800816 return false;
817 }
818
819 const Caps &caps = context->getCaps();
820 if (numGroupsX > caps.maxComputeWorkGroupCount[0])
821 {
822 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500823 InvalidValue() << "num_groups_x cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[0]="
824 << caps.maxComputeWorkGroupCount[0]);
Xinghua Cao2b396592017-03-29 15:36:04 +0800825 return false;
826 }
827 if (numGroupsY > caps.maxComputeWorkGroupCount[1])
828 {
829 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500830 InvalidValue() << "num_groups_y cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[1]="
831 << caps.maxComputeWorkGroupCount[1]);
Xinghua Cao2b396592017-03-29 15:36:04 +0800832 return false;
833 }
834 if (numGroupsZ > caps.maxComputeWorkGroupCount[2])
835 {
836 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500837 InvalidValue() << "num_groups_z cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[2]="
838 << caps.maxComputeWorkGroupCount[2]);
Xinghua Cao2b396592017-03-29 15:36:04 +0800839 return false;
840 }
841
842 return true;
843}
844
Xinghua Cao65ec0b22017-03-28 16:10:52 +0800845bool ValidateBindImageTexture(Context *context,
846 GLuint unit,
847 GLuint texture,
848 GLint level,
849 GLboolean layered,
850 GLint layer,
851 GLenum access,
852 GLenum format)
853{
854 GLuint maxImageUnits = context->getCaps().maxImageUnits;
855 if (unit >= maxImageUnits)
856 {
857 context->handleError(InvalidValue()
858 << "unit cannot be greater than or equal than MAX_IMAGE_UNITS = "
859 << maxImageUnits);
860 return false;
861 }
862
863 if (level < 0)
864 {
865 context->handleError(InvalidValue() << "level is negative.");
866 return false;
867 }
868
869 if (layer < 0)
870 {
871 context->handleError(InvalidValue() << "layer is negative.");
872 return false;
873 }
874
875 if (access != GL_READ_ONLY && access != GL_WRITE_ONLY && access != GL_READ_WRITE)
876 {
877 context->handleError(InvalidEnum() << "access is not one of the supported tokens.");
878 return false;
879 }
880
881 switch (format)
882 {
883 case GL_RGBA32F:
884 case GL_RGBA16F:
885 case GL_R32F:
886 case GL_RGBA32UI:
887 case GL_RGBA16UI:
888 case GL_RGBA8UI:
889 case GL_R32UI:
890 case GL_RGBA32I:
891 case GL_RGBA16I:
892 case GL_RGBA8I:
893 case GL_R32I:
894 case GL_RGBA8:
895 case GL_RGBA8_SNORM:
896 break;
897 default:
898 context->handleError(InvalidValue()
899 << "format is not one of supported image unit formats.");
900 return false;
901 }
902
903 if (texture != 0)
904 {
905 Texture *tex = context->getTexture(texture);
906
907 if (tex == nullptr)
908 {
909 context->handleError(InvalidValue()
910 << "texture is not the name of an existing texture object.");
911 return false;
912 }
913
914 if (!tex->getImmutableFormat())
915 {
916 context->handleError(InvalidOperation()
917 << "texture is not the name of an immutable texture object.");
918 return false;
919 }
920 }
921
922 return true;
923}
jchen10191381f2017-04-11 13:59:04 +0800924
925bool ValidateGetProgramResourceLocation(Context *context,
926 GLuint program,
927 GLenum programInterface,
928 const GLchar *name)
929{
930 if (context->getClientVersion() < ES_3_1)
931 {
932 context->handleError(InvalidOperation() << "Context does not support GLES3.1.");
933 return false;
934 }
935
936 Program *programObject = GetValidProgram(context, program);
937 if (programObject == nullptr)
938 {
939 return false;
940 }
941
942 if (!programObject->isLinked())
943 {
944 context->handleError(InvalidOperation() << "Program is not successfully linked.");
945 return false;
946 }
947
948 if (!ValidateLocationProgramInterface(programInterface))
949 {
950 context->handleError(InvalidEnum() << "Invalid program interface.");
951 return false;
952 }
953 return true;
954}
955
Martin Radev66fb8202016-07-28 11:45:20 +0300956} // namespace gl