blob: 40f59e731a204c544301cde0c99740205d5db1d6 [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
jchen10880683b2017-04-12 16:21:55 +0800260 // TODO(jie.a.chen@intel.com): more interfaces.
jchen10fd7c3b52017-03-21 15:36:03 +0800261 case GL_UNIFORM:
262 case GL_UNIFORM_BLOCK:
263 case GL_TRANSFORM_FEEDBACK_VARYING:
264 case GL_BUFFER_VARIABLE:
265 case GL_SHADER_STORAGE_BLOCK:
jchen10880683b2017-04-12 16:21:55 +0800266 case GL_ATOMIC_COUNTER_BUFFER:
jchen10fd7c3b52017-03-21 15:36:03 +0800267 UNIMPLEMENTED();
268 return false;
269
270 default:
271 UNREACHABLE();
272 return false;
273 }
274}
275
jchen1015015f72017-03-16 13:54:21 +0800276} // anonymous namespace
277
Martin Radev66fb8202016-07-28 11:45:20 +0300278bool ValidateGetBooleani_v(Context *context, GLenum target, GLuint index, GLboolean *data)
279{
Geoff Langeb66a6e2016-10-31 13:06:12 -0400280 if (context->getClientVersion() < ES_3_1)
Martin Radev66fb8202016-07-28 11:45:20 +0300281 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700282 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Martin Radev66fb8202016-07-28 11:45:20 +0300283 return false;
284 }
285
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400286 if (!ValidateIndexedStateQuery(context, target, index, nullptr))
287 {
288 return false;
289 }
290
291 return true;
292}
293
294bool ValidateGetBooleani_vRobustANGLE(Context *context,
295 GLenum target,
296 GLuint index,
297 GLsizei bufSize,
298 GLsizei *length,
299 GLboolean *data)
300{
Geoff Langeb66a6e2016-10-31 13:06:12 -0400301 if (context->getClientVersion() < ES_3_1)
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400302 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700303 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400304 return false;
305 }
306
307 if (!ValidateRobustEntryPoint(context, bufSize))
308 {
309 return false;
310 }
311
312 if (!ValidateIndexedStateQuery(context, target, index, length))
313 {
314 return false;
315 }
316
317 if (!ValidateRobustBufferSize(context, bufSize, *length))
Martin Radev66fb8202016-07-28 11:45:20 +0300318 {
319 return false;
320 }
321
322 return true;
323}
324
Jamie Madill876429b2017-04-20 15:46:24 -0400325bool ValidateDrawIndirectBase(Context *context, GLenum mode, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800326{
327 if (context->getClientVersion() < ES_3_1)
328 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700329 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jiajia Qind9671222016-11-29 16:30:31 +0800330 return false;
331 }
332
333 // Here the third parameter 1 is only to pass the count validation.
334 if (!ValidateDrawBase(context, mode, 1))
335 {
336 return false;
337 }
338
339 const State &state = context->getGLState();
340
341 // An INVALID_OPERATION error is generated if zero is bound to VERTEX_ARRAY_BINDING,
342 // DRAW_INDIRECT_BUFFER or to any enabled vertex array.
343 if (!state.getVertexArrayId())
344 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500345 context->handleError(InvalidOperation() << "zero is bound to VERTEX_ARRAY_BINDING");
Jiajia Qind9671222016-11-29 16:30:31 +0800346 return false;
347 }
348
349 gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
350 if (!drawIndirectBuffer)
351 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500352 context->handleError(InvalidOperation() << "zero is bound to DRAW_INDIRECT_BUFFER");
Jiajia Qind9671222016-11-29 16:30:31 +0800353 return false;
354 }
355
356 // An INVALID_VALUE error is generated if indirect is not a multiple of the size, in basic
357 // machine units, of uint.
358 GLint64 offset = reinterpret_cast<GLint64>(indirect);
359 if ((static_cast<GLuint>(offset) % sizeof(GLuint)) != 0)
360 {
361 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500362 InvalidValue()
363 << "indirect is not a multiple of the size, in basic machine units, of uint");
Jiajia Qind9671222016-11-29 16:30:31 +0800364 return false;
365 }
366
Martin Radev14a26ae2017-07-24 15:56:29 +0300367 // ANGLE_multiview spec, revision 1:
368 // An INVALID_OPERATION is generated by DrawArraysIndirect and DrawElementsIndirect if the
369 // number of views in the draw framebuffer is greater than 1.
370 const Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
371 ASSERT(drawFramebuffer != nullptr);
372 if (drawFramebuffer->getNumViews() > 1)
373 {
374 context->handleError(
375 InvalidOperation()
376 << "The number of views in the active draw framebuffer is greater than 1.");
377 return false;
378 }
379
Jiajia Qind9671222016-11-29 16:30:31 +0800380 return true;
381}
382
Jamie Madill876429b2017-04-20 15:46:24 -0400383bool ValidateDrawArraysIndirect(Context *context, GLenum mode, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800384{
385 const State &state = context->getGLState();
386 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
387 if (curTransformFeedback && curTransformFeedback->isActive() &&
388 !curTransformFeedback->isPaused())
389 {
390 // An INVALID_OPERATION error is generated if transform feedback is active and not paused.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500391 context->handleError(InvalidOperation() << "transform feedback is active and not paused.");
Jiajia Qind9671222016-11-29 16:30:31 +0800392 return false;
393 }
394
395 if (!ValidateDrawIndirectBase(context, mode, indirect))
396 return false;
397
398 gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
399 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
400 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawArraysIndirectCommand
401 // which's size is 4 * sizeof(uint).
402 auto checkedSum = checkedOffset + 4 * sizeof(GLuint);
403 if (!checkedSum.IsValid() ||
404 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
405 {
406 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500407 InvalidOperation()
408 << "the command would source data beyond the end of the buffer object.");
Jiajia Qind9671222016-11-29 16:30:31 +0800409 return false;
410 }
411
412 return true;
413}
414
Jamie Madill876429b2017-04-20 15:46:24 -0400415bool ValidateDrawElementsIndirect(Context *context, GLenum mode, GLenum type, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800416{
417 if (!ValidateDrawElementsBase(context, type))
418 return false;
419
420 const State &state = context->getGLState();
421 const VertexArray *vao = state.getVertexArray();
422 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
423 if (!elementArrayBuffer)
424 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500425 context->handleError(InvalidOperation() << "zero is bound to ELEMENT_ARRAY_BUFFER");
Jiajia Qind9671222016-11-29 16:30:31 +0800426 return false;
427 }
428
429 if (!ValidateDrawIndirectBase(context, mode, indirect))
430 return false;
431
432 gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
433 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
434 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawElementsIndirectCommand
435 // which's size is 5 * sizeof(uint).
436 auto checkedSum = checkedOffset + 5 * sizeof(GLuint);
437 if (!checkedSum.IsValid() ||
438 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
439 {
440 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500441 InvalidOperation()
442 << "the command would source data beyond the end of the buffer object.");
Jiajia Qind9671222016-11-29 16:30:31 +0800443 return false;
444 }
445
446 return true;
447}
448
He Yunchao11b038b2016-11-22 21:24:04 +0800449bool ValidateGetTexLevelParameterBase(Context *context,
450 GLenum target,
451 GLint level,
452 GLenum pname,
453 GLsizei *length)
454{
455 if (context->getClientVersion() < ES_3_1)
456 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700457 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
He Yunchao11b038b2016-11-22 21:24:04 +0800458 return false;
459 }
460
461 if (length)
462 {
463 *length = 0;
464 }
465
466 if (!ValidTexLevelDestinationTarget(context, target))
467 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700468 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
He Yunchao11b038b2016-11-22 21:24:04 +0800469 return false;
470 }
471
472 if (context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target) ==
473 nullptr)
474 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500475 context->handleError(InvalidEnum() << "No texture bound.");
He Yunchao11b038b2016-11-22 21:24:04 +0800476 return false;
477 }
478
479 if (!ValidMipLevel(context, target, level))
480 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500481 context->handleError(InvalidValue());
He Yunchao11b038b2016-11-22 21:24:04 +0800482 return false;
483 }
484
485 switch (pname)
486 {
487 case GL_TEXTURE_RED_TYPE:
488 case GL_TEXTURE_GREEN_TYPE:
489 case GL_TEXTURE_BLUE_TYPE:
490 case GL_TEXTURE_ALPHA_TYPE:
491 case GL_TEXTURE_DEPTH_TYPE:
492 break;
493 case GL_TEXTURE_RED_SIZE:
494 case GL_TEXTURE_GREEN_SIZE:
495 case GL_TEXTURE_BLUE_SIZE:
496 case GL_TEXTURE_ALPHA_SIZE:
497 case GL_TEXTURE_DEPTH_SIZE:
498 case GL_TEXTURE_STENCIL_SIZE:
499 case GL_TEXTURE_SHARED_SIZE:
500 break;
501 case GL_TEXTURE_INTERNAL_FORMAT:
502 case GL_TEXTURE_WIDTH:
503 case GL_TEXTURE_HEIGHT:
504 case GL_TEXTURE_DEPTH:
505 break;
506 case GL_TEXTURE_SAMPLES:
507 case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
508 break;
509 case GL_TEXTURE_COMPRESSED:
510 break;
511 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700512 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
He Yunchao11b038b2016-11-22 21:24:04 +0800513 return false;
514 }
515
516 if (length)
517 {
518 *length = 1;
519 }
520 return true;
521}
522
523bool ValidateGetTexLevelParameterfv(Context *context,
524 GLenum target,
525 GLint level,
526 GLenum pname,
527 GLfloat *params)
528{
529 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
530}
531
532bool ValidateGetTexLevelParameteriv(Context *context,
533 GLenum target,
534 GLint level,
535 GLenum pname,
536 GLint *params)
537{
538 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
539}
540
JiangYizhoubddc46b2016-12-09 09:50:51 +0800541bool ValidateTexStorage2DMultiSample(Context *context,
542 GLenum target,
543 GLsizei samples,
544 GLint internalFormat,
545 GLsizei width,
546 GLsizei height,
547 GLboolean fixedSampleLocations)
548{
549 if (context->getClientVersion() < ES_3_1)
550 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700551 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhoubddc46b2016-12-09 09:50:51 +0800552 return false;
553 }
554
555 if (target != GL_TEXTURE_2D_MULTISAMPLE)
556 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500557 context->handleError(InvalidEnum() << "Target must be TEXTURE_2D_MULTISAMPLE.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800558 return false;
559 }
560
561 if (width < 1 || height < 1)
562 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700563 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
JiangYizhoubddc46b2016-12-09 09:50:51 +0800564 return false;
565 }
566
567 const Caps &caps = context->getCaps();
568 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
569 static_cast<GLuint>(height) > caps.max2DTextureSize)
570 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500571 context
572 ->handleError(InvalidValue()
573 << "Width and height must be less than or equal to GL_MAX_TEXTURE_SIZE.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800574 return false;
575 }
576
577 if (samples == 0)
578 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500579 context->handleError(InvalidValue() << "Samples may not be zero.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800580 return false;
581 }
582
583 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
584 if (!formatCaps.renderable)
585 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500586 context->handleError(InvalidEnum() << "SizedInternalformat must be color-renderable, "
587 "depth-renderable, or stencil-renderable.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800588 return false;
589 }
590
591 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
592 // is one of the unsized base internalformats listed in table 8.11.
Geoff Langca271392017-04-05 12:30:00 -0400593 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
594 if (formatInfo.internalFormat == GL_NONE)
JiangYizhoubddc46b2016-12-09 09:50:51 +0800595 {
596 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500597 InvalidEnum()
598 << "Internalformat is one of the unsupported unsized base internalformats.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800599 return false;
600 }
601
602 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
603 {
604 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500605 InvalidOperation()
606 << "Samples must not be greater than maximum supported value for the format.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800607 return false;
608 }
609
610 Texture *texture = context->getTargetTexture(target);
611 if (!texture || texture->id() == 0)
612 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500613 context->handleError(InvalidOperation() << "Zero is bound to target.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800614 return false;
615 }
616
617 if (texture->getImmutableFormat())
618 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500619 context->handleError(InvalidOperation() << "The value of TEXTURE_IMMUTABLE_FORMAT for "
620 "the texture currently bound to target on "
621 "the active texture unit is true.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800622 return false;
623 }
624
625 return true;
626}
627
628bool ValidateGetMultisamplefv(Context *context, GLenum pname, GLuint index, GLfloat *val)
629{
630 if (context->getClientVersion() < ES_3_1)
631 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700632 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhoubddc46b2016-12-09 09:50:51 +0800633 return false;
634 }
635
636 if (pname != GL_SAMPLE_POSITION)
637 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500638 context->handleError(InvalidEnum() << "Pname must be SAMPLE_POSITION.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800639 return false;
640 }
641
JiangYizhou5b03f472017-01-09 10:22:53 +0800642 Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
643
644 if (index >= static_cast<GLuint>(framebuffer->getSamples(context)))
JiangYizhoubddc46b2016-12-09 09:50:51 +0800645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500646 context->handleError(InvalidValue() << "Index must be less than the value of SAMPLES.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800647 return false;
648 }
649
650 return true;
651}
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800652
653bool ValidationFramebufferParameteri(Context *context, GLenum target, GLenum pname, GLint param)
654{
655 if (context->getClientVersion() < ES_3_1)
656 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700657 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800658 return false;
659 }
660
661 if (!ValidFramebufferTarget(target))
662 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500663 context->handleError(InvalidEnum() << "Invalid framebuffer target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800664 return false;
665 }
666
667 switch (pname)
668 {
669 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
670 {
671 GLint maxWidth = context->getCaps().maxFramebufferWidth;
672 if (param < 0 || param > maxWidth)
673 {
674 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500675 InvalidValue()
676 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_WIDTH.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800677 return false;
678 }
679 break;
680 }
681 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
682 {
683 GLint maxHeight = context->getCaps().maxFramebufferHeight;
684 if (param < 0 || param > maxHeight)
685 {
686 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500687 InvalidValue()
688 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_HEIGHT.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800689 return false;
690 }
691 break;
692 }
693 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
694 {
695 GLint maxSamples = context->getCaps().maxFramebufferSamples;
696 if (param < 0 || param > maxSamples)
697 {
698 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500699 InvalidValue()
700 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_SAMPLES.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800701 return false;
702 }
703 break;
704 }
705 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
706 {
707 break;
708 }
709 default:
710 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700711 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800712 return false;
713 }
714 }
715
716 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
717 ASSERT(framebuffer);
718 if (framebuffer->id() == 0)
719 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500720 context->handleError(InvalidOperation() << "Default framebuffer is bound to target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800721 return false;
722 }
723 return true;
724}
725
726bool ValidationGetFramebufferParameteri(Context *context,
727 GLenum target,
728 GLenum pname,
729 GLint *params)
730{
731 if (context->getClientVersion() < ES_3_1)
732 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700733 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800734 return false;
735 }
736
737 if (!ValidFramebufferTarget(target))
738 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700739 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800740 return false;
741 }
742
743 switch (pname)
744 {
745 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
746 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
747 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
748 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
749 break;
750 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700751 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800752 return false;
753 }
754
755 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
756 ASSERT(framebuffer);
757
758 if (framebuffer->id() == 0)
759 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500760 context->handleError(InvalidOperation() << "Default framebuffer is bound to target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800761 return false;
762 }
763 return true;
764}
765
jchen1015015f72017-03-16 13:54:21 +0800766bool ValidateGetProgramResourceIndex(Context *context,
767 GLuint program,
768 GLenum programInterface,
769 const GLchar *name)
770{
771 if (context->getClientVersion() < ES_3_1)
772 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700773 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen1015015f72017-03-16 13:54:21 +0800774 return false;
775 }
776
777 Program *programObject = GetValidProgram(context, program);
778 if (programObject == nullptr)
779 {
780 return false;
781 }
782
783 if (!ValidateNamedProgramInterface(programInterface))
784 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500785 context->handleError(InvalidEnum() << "Invalid program interface: 0x" << std::hex
786 << std::uppercase << programInterface);
jchen1015015f72017-03-16 13:54:21 +0800787 return false;
788 }
Shao80957d92017-02-20 21:25:59 +0800789
790 return true;
791}
792
793bool ValidateBindVertexBuffer(ValidationContext *context,
794 GLuint bindingIndex,
795 GLuint buffer,
796 GLintptr offset,
797 GLsizei stride)
798{
799 if (context->getClientVersion() < ES_3_1)
800 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700801 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +0800802 return false;
803 }
804
805 if (!context->isBufferGenerated(buffer))
806 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500807 context->handleError(InvalidOperation() << "Buffer is not generated.");
Shao80957d92017-02-20 21:25:59 +0800808 return false;
809 }
810
811 const Caps &caps = context->getCaps();
812 if (bindingIndex >= caps.maxVertexAttribBindings)
813 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500814 context->handleError(InvalidValue()
815 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +0800816 return false;
817 }
818
819 if (offset < 0)
820 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700821 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Shao80957d92017-02-20 21:25:59 +0800822 return false;
823 }
824
825 if (stride < 0 || stride > caps.maxVertexAttribStride)
826 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500827 context->handleError(InvalidValue()
828 << "stride must be between 0 and MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +0800829 return false;
830 }
831
832 // [OpenGL ES 3.1] Section 10.3.1 page 244:
833 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
834 if (context->getGLState().getVertexArrayId() == 0)
835 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500836 context->handleError(InvalidOperation() << "Default vertex array buffer is bound.");
Shao80957d92017-02-20 21:25:59 +0800837 return false;
838 }
839
840 return true;
841}
842
843bool ValidateVertexBindingDivisor(ValidationContext *context, GLuint bindingIndex, GLuint divisor)
844{
845 if (context->getClientVersion() < ES_3_1)
846 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700847 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +0800848 return false;
849 }
850
851 const Caps &caps = context->getCaps();
852 if (bindingIndex >= caps.maxVertexAttribBindings)
853 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500854 context->handleError(InvalidValue()
855 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +0800856 return false;
857 }
858
859 // [OpenGL ES 3.1] Section 10.3.1 page 243:
860 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
861 if (context->getGLState().getVertexArrayId() == 0)
862 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500863 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +0800864 return false;
865 }
866
867 return true;
868}
869
870bool ValidateVertexAttribFormat(ValidationContext *context,
871 GLuint attribIndex,
872 GLint size,
873 GLenum type,
874 GLuint relativeOffset,
875 GLboolean pureInteger)
876{
877 if (context->getClientVersion() < ES_3_1)
878 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700879 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +0800880 return false;
881 }
882
883 const Caps &caps = context->getCaps();
884 if (relativeOffset > static_cast<GLuint>(caps.maxVertexAttribRelativeOffset))
885 {
886 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500887 InvalidValue()
888 << "relativeOffset cannot be greater than MAX_VERTEX_ATTRIB_RELATIVE_OFFSET.");
Shao80957d92017-02-20 21:25:59 +0800889 return false;
890 }
891
892 // [OpenGL ES 3.1] Section 10.3.1 page 243:
893 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
894 if (context->getGLState().getVertexArrayId() == 0)
895 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500896 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +0800897 return false;
898 }
899
900 return ValidateVertexFormatBase(context, attribIndex, size, type, pureInteger);
901}
902
903bool ValidateVertexAttribBinding(ValidationContext *context,
904 GLuint attribIndex,
905 GLuint bindingIndex)
906{
907 if (context->getClientVersion() < ES_3_1)
908 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700909 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +0800910 return false;
911 }
912
913 // [OpenGL ES 3.1] Section 10.3.1 page 243:
914 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
915 if (context->getGLState().getVertexArrayId() == 0)
916 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500917 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +0800918 return false;
919 }
920
921 const Caps &caps = context->getCaps();
922 if (attribIndex >= caps.maxVertexAttributes)
923 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700924 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +0800925 return false;
926 }
927
928 if (bindingIndex >= caps.maxVertexAttribBindings)
929 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500930 context->handleError(InvalidValue()
931 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS");
Shao80957d92017-02-20 21:25:59 +0800932 return false;
933 }
934
jchen1015015f72017-03-16 13:54:21 +0800935 return true;
936}
937
jchen10fd7c3b52017-03-21 15:36:03 +0800938bool ValidateGetProgramResourceName(Context *context,
939 GLuint program,
940 GLenum programInterface,
941 GLuint index,
942 GLsizei bufSize,
943 GLsizei *length,
944 GLchar *name)
945{
946 if (context->getClientVersion() < ES_3_1)
947 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700948 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen10fd7c3b52017-03-21 15:36:03 +0800949 return false;
950 }
951
952 Program *programObject = GetValidProgram(context, program);
953 if (programObject == nullptr)
954 {
955 return false;
956 }
957
958 if (!ValidateNamedProgramInterface(programInterface))
959 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500960 context->handleError(InvalidEnum() << "Invalid program interface: 0x" << std::hex
961 << std::uppercase << programInterface);
jchen10fd7c3b52017-03-21 15:36:03 +0800962 return false;
963 }
964
965 if (!ValidateProgramResourceIndex(programObject, programInterface, index))
966 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500967 context->handleError(InvalidValue() << "Invalid index: " << index);
jchen10fd7c3b52017-03-21 15:36:03 +0800968 return false;
969 }
970
971 if (bufSize < 0)
972 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700973 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
jchen10fd7c3b52017-03-21 15:36:03 +0800974 return false;
975 }
976
977 return true;
978}
979
Xinghua Cao2b396592017-03-29 15:36:04 +0800980bool ValidateDispatchCompute(Context *context,
981 GLuint numGroupsX,
982 GLuint numGroupsY,
983 GLuint numGroupsZ)
984{
985 if (context->getClientVersion() < ES_3_1)
986 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700987 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Xinghua Cao2b396592017-03-29 15:36:04 +0800988 return false;
989 }
990
991 const State &state = context->getGLState();
992 Program *program = state.getProgram();
993
994 if (program == nullptr)
995 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500996 context->handleError(InvalidOperation()
997 << "No active program object for the compute shader stage.");
Xinghua Cao2b396592017-03-29 15:36:04 +0800998 return false;
999 }
1000
1001 if (program->isLinked() == false || program->getAttachedComputeShader() == nullptr)
1002 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001003 context->handleError(
1004 InvalidOperation()
1005 << "Program has not been successfully linked, or program contains no compute shaders.");
Xinghua Cao2b396592017-03-29 15:36:04 +08001006 return false;
1007 }
1008
1009 const Caps &caps = context->getCaps();
1010 if (numGroupsX > caps.maxComputeWorkGroupCount[0])
1011 {
1012 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001013 InvalidValue() << "num_groups_x cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[0]="
1014 << caps.maxComputeWorkGroupCount[0]);
Xinghua Cao2b396592017-03-29 15:36:04 +08001015 return false;
1016 }
1017 if (numGroupsY > caps.maxComputeWorkGroupCount[1])
1018 {
1019 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001020 InvalidValue() << "num_groups_y cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[1]="
1021 << caps.maxComputeWorkGroupCount[1]);
Xinghua Cao2b396592017-03-29 15:36:04 +08001022 return false;
1023 }
1024 if (numGroupsZ > caps.maxComputeWorkGroupCount[2])
1025 {
1026 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001027 InvalidValue() << "num_groups_z cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[2]="
1028 << caps.maxComputeWorkGroupCount[2]);
Xinghua Cao2b396592017-03-29 15:36:04 +08001029 return false;
1030 }
1031
1032 return true;
1033}
1034
Xinghua Cao65ec0b22017-03-28 16:10:52 +08001035bool ValidateBindImageTexture(Context *context,
1036 GLuint unit,
1037 GLuint texture,
1038 GLint level,
1039 GLboolean layered,
1040 GLint layer,
1041 GLenum access,
1042 GLenum format)
1043{
1044 GLuint maxImageUnits = context->getCaps().maxImageUnits;
1045 if (unit >= maxImageUnits)
1046 {
1047 context->handleError(InvalidValue()
1048 << "unit cannot be greater than or equal than MAX_IMAGE_UNITS = "
1049 << maxImageUnits);
1050 return false;
1051 }
1052
1053 if (level < 0)
1054 {
1055 context->handleError(InvalidValue() << "level is negative.");
1056 return false;
1057 }
1058
1059 if (layer < 0)
1060 {
1061 context->handleError(InvalidValue() << "layer is negative.");
1062 return false;
1063 }
1064
1065 if (access != GL_READ_ONLY && access != GL_WRITE_ONLY && access != GL_READ_WRITE)
1066 {
1067 context->handleError(InvalidEnum() << "access is not one of the supported tokens.");
1068 return false;
1069 }
1070
1071 switch (format)
1072 {
1073 case GL_RGBA32F:
1074 case GL_RGBA16F:
1075 case GL_R32F:
1076 case GL_RGBA32UI:
1077 case GL_RGBA16UI:
1078 case GL_RGBA8UI:
1079 case GL_R32UI:
1080 case GL_RGBA32I:
1081 case GL_RGBA16I:
1082 case GL_RGBA8I:
1083 case GL_R32I:
1084 case GL_RGBA8:
1085 case GL_RGBA8_SNORM:
1086 break;
1087 default:
1088 context->handleError(InvalidValue()
1089 << "format is not one of supported image unit formats.");
1090 return false;
1091 }
1092
1093 if (texture != 0)
1094 {
1095 Texture *tex = context->getTexture(texture);
1096
1097 if (tex == nullptr)
1098 {
1099 context->handleError(InvalidValue()
1100 << "texture is not the name of an existing texture object.");
1101 return false;
1102 }
1103
1104 if (!tex->getImmutableFormat())
1105 {
1106 context->handleError(InvalidOperation()
1107 << "texture is not the name of an immutable texture object.");
1108 return false;
1109 }
1110 }
1111
1112 return true;
1113}
jchen10191381f2017-04-11 13:59:04 +08001114
1115bool ValidateGetProgramResourceLocation(Context *context,
1116 GLuint program,
1117 GLenum programInterface,
1118 const GLchar *name)
1119{
1120 if (context->getClientVersion() < ES_3_1)
1121 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001122 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen10191381f2017-04-11 13:59:04 +08001123 return false;
1124 }
1125
1126 Program *programObject = GetValidProgram(context, program);
1127 if (programObject == nullptr)
1128 {
1129 return false;
1130 }
1131
1132 if (!programObject->isLinked())
1133 {
1134 context->handleError(InvalidOperation() << "Program is not successfully linked.");
1135 return false;
1136 }
1137
1138 if (!ValidateLocationProgramInterface(programInterface))
1139 {
1140 context->handleError(InvalidEnum() << "Invalid program interface.");
1141 return false;
1142 }
1143 return true;
1144}
1145
jchen10880683b2017-04-12 16:21:55 +08001146bool ValidateGetProgramResourceiv(Context *context,
1147 GLuint program,
1148 GLenum programInterface,
1149 GLuint index,
1150 GLsizei propCount,
1151 const GLenum *props,
1152 GLsizei bufSize,
1153 GLsizei *length,
1154 GLint *params)
1155{
1156 if (context->getClientVersion() < ES_3_1)
1157 {
jchen10d9cd7b72017-08-30 15:04:25 +08001158 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen10880683b2017-04-12 16:21:55 +08001159 return false;
1160 }
1161
1162 Program *programObject = GetValidProgram(context, program);
1163 if (programObject == nullptr)
1164 {
1165 return false;
1166 }
1167 if (!ValidateProgramInterface(programInterface))
1168 {
1169 context->handleError(InvalidEnum() << "Invalid program interface.");
1170 return false;
1171 }
1172 if (propCount <= 0)
1173 {
1174 context->handleError(InvalidValue() << "Invalid propCount.");
1175 return false;
1176 }
1177 if (bufSize < 0)
1178 {
1179 context->handleError(InvalidValue() << "Invalid bufSize.");
1180 return false;
1181 }
1182 if (!ValidateProgramResourceIndex(programObject, programInterface, index))
1183 {
1184 context->handleError(InvalidValue() << "Invalid index: " << index);
1185 return false;
1186 }
1187 for (GLsizei i = 0; i < propCount; i++)
1188 {
1189 if (!ValidateProgramResourceProperty(props[i]))
1190 {
1191 context->handleError(InvalidEnum() << "Invalid prop.");
1192 return false;
1193 }
1194 if (!ValidateProgramResourcePropertyByInterface(props[i], programInterface))
1195 {
1196 context->handleError(InvalidOperation() << "Not an allowed prop for interface");
1197 return false;
1198 }
1199 }
1200 return true;
1201}
1202
jchen10d9cd7b72017-08-30 15:04:25 +08001203bool ValidateGetProgramInterfaceiv(Context *context,
1204 GLuint program,
1205 GLenum programInterface,
1206 GLenum pname,
1207 GLint *params)
1208{
1209 if (context->getClientVersion() < ES_3_1)
1210 {
1211 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1212 return false;
1213 }
1214
1215 Program *programObject = GetValidProgram(context, program);
1216 if (programObject == nullptr)
1217 {
1218 return false;
1219 }
1220
1221 if (!ValidateProgramInterface(programInterface))
1222 {
1223 context->handleError(InvalidEnum() << "Invalid program interface.");
1224 return false;
1225 }
1226
1227 switch (pname)
1228 {
1229 case GL_ACTIVE_RESOURCES:
1230 case GL_MAX_NAME_LENGTH:
1231 case GL_MAX_NUM_ACTIVE_VARIABLES:
1232 break;
1233
1234 default:
1235 context->handleError(InvalidEnum() << "Unknown property of program interface.");
1236 return false;
1237 }
1238
1239 if (pname == GL_MAX_NAME_LENGTH && programInterface == GL_ATOMIC_COUNTER_BUFFER)
1240 {
1241 context->handleError(InvalidOperation()
1242 << "Active atomic counter resources are not assigned name strings.");
1243 return false;
1244 }
1245
1246 if (pname == GL_MAX_NUM_ACTIVE_VARIABLES)
1247 {
1248 switch (programInterface)
1249 {
1250 case GL_ATOMIC_COUNTER_BUFFER:
1251 case GL_SHADER_STORAGE_BLOCK:
1252 case GL_UNIFORM_BLOCK:
1253 break;
1254
1255 default:
1256 context->handleError(
1257 InvalidOperation()
1258 << "MAX_NUM_ACTIVE_VARIABLES requires a buffer or block interface.");
1259 return false;
1260 }
1261 }
1262
1263 return true;
1264}
1265
Yunchao Hea336b902017-08-02 16:05:21 +08001266static bool ValidateGenOrDeleteES31(Context *context, GLint n)
1267{
1268 if (context->getClientVersion() < ES_3_1)
1269 {
1270 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1271 return false;
1272 }
1273
1274 return ValidateGenOrDelete(context, n);
1275}
1276
1277bool ValidateGenProgramPipelines(Context *context, GLint n, GLuint *)
1278{
1279 return ValidateGenOrDeleteES31(context, n);
1280}
1281
1282bool ValidateDeleteProgramPipelines(Context *context, GLint n, const GLuint *)
1283{
1284 return ValidateGenOrDeleteES31(context, n);
1285}
1286
1287bool ValidateBindProgramPipeline(Context *context, GLuint pipeline)
1288{
1289 if (context->getClientVersion() < ES_3_1)
1290 {
1291 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1292 return false;
1293 }
1294
1295 if (!context->isProgramPipelineGenerated(pipeline))
1296 {
1297 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
1298 return false;
1299 }
1300
1301 return true;
1302}
1303
1304bool ValidateIsProgramPipeline(Context *context, GLuint pipeline)
1305{
1306 if (context->getClientVersion() < ES_3_1)
1307 {
1308 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1309 return false;
1310 }
1311
1312 return true;
1313}
1314
Martin Radev66fb8202016-07-28 11:45:20 +03001315} // namespace gl