blob: f9cf8d57bcaeed61acd9a996491f88f251e58f0c [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
jchen10fd7c3b52017-03-21 15:36:03 +0800275 case GL_TRANSFORM_FEEDBACK_VARYING:
jchen10910a3da2017-11-15 09:40:11 +0800276 return (index < static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()));
jchen10fd7c3b52017-03-21 15:36:03 +0800277
278 default:
279 UNREACHABLE();
280 return false;
281 }
282}
283
Jamie Madill5b772312018-03-08 20:28:32 -0500284bool ValidateProgramUniform(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +0800285 GLenum valueType,
286 GLuint program,
287 GLint location,
288 GLsizei count)
289{
290 // Check for ES31 program uniform entry points
291 if (context->getClientVersion() < Version(3, 1))
292 {
293 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
294 return false;
295 }
296
297 const LinkedUniform *uniform = nullptr;
Jamie Madill5b772312018-03-08 20:28:32 -0500298 Program *programObject = GetValidProgram(context, program);
Jiajia Qin5451d532017-11-16 17:16:34 +0800299 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
300 ValidateUniformValue(context, valueType, uniform->type);
301}
302
Jamie Madill5b772312018-03-08 20:28:32 -0500303bool ValidateProgramUniformMatrix(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +0800304 GLenum valueType,
305 GLuint program,
306 GLint location,
307 GLsizei count,
308 GLboolean transpose)
309{
310 // Check for ES31 program uniform entry points
311 if (context->getClientVersion() < Version(3, 1))
312 {
313 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
314 return false;
315 }
316
317 const LinkedUniform *uniform = nullptr;
Jamie Madill5b772312018-03-08 20:28:32 -0500318 Program *programObject = GetValidProgram(context, program);
Jiajia Qin5451d532017-11-16 17:16:34 +0800319 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
320 ValidateUniformMatrixValue(context, valueType, uniform->type);
321}
322
Jamie Madill5b772312018-03-08 20:28:32 -0500323bool ValidateVertexAttribFormatCommon(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +0800324 GLuint attribIndex,
325 GLint size,
326 GLenum type,
327 GLuint relativeOffset,
328 GLboolean pureInteger)
329{
330 if (context->getClientVersion() < ES_3_1)
331 {
332 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
333 return false;
334 }
335
336 const Caps &caps = context->getCaps();
337 if (relativeOffset > static_cast<GLuint>(caps.maxVertexAttribRelativeOffset))
338 {
339 context->handleError(
340 InvalidValue()
341 << "relativeOffset cannot be greater than MAX_VERTEX_ATTRIB_RELATIVE_OFFSET.");
342 return false;
343 }
344
345 // [OpenGL ES 3.1] Section 10.3.1 page 243:
346 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
347 if (context->getGLState().getVertexArrayId() == 0)
348 {
349 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
350 return false;
351 }
352
353 return ValidateVertexFormatBase(context, attribIndex, size, type, pureInteger);
354}
355
jchen1015015f72017-03-16 13:54:21 +0800356} // anonymous namespace
357
Martin Radev66fb8202016-07-28 11:45:20 +0300358bool ValidateGetBooleani_v(Context *context, GLenum target, GLuint index, GLboolean *data)
359{
Geoff Langeb66a6e2016-10-31 13:06:12 -0400360 if (context->getClientVersion() < ES_3_1)
Martin Radev66fb8202016-07-28 11:45:20 +0300361 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700362 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Martin Radev66fb8202016-07-28 11:45:20 +0300363 return false;
364 }
365
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400366 if (!ValidateIndexedStateQuery(context, target, index, nullptr))
367 {
368 return false;
369 }
370
371 return true;
372}
373
374bool ValidateGetBooleani_vRobustANGLE(Context *context,
375 GLenum target,
376 GLuint index,
377 GLsizei bufSize,
378 GLsizei *length,
379 GLboolean *data)
380{
Geoff Langeb66a6e2016-10-31 13:06:12 -0400381 if (context->getClientVersion() < ES_3_1)
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400382 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700383 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400384 return false;
385 }
386
387 if (!ValidateRobustEntryPoint(context, bufSize))
388 {
389 return false;
390 }
391
392 if (!ValidateIndexedStateQuery(context, target, index, length))
393 {
394 return false;
395 }
396
397 if (!ValidateRobustBufferSize(context, bufSize, *length))
Martin Radev66fb8202016-07-28 11:45:20 +0300398 {
399 return false;
400 }
401
402 return true;
403}
404
Jamie Madill876429b2017-04-20 15:46:24 -0400405bool ValidateDrawIndirectBase(Context *context, GLenum mode, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800406{
407 if (context->getClientVersion() < ES_3_1)
408 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700409 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jiajia Qind9671222016-11-29 16:30:31 +0800410 return false;
411 }
412
413 // Here the third parameter 1 is only to pass the count validation.
414 if (!ValidateDrawBase(context, mode, 1))
415 {
416 return false;
417 }
418
419 const State &state = context->getGLState();
420
421 // An INVALID_OPERATION error is generated if zero is bound to VERTEX_ARRAY_BINDING,
422 // DRAW_INDIRECT_BUFFER or to any enabled vertex array.
423 if (!state.getVertexArrayId())
424 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500425 context->handleError(InvalidOperation() << "zero is bound to VERTEX_ARRAY_BINDING");
Jiajia Qind9671222016-11-29 16:30:31 +0800426 return false;
427 }
428
Jamie Madill5b772312018-03-08 20:28:32 -0500429 Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
Jiajia Qind9671222016-11-29 16:30:31 +0800430 if (!drawIndirectBuffer)
431 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500432 context->handleError(InvalidOperation() << "zero is bound to DRAW_INDIRECT_BUFFER");
Jiajia Qind9671222016-11-29 16:30:31 +0800433 return false;
434 }
435
436 // An INVALID_VALUE error is generated if indirect is not a multiple of the size, in basic
437 // machine units, of uint.
438 GLint64 offset = reinterpret_cast<GLint64>(indirect);
439 if ((static_cast<GLuint>(offset) % sizeof(GLuint)) != 0)
440 {
441 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500442 InvalidValue()
443 << "indirect is not a multiple of the size, in basic machine units, of uint");
Jiajia Qind9671222016-11-29 16:30:31 +0800444 return false;
445 }
446
Martin Radev14a26ae2017-07-24 15:56:29 +0300447 // ANGLE_multiview spec, revision 1:
448 // An INVALID_OPERATION is generated by DrawArraysIndirect and DrawElementsIndirect if the
449 // number of views in the draw framebuffer is greater than 1.
450 const Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
451 ASSERT(drawFramebuffer != nullptr);
452 if (drawFramebuffer->getNumViews() > 1)
453 {
454 context->handleError(
455 InvalidOperation()
456 << "The number of views in the active draw framebuffer is greater than 1.");
457 return false;
458 }
459
Jiajia Qind9671222016-11-29 16:30:31 +0800460 return true;
461}
462
Jamie Madill876429b2017-04-20 15:46:24 -0400463bool ValidateDrawArraysIndirect(Context *context, GLenum mode, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800464{
465 const State &state = context->getGLState();
Jamie Madill5b772312018-03-08 20:28:32 -0500466 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Jiajia Qind9671222016-11-29 16:30:31 +0800467 if (curTransformFeedback && curTransformFeedback->isActive() &&
468 !curTransformFeedback->isPaused())
469 {
470 // An INVALID_OPERATION error is generated if transform feedback is active and not paused.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500471 context->handleError(InvalidOperation() << "transform feedback is active and not paused.");
Jiajia Qind9671222016-11-29 16:30:31 +0800472 return false;
473 }
474
475 if (!ValidateDrawIndirectBase(context, mode, indirect))
476 return false;
477
Jamie Madill5b772312018-03-08 20:28:32 -0500478 Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
Jiajia Qind9671222016-11-29 16:30:31 +0800479 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
480 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawArraysIndirectCommand
481 // which's size is 4 * sizeof(uint).
482 auto checkedSum = checkedOffset + 4 * sizeof(GLuint);
483 if (!checkedSum.IsValid() ||
484 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
485 {
486 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500487 InvalidOperation()
488 << "the command would source data beyond the end of the buffer object.");
Jiajia Qind9671222016-11-29 16:30:31 +0800489 return false;
490 }
491
492 return true;
493}
494
Jamie Madill876429b2017-04-20 15:46:24 -0400495bool ValidateDrawElementsIndirect(Context *context, GLenum mode, GLenum type, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800496{
497 if (!ValidateDrawElementsBase(context, type))
498 return false;
499
500 const State &state = context->getGLState();
501 const VertexArray *vao = state.getVertexArray();
Jamie Madill5b772312018-03-08 20:28:32 -0500502 Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jiajia Qind9671222016-11-29 16:30:31 +0800503 if (!elementArrayBuffer)
504 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500505 context->handleError(InvalidOperation() << "zero is bound to ELEMENT_ARRAY_BUFFER");
Jiajia Qind9671222016-11-29 16:30:31 +0800506 return false;
507 }
508
509 if (!ValidateDrawIndirectBase(context, mode, indirect))
510 return false;
511
Jamie Madill5b772312018-03-08 20:28:32 -0500512 Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
Jiajia Qind9671222016-11-29 16:30:31 +0800513 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
514 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawElementsIndirectCommand
515 // which's size is 5 * sizeof(uint).
516 auto checkedSum = checkedOffset + 5 * sizeof(GLuint);
517 if (!checkedSum.IsValid() ||
518 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
519 {
520 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500521 InvalidOperation()
522 << "the command would source data beyond the end of the buffer object.");
Jiajia Qind9671222016-11-29 16:30:31 +0800523 return false;
524 }
525
526 return true;
527}
528
Jiajia Qin5451d532017-11-16 17:16:34 +0800529bool ValidateProgramUniform1i(Context *context, GLuint program, GLint location, GLint v0)
530{
531 return ValidateProgramUniform1iv(context, program, location, 1, &v0);
532}
533
534bool ValidateProgramUniform2i(Context *context, GLuint program, GLint location, GLint v0, GLint v1)
535{
536 GLint xy[2] = {v0, v1};
537 return ValidateProgramUniform2iv(context, program, location, 1, xy);
538}
539
540bool ValidateProgramUniform3i(Context *context,
541 GLuint program,
542 GLint location,
543 GLint v0,
544 GLint v1,
545 GLint v2)
546{
547 GLint xyz[3] = {v0, v1, v2};
548 return ValidateProgramUniform3iv(context, program, location, 1, xyz);
549}
550
551bool ValidateProgramUniform4i(Context *context,
552 GLuint program,
553 GLint location,
554 GLint v0,
555 GLint v1,
556 GLint v2,
557 GLint v3)
558{
559 GLint xyzw[4] = {v0, v1, v2, v3};
560 return ValidateProgramUniform4iv(context, program, location, 1, xyzw);
561}
562
563bool ValidateProgramUniform1ui(Context *context, GLuint program, GLint location, GLuint v0)
564{
565 return ValidateProgramUniform1uiv(context, program, location, 1, &v0);
566}
567
568bool ValidateProgramUniform2ui(Context *context,
569 GLuint program,
570 GLint location,
571 GLuint v0,
572 GLuint v1)
573{
574 GLuint xy[2] = {v0, v1};
575 return ValidateProgramUniform2uiv(context, program, location, 1, xy);
576}
577
578bool ValidateProgramUniform3ui(Context *context,
579 GLuint program,
580 GLint location,
581 GLuint v0,
582 GLuint v1,
583 GLuint v2)
584{
585 GLuint xyz[3] = {v0, v1, v2};
586 return ValidateProgramUniform3uiv(context, program, location, 1, xyz);
587}
588
589bool ValidateProgramUniform4ui(Context *context,
590 GLuint program,
591 GLint location,
592 GLuint v0,
593 GLuint v1,
594 GLuint v2,
595 GLuint v3)
596{
597 GLuint xyzw[4] = {v0, v1, v2, v3};
598 return ValidateProgramUniform4uiv(context, program, location, 1, xyzw);
599}
600
601bool ValidateProgramUniform1f(Context *context, GLuint program, GLint location, GLfloat v0)
602{
603 return ValidateProgramUniform1fv(context, program, location, 1, &v0);
604}
605
606bool ValidateProgramUniform2f(Context *context,
607 GLuint program,
608 GLint location,
609 GLfloat v0,
610 GLfloat v1)
611{
612 GLfloat xy[2] = {v0, v1};
613 return ValidateProgramUniform2fv(context, program, location, 1, xy);
614}
615
616bool ValidateProgramUniform3f(Context *context,
617 GLuint program,
618 GLint location,
619 GLfloat v0,
620 GLfloat v1,
621 GLfloat v2)
622{
623 GLfloat xyz[3] = {v0, v1, v2};
624 return ValidateProgramUniform3fv(context, program, location, 1, xyz);
625}
626
627bool ValidateProgramUniform4f(Context *context,
628 GLuint program,
629 GLint location,
630 GLfloat v0,
631 GLfloat v1,
632 GLfloat v2,
633 GLfloat v3)
634{
635 GLfloat xyzw[4] = {v0, v1, v2, v3};
636 return ValidateProgramUniform4fv(context, program, location, 1, xyzw);
637}
638
639bool ValidateProgramUniform1iv(Context *context,
640 GLuint program,
641 GLint location,
642 GLsizei count,
643 const GLint *value)
644{
645 // Check for ES31 program uniform entry points
646 if (context->getClientVersion() < Version(3, 1))
647 {
648 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
649 return false;
650 }
651
652 const LinkedUniform *uniform = nullptr;
Jamie Madill5b772312018-03-08 20:28:32 -0500653 Program *programObject = GetValidProgram(context, program);
Jiajia Qin5451d532017-11-16 17:16:34 +0800654 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
655 ValidateUniform1ivValue(context, uniform->type, count, value);
656}
657
658bool ValidateProgramUniform2iv(Context *context,
659 GLuint program,
660 GLint location,
661 GLsizei count,
662 const GLint *value)
663{
664 return ValidateProgramUniform(context, GL_INT_VEC2, program, location, count);
665}
666
667bool ValidateProgramUniform3iv(Context *context,
668 GLuint program,
669 GLint location,
670 GLsizei count,
671 const GLint *value)
672{
673 return ValidateProgramUniform(context, GL_INT_VEC3, program, location, count);
674}
675
676bool ValidateProgramUniform4iv(Context *context,
677 GLuint program,
678 GLint location,
679 GLsizei count,
680 const GLint *value)
681{
682 return ValidateProgramUniform(context, GL_INT_VEC4, program, location, count);
683}
684
685bool ValidateProgramUniform1uiv(Context *context,
686 GLuint program,
687 GLint location,
688 GLsizei count,
689 const GLuint *value)
690{
691 return ValidateProgramUniform(context, GL_UNSIGNED_INT, program, location, count);
692}
693
694bool ValidateProgramUniform2uiv(Context *context,
695 GLuint program,
696 GLint location,
697 GLsizei count,
698 const GLuint *value)
699{
700 return ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC2, program, location, count);
701}
702
703bool ValidateProgramUniform3uiv(Context *context,
704 GLuint program,
705 GLint location,
706 GLsizei count,
707 const GLuint *value)
708{
709 return ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC3, program, location, count);
710}
711
712bool ValidateProgramUniform4uiv(Context *context,
713 GLuint program,
714 GLint location,
715 GLsizei count,
716 const GLuint *value)
717{
718 return ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC4, program, location, count);
719}
720
721bool ValidateProgramUniform1fv(Context *context,
722 GLuint program,
723 GLint location,
724 GLsizei count,
725 const GLfloat *value)
726{
727 return ValidateProgramUniform(context, GL_FLOAT, program, location, count);
728}
729
730bool ValidateProgramUniform2fv(Context *context,
731 GLuint program,
732 GLint location,
733 GLsizei count,
734 const GLfloat *value)
735{
736 return ValidateProgramUniform(context, GL_FLOAT_VEC2, program, location, count);
737}
738
739bool ValidateProgramUniform3fv(Context *context,
740 GLuint program,
741 GLint location,
742 GLsizei count,
743 const GLfloat *value)
744{
745 return ValidateProgramUniform(context, GL_FLOAT_VEC3, program, location, count);
746}
747
748bool ValidateProgramUniform4fv(Context *context,
749 GLuint program,
750 GLint location,
751 GLsizei count,
752 const GLfloat *value)
753{
754 return ValidateProgramUniform(context, GL_FLOAT_VEC4, program, location, count);
755}
756
757bool ValidateProgramUniformMatrix2fv(Context *context,
758 GLuint program,
759 GLint location,
760 GLsizei count,
761 GLboolean transpose,
762 const GLfloat *value)
763{
764 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2, program, location, count,
765 transpose);
766}
767
768bool ValidateProgramUniformMatrix3fv(Context *context,
769 GLuint program,
770 GLint location,
771 GLsizei count,
772 GLboolean transpose,
773 const GLfloat *value)
774{
775 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3, program, location, count,
776 transpose);
777}
778
779bool ValidateProgramUniformMatrix4fv(Context *context,
780 GLuint program,
781 GLint location,
782 GLsizei count,
783 GLboolean transpose,
784 const GLfloat *value)
785{
786 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4, program, location, count,
787 transpose);
788}
789
790bool ValidateProgramUniformMatrix2x3fv(Context *context,
791 GLuint program,
792 GLint location,
793 GLsizei count,
794 GLboolean transpose,
795 const GLfloat *value)
796{
797 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2x3, program, location, count,
798 transpose);
799}
800
801bool ValidateProgramUniformMatrix3x2fv(Context *context,
802 GLuint program,
803 GLint location,
804 GLsizei count,
805 GLboolean transpose,
806 const GLfloat *value)
807{
808 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3x2, program, location, count,
809 transpose);
810}
811
812bool ValidateProgramUniformMatrix2x4fv(Context *context,
813 GLuint program,
814 GLint location,
815 GLsizei count,
816 GLboolean transpose,
817 const GLfloat *value)
818{
819 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2x4, program, location, count,
820 transpose);
821}
822
823bool ValidateProgramUniformMatrix4x2fv(Context *context,
824 GLuint program,
825 GLint location,
826 GLsizei count,
827 GLboolean transpose,
828 const GLfloat *value)
829{
830 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4x2, program, location, count,
831 transpose);
832}
833
834bool ValidateProgramUniformMatrix3x4fv(Context *context,
835 GLuint program,
836 GLint location,
837 GLsizei count,
838 GLboolean transpose,
839 const GLfloat *value)
840{
841 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3x4, program, location, count,
842 transpose);
843}
844
845bool ValidateProgramUniformMatrix4x3fv(Context *context,
846 GLuint program,
847 GLint location,
848 GLsizei count,
849 GLboolean transpose,
850 const GLfloat *value)
851{
852 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4x3, program, location, count,
853 transpose);
854}
855
He Yunchao11b038b2016-11-22 21:24:04 +0800856bool ValidateGetTexLevelParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800857 TextureTarget target,
He Yunchao11b038b2016-11-22 21:24:04 +0800858 GLint level,
859 GLenum pname,
860 GLsizei *length)
861{
862 if (context->getClientVersion() < ES_3_1)
863 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700864 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
He Yunchao11b038b2016-11-22 21:24:04 +0800865 return false;
866 }
867
868 if (length)
869 {
870 *length = 0;
871 }
872
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800873 TextureType type = TextureTargetToType(target);
874
875 if (!ValidTexLevelDestinationTarget(context, type))
He Yunchao11b038b2016-11-22 21:24:04 +0800876 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700877 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
He Yunchao11b038b2016-11-22 21:24:04 +0800878 return false;
879 }
880
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800881 if (context->getTargetTexture(type) == nullptr)
He Yunchao11b038b2016-11-22 21:24:04 +0800882 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500883 context->handleError(InvalidEnum() << "No texture bound.");
He Yunchao11b038b2016-11-22 21:24:04 +0800884 return false;
885 }
886
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800887 if (!ValidMipLevel(context, type, level))
He Yunchao11b038b2016-11-22 21:24:04 +0800888 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500889 context->handleError(InvalidValue());
He Yunchao11b038b2016-11-22 21:24:04 +0800890 return false;
891 }
892
893 switch (pname)
894 {
895 case GL_TEXTURE_RED_TYPE:
896 case GL_TEXTURE_GREEN_TYPE:
897 case GL_TEXTURE_BLUE_TYPE:
898 case GL_TEXTURE_ALPHA_TYPE:
899 case GL_TEXTURE_DEPTH_TYPE:
900 break;
901 case GL_TEXTURE_RED_SIZE:
902 case GL_TEXTURE_GREEN_SIZE:
903 case GL_TEXTURE_BLUE_SIZE:
904 case GL_TEXTURE_ALPHA_SIZE:
905 case GL_TEXTURE_DEPTH_SIZE:
906 case GL_TEXTURE_STENCIL_SIZE:
907 case GL_TEXTURE_SHARED_SIZE:
908 break;
909 case GL_TEXTURE_INTERNAL_FORMAT:
910 case GL_TEXTURE_WIDTH:
911 case GL_TEXTURE_HEIGHT:
912 case GL_TEXTURE_DEPTH:
913 break;
914 case GL_TEXTURE_SAMPLES:
915 case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
916 break;
917 case GL_TEXTURE_COMPRESSED:
918 break;
919 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700920 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
He Yunchao11b038b2016-11-22 21:24:04 +0800921 return false;
922 }
923
924 if (length)
925 {
926 *length = 1;
927 }
928 return true;
929}
930
931bool ValidateGetTexLevelParameterfv(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800932 TextureTarget target,
He Yunchao11b038b2016-11-22 21:24:04 +0800933 GLint level,
934 GLenum pname,
935 GLfloat *params)
936{
937 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
938}
939
940bool ValidateGetTexLevelParameteriv(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800941 TextureTarget target,
He Yunchao11b038b2016-11-22 21:24:04 +0800942 GLint level,
943 GLenum pname,
944 GLint *params)
945{
946 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
947}
948
Jiajia Qin5451d532017-11-16 17:16:34 +0800949bool ValidateTexStorage2DMultisample(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800950 TextureType target,
JiangYizhoubddc46b2016-12-09 09:50:51 +0800951 GLsizei samples,
952 GLint internalFormat,
953 GLsizei width,
954 GLsizei height,
955 GLboolean fixedSampleLocations)
956{
957 if (context->getClientVersion() < ES_3_1)
958 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700959 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhoubddc46b2016-12-09 09:50:51 +0800960 return false;
961 }
962
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800963 if (target != TextureType::_2DMultisample)
JiangYizhoubddc46b2016-12-09 09:50:51 +0800964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500965 context->handleError(InvalidEnum() << "Target must be TEXTURE_2D_MULTISAMPLE.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800966 return false;
967 }
968
969 if (width < 1 || height < 1)
970 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700971 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
JiangYizhoubddc46b2016-12-09 09:50:51 +0800972 return false;
973 }
974
975 const Caps &caps = context->getCaps();
976 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
977 static_cast<GLuint>(height) > caps.max2DTextureSize)
978 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500979 context
980 ->handleError(InvalidValue()
981 << "Width and height must be less than or equal to GL_MAX_TEXTURE_SIZE.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800982 return false;
983 }
984
985 if (samples == 0)
986 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500987 context->handleError(InvalidValue() << "Samples may not be zero.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800988 return false;
989 }
990
991 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
992 if (!formatCaps.renderable)
993 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500994 context->handleError(InvalidEnum() << "SizedInternalformat must be color-renderable, "
995 "depth-renderable, or stencil-renderable.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800996 return false;
997 }
998
999 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
1000 // is one of the unsized base internalformats listed in table 8.11.
Geoff Langca271392017-04-05 12:30:00 -04001001 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
1002 if (formatInfo.internalFormat == GL_NONE)
JiangYizhoubddc46b2016-12-09 09:50:51 +08001003 {
1004 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001005 InvalidEnum()
1006 << "Internalformat is one of the unsupported unsized base internalformats.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001007 return false;
1008 }
1009
1010 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1011 {
1012 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001013 InvalidOperation()
1014 << "Samples must not be greater than maximum supported value for the format.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001015 return false;
1016 }
1017
1018 Texture *texture = context->getTargetTexture(target);
1019 if (!texture || texture->id() == 0)
1020 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001021 context->handleError(InvalidOperation() << "Zero is bound to target.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001022 return false;
1023 }
1024
1025 if (texture->getImmutableFormat())
1026 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001027 context->handleError(InvalidOperation() << "The value of TEXTURE_IMMUTABLE_FORMAT for "
1028 "the texture currently bound to target on "
1029 "the active texture unit is true.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001030 return false;
1031 }
1032
1033 return true;
1034}
1035
1036bool ValidateGetMultisamplefv(Context *context, GLenum pname, GLuint index, GLfloat *val)
1037{
1038 if (context->getClientVersion() < ES_3_1)
1039 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001040 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhoubddc46b2016-12-09 09:50:51 +08001041 return false;
1042 }
1043
1044 if (pname != GL_SAMPLE_POSITION)
1045 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001046 context->handleError(InvalidEnum() << "Pname must be SAMPLE_POSITION.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001047 return false;
1048 }
1049
JiangYizhou5b03f472017-01-09 10:22:53 +08001050 Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madille98b1b52018-03-08 09:47:23 -05001051 GLint samples = 0;
1052 ANGLE_VALIDATION_TRY(framebuffer->getSamples(context, &samples));
JiangYizhou5b03f472017-01-09 10:22:53 +08001053
Jamie Madille98b1b52018-03-08 09:47:23 -05001054 if (index >= static_cast<GLuint>(samples))
JiangYizhoubddc46b2016-12-09 09:50:51 +08001055 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001056 context->handleError(InvalidValue() << "Index must be less than the value of SAMPLES.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001057 return false;
1058 }
1059
1060 return true;
1061}
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001062
Jiajia Qin5451d532017-11-16 17:16:34 +08001063bool ValidateFramebufferParameteri(Context *context, GLenum target, GLenum pname, GLint param)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001064{
1065 if (context->getClientVersion() < ES_3_1)
1066 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001067 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001068 return false;
1069 }
1070
Geoff Lange8afa902017-09-27 15:00:43 -04001071 if (!ValidFramebufferTarget(context, target))
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001072 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001073 context->handleError(InvalidEnum() << "Invalid framebuffer target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001074 return false;
1075 }
1076
1077 switch (pname)
1078 {
1079 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1080 {
1081 GLint maxWidth = context->getCaps().maxFramebufferWidth;
1082 if (param < 0 || param > maxWidth)
1083 {
1084 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001085 InvalidValue()
1086 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_WIDTH.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001087 return false;
1088 }
1089 break;
1090 }
1091 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1092 {
1093 GLint maxHeight = context->getCaps().maxFramebufferHeight;
1094 if (param < 0 || param > maxHeight)
1095 {
1096 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001097 InvalidValue()
1098 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_HEIGHT.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001099 return false;
1100 }
1101 break;
1102 }
1103 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1104 {
1105 GLint maxSamples = context->getCaps().maxFramebufferSamples;
1106 if (param < 0 || param > maxSamples)
1107 {
1108 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001109 InvalidValue()
1110 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_SAMPLES.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001111 return false;
1112 }
1113 break;
1114 }
1115 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1116 {
1117 break;
1118 }
1119 default:
1120 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001121 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001122 return false;
1123 }
1124 }
1125
1126 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
1127 ASSERT(framebuffer);
1128 if (framebuffer->id() == 0)
1129 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001130 context->handleError(InvalidOperation() << "Default framebuffer is bound to target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001131 return false;
1132 }
1133 return true;
1134}
1135
Jiajia Qin5451d532017-11-16 17:16:34 +08001136bool ValidateGetFramebufferParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001137{
1138 if (context->getClientVersion() < ES_3_1)
1139 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001140 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001141 return false;
1142 }
1143
Geoff Lange8afa902017-09-27 15:00:43 -04001144 if (!ValidFramebufferTarget(context, target))
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001145 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001146 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001147 return false;
1148 }
1149
1150 switch (pname)
1151 {
1152 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1153 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1154 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1155 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1156 break;
1157 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001158 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001159 return false;
1160 }
1161
1162 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
1163 ASSERT(framebuffer);
1164
1165 if (framebuffer->id() == 0)
1166 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001167 context->handleError(InvalidOperation() << "Default framebuffer is bound to target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001168 return false;
1169 }
1170 return true;
1171}
1172
jchen1015015f72017-03-16 13:54:21 +08001173bool ValidateGetProgramResourceIndex(Context *context,
1174 GLuint program,
1175 GLenum programInterface,
1176 const GLchar *name)
1177{
1178 if (context->getClientVersion() < ES_3_1)
1179 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001180 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen1015015f72017-03-16 13:54:21 +08001181 return false;
1182 }
1183
1184 Program *programObject = GetValidProgram(context, program);
1185 if (programObject == nullptr)
1186 {
1187 return false;
1188 }
1189
1190 if (!ValidateNamedProgramInterface(programInterface))
1191 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001192 context->handleError(InvalidEnum() << "Invalid program interface: 0x" << std::hex
1193 << std::uppercase << programInterface);
jchen1015015f72017-03-16 13:54:21 +08001194 return false;
1195 }
Shao80957d92017-02-20 21:25:59 +08001196
1197 return true;
1198}
1199
Jamie Madill5b772312018-03-08 20:28:32 -05001200bool ValidateBindVertexBuffer(Context *context,
Shao80957d92017-02-20 21:25:59 +08001201 GLuint bindingIndex,
1202 GLuint buffer,
1203 GLintptr offset,
1204 GLsizei stride)
1205{
1206 if (context->getClientVersion() < ES_3_1)
1207 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001208 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +08001209 return false;
1210 }
1211
1212 if (!context->isBufferGenerated(buffer))
1213 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001214 context->handleError(InvalidOperation() << "Buffer is not generated.");
Shao80957d92017-02-20 21:25:59 +08001215 return false;
1216 }
1217
1218 const Caps &caps = context->getCaps();
1219 if (bindingIndex >= caps.maxVertexAttribBindings)
1220 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001221 context->handleError(InvalidValue()
1222 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08001223 return false;
1224 }
1225
1226 if (offset < 0)
1227 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001228 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Shao80957d92017-02-20 21:25:59 +08001229 return false;
1230 }
1231
1232 if (stride < 0 || stride > caps.maxVertexAttribStride)
1233 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001234 context->handleError(InvalidValue()
1235 << "stride must be between 0 and MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08001236 return false;
1237 }
1238
1239 // [OpenGL ES 3.1] Section 10.3.1 page 244:
1240 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
1241 if (context->getGLState().getVertexArrayId() == 0)
1242 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001243 context->handleError(InvalidOperation() << "Default vertex array buffer is bound.");
Shao80957d92017-02-20 21:25:59 +08001244 return false;
1245 }
1246
1247 return true;
1248}
1249
Jamie Madill5b772312018-03-08 20:28:32 -05001250bool ValidateVertexBindingDivisor(Context *context, GLuint bindingIndex, GLuint divisor)
Shao80957d92017-02-20 21:25:59 +08001251{
1252 if (context->getClientVersion() < ES_3_1)
1253 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001254 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +08001255 return false;
1256 }
1257
1258 const Caps &caps = context->getCaps();
1259 if (bindingIndex >= caps.maxVertexAttribBindings)
1260 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001261 context->handleError(InvalidValue()
1262 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08001263 return false;
1264 }
1265
1266 // [OpenGL ES 3.1] Section 10.3.1 page 243:
1267 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
1268 if (context->getGLState().getVertexArrayId() == 0)
1269 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001270 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +08001271 return false;
1272 }
1273
1274 return true;
1275}
1276
Jamie Madill5b772312018-03-08 20:28:32 -05001277bool ValidateVertexAttribFormat(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08001278 GLuint attribindex,
Shao80957d92017-02-20 21:25:59 +08001279 GLint size,
1280 GLenum type,
Jiajia Qin5451d532017-11-16 17:16:34 +08001281 GLboolean normalized,
1282 GLuint relativeoffset)
Shao80957d92017-02-20 21:25:59 +08001283{
Jiajia Qin5451d532017-11-16 17:16:34 +08001284 return ValidateVertexAttribFormatCommon(context, attribindex, size, type, relativeoffset,
1285 false);
1286}
Shao80957d92017-02-20 21:25:59 +08001287
Jamie Madill5b772312018-03-08 20:28:32 -05001288bool ValidateVertexAttribIFormat(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08001289 GLuint attribindex,
1290 GLint size,
1291 GLenum type,
1292 GLuint relativeoffset)
1293{
1294 return ValidateVertexAttribFormatCommon(context, attribindex, size, type, relativeoffset, true);
Shao80957d92017-02-20 21:25:59 +08001295}
1296
Jamie Madill5b772312018-03-08 20:28:32 -05001297bool ValidateVertexAttribBinding(Context *context, GLuint attribIndex, GLuint bindingIndex)
Shao80957d92017-02-20 21:25:59 +08001298{
1299 if (context->getClientVersion() < ES_3_1)
1300 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001301 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +08001302 return false;
1303 }
1304
1305 // [OpenGL ES 3.1] Section 10.3.1 page 243:
1306 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
1307 if (context->getGLState().getVertexArrayId() == 0)
1308 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001309 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +08001310 return false;
1311 }
1312
1313 const Caps &caps = context->getCaps();
1314 if (attribIndex >= caps.maxVertexAttributes)
1315 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001316 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08001317 return false;
1318 }
1319
1320 if (bindingIndex >= caps.maxVertexAttribBindings)
1321 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001322 context->handleError(InvalidValue()
1323 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS");
Shao80957d92017-02-20 21:25:59 +08001324 return false;
1325 }
1326
jchen1015015f72017-03-16 13:54:21 +08001327 return true;
1328}
1329
jchen10fd7c3b52017-03-21 15:36:03 +08001330bool ValidateGetProgramResourceName(Context *context,
1331 GLuint program,
1332 GLenum programInterface,
1333 GLuint index,
1334 GLsizei bufSize,
1335 GLsizei *length,
1336 GLchar *name)
1337{
1338 if (context->getClientVersion() < ES_3_1)
1339 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001340 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen10fd7c3b52017-03-21 15:36:03 +08001341 return false;
1342 }
1343
1344 Program *programObject = GetValidProgram(context, program);
1345 if (programObject == nullptr)
1346 {
1347 return false;
1348 }
1349
1350 if (!ValidateNamedProgramInterface(programInterface))
1351 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001352 context->handleError(InvalidEnum() << "Invalid program interface: 0x" << std::hex
1353 << std::uppercase << programInterface);
jchen10fd7c3b52017-03-21 15:36:03 +08001354 return false;
1355 }
1356
1357 if (!ValidateProgramResourceIndex(programObject, programInterface, index))
1358 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001359 context->handleError(InvalidValue() << "Invalid index: " << index);
jchen10fd7c3b52017-03-21 15:36:03 +08001360 return false;
1361 }
1362
1363 if (bufSize < 0)
1364 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001365 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
jchen10fd7c3b52017-03-21 15:36:03 +08001366 return false;
1367 }
1368
1369 return true;
1370}
1371
Xinghua Cao2b396592017-03-29 15:36:04 +08001372bool ValidateDispatchCompute(Context *context,
1373 GLuint numGroupsX,
1374 GLuint numGroupsY,
1375 GLuint numGroupsZ)
1376{
1377 if (context->getClientVersion() < ES_3_1)
1378 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001379 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Xinghua Cao2b396592017-03-29 15:36:04 +08001380 return false;
1381 }
1382
1383 const State &state = context->getGLState();
1384 Program *program = state.getProgram();
1385
Qin Jiajia62fcf622017-11-30 16:16:12 +08001386 if (program == nullptr || !program->hasLinkedComputeShader())
Xinghua Cao2b396592017-03-29 15:36:04 +08001387 {
Qin Jiajia62fcf622017-11-30 16:16:12 +08001388 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveProgramWithComputeShader);
Xinghua Cao2b396592017-03-29 15:36:04 +08001389 return false;
1390 }
1391
1392 const Caps &caps = context->getCaps();
1393 if (numGroupsX > caps.maxComputeWorkGroupCount[0])
1394 {
1395 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001396 InvalidValue() << "num_groups_x cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[0]="
1397 << caps.maxComputeWorkGroupCount[0]);
Xinghua Cao2b396592017-03-29 15:36:04 +08001398 return false;
1399 }
1400 if (numGroupsY > caps.maxComputeWorkGroupCount[1])
1401 {
1402 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001403 InvalidValue() << "num_groups_y cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[1]="
1404 << caps.maxComputeWorkGroupCount[1]);
Xinghua Cao2b396592017-03-29 15:36:04 +08001405 return false;
1406 }
1407 if (numGroupsZ > caps.maxComputeWorkGroupCount[2])
1408 {
1409 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001410 InvalidValue() << "num_groups_z cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[2]="
1411 << caps.maxComputeWorkGroupCount[2]);
Xinghua Cao2b396592017-03-29 15:36:04 +08001412 return false;
1413 }
1414
1415 return true;
1416}
1417
Jiajia Qin5451d532017-11-16 17:16:34 +08001418bool ValidateDispatchComputeIndirect(Context *context, GLintptr indirect)
1419{
Qin Jiajia62fcf622017-11-30 16:16:12 +08001420 if (context->getClientVersion() < ES_3_1)
1421 {
1422 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1423 return false;
1424 }
1425
1426 const State &state = context->getGLState();
1427 Program *program = state.getProgram();
1428
1429 if (program == nullptr || !program->hasLinkedComputeShader())
1430 {
1431 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveProgramWithComputeShader);
1432 return false;
1433 }
1434
Qin Jiajia62fcf622017-11-30 16:16:12 +08001435 if (indirect < 0)
1436 {
1437 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
1438 return false;
1439 }
1440
1441 if ((indirect & (sizeof(GLuint) - 1)) != 0)
1442 {
Qin Jiajiaa4ef8432018-02-22 16:02:24 +08001443 ANGLE_VALIDATION_ERR(context, InvalidValue(), OffsetMustBeMultipleOfUint);
1444 return false;
1445 }
1446
Jamie Madill5b772312018-03-08 20:28:32 -05001447 Buffer *dispatchIndirectBuffer = state.getTargetBuffer(BufferBinding::DispatchIndirect);
Qin Jiajiaa4ef8432018-02-22 16:02:24 +08001448 if (!dispatchIndirectBuffer)
1449 {
1450 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DispatchIndirectBufferNotBound);
Qin Jiajia62fcf622017-11-30 16:16:12 +08001451 return false;
1452 }
1453
1454 CheckedNumeric<GLuint64> checkedOffset(static_cast<GLuint64>(indirect));
1455 auto checkedSum = checkedOffset + static_cast<GLuint64>(3 * sizeof(GLuint));
1456 if (!checkedSum.IsValid() ||
1457 checkedSum.ValueOrDie() > static_cast<GLuint64>(dispatchIndirectBuffer->getSize()))
1458 {
1459 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
1460 return false;
1461 }
1462
1463 return true;
Jiajia Qin5451d532017-11-16 17:16:34 +08001464}
1465
Xinghua Cao65ec0b22017-03-28 16:10:52 +08001466bool ValidateBindImageTexture(Context *context,
1467 GLuint unit,
1468 GLuint texture,
1469 GLint level,
1470 GLboolean layered,
1471 GLint layer,
1472 GLenum access,
1473 GLenum format)
1474{
1475 GLuint maxImageUnits = context->getCaps().maxImageUnits;
1476 if (unit >= maxImageUnits)
1477 {
1478 context->handleError(InvalidValue()
1479 << "unit cannot be greater than or equal than MAX_IMAGE_UNITS = "
1480 << maxImageUnits);
1481 return false;
1482 }
1483
1484 if (level < 0)
1485 {
1486 context->handleError(InvalidValue() << "level is negative.");
1487 return false;
1488 }
1489
1490 if (layer < 0)
1491 {
1492 context->handleError(InvalidValue() << "layer is negative.");
1493 return false;
1494 }
1495
1496 if (access != GL_READ_ONLY && access != GL_WRITE_ONLY && access != GL_READ_WRITE)
1497 {
1498 context->handleError(InvalidEnum() << "access is not one of the supported tokens.");
1499 return false;
1500 }
1501
1502 switch (format)
1503 {
1504 case GL_RGBA32F:
1505 case GL_RGBA16F:
1506 case GL_R32F:
1507 case GL_RGBA32UI:
1508 case GL_RGBA16UI:
1509 case GL_RGBA8UI:
1510 case GL_R32UI:
1511 case GL_RGBA32I:
1512 case GL_RGBA16I:
1513 case GL_RGBA8I:
1514 case GL_R32I:
1515 case GL_RGBA8:
1516 case GL_RGBA8_SNORM:
1517 break;
1518 default:
1519 context->handleError(InvalidValue()
1520 << "format is not one of supported image unit formats.");
1521 return false;
1522 }
1523
1524 if (texture != 0)
1525 {
1526 Texture *tex = context->getTexture(texture);
1527
1528 if (tex == nullptr)
1529 {
1530 context->handleError(InvalidValue()
1531 << "texture is not the name of an existing texture object.");
1532 return false;
1533 }
1534
1535 if (!tex->getImmutableFormat())
1536 {
1537 context->handleError(InvalidOperation()
1538 << "texture is not the name of an immutable texture object.");
1539 return false;
1540 }
1541 }
1542
1543 return true;
1544}
jchen10191381f2017-04-11 13:59:04 +08001545
1546bool ValidateGetProgramResourceLocation(Context *context,
1547 GLuint program,
1548 GLenum programInterface,
1549 const GLchar *name)
1550{
1551 if (context->getClientVersion() < ES_3_1)
1552 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001553 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen10191381f2017-04-11 13:59:04 +08001554 return false;
1555 }
1556
1557 Program *programObject = GetValidProgram(context, program);
1558 if (programObject == nullptr)
1559 {
1560 return false;
1561 }
1562
1563 if (!programObject->isLinked())
1564 {
1565 context->handleError(InvalidOperation() << "Program is not successfully linked.");
1566 return false;
1567 }
1568
1569 if (!ValidateLocationProgramInterface(programInterface))
1570 {
1571 context->handleError(InvalidEnum() << "Invalid program interface.");
1572 return false;
1573 }
1574 return true;
1575}
1576
jchen10880683b2017-04-12 16:21:55 +08001577bool ValidateGetProgramResourceiv(Context *context,
1578 GLuint program,
1579 GLenum programInterface,
1580 GLuint index,
1581 GLsizei propCount,
1582 const GLenum *props,
1583 GLsizei bufSize,
1584 GLsizei *length,
1585 GLint *params)
1586{
1587 if (context->getClientVersion() < ES_3_1)
1588 {
jchen10d9cd7b72017-08-30 15:04:25 +08001589 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen10880683b2017-04-12 16:21:55 +08001590 return false;
1591 }
1592
1593 Program *programObject = GetValidProgram(context, program);
1594 if (programObject == nullptr)
1595 {
1596 return false;
1597 }
1598 if (!ValidateProgramInterface(programInterface))
1599 {
1600 context->handleError(InvalidEnum() << "Invalid program interface.");
1601 return false;
1602 }
1603 if (propCount <= 0)
1604 {
1605 context->handleError(InvalidValue() << "Invalid propCount.");
1606 return false;
1607 }
1608 if (bufSize < 0)
1609 {
1610 context->handleError(InvalidValue() << "Invalid bufSize.");
1611 return false;
1612 }
1613 if (!ValidateProgramResourceIndex(programObject, programInterface, index))
1614 {
1615 context->handleError(InvalidValue() << "Invalid index: " << index);
1616 return false;
1617 }
1618 for (GLsizei i = 0; i < propCount; i++)
1619 {
1620 if (!ValidateProgramResourceProperty(props[i]))
1621 {
1622 context->handleError(InvalidEnum() << "Invalid prop.");
1623 return false;
1624 }
1625 if (!ValidateProgramResourcePropertyByInterface(props[i], programInterface))
1626 {
1627 context->handleError(InvalidOperation() << "Not an allowed prop for interface");
1628 return false;
1629 }
1630 }
1631 return true;
1632}
1633
jchen10d9cd7b72017-08-30 15:04:25 +08001634bool ValidateGetProgramInterfaceiv(Context *context,
1635 GLuint program,
1636 GLenum programInterface,
1637 GLenum pname,
1638 GLint *params)
1639{
1640 if (context->getClientVersion() < ES_3_1)
1641 {
1642 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1643 return false;
1644 }
1645
1646 Program *programObject = GetValidProgram(context, program);
1647 if (programObject == nullptr)
1648 {
1649 return false;
1650 }
1651
1652 if (!ValidateProgramInterface(programInterface))
1653 {
1654 context->handleError(InvalidEnum() << "Invalid program interface.");
1655 return false;
1656 }
1657
1658 switch (pname)
1659 {
1660 case GL_ACTIVE_RESOURCES:
1661 case GL_MAX_NAME_LENGTH:
1662 case GL_MAX_NUM_ACTIVE_VARIABLES:
1663 break;
1664
1665 default:
1666 context->handleError(InvalidEnum() << "Unknown property of program interface.");
1667 return false;
1668 }
1669
1670 if (pname == GL_MAX_NAME_LENGTH && programInterface == GL_ATOMIC_COUNTER_BUFFER)
1671 {
1672 context->handleError(InvalidOperation()
1673 << "Active atomic counter resources are not assigned name strings.");
1674 return false;
1675 }
1676
1677 if (pname == GL_MAX_NUM_ACTIVE_VARIABLES)
1678 {
1679 switch (programInterface)
1680 {
1681 case GL_ATOMIC_COUNTER_BUFFER:
1682 case GL_SHADER_STORAGE_BLOCK:
1683 case GL_UNIFORM_BLOCK:
1684 break;
1685
1686 default:
1687 context->handleError(
1688 InvalidOperation()
1689 << "MAX_NUM_ACTIVE_VARIABLES requires a buffer or block interface.");
1690 return false;
1691 }
1692 }
1693
1694 return true;
1695}
1696
Yunchao Hea336b902017-08-02 16:05:21 +08001697static bool ValidateGenOrDeleteES31(Context *context, GLint n)
1698{
1699 if (context->getClientVersion() < ES_3_1)
1700 {
1701 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1702 return false;
1703 }
1704
1705 return ValidateGenOrDelete(context, n);
1706}
1707
1708bool ValidateGenProgramPipelines(Context *context, GLint n, GLuint *)
1709{
1710 return ValidateGenOrDeleteES31(context, n);
1711}
1712
1713bool ValidateDeleteProgramPipelines(Context *context, GLint n, const GLuint *)
1714{
1715 return ValidateGenOrDeleteES31(context, n);
1716}
1717
1718bool ValidateBindProgramPipeline(Context *context, GLuint pipeline)
1719{
1720 if (context->getClientVersion() < ES_3_1)
1721 {
1722 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1723 return false;
1724 }
1725
1726 if (!context->isProgramPipelineGenerated(pipeline))
1727 {
1728 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
1729 return false;
1730 }
1731
1732 return true;
1733}
1734
1735bool ValidateIsProgramPipeline(Context *context, GLuint pipeline)
1736{
1737 if (context->getClientVersion() < ES_3_1)
1738 {
1739 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1740 return false;
1741 }
1742
1743 return true;
1744}
1745
Jiajia Qin5451d532017-11-16 17:16:34 +08001746bool ValidateUseProgramStages(Context *context, GLuint pipeline, GLbitfield stages, GLuint program)
1747{
1748 UNIMPLEMENTED();
1749 return false;
1750}
1751
1752bool ValidateActiveShaderProgram(Context *context, GLuint pipeline, GLuint program)
1753{
1754 UNIMPLEMENTED();
1755 return false;
1756}
1757
1758bool ValidateCreateShaderProgramv(Context *context,
1759 GLenum type,
1760 GLsizei count,
1761 const GLchar *const *strings)
1762{
1763 UNIMPLEMENTED();
1764 return false;
1765}
1766
1767bool ValidateGetProgramPipelineiv(Context *context, GLuint pipeline, GLenum pname, GLint *params)
1768{
1769 UNIMPLEMENTED();
1770 return false;
1771}
1772
1773bool ValidateValidateProgramPipeline(Context *context, GLuint pipeline)
1774{
1775 UNIMPLEMENTED();
1776 return false;
1777}
1778
1779bool ValidateGetProgramPipelineInfoLog(Context *context,
1780 GLuint pipeline,
1781 GLsizei bufSize,
1782 GLsizei *length,
1783 GLchar *infoLog)
1784{
1785 UNIMPLEMENTED();
1786 return false;
1787}
1788
1789bool ValidateMemoryBarrier(Context *context, GLbitfield barriers)
1790{
Xinghua Cao89c422a2017-11-29 18:24:20 +08001791 if (context->getClientVersion() < ES_3_1)
1792 {
1793 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1794 return false;
1795 }
1796
1797 if (barriers == GL_ALL_BARRIER_BITS)
1798 {
1799 return true;
1800 }
1801
1802 GLbitfield supported_barrier_bits =
1803 GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT |
1804 GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT |
1805 GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT |
1806 GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT |
1807 GL_ATOMIC_COUNTER_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT;
1808 if ((barriers & ~supported_barrier_bits) != 0)
1809 {
1810 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMemoryBarrierBit);
1811 return false;
1812 }
1813
1814 return true;
Jiajia Qin5451d532017-11-16 17:16:34 +08001815}
1816
1817bool ValidateMemoryBarrierByRegion(Context *context, GLbitfield barriers)
1818{
Xinghua Cao89c422a2017-11-29 18:24:20 +08001819 if (context->getClientVersion() < ES_3_1)
1820 {
1821 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1822 return false;
1823 }
1824
1825 if (barriers == GL_ALL_BARRIER_BITS)
1826 {
1827 return true;
1828 }
1829
1830 GLbitfield supported_barrier_bits = GL_ATOMIC_COUNTER_BARRIER_BIT | GL_FRAMEBUFFER_BARRIER_BIT |
1831 GL_SHADER_IMAGE_ACCESS_BARRIER_BIT |
1832 GL_SHADER_STORAGE_BARRIER_BIT |
1833 GL_TEXTURE_FETCH_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT;
1834 if ((barriers & ~supported_barrier_bits) != 0)
1835 {
1836 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMemoryBarrierBit);
1837 return false;
1838 }
1839
1840 return true;
Jiajia Qin5451d532017-11-16 17:16:34 +08001841}
1842
1843bool ValidateSampleMaski(Context *context, GLuint maskNumber, GLbitfield mask)
Jiawei Shaodb342272017-09-27 10:21:45 +08001844{
1845 if (context->getClientVersion() < ES_3_1)
1846 {
1847 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1848 return false;
1849 }
1850
1851 if (maskNumber >= context->getCaps().maxSampleMaskWords)
1852 {
1853 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
1854 return false;
1855 }
1856
1857 return true;
1858}
1859
Martin Radev66fb8202016-07-28 11:45:20 +03001860} // namespace gl