blob: 5fff6580af69e628f6dcd8b94682cc4e2c0bbd06 [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"
Brandon Jonesafa75152017-07-21 13:11:29 -070012#include "libANGLE/ErrorStrings.h"
JiangYizhouf7bbc8a2016-11-16 09:57:22 +080013#include "libANGLE/Framebuffer.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040014#include "libANGLE/VertexArray.h"
Geoff Lang2e43dbb2016-10-14 12:27:35 -040015#include "libANGLE/validationES.h"
Yunchao Hea336b902017-08-02 16:05:21 +080016#include "libANGLE/validationES2.h"
Geoff Lang2e43dbb2016-10-14 12:27:35 -040017#include "libANGLE/validationES3.h"
Martin Radev66fb8202016-07-28 11:45:20 +030018
He Yunchao11b038b2016-11-22 21:24:04 +080019#include "common/utilities.h"
20
Martin Radev66fb8202016-07-28 11:45:20 +030021using namespace angle;
22
23namespace gl
24{
25
jchen1015015f72017-03-16 13:54:21 +080026namespace
27{
28
29bool ValidateNamedProgramInterface(GLenum programInterface)
30{
31 switch (programInterface)
32 {
33 case GL_UNIFORM:
34 case GL_UNIFORM_BLOCK:
35 case GL_PROGRAM_INPUT:
36 case GL_PROGRAM_OUTPUT:
37 case GL_TRANSFORM_FEEDBACK_VARYING:
38 case GL_BUFFER_VARIABLE:
39 case GL_SHADER_STORAGE_BLOCK:
40 return true;
41 default:
42 return false;
43 }
44}
45
jchen10191381f2017-04-11 13:59:04 +080046bool ValidateLocationProgramInterface(GLenum programInterface)
47{
48 switch (programInterface)
49 {
50 case GL_UNIFORM:
51 case GL_PROGRAM_INPUT:
52 case GL_PROGRAM_OUTPUT:
53 return true;
54 default:
55 return false;
56 }
57}
58
jchen10880683b2017-04-12 16:21:55 +080059bool ValidateProgramInterface(GLenum programInterface)
60{
61 return (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
62 ValidateNamedProgramInterface(programInterface));
63}
64
65bool ValidateProgramResourceProperty(GLenum prop)
66{
67 switch (prop)
68 {
69 case GL_ACTIVE_VARIABLES:
70 case GL_BUFFER_BINDING:
71 case GL_NUM_ACTIVE_VARIABLES:
72
73 case GL_ARRAY_SIZE:
74
75 case GL_ARRAY_STRIDE:
76 case GL_BLOCK_INDEX:
77 case GL_IS_ROW_MAJOR:
78 case GL_MATRIX_STRIDE:
79
80 case GL_ATOMIC_COUNTER_BUFFER_INDEX:
81
82 case GL_BUFFER_DATA_SIZE:
83
84 case GL_LOCATION:
85
86 case GL_NAME_LENGTH:
87
88 case GL_OFFSET:
89
90 case GL_REFERENCED_BY_VERTEX_SHADER:
91 case GL_REFERENCED_BY_FRAGMENT_SHADER:
92 case GL_REFERENCED_BY_COMPUTE_SHADER:
93
94 case GL_TOP_LEVEL_ARRAY_SIZE:
95 case GL_TOP_LEVEL_ARRAY_STRIDE:
96
97 case GL_TYPE:
98 return true;
99
100 default:
101 return false;
102 }
103}
104
105// GLES 3.10 spec: Page 82 -- Table 7.2
106bool ValidateProgramResourcePropertyByInterface(GLenum prop, GLenum programInterface)
107{
108 switch (prop)
109 {
110 case GL_ACTIVE_VARIABLES:
111 case GL_BUFFER_BINDING:
112 case GL_NUM_ACTIVE_VARIABLES:
113 {
114 switch (programInterface)
115 {
116 case GL_ATOMIC_COUNTER_BUFFER:
117 case GL_SHADER_STORAGE_BLOCK:
118 case GL_UNIFORM_BLOCK:
119 return true;
120 default:
121 return false;
122 }
123 }
124
125 case GL_ARRAY_SIZE:
126 {
127 switch (programInterface)
128 {
129 case GL_BUFFER_VARIABLE:
130 case GL_PROGRAM_INPUT:
131 case GL_PROGRAM_OUTPUT:
132 case GL_TRANSFORM_FEEDBACK_VARYING:
133 case GL_UNIFORM:
134 return true;
135 default:
136 return false;
137 }
138 }
139
140 case GL_ARRAY_STRIDE:
141 case GL_BLOCK_INDEX:
142 case GL_IS_ROW_MAJOR:
143 case GL_MATRIX_STRIDE:
144 {
145 switch (programInterface)
146 {
147 case GL_BUFFER_VARIABLE:
148 case GL_UNIFORM:
149 return true;
150 default:
151 return false;
152 }
153 }
154
155 case GL_ATOMIC_COUNTER_BUFFER_INDEX:
156 {
157 if (programInterface == GL_UNIFORM)
158 {
159 return true;
160 }
161 return false;
162 }
163
164 case GL_BUFFER_DATA_SIZE:
165 {
166 switch (programInterface)
167 {
168 case GL_ATOMIC_COUNTER_BUFFER:
169 case GL_SHADER_STORAGE_BLOCK:
170 case GL_UNIFORM_BLOCK:
171 return true;
172 default:
173 return false;
174 }
175 }
176
177 case GL_LOCATION:
178 {
179 return ValidateLocationProgramInterface(programInterface);
180 }
181
182 case GL_NAME_LENGTH:
183 {
184 return ValidateNamedProgramInterface(programInterface);
185 }
186
187 case GL_OFFSET:
188 {
189 switch (programInterface)
190 {
191 case GL_BUFFER_VARIABLE:
192 case GL_UNIFORM:
193 return true;
194 default:
195 return false;
196 }
197 }
198
199 case GL_REFERENCED_BY_VERTEX_SHADER:
200 case GL_REFERENCED_BY_FRAGMENT_SHADER:
201 case GL_REFERENCED_BY_COMPUTE_SHADER:
202 {
203 switch (programInterface)
204 {
205 case GL_ATOMIC_COUNTER_BUFFER:
206 case GL_BUFFER_VARIABLE:
207 case GL_PROGRAM_INPUT:
208 case GL_PROGRAM_OUTPUT:
209 case GL_SHADER_STORAGE_BLOCK:
210 case GL_UNIFORM:
211 case GL_UNIFORM_BLOCK:
212 return true;
213 default:
214 return false;
215 }
216 }
217
218 case GL_TOP_LEVEL_ARRAY_SIZE:
219 case GL_TOP_LEVEL_ARRAY_STRIDE:
220 {
221 if (programInterface == GL_BUFFER_VARIABLE)
222 {
223 return true;
224 }
225 return false;
226 }
227
228 case GL_TYPE:
229 {
230 switch (programInterface)
231 {
232 case GL_BUFFER_VARIABLE:
233 case GL_PROGRAM_INPUT:
234 case GL_PROGRAM_OUTPUT:
235 case GL_TRANSFORM_FEEDBACK_VARYING:
236 case GL_UNIFORM:
237 return true;
238 default:
239 return false;
240 }
241 }
242
243 default:
244 return false;
245 }
246}
247
jchen10fd7c3b52017-03-21 15:36:03 +0800248bool ValidateProgramResourceIndex(const Program *programObject,
249 GLenum programInterface,
250 GLuint index)
251{
252 switch (programInterface)
253 {
254 case GL_PROGRAM_INPUT:
255 return (index < static_cast<GLuint>(programObject->getActiveAttributeCount()));
256
257 case GL_PROGRAM_OUTPUT:
258 return (index < static_cast<GLuint>(programObject->getOutputResourceCount()));
259
jchen10fd7c3b52017-03-21 15:36:03 +0800260 case GL_UNIFORM:
jchen10baf5d942017-08-28 20:45:48 +0800261 return (index < static_cast<GLuint>(programObject->getActiveUniformCount()));
262
263 // TODO(jie.a.chen@intel.com): more interfaces.
jchen10fd7c3b52017-03-21 15:36:03 +0800264 case GL_UNIFORM_BLOCK:
265 case GL_TRANSFORM_FEEDBACK_VARYING:
266 case GL_BUFFER_VARIABLE:
267 case GL_SHADER_STORAGE_BLOCK:
jchen10880683b2017-04-12 16:21:55 +0800268 case GL_ATOMIC_COUNTER_BUFFER:
jchen10fd7c3b52017-03-21 15:36:03 +0800269 UNIMPLEMENTED();
270 return false;
271
272 default:
273 UNREACHABLE();
274 return false;
275 }
276}
277
jchen1015015f72017-03-16 13:54:21 +0800278} // anonymous namespace
279
Martin Radev66fb8202016-07-28 11:45:20 +0300280bool ValidateGetBooleani_v(Context *context, GLenum target, GLuint index, GLboolean *data)
281{
Geoff Langeb66a6e2016-10-31 13:06:12 -0400282 if (context->getClientVersion() < ES_3_1)
Martin Radev66fb8202016-07-28 11:45:20 +0300283 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700284 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Martin Radev66fb8202016-07-28 11:45:20 +0300285 return false;
286 }
287
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400288 if (!ValidateIndexedStateQuery(context, target, index, nullptr))
289 {
290 return false;
291 }
292
293 return true;
294}
295
296bool ValidateGetBooleani_vRobustANGLE(Context *context,
297 GLenum target,
298 GLuint index,
299 GLsizei bufSize,
300 GLsizei *length,
301 GLboolean *data)
302{
Geoff Langeb66a6e2016-10-31 13:06:12 -0400303 if (context->getClientVersion() < ES_3_1)
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400304 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700305 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400306 return false;
307 }
308
309 if (!ValidateRobustEntryPoint(context, bufSize))
310 {
311 return false;
312 }
313
314 if (!ValidateIndexedStateQuery(context, target, index, length))
315 {
316 return false;
317 }
318
319 if (!ValidateRobustBufferSize(context, bufSize, *length))
Martin Radev66fb8202016-07-28 11:45:20 +0300320 {
321 return false;
322 }
323
324 return true;
325}
326
Jamie Madill876429b2017-04-20 15:46:24 -0400327bool ValidateDrawIndirectBase(Context *context, GLenum mode, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800328{
329 if (context->getClientVersion() < ES_3_1)
330 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700331 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jiajia Qind9671222016-11-29 16:30:31 +0800332 return false;
333 }
334
335 // Here the third parameter 1 is only to pass the count validation.
336 if (!ValidateDrawBase(context, mode, 1))
337 {
338 return false;
339 }
340
341 const State &state = context->getGLState();
342
343 // An INVALID_OPERATION error is generated if zero is bound to VERTEX_ARRAY_BINDING,
344 // DRAW_INDIRECT_BUFFER or to any enabled vertex array.
345 if (!state.getVertexArrayId())
346 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500347 context->handleError(InvalidOperation() << "zero is bound to VERTEX_ARRAY_BINDING");
Jiajia Qind9671222016-11-29 16:30:31 +0800348 return false;
349 }
350
351 gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
352 if (!drawIndirectBuffer)
353 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500354 context->handleError(InvalidOperation() << "zero is bound to DRAW_INDIRECT_BUFFER");
Jiajia Qind9671222016-11-29 16:30:31 +0800355 return false;
356 }
357
358 // An INVALID_VALUE error is generated if indirect is not a multiple of the size, in basic
359 // machine units, of uint.
360 GLint64 offset = reinterpret_cast<GLint64>(indirect);
361 if ((static_cast<GLuint>(offset) % sizeof(GLuint)) != 0)
362 {
363 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500364 InvalidValue()
365 << "indirect is not a multiple of the size, in basic machine units, of uint");
Jiajia Qind9671222016-11-29 16:30:31 +0800366 return false;
367 }
368
Martin Radev14a26ae2017-07-24 15:56:29 +0300369 // ANGLE_multiview spec, revision 1:
370 // An INVALID_OPERATION is generated by DrawArraysIndirect and DrawElementsIndirect if the
371 // number of views in the draw framebuffer is greater than 1.
372 const Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
373 ASSERT(drawFramebuffer != nullptr);
374 if (drawFramebuffer->getNumViews() > 1)
375 {
376 context->handleError(
377 InvalidOperation()
378 << "The number of views in the active draw framebuffer is greater than 1.");
379 return false;
380 }
381
Jiajia Qind9671222016-11-29 16:30:31 +0800382 return true;
383}
384
Jamie Madill876429b2017-04-20 15:46:24 -0400385bool ValidateDrawArraysIndirect(Context *context, GLenum mode, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800386{
387 const State &state = context->getGLState();
388 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
389 if (curTransformFeedback && curTransformFeedback->isActive() &&
390 !curTransformFeedback->isPaused())
391 {
392 // An INVALID_OPERATION error is generated if transform feedback is active and not paused.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500393 context->handleError(InvalidOperation() << "transform feedback is active and not paused.");
Jiajia Qind9671222016-11-29 16:30:31 +0800394 return false;
395 }
396
397 if (!ValidateDrawIndirectBase(context, mode, indirect))
398 return false;
399
400 gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
401 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
402 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawArraysIndirectCommand
403 // which's size is 4 * sizeof(uint).
404 auto checkedSum = checkedOffset + 4 * sizeof(GLuint);
405 if (!checkedSum.IsValid() ||
406 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
407 {
408 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500409 InvalidOperation()
410 << "the command would source data beyond the end of the buffer object.");
Jiajia Qind9671222016-11-29 16:30:31 +0800411 return false;
412 }
413
414 return true;
415}
416
Jamie Madill876429b2017-04-20 15:46:24 -0400417bool ValidateDrawElementsIndirect(Context *context, GLenum mode, GLenum type, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800418{
419 if (!ValidateDrawElementsBase(context, type))
420 return false;
421
422 const State &state = context->getGLState();
423 const VertexArray *vao = state.getVertexArray();
424 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
425 if (!elementArrayBuffer)
426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500427 context->handleError(InvalidOperation() << "zero is bound to ELEMENT_ARRAY_BUFFER");
Jiajia Qind9671222016-11-29 16:30:31 +0800428 return false;
429 }
430
431 if (!ValidateDrawIndirectBase(context, mode, indirect))
432 return false;
433
434 gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
435 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
436 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawElementsIndirectCommand
437 // which's size is 5 * sizeof(uint).
438 auto checkedSum = checkedOffset + 5 * sizeof(GLuint);
439 if (!checkedSum.IsValid() ||
440 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
441 {
442 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500443 InvalidOperation()
444 << "the command would source data beyond the end of the buffer object.");
Jiajia Qind9671222016-11-29 16:30:31 +0800445 return false;
446 }
447
448 return true;
449}
450
He Yunchao11b038b2016-11-22 21:24:04 +0800451bool ValidateGetTexLevelParameterBase(Context *context,
452 GLenum target,
453 GLint level,
454 GLenum pname,
455 GLsizei *length)
456{
457 if (context->getClientVersion() < ES_3_1)
458 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700459 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
He Yunchao11b038b2016-11-22 21:24:04 +0800460 return false;
461 }
462
463 if (length)
464 {
465 *length = 0;
466 }
467
468 if (!ValidTexLevelDestinationTarget(context, target))
469 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700470 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
He Yunchao11b038b2016-11-22 21:24:04 +0800471 return false;
472 }
473
474 if (context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target) ==
475 nullptr)
476 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500477 context->handleError(InvalidEnum() << "No texture bound.");
He Yunchao11b038b2016-11-22 21:24:04 +0800478 return false;
479 }
480
481 if (!ValidMipLevel(context, target, level))
482 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500483 context->handleError(InvalidValue());
He Yunchao11b038b2016-11-22 21:24:04 +0800484 return false;
485 }
486
487 switch (pname)
488 {
489 case GL_TEXTURE_RED_TYPE:
490 case GL_TEXTURE_GREEN_TYPE:
491 case GL_TEXTURE_BLUE_TYPE:
492 case GL_TEXTURE_ALPHA_TYPE:
493 case GL_TEXTURE_DEPTH_TYPE:
494 break;
495 case GL_TEXTURE_RED_SIZE:
496 case GL_TEXTURE_GREEN_SIZE:
497 case GL_TEXTURE_BLUE_SIZE:
498 case GL_TEXTURE_ALPHA_SIZE:
499 case GL_TEXTURE_DEPTH_SIZE:
500 case GL_TEXTURE_STENCIL_SIZE:
501 case GL_TEXTURE_SHARED_SIZE:
502 break;
503 case GL_TEXTURE_INTERNAL_FORMAT:
504 case GL_TEXTURE_WIDTH:
505 case GL_TEXTURE_HEIGHT:
506 case GL_TEXTURE_DEPTH:
507 break;
508 case GL_TEXTURE_SAMPLES:
509 case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
510 break;
511 case GL_TEXTURE_COMPRESSED:
512 break;
513 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700514 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
He Yunchao11b038b2016-11-22 21:24:04 +0800515 return false;
516 }
517
518 if (length)
519 {
520 *length = 1;
521 }
522 return true;
523}
524
525bool ValidateGetTexLevelParameterfv(Context *context,
526 GLenum target,
527 GLint level,
528 GLenum pname,
529 GLfloat *params)
530{
531 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
532}
533
534bool ValidateGetTexLevelParameteriv(Context *context,
535 GLenum target,
536 GLint level,
537 GLenum pname,
538 GLint *params)
539{
540 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
541}
542
JiangYizhoubddc46b2016-12-09 09:50:51 +0800543bool ValidateTexStorage2DMultiSample(Context *context,
544 GLenum target,
545 GLsizei samples,
546 GLint internalFormat,
547 GLsizei width,
548 GLsizei height,
549 GLboolean fixedSampleLocations)
550{
551 if (context->getClientVersion() < ES_3_1)
552 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700553 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhoubddc46b2016-12-09 09:50:51 +0800554 return false;
555 }
556
557 if (target != GL_TEXTURE_2D_MULTISAMPLE)
558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500559 context->handleError(InvalidEnum() << "Target must be TEXTURE_2D_MULTISAMPLE.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800560 return false;
561 }
562
563 if (width < 1 || height < 1)
564 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700565 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
JiangYizhoubddc46b2016-12-09 09:50:51 +0800566 return false;
567 }
568
569 const Caps &caps = context->getCaps();
570 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
571 static_cast<GLuint>(height) > caps.max2DTextureSize)
572 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500573 context
574 ->handleError(InvalidValue()
575 << "Width and height must be less than or equal to GL_MAX_TEXTURE_SIZE.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800576 return false;
577 }
578
579 if (samples == 0)
580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500581 context->handleError(InvalidValue() << "Samples may not be zero.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800582 return false;
583 }
584
585 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
586 if (!formatCaps.renderable)
587 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500588 context->handleError(InvalidEnum() << "SizedInternalformat must be color-renderable, "
589 "depth-renderable, or stencil-renderable.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800590 return false;
591 }
592
593 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
594 // is one of the unsized base internalformats listed in table 8.11.
Geoff Langca271392017-04-05 12:30:00 -0400595 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
596 if (formatInfo.internalFormat == GL_NONE)
JiangYizhoubddc46b2016-12-09 09:50:51 +0800597 {
598 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500599 InvalidEnum()
600 << "Internalformat is one of the unsupported unsized base internalformats.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800601 return false;
602 }
603
604 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
605 {
606 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500607 InvalidOperation()
608 << "Samples must not be greater than maximum supported value for the format.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800609 return false;
610 }
611
612 Texture *texture = context->getTargetTexture(target);
613 if (!texture || texture->id() == 0)
614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500615 context->handleError(InvalidOperation() << "Zero is bound to target.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800616 return false;
617 }
618
619 if (texture->getImmutableFormat())
620 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500621 context->handleError(InvalidOperation() << "The value of TEXTURE_IMMUTABLE_FORMAT for "
622 "the texture currently bound to target on "
623 "the active texture unit is true.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800624 return false;
625 }
626
627 return true;
628}
629
630bool ValidateGetMultisamplefv(Context *context, GLenum pname, GLuint index, GLfloat *val)
631{
632 if (context->getClientVersion() < ES_3_1)
633 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700634 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhoubddc46b2016-12-09 09:50:51 +0800635 return false;
636 }
637
638 if (pname != GL_SAMPLE_POSITION)
639 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500640 context->handleError(InvalidEnum() << "Pname must be SAMPLE_POSITION.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800641 return false;
642 }
643
JiangYizhou5b03f472017-01-09 10:22:53 +0800644 Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
645
646 if (index >= static_cast<GLuint>(framebuffer->getSamples(context)))
JiangYizhoubddc46b2016-12-09 09:50:51 +0800647 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500648 context->handleError(InvalidValue() << "Index must be less than the value of SAMPLES.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800649 return false;
650 }
651
652 return true;
653}
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800654
655bool ValidationFramebufferParameteri(Context *context, GLenum target, GLenum pname, GLint param)
656{
657 if (context->getClientVersion() < ES_3_1)
658 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700659 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800660 return false;
661 }
662
663 if (!ValidFramebufferTarget(target))
664 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500665 context->handleError(InvalidEnum() << "Invalid framebuffer target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800666 return false;
667 }
668
669 switch (pname)
670 {
671 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
672 {
673 GLint maxWidth = context->getCaps().maxFramebufferWidth;
674 if (param < 0 || param > maxWidth)
675 {
676 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500677 InvalidValue()
678 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_WIDTH.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800679 return false;
680 }
681 break;
682 }
683 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
684 {
685 GLint maxHeight = context->getCaps().maxFramebufferHeight;
686 if (param < 0 || param > maxHeight)
687 {
688 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500689 InvalidValue()
690 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_HEIGHT.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800691 return false;
692 }
693 break;
694 }
695 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
696 {
697 GLint maxSamples = context->getCaps().maxFramebufferSamples;
698 if (param < 0 || param > maxSamples)
699 {
700 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500701 InvalidValue()
702 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_SAMPLES.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800703 return false;
704 }
705 break;
706 }
707 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
708 {
709 break;
710 }
711 default:
712 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700713 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800714 return false;
715 }
716 }
717
718 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
719 ASSERT(framebuffer);
720 if (framebuffer->id() == 0)
721 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500722 context->handleError(InvalidOperation() << "Default framebuffer is bound to target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800723 return false;
724 }
725 return true;
726}
727
728bool ValidationGetFramebufferParameteri(Context *context,
729 GLenum target,
730 GLenum pname,
731 GLint *params)
732{
733 if (context->getClientVersion() < ES_3_1)
734 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700735 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800736 return false;
737 }
738
739 if (!ValidFramebufferTarget(target))
740 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700741 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800742 return false;
743 }
744
745 switch (pname)
746 {
747 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
748 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
749 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
750 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
751 break;
752 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700753 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800754 return false;
755 }
756
757 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
758 ASSERT(framebuffer);
759
760 if (framebuffer->id() == 0)
761 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500762 context->handleError(InvalidOperation() << "Default framebuffer is bound to target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800763 return false;
764 }
765 return true;
766}
767
jchen1015015f72017-03-16 13:54:21 +0800768bool ValidateGetProgramResourceIndex(Context *context,
769 GLuint program,
770 GLenum programInterface,
771 const GLchar *name)
772{
773 if (context->getClientVersion() < ES_3_1)
774 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700775 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen1015015f72017-03-16 13:54:21 +0800776 return false;
777 }
778
779 Program *programObject = GetValidProgram(context, program);
780 if (programObject == nullptr)
781 {
782 return false;
783 }
784
785 if (!ValidateNamedProgramInterface(programInterface))
786 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500787 context->handleError(InvalidEnum() << "Invalid program interface: 0x" << std::hex
788 << std::uppercase << programInterface);
jchen1015015f72017-03-16 13:54:21 +0800789 return false;
790 }
Shao80957d92017-02-20 21:25:59 +0800791
792 return true;
793}
794
795bool ValidateBindVertexBuffer(ValidationContext *context,
796 GLuint bindingIndex,
797 GLuint buffer,
798 GLintptr offset,
799 GLsizei stride)
800{
801 if (context->getClientVersion() < ES_3_1)
802 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700803 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +0800804 return false;
805 }
806
807 if (!context->isBufferGenerated(buffer))
808 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500809 context->handleError(InvalidOperation() << "Buffer is not generated.");
Shao80957d92017-02-20 21:25:59 +0800810 return false;
811 }
812
813 const Caps &caps = context->getCaps();
814 if (bindingIndex >= caps.maxVertexAttribBindings)
815 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500816 context->handleError(InvalidValue()
817 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +0800818 return false;
819 }
820
821 if (offset < 0)
822 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700823 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Shao80957d92017-02-20 21:25:59 +0800824 return false;
825 }
826
827 if (stride < 0 || stride > caps.maxVertexAttribStride)
828 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500829 context->handleError(InvalidValue()
830 << "stride must be between 0 and MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +0800831 return false;
832 }
833
834 // [OpenGL ES 3.1] Section 10.3.1 page 244:
835 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
836 if (context->getGLState().getVertexArrayId() == 0)
837 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500838 context->handleError(InvalidOperation() << "Default vertex array buffer is bound.");
Shao80957d92017-02-20 21:25:59 +0800839 return false;
840 }
841
842 return true;
843}
844
845bool ValidateVertexBindingDivisor(ValidationContext *context, GLuint bindingIndex, GLuint divisor)
846{
847 if (context->getClientVersion() < ES_3_1)
848 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700849 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +0800850 return false;
851 }
852
853 const Caps &caps = context->getCaps();
854 if (bindingIndex >= caps.maxVertexAttribBindings)
855 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500856 context->handleError(InvalidValue()
857 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +0800858 return false;
859 }
860
861 // [OpenGL ES 3.1] Section 10.3.1 page 243:
862 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
863 if (context->getGLState().getVertexArrayId() == 0)
864 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500865 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +0800866 return false;
867 }
868
869 return true;
870}
871
872bool ValidateVertexAttribFormat(ValidationContext *context,
873 GLuint attribIndex,
874 GLint size,
875 GLenum type,
876 GLuint relativeOffset,
877 GLboolean pureInteger)
878{
879 if (context->getClientVersion() < ES_3_1)
880 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700881 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +0800882 return false;
883 }
884
885 const Caps &caps = context->getCaps();
886 if (relativeOffset > static_cast<GLuint>(caps.maxVertexAttribRelativeOffset))
887 {
888 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500889 InvalidValue()
890 << "relativeOffset cannot be greater than MAX_VERTEX_ATTRIB_RELATIVE_OFFSET.");
Shao80957d92017-02-20 21:25:59 +0800891 return false;
892 }
893
894 // [OpenGL ES 3.1] Section 10.3.1 page 243:
895 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
896 if (context->getGLState().getVertexArrayId() == 0)
897 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500898 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +0800899 return false;
900 }
901
902 return ValidateVertexFormatBase(context, attribIndex, size, type, pureInteger);
903}
904
905bool ValidateVertexAttribBinding(ValidationContext *context,
906 GLuint attribIndex,
907 GLuint bindingIndex)
908{
909 if (context->getClientVersion() < ES_3_1)
910 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700911 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +0800912 return false;
913 }
914
915 // [OpenGL ES 3.1] Section 10.3.1 page 243:
916 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
917 if (context->getGLState().getVertexArrayId() == 0)
918 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500919 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +0800920 return false;
921 }
922
923 const Caps &caps = context->getCaps();
924 if (attribIndex >= caps.maxVertexAttributes)
925 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700926 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +0800927 return false;
928 }
929
930 if (bindingIndex >= caps.maxVertexAttribBindings)
931 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500932 context->handleError(InvalidValue()
933 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS");
Shao80957d92017-02-20 21:25:59 +0800934 return false;
935 }
936
jchen1015015f72017-03-16 13:54:21 +0800937 return true;
938}
939
jchen10fd7c3b52017-03-21 15:36:03 +0800940bool ValidateGetProgramResourceName(Context *context,
941 GLuint program,
942 GLenum programInterface,
943 GLuint index,
944 GLsizei bufSize,
945 GLsizei *length,
946 GLchar *name)
947{
948 if (context->getClientVersion() < ES_3_1)
949 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700950 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen10fd7c3b52017-03-21 15:36:03 +0800951 return false;
952 }
953
954 Program *programObject = GetValidProgram(context, program);
955 if (programObject == nullptr)
956 {
957 return false;
958 }
959
960 if (!ValidateNamedProgramInterface(programInterface))
961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500962 context->handleError(InvalidEnum() << "Invalid program interface: 0x" << std::hex
963 << std::uppercase << programInterface);
jchen10fd7c3b52017-03-21 15:36:03 +0800964 return false;
965 }
966
967 if (!ValidateProgramResourceIndex(programObject, programInterface, index))
968 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500969 context->handleError(InvalidValue() << "Invalid index: " << index);
jchen10fd7c3b52017-03-21 15:36:03 +0800970 return false;
971 }
972
973 if (bufSize < 0)
974 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700975 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
jchen10fd7c3b52017-03-21 15:36:03 +0800976 return false;
977 }
978
979 return true;
980}
981
Xinghua Cao2b396592017-03-29 15:36:04 +0800982bool ValidateDispatchCompute(Context *context,
983 GLuint numGroupsX,
984 GLuint numGroupsY,
985 GLuint numGroupsZ)
986{
987 if (context->getClientVersion() < ES_3_1)
988 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700989 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Xinghua Cao2b396592017-03-29 15:36:04 +0800990 return false;
991 }
992
993 const State &state = context->getGLState();
994 Program *program = state.getProgram();
995
996 if (program == nullptr)
997 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500998 context->handleError(InvalidOperation()
999 << "No active program object for the compute shader stage.");
Xinghua Cao2b396592017-03-29 15:36:04 +08001000 return false;
1001 }
1002
1003 if (program->isLinked() == false || program->getAttachedComputeShader() == nullptr)
1004 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001005 context->handleError(
1006 InvalidOperation()
1007 << "Program has not been successfully linked, or program contains no compute shaders.");
Xinghua Cao2b396592017-03-29 15:36:04 +08001008 return false;
1009 }
1010
1011 const Caps &caps = context->getCaps();
1012 if (numGroupsX > caps.maxComputeWorkGroupCount[0])
1013 {
1014 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001015 InvalidValue() << "num_groups_x cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[0]="
1016 << caps.maxComputeWorkGroupCount[0]);
Xinghua Cao2b396592017-03-29 15:36:04 +08001017 return false;
1018 }
1019 if (numGroupsY > caps.maxComputeWorkGroupCount[1])
1020 {
1021 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001022 InvalidValue() << "num_groups_y cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[1]="
1023 << caps.maxComputeWorkGroupCount[1]);
Xinghua Cao2b396592017-03-29 15:36:04 +08001024 return false;
1025 }
1026 if (numGroupsZ > caps.maxComputeWorkGroupCount[2])
1027 {
1028 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001029 InvalidValue() << "num_groups_z cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[2]="
1030 << caps.maxComputeWorkGroupCount[2]);
Xinghua Cao2b396592017-03-29 15:36:04 +08001031 return false;
1032 }
1033
1034 return true;
1035}
1036
Xinghua Cao65ec0b22017-03-28 16:10:52 +08001037bool ValidateBindImageTexture(Context *context,
1038 GLuint unit,
1039 GLuint texture,
1040 GLint level,
1041 GLboolean layered,
1042 GLint layer,
1043 GLenum access,
1044 GLenum format)
1045{
1046 GLuint maxImageUnits = context->getCaps().maxImageUnits;
1047 if (unit >= maxImageUnits)
1048 {
1049 context->handleError(InvalidValue()
1050 << "unit cannot be greater than or equal than MAX_IMAGE_UNITS = "
1051 << maxImageUnits);
1052 return false;
1053 }
1054
1055 if (level < 0)
1056 {
1057 context->handleError(InvalidValue() << "level is negative.");
1058 return false;
1059 }
1060
1061 if (layer < 0)
1062 {
1063 context->handleError(InvalidValue() << "layer is negative.");
1064 return false;
1065 }
1066
1067 if (access != GL_READ_ONLY && access != GL_WRITE_ONLY && access != GL_READ_WRITE)
1068 {
1069 context->handleError(InvalidEnum() << "access is not one of the supported tokens.");
1070 return false;
1071 }
1072
1073 switch (format)
1074 {
1075 case GL_RGBA32F:
1076 case GL_RGBA16F:
1077 case GL_R32F:
1078 case GL_RGBA32UI:
1079 case GL_RGBA16UI:
1080 case GL_RGBA8UI:
1081 case GL_R32UI:
1082 case GL_RGBA32I:
1083 case GL_RGBA16I:
1084 case GL_RGBA8I:
1085 case GL_R32I:
1086 case GL_RGBA8:
1087 case GL_RGBA8_SNORM:
1088 break;
1089 default:
1090 context->handleError(InvalidValue()
1091 << "format is not one of supported image unit formats.");
1092 return false;
1093 }
1094
1095 if (texture != 0)
1096 {
1097 Texture *tex = context->getTexture(texture);
1098
1099 if (tex == nullptr)
1100 {
1101 context->handleError(InvalidValue()
1102 << "texture is not the name of an existing texture object.");
1103 return false;
1104 }
1105
1106 if (!tex->getImmutableFormat())
1107 {
1108 context->handleError(InvalidOperation()
1109 << "texture is not the name of an immutable texture object.");
1110 return false;
1111 }
1112 }
1113
1114 return true;
1115}
jchen10191381f2017-04-11 13:59:04 +08001116
1117bool ValidateGetProgramResourceLocation(Context *context,
1118 GLuint program,
1119 GLenum programInterface,
1120 const GLchar *name)
1121{
1122 if (context->getClientVersion() < ES_3_1)
1123 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001124 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen10191381f2017-04-11 13:59:04 +08001125 return false;
1126 }
1127
1128 Program *programObject = GetValidProgram(context, program);
1129 if (programObject == nullptr)
1130 {
1131 return false;
1132 }
1133
1134 if (!programObject->isLinked())
1135 {
1136 context->handleError(InvalidOperation() << "Program is not successfully linked.");
1137 return false;
1138 }
1139
1140 if (!ValidateLocationProgramInterface(programInterface))
1141 {
1142 context->handleError(InvalidEnum() << "Invalid program interface.");
1143 return false;
1144 }
1145 return true;
1146}
1147
jchen10880683b2017-04-12 16:21:55 +08001148bool ValidateGetProgramResourceiv(Context *context,
1149 GLuint program,
1150 GLenum programInterface,
1151 GLuint index,
1152 GLsizei propCount,
1153 const GLenum *props,
1154 GLsizei bufSize,
1155 GLsizei *length,
1156 GLint *params)
1157{
1158 if (context->getClientVersion() < ES_3_1)
1159 {
jchen10d9cd7b72017-08-30 15:04:25 +08001160 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen10880683b2017-04-12 16:21:55 +08001161 return false;
1162 }
1163
1164 Program *programObject = GetValidProgram(context, program);
1165 if (programObject == nullptr)
1166 {
1167 return false;
1168 }
1169 if (!ValidateProgramInterface(programInterface))
1170 {
1171 context->handleError(InvalidEnum() << "Invalid program interface.");
1172 return false;
1173 }
1174 if (propCount <= 0)
1175 {
1176 context->handleError(InvalidValue() << "Invalid propCount.");
1177 return false;
1178 }
1179 if (bufSize < 0)
1180 {
1181 context->handleError(InvalidValue() << "Invalid bufSize.");
1182 return false;
1183 }
1184 if (!ValidateProgramResourceIndex(programObject, programInterface, index))
1185 {
1186 context->handleError(InvalidValue() << "Invalid index: " << index);
1187 return false;
1188 }
1189 for (GLsizei i = 0; i < propCount; i++)
1190 {
1191 if (!ValidateProgramResourceProperty(props[i]))
1192 {
1193 context->handleError(InvalidEnum() << "Invalid prop.");
1194 return false;
1195 }
1196 if (!ValidateProgramResourcePropertyByInterface(props[i], programInterface))
1197 {
1198 context->handleError(InvalidOperation() << "Not an allowed prop for interface");
1199 return false;
1200 }
1201 }
1202 return true;
1203}
1204
jchen10d9cd7b72017-08-30 15:04:25 +08001205bool ValidateGetProgramInterfaceiv(Context *context,
1206 GLuint program,
1207 GLenum programInterface,
1208 GLenum pname,
1209 GLint *params)
1210{
1211 if (context->getClientVersion() < ES_3_1)
1212 {
1213 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1214 return false;
1215 }
1216
1217 Program *programObject = GetValidProgram(context, program);
1218 if (programObject == nullptr)
1219 {
1220 return false;
1221 }
1222
1223 if (!ValidateProgramInterface(programInterface))
1224 {
1225 context->handleError(InvalidEnum() << "Invalid program interface.");
1226 return false;
1227 }
1228
1229 switch (pname)
1230 {
1231 case GL_ACTIVE_RESOURCES:
1232 case GL_MAX_NAME_LENGTH:
1233 case GL_MAX_NUM_ACTIVE_VARIABLES:
1234 break;
1235
1236 default:
1237 context->handleError(InvalidEnum() << "Unknown property of program interface.");
1238 return false;
1239 }
1240
1241 if (pname == GL_MAX_NAME_LENGTH && programInterface == GL_ATOMIC_COUNTER_BUFFER)
1242 {
1243 context->handleError(InvalidOperation()
1244 << "Active atomic counter resources are not assigned name strings.");
1245 return false;
1246 }
1247
1248 if (pname == GL_MAX_NUM_ACTIVE_VARIABLES)
1249 {
1250 switch (programInterface)
1251 {
1252 case GL_ATOMIC_COUNTER_BUFFER:
1253 case GL_SHADER_STORAGE_BLOCK:
1254 case GL_UNIFORM_BLOCK:
1255 break;
1256
1257 default:
1258 context->handleError(
1259 InvalidOperation()
1260 << "MAX_NUM_ACTIVE_VARIABLES requires a buffer or block interface.");
1261 return false;
1262 }
1263 }
1264
1265 return true;
1266}
1267
Yunchao Hea336b902017-08-02 16:05:21 +08001268static bool ValidateGenOrDeleteES31(Context *context, GLint n)
1269{
1270 if (context->getClientVersion() < ES_3_1)
1271 {
1272 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1273 return false;
1274 }
1275
1276 return ValidateGenOrDelete(context, n);
1277}
1278
1279bool ValidateGenProgramPipelines(Context *context, GLint n, GLuint *)
1280{
1281 return ValidateGenOrDeleteES31(context, n);
1282}
1283
1284bool ValidateDeleteProgramPipelines(Context *context, GLint n, const GLuint *)
1285{
1286 return ValidateGenOrDeleteES31(context, n);
1287}
1288
1289bool ValidateBindProgramPipeline(Context *context, GLuint pipeline)
1290{
1291 if (context->getClientVersion() < ES_3_1)
1292 {
1293 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1294 return false;
1295 }
1296
1297 if (!context->isProgramPipelineGenerated(pipeline))
1298 {
1299 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
1300 return false;
1301 }
1302
1303 return true;
1304}
1305
1306bool ValidateIsProgramPipeline(Context *context, GLuint pipeline)
1307{
1308 if (context->getClientVersion() < ES_3_1)
1309 {
1310 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1311 return false;
1312 }
1313
1314 return true;
1315}
1316
Jiawei Shaodb342272017-09-27 10:21:45 +08001317bool ValidateSampleMaski(Context *context, GLuint maskNumber)
1318{
1319 if (context->getClientVersion() < ES_3_1)
1320 {
1321 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1322 return false;
1323 }
1324
1325 if (maskNumber >= context->getCaps().maxSampleMaskWords)
1326 {
1327 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
1328 return false;
1329 }
1330
1331 return true;
1332}
1333
Martin Radev66fb8202016-07-28 11:45:20 +03001334} // namespace gl