blob: d44d17fa04f21460036d1050d14429176010a02c [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
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800263 case GL_BUFFER_VARIABLE:
264 return (index < static_cast<GLuint>(programObject->getActiveBufferVariableCount()));
265
266 case GL_SHADER_STORAGE_BLOCK:
267 return (index < static_cast<GLuint>(programObject->getActiveShaderStorageBlockCount()));
268
jchen10fd7c3b52017-03-21 15:36:03 +0800269 case GL_UNIFORM_BLOCK:
jchen1058f67be2017-10-27 08:59:27 +0800270 return (index < programObject->getActiveUniformBlockCount());
271
272 case GL_ATOMIC_COUNTER_BUFFER:
273 return (index < programObject->getActiveAtomicCounterBufferCount());
274
275 // TODO(jie.a.chen@intel.com): more interfaces.
jchen10fd7c3b52017-03-21 15:36:03 +0800276 case GL_TRANSFORM_FEEDBACK_VARYING:
jchen10fd7c3b52017-03-21 15:36:03 +0800277 UNIMPLEMENTED();
278 return false;
279
280 default:
281 UNREACHABLE();
282 return false;
283 }
284}
285
jchen1015015f72017-03-16 13:54:21 +0800286} // anonymous namespace
287
Martin Radev66fb8202016-07-28 11:45:20 +0300288bool ValidateGetBooleani_v(Context *context, GLenum target, GLuint index, GLboolean *data)
289{
Geoff Langeb66a6e2016-10-31 13:06:12 -0400290 if (context->getClientVersion() < ES_3_1)
Martin Radev66fb8202016-07-28 11:45:20 +0300291 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700292 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Martin Radev66fb8202016-07-28 11:45:20 +0300293 return false;
294 }
295
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400296 if (!ValidateIndexedStateQuery(context, target, index, nullptr))
297 {
298 return false;
299 }
300
301 return true;
302}
303
304bool ValidateGetBooleani_vRobustANGLE(Context *context,
305 GLenum target,
306 GLuint index,
307 GLsizei bufSize,
308 GLsizei *length,
309 GLboolean *data)
310{
Geoff Langeb66a6e2016-10-31 13:06:12 -0400311 if (context->getClientVersion() < ES_3_1)
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400312 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700313 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400314 return false;
315 }
316
317 if (!ValidateRobustEntryPoint(context, bufSize))
318 {
319 return false;
320 }
321
322 if (!ValidateIndexedStateQuery(context, target, index, length))
323 {
324 return false;
325 }
326
327 if (!ValidateRobustBufferSize(context, bufSize, *length))
Martin Radev66fb8202016-07-28 11:45:20 +0300328 {
329 return false;
330 }
331
332 return true;
333}
334
Jamie Madill876429b2017-04-20 15:46:24 -0400335bool ValidateDrawIndirectBase(Context *context, GLenum mode, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800336{
337 if (context->getClientVersion() < ES_3_1)
338 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700339 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jiajia Qind9671222016-11-29 16:30:31 +0800340 return false;
341 }
342
343 // Here the third parameter 1 is only to pass the count validation.
344 if (!ValidateDrawBase(context, mode, 1))
345 {
346 return false;
347 }
348
349 const State &state = context->getGLState();
350
351 // An INVALID_OPERATION error is generated if zero is bound to VERTEX_ARRAY_BINDING,
352 // DRAW_INDIRECT_BUFFER or to any enabled vertex array.
353 if (!state.getVertexArrayId())
354 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500355 context->handleError(InvalidOperation() << "zero is bound to VERTEX_ARRAY_BINDING");
Jiajia Qind9671222016-11-29 16:30:31 +0800356 return false;
357 }
358
Corentin Wallez336129f2017-10-17 15:55:40 -0400359 gl::Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
Jiajia Qind9671222016-11-29 16:30:31 +0800360 if (!drawIndirectBuffer)
361 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500362 context->handleError(InvalidOperation() << "zero is bound to DRAW_INDIRECT_BUFFER");
Jiajia Qind9671222016-11-29 16:30:31 +0800363 return false;
364 }
365
366 // An INVALID_VALUE error is generated if indirect is not a multiple of the size, in basic
367 // machine units, of uint.
368 GLint64 offset = reinterpret_cast<GLint64>(indirect);
369 if ((static_cast<GLuint>(offset) % sizeof(GLuint)) != 0)
370 {
371 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500372 InvalidValue()
373 << "indirect is not a multiple of the size, in basic machine units, of uint");
Jiajia Qind9671222016-11-29 16:30:31 +0800374 return false;
375 }
376
Martin Radev14a26ae2017-07-24 15:56:29 +0300377 // ANGLE_multiview spec, revision 1:
378 // An INVALID_OPERATION is generated by DrawArraysIndirect and DrawElementsIndirect if the
379 // number of views in the draw framebuffer is greater than 1.
380 const Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
381 ASSERT(drawFramebuffer != nullptr);
382 if (drawFramebuffer->getNumViews() > 1)
383 {
384 context->handleError(
385 InvalidOperation()
386 << "The number of views in the active draw framebuffer is greater than 1.");
387 return false;
388 }
389
Jiajia Qind9671222016-11-29 16:30:31 +0800390 return true;
391}
392
Jamie Madill876429b2017-04-20 15:46:24 -0400393bool ValidateDrawArraysIndirect(Context *context, GLenum mode, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800394{
395 const State &state = context->getGLState();
396 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
397 if (curTransformFeedback && curTransformFeedback->isActive() &&
398 !curTransformFeedback->isPaused())
399 {
400 // An INVALID_OPERATION error is generated if transform feedback is active and not paused.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500401 context->handleError(InvalidOperation() << "transform feedback is active and not paused.");
Jiajia Qind9671222016-11-29 16:30:31 +0800402 return false;
403 }
404
405 if (!ValidateDrawIndirectBase(context, mode, indirect))
406 return false;
407
Corentin Wallez336129f2017-10-17 15:55:40 -0400408 gl::Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
Jiajia Qind9671222016-11-29 16:30:31 +0800409 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
410 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawArraysIndirectCommand
411 // which's size is 4 * sizeof(uint).
412 auto checkedSum = checkedOffset + 4 * sizeof(GLuint);
413 if (!checkedSum.IsValid() ||
414 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
415 {
416 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500417 InvalidOperation()
418 << "the command would source data beyond the end of the buffer object.");
Jiajia Qind9671222016-11-29 16:30:31 +0800419 return false;
420 }
421
422 return true;
423}
424
Jamie Madill876429b2017-04-20 15:46:24 -0400425bool ValidateDrawElementsIndirect(Context *context, GLenum mode, GLenum type, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800426{
427 if (!ValidateDrawElementsBase(context, type))
428 return false;
429
430 const State &state = context->getGLState();
431 const VertexArray *vao = state.getVertexArray();
432 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
433 if (!elementArrayBuffer)
434 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500435 context->handleError(InvalidOperation() << "zero is bound to ELEMENT_ARRAY_BUFFER");
Jiajia Qind9671222016-11-29 16:30:31 +0800436 return false;
437 }
438
439 if (!ValidateDrawIndirectBase(context, mode, indirect))
440 return false;
441
Corentin Wallez336129f2017-10-17 15:55:40 -0400442 gl::Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
Jiajia Qind9671222016-11-29 16:30:31 +0800443 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
444 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawElementsIndirectCommand
445 // which's size is 5 * sizeof(uint).
446 auto checkedSum = checkedOffset + 5 * sizeof(GLuint);
447 if (!checkedSum.IsValid() ||
448 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
449 {
450 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500451 InvalidOperation()
452 << "the command would source data beyond the end of the buffer object.");
Jiajia Qind9671222016-11-29 16:30:31 +0800453 return false;
454 }
455
456 return true;
457}
458
He Yunchao11b038b2016-11-22 21:24:04 +0800459bool ValidateGetTexLevelParameterBase(Context *context,
460 GLenum target,
461 GLint level,
462 GLenum pname,
463 GLsizei *length)
464{
465 if (context->getClientVersion() < ES_3_1)
466 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700467 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
He Yunchao11b038b2016-11-22 21:24:04 +0800468 return false;
469 }
470
471 if (length)
472 {
473 *length = 0;
474 }
475
476 if (!ValidTexLevelDestinationTarget(context, target))
477 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700478 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
He Yunchao11b038b2016-11-22 21:24:04 +0800479 return false;
480 }
481
482 if (context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target) ==
483 nullptr)
484 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500485 context->handleError(InvalidEnum() << "No texture bound.");
He Yunchao11b038b2016-11-22 21:24:04 +0800486 return false;
487 }
488
489 if (!ValidMipLevel(context, target, level))
490 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500491 context->handleError(InvalidValue());
He Yunchao11b038b2016-11-22 21:24:04 +0800492 return false;
493 }
494
495 switch (pname)
496 {
497 case GL_TEXTURE_RED_TYPE:
498 case GL_TEXTURE_GREEN_TYPE:
499 case GL_TEXTURE_BLUE_TYPE:
500 case GL_TEXTURE_ALPHA_TYPE:
501 case GL_TEXTURE_DEPTH_TYPE:
502 break;
503 case GL_TEXTURE_RED_SIZE:
504 case GL_TEXTURE_GREEN_SIZE:
505 case GL_TEXTURE_BLUE_SIZE:
506 case GL_TEXTURE_ALPHA_SIZE:
507 case GL_TEXTURE_DEPTH_SIZE:
508 case GL_TEXTURE_STENCIL_SIZE:
509 case GL_TEXTURE_SHARED_SIZE:
510 break;
511 case GL_TEXTURE_INTERNAL_FORMAT:
512 case GL_TEXTURE_WIDTH:
513 case GL_TEXTURE_HEIGHT:
514 case GL_TEXTURE_DEPTH:
515 break;
516 case GL_TEXTURE_SAMPLES:
517 case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
518 break;
519 case GL_TEXTURE_COMPRESSED:
520 break;
521 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700522 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
He Yunchao11b038b2016-11-22 21:24:04 +0800523 return false;
524 }
525
526 if (length)
527 {
528 *length = 1;
529 }
530 return true;
531}
532
533bool ValidateGetTexLevelParameterfv(Context *context,
534 GLenum target,
535 GLint level,
536 GLenum pname,
537 GLfloat *params)
538{
539 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
540}
541
542bool ValidateGetTexLevelParameteriv(Context *context,
543 GLenum target,
544 GLint level,
545 GLenum pname,
546 GLint *params)
547{
548 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
549}
550
JiangYizhoubddc46b2016-12-09 09:50:51 +0800551bool ValidateTexStorage2DMultiSample(Context *context,
552 GLenum target,
553 GLsizei samples,
554 GLint internalFormat,
555 GLsizei width,
556 GLsizei height,
557 GLboolean fixedSampleLocations)
558{
559 if (context->getClientVersion() < ES_3_1)
560 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700561 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhoubddc46b2016-12-09 09:50:51 +0800562 return false;
563 }
564
565 if (target != GL_TEXTURE_2D_MULTISAMPLE)
566 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500567 context->handleError(InvalidEnum() << "Target must be TEXTURE_2D_MULTISAMPLE.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800568 return false;
569 }
570
571 if (width < 1 || height < 1)
572 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700573 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
JiangYizhoubddc46b2016-12-09 09:50:51 +0800574 return false;
575 }
576
577 const Caps &caps = context->getCaps();
578 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
579 static_cast<GLuint>(height) > caps.max2DTextureSize)
580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500581 context
582 ->handleError(InvalidValue()
583 << "Width and height must be less than or equal to GL_MAX_TEXTURE_SIZE.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800584 return false;
585 }
586
587 if (samples == 0)
588 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500589 context->handleError(InvalidValue() << "Samples may not be zero.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800590 return false;
591 }
592
593 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
594 if (!formatCaps.renderable)
595 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500596 context->handleError(InvalidEnum() << "SizedInternalformat must be color-renderable, "
597 "depth-renderable, or stencil-renderable.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800598 return false;
599 }
600
601 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
602 // is one of the unsized base internalformats listed in table 8.11.
Geoff Langca271392017-04-05 12:30:00 -0400603 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
604 if (formatInfo.internalFormat == GL_NONE)
JiangYizhoubddc46b2016-12-09 09:50:51 +0800605 {
606 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500607 InvalidEnum()
608 << "Internalformat is one of the unsupported unsized base internalformats.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800609 return false;
610 }
611
612 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
613 {
614 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500615 InvalidOperation()
616 << "Samples must not be greater than maximum supported value for the format.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800617 return false;
618 }
619
620 Texture *texture = context->getTargetTexture(target);
621 if (!texture || texture->id() == 0)
622 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500623 context->handleError(InvalidOperation() << "Zero is bound to target.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800624 return false;
625 }
626
627 if (texture->getImmutableFormat())
628 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500629 context->handleError(InvalidOperation() << "The value of TEXTURE_IMMUTABLE_FORMAT for "
630 "the texture currently bound to target on "
631 "the active texture unit is true.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800632 return false;
633 }
634
635 return true;
636}
637
638bool ValidateGetMultisamplefv(Context *context, GLenum pname, GLuint index, GLfloat *val)
639{
640 if (context->getClientVersion() < ES_3_1)
641 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700642 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhoubddc46b2016-12-09 09:50:51 +0800643 return false;
644 }
645
646 if (pname != GL_SAMPLE_POSITION)
647 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500648 context->handleError(InvalidEnum() << "Pname must be SAMPLE_POSITION.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800649 return false;
650 }
651
JiangYizhou5b03f472017-01-09 10:22:53 +0800652 Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
653
654 if (index >= static_cast<GLuint>(framebuffer->getSamples(context)))
JiangYizhoubddc46b2016-12-09 09:50:51 +0800655 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500656 context->handleError(InvalidValue() << "Index must be less than the value of SAMPLES.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800657 return false;
658 }
659
660 return true;
661}
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800662
663bool ValidationFramebufferParameteri(Context *context, GLenum target, GLenum pname, GLint param)
664{
665 if (context->getClientVersion() < ES_3_1)
666 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700667 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800668 return false;
669 }
670
671 if (!ValidFramebufferTarget(target))
672 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500673 context->handleError(InvalidEnum() << "Invalid framebuffer target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800674 return false;
675 }
676
677 switch (pname)
678 {
679 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
680 {
681 GLint maxWidth = context->getCaps().maxFramebufferWidth;
682 if (param < 0 || param > maxWidth)
683 {
684 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500685 InvalidValue()
686 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_WIDTH.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800687 return false;
688 }
689 break;
690 }
691 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
692 {
693 GLint maxHeight = context->getCaps().maxFramebufferHeight;
694 if (param < 0 || param > maxHeight)
695 {
696 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500697 InvalidValue()
698 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_HEIGHT.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800699 return false;
700 }
701 break;
702 }
703 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
704 {
705 GLint maxSamples = context->getCaps().maxFramebufferSamples;
706 if (param < 0 || param > maxSamples)
707 {
708 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500709 InvalidValue()
710 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_SAMPLES.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800711 return false;
712 }
713 break;
714 }
715 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
716 {
717 break;
718 }
719 default:
720 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700721 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800722 return false;
723 }
724 }
725
726 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
727 ASSERT(framebuffer);
728 if (framebuffer->id() == 0)
729 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500730 context->handleError(InvalidOperation() << "Default framebuffer is bound to target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800731 return false;
732 }
733 return true;
734}
735
736bool ValidationGetFramebufferParameteri(Context *context,
737 GLenum target,
738 GLenum pname,
739 GLint *params)
740{
741 if (context->getClientVersion() < ES_3_1)
742 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700743 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800744 return false;
745 }
746
747 if (!ValidFramebufferTarget(target))
748 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700749 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800750 return false;
751 }
752
753 switch (pname)
754 {
755 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
756 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
757 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
758 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
759 break;
760 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700761 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800762 return false;
763 }
764
765 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
766 ASSERT(framebuffer);
767
768 if (framebuffer->id() == 0)
769 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500770 context->handleError(InvalidOperation() << "Default framebuffer is bound to target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800771 return false;
772 }
773 return true;
774}
775
jchen1015015f72017-03-16 13:54:21 +0800776bool ValidateGetProgramResourceIndex(Context *context,
777 GLuint program,
778 GLenum programInterface,
779 const GLchar *name)
780{
781 if (context->getClientVersion() < ES_3_1)
782 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700783 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen1015015f72017-03-16 13:54:21 +0800784 return false;
785 }
786
787 Program *programObject = GetValidProgram(context, program);
788 if (programObject == nullptr)
789 {
790 return false;
791 }
792
793 if (!ValidateNamedProgramInterface(programInterface))
794 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500795 context->handleError(InvalidEnum() << "Invalid program interface: 0x" << std::hex
796 << std::uppercase << programInterface);
jchen1015015f72017-03-16 13:54:21 +0800797 return false;
798 }
Shao80957d92017-02-20 21:25:59 +0800799
800 return true;
801}
802
803bool ValidateBindVertexBuffer(ValidationContext *context,
804 GLuint bindingIndex,
805 GLuint buffer,
806 GLintptr offset,
807 GLsizei stride)
808{
809 if (context->getClientVersion() < ES_3_1)
810 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700811 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +0800812 return false;
813 }
814
815 if (!context->isBufferGenerated(buffer))
816 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500817 context->handleError(InvalidOperation() << "Buffer is not generated.");
Shao80957d92017-02-20 21:25:59 +0800818 return false;
819 }
820
821 const Caps &caps = context->getCaps();
822 if (bindingIndex >= caps.maxVertexAttribBindings)
823 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500824 context->handleError(InvalidValue()
825 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +0800826 return false;
827 }
828
829 if (offset < 0)
830 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700831 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Shao80957d92017-02-20 21:25:59 +0800832 return false;
833 }
834
835 if (stride < 0 || stride > caps.maxVertexAttribStride)
836 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500837 context->handleError(InvalidValue()
838 << "stride must be between 0 and MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +0800839 return false;
840 }
841
842 // [OpenGL ES 3.1] Section 10.3.1 page 244:
843 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
844 if (context->getGLState().getVertexArrayId() == 0)
845 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500846 context->handleError(InvalidOperation() << "Default vertex array buffer is bound.");
Shao80957d92017-02-20 21:25:59 +0800847 return false;
848 }
849
850 return true;
851}
852
853bool ValidateVertexBindingDivisor(ValidationContext *context, GLuint bindingIndex, GLuint divisor)
854{
855 if (context->getClientVersion() < ES_3_1)
856 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700857 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +0800858 return false;
859 }
860
861 const Caps &caps = context->getCaps();
862 if (bindingIndex >= caps.maxVertexAttribBindings)
863 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500864 context->handleError(InvalidValue()
865 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +0800866 return false;
867 }
868
869 // [OpenGL ES 3.1] Section 10.3.1 page 243:
870 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
871 if (context->getGLState().getVertexArrayId() == 0)
872 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500873 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +0800874 return false;
875 }
876
877 return true;
878}
879
880bool ValidateVertexAttribFormat(ValidationContext *context,
881 GLuint attribIndex,
882 GLint size,
883 GLenum type,
884 GLuint relativeOffset,
885 GLboolean pureInteger)
886{
887 if (context->getClientVersion() < ES_3_1)
888 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700889 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +0800890 return false;
891 }
892
893 const Caps &caps = context->getCaps();
894 if (relativeOffset > static_cast<GLuint>(caps.maxVertexAttribRelativeOffset))
895 {
896 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500897 InvalidValue()
898 << "relativeOffset cannot be greater than MAX_VERTEX_ATTRIB_RELATIVE_OFFSET.");
Shao80957d92017-02-20 21:25:59 +0800899 return false;
900 }
901
902 // [OpenGL ES 3.1] Section 10.3.1 page 243:
903 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
904 if (context->getGLState().getVertexArrayId() == 0)
905 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500906 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +0800907 return false;
908 }
909
910 return ValidateVertexFormatBase(context, attribIndex, size, type, pureInteger);
911}
912
913bool ValidateVertexAttribBinding(ValidationContext *context,
914 GLuint attribIndex,
915 GLuint bindingIndex)
916{
917 if (context->getClientVersion() < ES_3_1)
918 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700919 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +0800920 return false;
921 }
922
923 // [OpenGL ES 3.1] Section 10.3.1 page 243:
924 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
925 if (context->getGLState().getVertexArrayId() == 0)
926 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500927 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +0800928 return false;
929 }
930
931 const Caps &caps = context->getCaps();
932 if (attribIndex >= caps.maxVertexAttributes)
933 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700934 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +0800935 return false;
936 }
937
938 if (bindingIndex >= caps.maxVertexAttribBindings)
939 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500940 context->handleError(InvalidValue()
941 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS");
Shao80957d92017-02-20 21:25:59 +0800942 return false;
943 }
944
jchen1015015f72017-03-16 13:54:21 +0800945 return true;
946}
947
jchen10fd7c3b52017-03-21 15:36:03 +0800948bool ValidateGetProgramResourceName(Context *context,
949 GLuint program,
950 GLenum programInterface,
951 GLuint index,
952 GLsizei bufSize,
953 GLsizei *length,
954 GLchar *name)
955{
956 if (context->getClientVersion() < ES_3_1)
957 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700958 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen10fd7c3b52017-03-21 15:36:03 +0800959 return false;
960 }
961
962 Program *programObject = GetValidProgram(context, program);
963 if (programObject == nullptr)
964 {
965 return false;
966 }
967
968 if (!ValidateNamedProgramInterface(programInterface))
969 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500970 context->handleError(InvalidEnum() << "Invalid program interface: 0x" << std::hex
971 << std::uppercase << programInterface);
jchen10fd7c3b52017-03-21 15:36:03 +0800972 return false;
973 }
974
975 if (!ValidateProgramResourceIndex(programObject, programInterface, index))
976 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500977 context->handleError(InvalidValue() << "Invalid index: " << index);
jchen10fd7c3b52017-03-21 15:36:03 +0800978 return false;
979 }
980
981 if (bufSize < 0)
982 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700983 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
jchen10fd7c3b52017-03-21 15:36:03 +0800984 return false;
985 }
986
987 return true;
988}
989
Xinghua Cao2b396592017-03-29 15:36:04 +0800990bool ValidateDispatchCompute(Context *context,
991 GLuint numGroupsX,
992 GLuint numGroupsY,
993 GLuint numGroupsZ)
994{
995 if (context->getClientVersion() < ES_3_1)
996 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700997 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Xinghua Cao2b396592017-03-29 15:36:04 +0800998 return false;
999 }
1000
1001 const State &state = context->getGLState();
1002 Program *program = state.getProgram();
1003
1004 if (program == nullptr)
1005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001006 context->handleError(InvalidOperation()
1007 << "No active program object for the compute shader stage.");
Xinghua Cao2b396592017-03-29 15:36:04 +08001008 return false;
1009 }
1010
1011 if (program->isLinked() == false || program->getAttachedComputeShader() == nullptr)
1012 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001013 context->handleError(
1014 InvalidOperation()
1015 << "Program has not been successfully linked, or program contains no compute shaders.");
Xinghua Cao2b396592017-03-29 15:36:04 +08001016 return false;
1017 }
1018
1019 const Caps &caps = context->getCaps();
1020 if (numGroupsX > caps.maxComputeWorkGroupCount[0])
1021 {
1022 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001023 InvalidValue() << "num_groups_x cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[0]="
1024 << caps.maxComputeWorkGroupCount[0]);
Xinghua Cao2b396592017-03-29 15:36:04 +08001025 return false;
1026 }
1027 if (numGroupsY > caps.maxComputeWorkGroupCount[1])
1028 {
1029 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001030 InvalidValue() << "num_groups_y cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[1]="
1031 << caps.maxComputeWorkGroupCount[1]);
Xinghua Cao2b396592017-03-29 15:36:04 +08001032 return false;
1033 }
1034 if (numGroupsZ > caps.maxComputeWorkGroupCount[2])
1035 {
1036 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001037 InvalidValue() << "num_groups_z cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[2]="
1038 << caps.maxComputeWorkGroupCount[2]);
Xinghua Cao2b396592017-03-29 15:36:04 +08001039 return false;
1040 }
1041
1042 return true;
1043}
1044
Xinghua Cao65ec0b22017-03-28 16:10:52 +08001045bool ValidateBindImageTexture(Context *context,
1046 GLuint unit,
1047 GLuint texture,
1048 GLint level,
1049 GLboolean layered,
1050 GLint layer,
1051 GLenum access,
1052 GLenum format)
1053{
1054 GLuint maxImageUnits = context->getCaps().maxImageUnits;
1055 if (unit >= maxImageUnits)
1056 {
1057 context->handleError(InvalidValue()
1058 << "unit cannot be greater than or equal than MAX_IMAGE_UNITS = "
1059 << maxImageUnits);
1060 return false;
1061 }
1062
1063 if (level < 0)
1064 {
1065 context->handleError(InvalidValue() << "level is negative.");
1066 return false;
1067 }
1068
1069 if (layer < 0)
1070 {
1071 context->handleError(InvalidValue() << "layer is negative.");
1072 return false;
1073 }
1074
1075 if (access != GL_READ_ONLY && access != GL_WRITE_ONLY && access != GL_READ_WRITE)
1076 {
1077 context->handleError(InvalidEnum() << "access is not one of the supported tokens.");
1078 return false;
1079 }
1080
1081 switch (format)
1082 {
1083 case GL_RGBA32F:
1084 case GL_RGBA16F:
1085 case GL_R32F:
1086 case GL_RGBA32UI:
1087 case GL_RGBA16UI:
1088 case GL_RGBA8UI:
1089 case GL_R32UI:
1090 case GL_RGBA32I:
1091 case GL_RGBA16I:
1092 case GL_RGBA8I:
1093 case GL_R32I:
1094 case GL_RGBA8:
1095 case GL_RGBA8_SNORM:
1096 break;
1097 default:
1098 context->handleError(InvalidValue()
1099 << "format is not one of supported image unit formats.");
1100 return false;
1101 }
1102
1103 if (texture != 0)
1104 {
1105 Texture *tex = context->getTexture(texture);
1106
1107 if (tex == nullptr)
1108 {
1109 context->handleError(InvalidValue()
1110 << "texture is not the name of an existing texture object.");
1111 return false;
1112 }
1113
1114 if (!tex->getImmutableFormat())
1115 {
1116 context->handleError(InvalidOperation()
1117 << "texture is not the name of an immutable texture object.");
1118 return false;
1119 }
1120 }
1121
1122 return true;
1123}
jchen10191381f2017-04-11 13:59:04 +08001124
1125bool ValidateGetProgramResourceLocation(Context *context,
1126 GLuint program,
1127 GLenum programInterface,
1128 const GLchar *name)
1129{
1130 if (context->getClientVersion() < ES_3_1)
1131 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001132 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen10191381f2017-04-11 13:59:04 +08001133 return false;
1134 }
1135
1136 Program *programObject = GetValidProgram(context, program);
1137 if (programObject == nullptr)
1138 {
1139 return false;
1140 }
1141
1142 if (!programObject->isLinked())
1143 {
1144 context->handleError(InvalidOperation() << "Program is not successfully linked.");
1145 return false;
1146 }
1147
1148 if (!ValidateLocationProgramInterface(programInterface))
1149 {
1150 context->handleError(InvalidEnum() << "Invalid program interface.");
1151 return false;
1152 }
1153 return true;
1154}
1155
jchen10880683b2017-04-12 16:21:55 +08001156bool ValidateGetProgramResourceiv(Context *context,
1157 GLuint program,
1158 GLenum programInterface,
1159 GLuint index,
1160 GLsizei propCount,
1161 const GLenum *props,
1162 GLsizei bufSize,
1163 GLsizei *length,
1164 GLint *params)
1165{
1166 if (context->getClientVersion() < ES_3_1)
1167 {
jchen10d9cd7b72017-08-30 15:04:25 +08001168 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen10880683b2017-04-12 16:21:55 +08001169 return false;
1170 }
1171
1172 Program *programObject = GetValidProgram(context, program);
1173 if (programObject == nullptr)
1174 {
1175 return false;
1176 }
1177 if (!ValidateProgramInterface(programInterface))
1178 {
1179 context->handleError(InvalidEnum() << "Invalid program interface.");
1180 return false;
1181 }
1182 if (propCount <= 0)
1183 {
1184 context->handleError(InvalidValue() << "Invalid propCount.");
1185 return false;
1186 }
1187 if (bufSize < 0)
1188 {
1189 context->handleError(InvalidValue() << "Invalid bufSize.");
1190 return false;
1191 }
1192 if (!ValidateProgramResourceIndex(programObject, programInterface, index))
1193 {
1194 context->handleError(InvalidValue() << "Invalid index: " << index);
1195 return false;
1196 }
1197 for (GLsizei i = 0; i < propCount; i++)
1198 {
1199 if (!ValidateProgramResourceProperty(props[i]))
1200 {
1201 context->handleError(InvalidEnum() << "Invalid prop.");
1202 return false;
1203 }
1204 if (!ValidateProgramResourcePropertyByInterface(props[i], programInterface))
1205 {
1206 context->handleError(InvalidOperation() << "Not an allowed prop for interface");
1207 return false;
1208 }
1209 }
1210 return true;
1211}
1212
jchen10d9cd7b72017-08-30 15:04:25 +08001213bool ValidateGetProgramInterfaceiv(Context *context,
1214 GLuint program,
1215 GLenum programInterface,
1216 GLenum pname,
1217 GLint *params)
1218{
1219 if (context->getClientVersion() < ES_3_1)
1220 {
1221 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1222 return false;
1223 }
1224
1225 Program *programObject = GetValidProgram(context, program);
1226 if (programObject == nullptr)
1227 {
1228 return false;
1229 }
1230
1231 if (!ValidateProgramInterface(programInterface))
1232 {
1233 context->handleError(InvalidEnum() << "Invalid program interface.");
1234 return false;
1235 }
1236
1237 switch (pname)
1238 {
1239 case GL_ACTIVE_RESOURCES:
1240 case GL_MAX_NAME_LENGTH:
1241 case GL_MAX_NUM_ACTIVE_VARIABLES:
1242 break;
1243
1244 default:
1245 context->handleError(InvalidEnum() << "Unknown property of program interface.");
1246 return false;
1247 }
1248
1249 if (pname == GL_MAX_NAME_LENGTH && programInterface == GL_ATOMIC_COUNTER_BUFFER)
1250 {
1251 context->handleError(InvalidOperation()
1252 << "Active atomic counter resources are not assigned name strings.");
1253 return false;
1254 }
1255
1256 if (pname == GL_MAX_NUM_ACTIVE_VARIABLES)
1257 {
1258 switch (programInterface)
1259 {
1260 case GL_ATOMIC_COUNTER_BUFFER:
1261 case GL_SHADER_STORAGE_BLOCK:
1262 case GL_UNIFORM_BLOCK:
1263 break;
1264
1265 default:
1266 context->handleError(
1267 InvalidOperation()
1268 << "MAX_NUM_ACTIVE_VARIABLES requires a buffer or block interface.");
1269 return false;
1270 }
1271 }
1272
1273 return true;
1274}
1275
Yunchao Hea336b902017-08-02 16:05:21 +08001276static bool ValidateGenOrDeleteES31(Context *context, GLint n)
1277{
1278 if (context->getClientVersion() < ES_3_1)
1279 {
1280 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1281 return false;
1282 }
1283
1284 return ValidateGenOrDelete(context, n);
1285}
1286
1287bool ValidateGenProgramPipelines(Context *context, GLint n, GLuint *)
1288{
1289 return ValidateGenOrDeleteES31(context, n);
1290}
1291
1292bool ValidateDeleteProgramPipelines(Context *context, GLint n, const GLuint *)
1293{
1294 return ValidateGenOrDeleteES31(context, n);
1295}
1296
1297bool ValidateBindProgramPipeline(Context *context, GLuint pipeline)
1298{
1299 if (context->getClientVersion() < ES_3_1)
1300 {
1301 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1302 return false;
1303 }
1304
1305 if (!context->isProgramPipelineGenerated(pipeline))
1306 {
1307 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
1308 return false;
1309 }
1310
1311 return true;
1312}
1313
1314bool ValidateIsProgramPipeline(Context *context, GLuint pipeline)
1315{
1316 if (context->getClientVersion() < ES_3_1)
1317 {
1318 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1319 return false;
1320 }
1321
1322 return true;
1323}
1324
Jiawei Shaodb342272017-09-27 10:21:45 +08001325bool ValidateSampleMaski(Context *context, GLuint maskNumber)
1326{
1327 if (context->getClientVersion() < ES_3_1)
1328 {
1329 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1330 return false;
1331 }
1332
1333 if (maskNumber >= context->getCaps().maxSampleMaskWords)
1334 {
1335 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
1336 return false;
1337 }
1338
1339 return true;
1340}
1341
Martin Radev66fb8202016-07-28 11:45:20 +03001342} // namespace gl