blob: 86cf37175efcb330d846ae7ed8381d4dd034921b [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
jchen10fd7c3b52017-03-21 15:36:03 +0800263 case GL_UNIFORM_BLOCK:
jchen1058f67be2017-10-27 08:59:27 +0800264 return (index < programObject->getActiveUniformBlockCount());
265
266 case GL_ATOMIC_COUNTER_BUFFER:
267 return (index < programObject->getActiveAtomicCounterBufferCount());
268
269 // TODO(jie.a.chen@intel.com): more interfaces.
jchen10fd7c3b52017-03-21 15:36:03 +0800270 case GL_TRANSFORM_FEEDBACK_VARYING:
271 case GL_BUFFER_VARIABLE:
272 case GL_SHADER_STORAGE_BLOCK:
273 UNIMPLEMENTED();
274 return false;
275
276 default:
277 UNREACHABLE();
278 return false;
279 }
280}
281
jchen1015015f72017-03-16 13:54:21 +0800282} // anonymous namespace
283
Martin Radev66fb8202016-07-28 11:45:20 +0300284bool ValidateGetBooleani_v(Context *context, GLenum target, GLuint index, GLboolean *data)
285{
Geoff Langeb66a6e2016-10-31 13:06:12 -0400286 if (context->getClientVersion() < ES_3_1)
Martin Radev66fb8202016-07-28 11:45:20 +0300287 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700288 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Martin Radev66fb8202016-07-28 11:45:20 +0300289 return false;
290 }
291
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400292 if (!ValidateIndexedStateQuery(context, target, index, nullptr))
293 {
294 return false;
295 }
296
297 return true;
298}
299
300bool ValidateGetBooleani_vRobustANGLE(Context *context,
301 GLenum target,
302 GLuint index,
303 GLsizei bufSize,
304 GLsizei *length,
305 GLboolean *data)
306{
Geoff Langeb66a6e2016-10-31 13:06:12 -0400307 if (context->getClientVersion() < ES_3_1)
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400308 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700309 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400310 return false;
311 }
312
313 if (!ValidateRobustEntryPoint(context, bufSize))
314 {
315 return false;
316 }
317
318 if (!ValidateIndexedStateQuery(context, target, index, length))
319 {
320 return false;
321 }
322
323 if (!ValidateRobustBufferSize(context, bufSize, *length))
Martin Radev66fb8202016-07-28 11:45:20 +0300324 {
325 return false;
326 }
327
328 return true;
329}
330
Jamie Madill876429b2017-04-20 15:46:24 -0400331bool ValidateDrawIndirectBase(Context *context, GLenum mode, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800332{
333 if (context->getClientVersion() < ES_3_1)
334 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700335 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jiajia Qind9671222016-11-29 16:30:31 +0800336 return false;
337 }
338
339 // Here the third parameter 1 is only to pass the count validation.
340 if (!ValidateDrawBase(context, mode, 1))
341 {
342 return false;
343 }
344
345 const State &state = context->getGLState();
346
347 // An INVALID_OPERATION error is generated if zero is bound to VERTEX_ARRAY_BINDING,
348 // DRAW_INDIRECT_BUFFER or to any enabled vertex array.
349 if (!state.getVertexArrayId())
350 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500351 context->handleError(InvalidOperation() << "zero is bound to VERTEX_ARRAY_BINDING");
Jiajia Qind9671222016-11-29 16:30:31 +0800352 return false;
353 }
354
355 gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
356 if (!drawIndirectBuffer)
357 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500358 context->handleError(InvalidOperation() << "zero is bound to DRAW_INDIRECT_BUFFER");
Jiajia Qind9671222016-11-29 16:30:31 +0800359 return false;
360 }
361
362 // An INVALID_VALUE error is generated if indirect is not a multiple of the size, in basic
363 // machine units, of uint.
364 GLint64 offset = reinterpret_cast<GLint64>(indirect);
365 if ((static_cast<GLuint>(offset) % sizeof(GLuint)) != 0)
366 {
367 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500368 InvalidValue()
369 << "indirect is not a multiple of the size, in basic machine units, of uint");
Jiajia Qind9671222016-11-29 16:30:31 +0800370 return false;
371 }
372
Martin Radev14a26ae2017-07-24 15:56:29 +0300373 // ANGLE_multiview spec, revision 1:
374 // An INVALID_OPERATION is generated by DrawArraysIndirect and DrawElementsIndirect if the
375 // number of views in the draw framebuffer is greater than 1.
376 const Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
377 ASSERT(drawFramebuffer != nullptr);
378 if (drawFramebuffer->getNumViews() > 1)
379 {
380 context->handleError(
381 InvalidOperation()
382 << "The number of views in the active draw framebuffer is greater than 1.");
383 return false;
384 }
385
Jiajia Qind9671222016-11-29 16:30:31 +0800386 return true;
387}
388
Jamie Madill876429b2017-04-20 15:46:24 -0400389bool ValidateDrawArraysIndirect(Context *context, GLenum mode, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800390{
391 const State &state = context->getGLState();
392 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
393 if (curTransformFeedback && curTransformFeedback->isActive() &&
394 !curTransformFeedback->isPaused())
395 {
396 // An INVALID_OPERATION error is generated if transform feedback is active and not paused.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500397 context->handleError(InvalidOperation() << "transform feedback is active and not paused.");
Jiajia Qind9671222016-11-29 16:30:31 +0800398 return false;
399 }
400
401 if (!ValidateDrawIndirectBase(context, mode, indirect))
402 return false;
403
404 gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
405 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
406 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawArraysIndirectCommand
407 // which's size is 4 * sizeof(uint).
408 auto checkedSum = checkedOffset + 4 * sizeof(GLuint);
409 if (!checkedSum.IsValid() ||
410 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
411 {
412 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500413 InvalidOperation()
414 << "the command would source data beyond the end of the buffer object.");
Jiajia Qind9671222016-11-29 16:30:31 +0800415 return false;
416 }
417
418 return true;
419}
420
Jamie Madill876429b2017-04-20 15:46:24 -0400421bool ValidateDrawElementsIndirect(Context *context, GLenum mode, GLenum type, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800422{
423 if (!ValidateDrawElementsBase(context, type))
424 return false;
425
426 const State &state = context->getGLState();
427 const VertexArray *vao = state.getVertexArray();
428 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
429 if (!elementArrayBuffer)
430 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500431 context->handleError(InvalidOperation() << "zero is bound to ELEMENT_ARRAY_BUFFER");
Jiajia Qind9671222016-11-29 16:30:31 +0800432 return false;
433 }
434
435 if (!ValidateDrawIndirectBase(context, mode, indirect))
436 return false;
437
438 gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
439 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
440 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawElementsIndirectCommand
441 // which's size is 5 * sizeof(uint).
442 auto checkedSum = checkedOffset + 5 * sizeof(GLuint);
443 if (!checkedSum.IsValid() ||
444 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
445 {
446 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500447 InvalidOperation()
448 << "the command would source data beyond the end of the buffer object.");
Jiajia Qind9671222016-11-29 16:30:31 +0800449 return false;
450 }
451
452 return true;
453}
454
He Yunchao11b038b2016-11-22 21:24:04 +0800455bool ValidateGetTexLevelParameterBase(Context *context,
456 GLenum target,
457 GLint level,
458 GLenum pname,
459 GLsizei *length)
460{
461 if (context->getClientVersion() < ES_3_1)
462 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700463 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
He Yunchao11b038b2016-11-22 21:24:04 +0800464 return false;
465 }
466
467 if (length)
468 {
469 *length = 0;
470 }
471
472 if (!ValidTexLevelDestinationTarget(context, target))
473 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700474 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
He Yunchao11b038b2016-11-22 21:24:04 +0800475 return false;
476 }
477
478 if (context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target) ==
479 nullptr)
480 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500481 context->handleError(InvalidEnum() << "No texture bound.");
He Yunchao11b038b2016-11-22 21:24:04 +0800482 return false;
483 }
484
485 if (!ValidMipLevel(context, target, level))
486 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500487 context->handleError(InvalidValue());
He Yunchao11b038b2016-11-22 21:24:04 +0800488 return false;
489 }
490
491 switch (pname)
492 {
493 case GL_TEXTURE_RED_TYPE:
494 case GL_TEXTURE_GREEN_TYPE:
495 case GL_TEXTURE_BLUE_TYPE:
496 case GL_TEXTURE_ALPHA_TYPE:
497 case GL_TEXTURE_DEPTH_TYPE:
498 break;
499 case GL_TEXTURE_RED_SIZE:
500 case GL_TEXTURE_GREEN_SIZE:
501 case GL_TEXTURE_BLUE_SIZE:
502 case GL_TEXTURE_ALPHA_SIZE:
503 case GL_TEXTURE_DEPTH_SIZE:
504 case GL_TEXTURE_STENCIL_SIZE:
505 case GL_TEXTURE_SHARED_SIZE:
506 break;
507 case GL_TEXTURE_INTERNAL_FORMAT:
508 case GL_TEXTURE_WIDTH:
509 case GL_TEXTURE_HEIGHT:
510 case GL_TEXTURE_DEPTH:
511 break;
512 case GL_TEXTURE_SAMPLES:
513 case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
514 break;
515 case GL_TEXTURE_COMPRESSED:
516 break;
517 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700518 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
He Yunchao11b038b2016-11-22 21:24:04 +0800519 return false;
520 }
521
522 if (length)
523 {
524 *length = 1;
525 }
526 return true;
527}
528
529bool ValidateGetTexLevelParameterfv(Context *context,
530 GLenum target,
531 GLint level,
532 GLenum pname,
533 GLfloat *params)
534{
535 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
536}
537
538bool ValidateGetTexLevelParameteriv(Context *context,
539 GLenum target,
540 GLint level,
541 GLenum pname,
542 GLint *params)
543{
544 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
545}
546
JiangYizhoubddc46b2016-12-09 09:50:51 +0800547bool ValidateTexStorage2DMultiSample(Context *context,
548 GLenum target,
549 GLsizei samples,
550 GLint internalFormat,
551 GLsizei width,
552 GLsizei height,
553 GLboolean fixedSampleLocations)
554{
555 if (context->getClientVersion() < ES_3_1)
556 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700557 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhoubddc46b2016-12-09 09:50:51 +0800558 return false;
559 }
560
561 if (target != GL_TEXTURE_2D_MULTISAMPLE)
562 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500563 context->handleError(InvalidEnum() << "Target must be TEXTURE_2D_MULTISAMPLE.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800564 return false;
565 }
566
567 if (width < 1 || height < 1)
568 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700569 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
JiangYizhoubddc46b2016-12-09 09:50:51 +0800570 return false;
571 }
572
573 const Caps &caps = context->getCaps();
574 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
575 static_cast<GLuint>(height) > caps.max2DTextureSize)
576 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500577 context
578 ->handleError(InvalidValue()
579 << "Width and height must be less than or equal to GL_MAX_TEXTURE_SIZE.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800580 return false;
581 }
582
583 if (samples == 0)
584 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500585 context->handleError(InvalidValue() << "Samples may not be zero.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800586 return false;
587 }
588
589 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
590 if (!formatCaps.renderable)
591 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500592 context->handleError(InvalidEnum() << "SizedInternalformat must be color-renderable, "
593 "depth-renderable, or stencil-renderable.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800594 return false;
595 }
596
597 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
598 // is one of the unsized base internalformats listed in table 8.11.
Geoff Langca271392017-04-05 12:30:00 -0400599 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
600 if (formatInfo.internalFormat == GL_NONE)
JiangYizhoubddc46b2016-12-09 09:50:51 +0800601 {
602 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500603 InvalidEnum()
604 << "Internalformat is one of the unsupported unsized base internalformats.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800605 return false;
606 }
607
608 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
609 {
610 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500611 InvalidOperation()
612 << "Samples must not be greater than maximum supported value for the format.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800613 return false;
614 }
615
616 Texture *texture = context->getTargetTexture(target);
617 if (!texture || texture->id() == 0)
618 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500619 context->handleError(InvalidOperation() << "Zero is bound to target.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800620 return false;
621 }
622
623 if (texture->getImmutableFormat())
624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500625 context->handleError(InvalidOperation() << "The value of TEXTURE_IMMUTABLE_FORMAT for "
626 "the texture currently bound to target on "
627 "the active texture unit is true.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800628 return false;
629 }
630
631 return true;
632}
633
634bool ValidateGetMultisamplefv(Context *context, GLenum pname, GLuint index, GLfloat *val)
635{
636 if (context->getClientVersion() < ES_3_1)
637 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700638 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhoubddc46b2016-12-09 09:50:51 +0800639 return false;
640 }
641
642 if (pname != GL_SAMPLE_POSITION)
643 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500644 context->handleError(InvalidEnum() << "Pname must be SAMPLE_POSITION.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800645 return false;
646 }
647
JiangYizhou5b03f472017-01-09 10:22:53 +0800648 Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
649
650 if (index >= static_cast<GLuint>(framebuffer->getSamples(context)))
JiangYizhoubddc46b2016-12-09 09:50:51 +0800651 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500652 context->handleError(InvalidValue() << "Index must be less than the value of SAMPLES.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800653 return false;
654 }
655
656 return true;
657}
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800658
659bool ValidationFramebufferParameteri(Context *context, GLenum target, GLenum pname, GLint param)
660{
661 if (context->getClientVersion() < ES_3_1)
662 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700663 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800664 return false;
665 }
666
667 if (!ValidFramebufferTarget(target))
668 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500669 context->handleError(InvalidEnum() << "Invalid framebuffer target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800670 return false;
671 }
672
673 switch (pname)
674 {
675 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
676 {
677 GLint maxWidth = context->getCaps().maxFramebufferWidth;
678 if (param < 0 || param > maxWidth)
679 {
680 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500681 InvalidValue()
682 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_WIDTH.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800683 return false;
684 }
685 break;
686 }
687 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
688 {
689 GLint maxHeight = context->getCaps().maxFramebufferHeight;
690 if (param < 0 || param > maxHeight)
691 {
692 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500693 InvalidValue()
694 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_HEIGHT.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800695 return false;
696 }
697 break;
698 }
699 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
700 {
701 GLint maxSamples = context->getCaps().maxFramebufferSamples;
702 if (param < 0 || param > maxSamples)
703 {
704 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500705 InvalidValue()
706 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_SAMPLES.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800707 return false;
708 }
709 break;
710 }
711 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
712 {
713 break;
714 }
715 default:
716 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700717 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800718 return false;
719 }
720 }
721
722 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
723 ASSERT(framebuffer);
724 if (framebuffer->id() == 0)
725 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500726 context->handleError(InvalidOperation() << "Default framebuffer is bound to target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800727 return false;
728 }
729 return true;
730}
731
732bool ValidationGetFramebufferParameteri(Context *context,
733 GLenum target,
734 GLenum pname,
735 GLint *params)
736{
737 if (context->getClientVersion() < ES_3_1)
738 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700739 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800740 return false;
741 }
742
743 if (!ValidFramebufferTarget(target))
744 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700745 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800746 return false;
747 }
748
749 switch (pname)
750 {
751 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
752 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
753 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
754 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
755 break;
756 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700757 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800758 return false;
759 }
760
761 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
762 ASSERT(framebuffer);
763
764 if (framebuffer->id() == 0)
765 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500766 context->handleError(InvalidOperation() << "Default framebuffer is bound to target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800767 return false;
768 }
769 return true;
770}
771
jchen1015015f72017-03-16 13:54:21 +0800772bool ValidateGetProgramResourceIndex(Context *context,
773 GLuint program,
774 GLenum programInterface,
775 const GLchar *name)
776{
777 if (context->getClientVersion() < ES_3_1)
778 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700779 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen1015015f72017-03-16 13:54:21 +0800780 return false;
781 }
782
783 Program *programObject = GetValidProgram(context, program);
784 if (programObject == nullptr)
785 {
786 return false;
787 }
788
789 if (!ValidateNamedProgramInterface(programInterface))
790 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500791 context->handleError(InvalidEnum() << "Invalid program interface: 0x" << std::hex
792 << std::uppercase << programInterface);
jchen1015015f72017-03-16 13:54:21 +0800793 return false;
794 }
Shao80957d92017-02-20 21:25:59 +0800795
796 return true;
797}
798
799bool ValidateBindVertexBuffer(ValidationContext *context,
800 GLuint bindingIndex,
801 GLuint buffer,
802 GLintptr offset,
803 GLsizei stride)
804{
805 if (context->getClientVersion() < ES_3_1)
806 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700807 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +0800808 return false;
809 }
810
811 if (!context->isBufferGenerated(buffer))
812 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500813 context->handleError(InvalidOperation() << "Buffer is not generated.");
Shao80957d92017-02-20 21:25:59 +0800814 return false;
815 }
816
817 const Caps &caps = context->getCaps();
818 if (bindingIndex >= caps.maxVertexAttribBindings)
819 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500820 context->handleError(InvalidValue()
821 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +0800822 return false;
823 }
824
825 if (offset < 0)
826 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700827 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Shao80957d92017-02-20 21:25:59 +0800828 return false;
829 }
830
831 if (stride < 0 || stride > caps.maxVertexAttribStride)
832 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500833 context->handleError(InvalidValue()
834 << "stride must be between 0 and MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +0800835 return false;
836 }
837
838 // [OpenGL ES 3.1] Section 10.3.1 page 244:
839 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
840 if (context->getGLState().getVertexArrayId() == 0)
841 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500842 context->handleError(InvalidOperation() << "Default vertex array buffer is bound.");
Shao80957d92017-02-20 21:25:59 +0800843 return false;
844 }
845
846 return true;
847}
848
849bool ValidateVertexBindingDivisor(ValidationContext *context, GLuint bindingIndex, GLuint divisor)
850{
851 if (context->getClientVersion() < ES_3_1)
852 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700853 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +0800854 return false;
855 }
856
857 const Caps &caps = context->getCaps();
858 if (bindingIndex >= caps.maxVertexAttribBindings)
859 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500860 context->handleError(InvalidValue()
861 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +0800862 return false;
863 }
864
865 // [OpenGL ES 3.1] Section 10.3.1 page 243:
866 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
867 if (context->getGLState().getVertexArrayId() == 0)
868 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500869 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +0800870 return false;
871 }
872
873 return true;
874}
875
876bool ValidateVertexAttribFormat(ValidationContext *context,
877 GLuint attribIndex,
878 GLint size,
879 GLenum type,
880 GLuint relativeOffset,
881 GLboolean pureInteger)
882{
883 if (context->getClientVersion() < ES_3_1)
884 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700885 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +0800886 return false;
887 }
888
889 const Caps &caps = context->getCaps();
890 if (relativeOffset > static_cast<GLuint>(caps.maxVertexAttribRelativeOffset))
891 {
892 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500893 InvalidValue()
894 << "relativeOffset cannot be greater than MAX_VERTEX_ATTRIB_RELATIVE_OFFSET.");
Shao80957d92017-02-20 21:25:59 +0800895 return false;
896 }
897
898 // [OpenGL ES 3.1] Section 10.3.1 page 243:
899 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
900 if (context->getGLState().getVertexArrayId() == 0)
901 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500902 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +0800903 return false;
904 }
905
906 return ValidateVertexFormatBase(context, attribIndex, size, type, pureInteger);
907}
908
909bool ValidateVertexAttribBinding(ValidationContext *context,
910 GLuint attribIndex,
911 GLuint bindingIndex)
912{
913 if (context->getClientVersion() < ES_3_1)
914 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700915 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +0800916 return false;
917 }
918
919 // [OpenGL ES 3.1] Section 10.3.1 page 243:
920 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
921 if (context->getGLState().getVertexArrayId() == 0)
922 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500923 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +0800924 return false;
925 }
926
927 const Caps &caps = context->getCaps();
928 if (attribIndex >= caps.maxVertexAttributes)
929 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700930 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +0800931 return false;
932 }
933
934 if (bindingIndex >= caps.maxVertexAttribBindings)
935 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500936 context->handleError(InvalidValue()
937 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS");
Shao80957d92017-02-20 21:25:59 +0800938 return false;
939 }
940
jchen1015015f72017-03-16 13:54:21 +0800941 return true;
942}
943
jchen10fd7c3b52017-03-21 15:36:03 +0800944bool ValidateGetProgramResourceName(Context *context,
945 GLuint program,
946 GLenum programInterface,
947 GLuint index,
948 GLsizei bufSize,
949 GLsizei *length,
950 GLchar *name)
951{
952 if (context->getClientVersion() < ES_3_1)
953 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700954 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen10fd7c3b52017-03-21 15:36:03 +0800955 return false;
956 }
957
958 Program *programObject = GetValidProgram(context, program);
959 if (programObject == nullptr)
960 {
961 return false;
962 }
963
964 if (!ValidateNamedProgramInterface(programInterface))
965 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500966 context->handleError(InvalidEnum() << "Invalid program interface: 0x" << std::hex
967 << std::uppercase << programInterface);
jchen10fd7c3b52017-03-21 15:36:03 +0800968 return false;
969 }
970
971 if (!ValidateProgramResourceIndex(programObject, programInterface, index))
972 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500973 context->handleError(InvalidValue() << "Invalid index: " << index);
jchen10fd7c3b52017-03-21 15:36:03 +0800974 return false;
975 }
976
977 if (bufSize < 0)
978 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700979 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
jchen10fd7c3b52017-03-21 15:36:03 +0800980 return false;
981 }
982
983 return true;
984}
985
Xinghua Cao2b396592017-03-29 15:36:04 +0800986bool ValidateDispatchCompute(Context *context,
987 GLuint numGroupsX,
988 GLuint numGroupsY,
989 GLuint numGroupsZ)
990{
991 if (context->getClientVersion() < ES_3_1)
992 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700993 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Xinghua Cao2b396592017-03-29 15:36:04 +0800994 return false;
995 }
996
997 const State &state = context->getGLState();
998 Program *program = state.getProgram();
999
1000 if (program == nullptr)
1001 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001002 context->handleError(InvalidOperation()
1003 << "No active program object for the compute shader stage.");
Xinghua Cao2b396592017-03-29 15:36:04 +08001004 return false;
1005 }
1006
1007 if (program->isLinked() == false || program->getAttachedComputeShader() == nullptr)
1008 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001009 context->handleError(
1010 InvalidOperation()
1011 << "Program has not been successfully linked, or program contains no compute shaders.");
Xinghua Cao2b396592017-03-29 15:36:04 +08001012 return false;
1013 }
1014
1015 const Caps &caps = context->getCaps();
1016 if (numGroupsX > caps.maxComputeWorkGroupCount[0])
1017 {
1018 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001019 InvalidValue() << "num_groups_x cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[0]="
1020 << caps.maxComputeWorkGroupCount[0]);
Xinghua Cao2b396592017-03-29 15:36:04 +08001021 return false;
1022 }
1023 if (numGroupsY > caps.maxComputeWorkGroupCount[1])
1024 {
1025 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001026 InvalidValue() << "num_groups_y cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[1]="
1027 << caps.maxComputeWorkGroupCount[1]);
Xinghua Cao2b396592017-03-29 15:36:04 +08001028 return false;
1029 }
1030 if (numGroupsZ > caps.maxComputeWorkGroupCount[2])
1031 {
1032 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001033 InvalidValue() << "num_groups_z cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[2]="
1034 << caps.maxComputeWorkGroupCount[2]);
Xinghua Cao2b396592017-03-29 15:36:04 +08001035 return false;
1036 }
1037
1038 return true;
1039}
1040
Xinghua Cao65ec0b22017-03-28 16:10:52 +08001041bool ValidateBindImageTexture(Context *context,
1042 GLuint unit,
1043 GLuint texture,
1044 GLint level,
1045 GLboolean layered,
1046 GLint layer,
1047 GLenum access,
1048 GLenum format)
1049{
1050 GLuint maxImageUnits = context->getCaps().maxImageUnits;
1051 if (unit >= maxImageUnits)
1052 {
1053 context->handleError(InvalidValue()
1054 << "unit cannot be greater than or equal than MAX_IMAGE_UNITS = "
1055 << maxImageUnits);
1056 return false;
1057 }
1058
1059 if (level < 0)
1060 {
1061 context->handleError(InvalidValue() << "level is negative.");
1062 return false;
1063 }
1064
1065 if (layer < 0)
1066 {
1067 context->handleError(InvalidValue() << "layer is negative.");
1068 return false;
1069 }
1070
1071 if (access != GL_READ_ONLY && access != GL_WRITE_ONLY && access != GL_READ_WRITE)
1072 {
1073 context->handleError(InvalidEnum() << "access is not one of the supported tokens.");
1074 return false;
1075 }
1076
1077 switch (format)
1078 {
1079 case GL_RGBA32F:
1080 case GL_RGBA16F:
1081 case GL_R32F:
1082 case GL_RGBA32UI:
1083 case GL_RGBA16UI:
1084 case GL_RGBA8UI:
1085 case GL_R32UI:
1086 case GL_RGBA32I:
1087 case GL_RGBA16I:
1088 case GL_RGBA8I:
1089 case GL_R32I:
1090 case GL_RGBA8:
1091 case GL_RGBA8_SNORM:
1092 break;
1093 default:
1094 context->handleError(InvalidValue()
1095 << "format is not one of supported image unit formats.");
1096 return false;
1097 }
1098
1099 if (texture != 0)
1100 {
1101 Texture *tex = context->getTexture(texture);
1102
1103 if (tex == nullptr)
1104 {
1105 context->handleError(InvalidValue()
1106 << "texture is not the name of an existing texture object.");
1107 return false;
1108 }
1109
1110 if (!tex->getImmutableFormat())
1111 {
1112 context->handleError(InvalidOperation()
1113 << "texture is not the name of an immutable texture object.");
1114 return false;
1115 }
1116 }
1117
1118 return true;
1119}
jchen10191381f2017-04-11 13:59:04 +08001120
1121bool ValidateGetProgramResourceLocation(Context *context,
1122 GLuint program,
1123 GLenum programInterface,
1124 const GLchar *name)
1125{
1126 if (context->getClientVersion() < ES_3_1)
1127 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001128 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen10191381f2017-04-11 13:59:04 +08001129 return false;
1130 }
1131
1132 Program *programObject = GetValidProgram(context, program);
1133 if (programObject == nullptr)
1134 {
1135 return false;
1136 }
1137
1138 if (!programObject->isLinked())
1139 {
1140 context->handleError(InvalidOperation() << "Program is not successfully linked.");
1141 return false;
1142 }
1143
1144 if (!ValidateLocationProgramInterface(programInterface))
1145 {
1146 context->handleError(InvalidEnum() << "Invalid program interface.");
1147 return false;
1148 }
1149 return true;
1150}
1151
jchen10880683b2017-04-12 16:21:55 +08001152bool ValidateGetProgramResourceiv(Context *context,
1153 GLuint program,
1154 GLenum programInterface,
1155 GLuint index,
1156 GLsizei propCount,
1157 const GLenum *props,
1158 GLsizei bufSize,
1159 GLsizei *length,
1160 GLint *params)
1161{
1162 if (context->getClientVersion() < ES_3_1)
1163 {
jchen10d9cd7b72017-08-30 15:04:25 +08001164 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen10880683b2017-04-12 16:21:55 +08001165 return false;
1166 }
1167
1168 Program *programObject = GetValidProgram(context, program);
1169 if (programObject == nullptr)
1170 {
1171 return false;
1172 }
1173 if (!ValidateProgramInterface(programInterface))
1174 {
1175 context->handleError(InvalidEnum() << "Invalid program interface.");
1176 return false;
1177 }
1178 if (propCount <= 0)
1179 {
1180 context->handleError(InvalidValue() << "Invalid propCount.");
1181 return false;
1182 }
1183 if (bufSize < 0)
1184 {
1185 context->handleError(InvalidValue() << "Invalid bufSize.");
1186 return false;
1187 }
1188 if (!ValidateProgramResourceIndex(programObject, programInterface, index))
1189 {
1190 context->handleError(InvalidValue() << "Invalid index: " << index);
1191 return false;
1192 }
1193 for (GLsizei i = 0; i < propCount; i++)
1194 {
1195 if (!ValidateProgramResourceProperty(props[i]))
1196 {
1197 context->handleError(InvalidEnum() << "Invalid prop.");
1198 return false;
1199 }
1200 if (!ValidateProgramResourcePropertyByInterface(props[i], programInterface))
1201 {
1202 context->handleError(InvalidOperation() << "Not an allowed prop for interface");
1203 return false;
1204 }
1205 }
1206 return true;
1207}
1208
jchen10d9cd7b72017-08-30 15:04:25 +08001209bool ValidateGetProgramInterfaceiv(Context *context,
1210 GLuint program,
1211 GLenum programInterface,
1212 GLenum pname,
1213 GLint *params)
1214{
1215 if (context->getClientVersion() < ES_3_1)
1216 {
1217 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1218 return false;
1219 }
1220
1221 Program *programObject = GetValidProgram(context, program);
1222 if (programObject == nullptr)
1223 {
1224 return false;
1225 }
1226
1227 if (!ValidateProgramInterface(programInterface))
1228 {
1229 context->handleError(InvalidEnum() << "Invalid program interface.");
1230 return false;
1231 }
1232
1233 switch (pname)
1234 {
1235 case GL_ACTIVE_RESOURCES:
1236 case GL_MAX_NAME_LENGTH:
1237 case GL_MAX_NUM_ACTIVE_VARIABLES:
1238 break;
1239
1240 default:
1241 context->handleError(InvalidEnum() << "Unknown property of program interface.");
1242 return false;
1243 }
1244
1245 if (pname == GL_MAX_NAME_LENGTH && programInterface == GL_ATOMIC_COUNTER_BUFFER)
1246 {
1247 context->handleError(InvalidOperation()
1248 << "Active atomic counter resources are not assigned name strings.");
1249 return false;
1250 }
1251
1252 if (pname == GL_MAX_NUM_ACTIVE_VARIABLES)
1253 {
1254 switch (programInterface)
1255 {
1256 case GL_ATOMIC_COUNTER_BUFFER:
1257 case GL_SHADER_STORAGE_BLOCK:
1258 case GL_UNIFORM_BLOCK:
1259 break;
1260
1261 default:
1262 context->handleError(
1263 InvalidOperation()
1264 << "MAX_NUM_ACTIVE_VARIABLES requires a buffer or block interface.");
1265 return false;
1266 }
1267 }
1268
1269 return true;
1270}
1271
Yunchao Hea336b902017-08-02 16:05:21 +08001272static bool ValidateGenOrDeleteES31(Context *context, GLint n)
1273{
1274 if (context->getClientVersion() < ES_3_1)
1275 {
1276 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1277 return false;
1278 }
1279
1280 return ValidateGenOrDelete(context, n);
1281}
1282
1283bool ValidateGenProgramPipelines(Context *context, GLint n, GLuint *)
1284{
1285 return ValidateGenOrDeleteES31(context, n);
1286}
1287
1288bool ValidateDeleteProgramPipelines(Context *context, GLint n, const GLuint *)
1289{
1290 return ValidateGenOrDeleteES31(context, n);
1291}
1292
1293bool ValidateBindProgramPipeline(Context *context, GLuint pipeline)
1294{
1295 if (context->getClientVersion() < ES_3_1)
1296 {
1297 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1298 return false;
1299 }
1300
1301 if (!context->isProgramPipelineGenerated(pipeline))
1302 {
1303 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
1304 return false;
1305 }
1306
1307 return true;
1308}
1309
1310bool ValidateIsProgramPipeline(Context *context, GLuint pipeline)
1311{
1312 if (context->getClientVersion() < ES_3_1)
1313 {
1314 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1315 return false;
1316 }
1317
1318 return true;
1319}
1320
Jiawei Shaodb342272017-09-27 10:21:45 +08001321bool ValidateSampleMaski(Context *context, GLuint maskNumber)
1322{
1323 if (context->getClientVersion() < ES_3_1)
1324 {
1325 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1326 return false;
1327 }
1328
1329 if (maskNumber >= context->getCaps().maxSampleMaskWords)
1330 {
1331 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
1332 return false;
1333 }
1334
1335 return true;
1336}
1337
Martin Radev66fb8202016-07-28 11:45:20 +03001338} // namespace gl