blob: 86c6f9bb4f1be0609277609a4cce1f0d3e2bb9c2 [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
Jiawei Shaoc6f82872018-04-24 14:14:50 +080065bool ValidateProgramResourceProperty(const Context *context, GLenum prop)
jchen10880683b2017-04-12 16:21:55 +080066{
Jiawei Shaoc6f82872018-04-24 14:14:50 +080067 ASSERT(context);
jchen10880683b2017-04-12 16:21:55 +080068 switch (prop)
69 {
70 case GL_ACTIVE_VARIABLES:
71 case GL_BUFFER_BINDING:
72 case GL_NUM_ACTIVE_VARIABLES:
73
74 case GL_ARRAY_SIZE:
75
76 case GL_ARRAY_STRIDE:
77 case GL_BLOCK_INDEX:
78 case GL_IS_ROW_MAJOR:
79 case GL_MATRIX_STRIDE:
80
81 case GL_ATOMIC_COUNTER_BUFFER_INDEX:
82
83 case GL_BUFFER_DATA_SIZE:
84
85 case GL_LOCATION:
86
87 case GL_NAME_LENGTH:
88
89 case GL_OFFSET:
90
91 case GL_REFERENCED_BY_VERTEX_SHADER:
92 case GL_REFERENCED_BY_FRAGMENT_SHADER:
93 case GL_REFERENCED_BY_COMPUTE_SHADER:
94
95 case GL_TOP_LEVEL_ARRAY_SIZE:
96 case GL_TOP_LEVEL_ARRAY_STRIDE:
97
98 case GL_TYPE:
99 return true;
100
Jiawei Shaoc6f82872018-04-24 14:14:50 +0800101 case GL_REFERENCED_BY_GEOMETRY_SHADER_EXT:
102 return context->getExtensions().geometryShader;
103
jchen10880683b2017-04-12 16:21:55 +0800104 default:
105 return false;
106 }
107}
108
109// GLES 3.10 spec: Page 82 -- Table 7.2
110bool ValidateProgramResourcePropertyByInterface(GLenum prop, GLenum programInterface)
111{
112 switch (prop)
113 {
114 case GL_ACTIVE_VARIABLES:
115 case GL_BUFFER_BINDING:
116 case GL_NUM_ACTIVE_VARIABLES:
117 {
118 switch (programInterface)
119 {
120 case GL_ATOMIC_COUNTER_BUFFER:
121 case GL_SHADER_STORAGE_BLOCK:
122 case GL_UNIFORM_BLOCK:
123 return true;
124 default:
125 return false;
126 }
127 }
128
129 case GL_ARRAY_SIZE:
130 {
131 switch (programInterface)
132 {
133 case GL_BUFFER_VARIABLE:
134 case GL_PROGRAM_INPUT:
135 case GL_PROGRAM_OUTPUT:
136 case GL_TRANSFORM_FEEDBACK_VARYING:
137 case GL_UNIFORM:
138 return true;
139 default:
140 return false;
141 }
142 }
143
144 case GL_ARRAY_STRIDE:
145 case GL_BLOCK_INDEX:
146 case GL_IS_ROW_MAJOR:
147 case GL_MATRIX_STRIDE:
148 {
149 switch (programInterface)
150 {
151 case GL_BUFFER_VARIABLE:
152 case GL_UNIFORM:
153 return true;
154 default:
155 return false;
156 }
157 }
158
159 case GL_ATOMIC_COUNTER_BUFFER_INDEX:
160 {
161 if (programInterface == GL_UNIFORM)
162 {
163 return true;
164 }
165 return false;
166 }
167
168 case GL_BUFFER_DATA_SIZE:
169 {
170 switch (programInterface)
171 {
172 case GL_ATOMIC_COUNTER_BUFFER:
173 case GL_SHADER_STORAGE_BLOCK:
174 case GL_UNIFORM_BLOCK:
175 return true;
176 default:
177 return false;
178 }
179 }
180
181 case GL_LOCATION:
182 {
183 return ValidateLocationProgramInterface(programInterface);
184 }
185
186 case GL_NAME_LENGTH:
187 {
188 return ValidateNamedProgramInterface(programInterface);
189 }
190
191 case GL_OFFSET:
192 {
193 switch (programInterface)
194 {
195 case GL_BUFFER_VARIABLE:
196 case GL_UNIFORM:
197 return true;
198 default:
199 return false;
200 }
201 }
202
203 case GL_REFERENCED_BY_VERTEX_SHADER:
204 case GL_REFERENCED_BY_FRAGMENT_SHADER:
205 case GL_REFERENCED_BY_COMPUTE_SHADER:
Jiawei Shaoc6f82872018-04-24 14:14:50 +0800206 case GL_REFERENCED_BY_GEOMETRY_SHADER_EXT:
jchen10880683b2017-04-12 16:21:55 +0800207 {
208 switch (programInterface)
209 {
210 case GL_ATOMIC_COUNTER_BUFFER:
211 case GL_BUFFER_VARIABLE:
212 case GL_PROGRAM_INPUT:
213 case GL_PROGRAM_OUTPUT:
214 case GL_SHADER_STORAGE_BLOCK:
215 case GL_UNIFORM:
216 case GL_UNIFORM_BLOCK:
217 return true;
218 default:
219 return false;
220 }
221 }
222
223 case GL_TOP_LEVEL_ARRAY_SIZE:
224 case GL_TOP_LEVEL_ARRAY_STRIDE:
225 {
226 if (programInterface == GL_BUFFER_VARIABLE)
227 {
228 return true;
229 }
230 return false;
231 }
232
233 case GL_TYPE:
234 {
235 switch (programInterface)
236 {
237 case GL_BUFFER_VARIABLE:
238 case GL_PROGRAM_INPUT:
239 case GL_PROGRAM_OUTPUT:
240 case GL_TRANSFORM_FEEDBACK_VARYING:
241 case GL_UNIFORM:
242 return true;
243 default:
244 return false;
245 }
246 }
247
248 default:
249 return false;
250 }
251}
252
jchen10fd7c3b52017-03-21 15:36:03 +0800253bool ValidateProgramResourceIndex(const Program *programObject,
254 GLenum programInterface,
255 GLuint index)
256{
257 switch (programInterface)
258 {
259 case GL_PROGRAM_INPUT:
260 return (index < static_cast<GLuint>(programObject->getActiveAttributeCount()));
261
262 case GL_PROGRAM_OUTPUT:
263 return (index < static_cast<GLuint>(programObject->getOutputResourceCount()));
264
jchen10fd7c3b52017-03-21 15:36:03 +0800265 case GL_UNIFORM:
jchen10baf5d942017-08-28 20:45:48 +0800266 return (index < static_cast<GLuint>(programObject->getActiveUniformCount()));
267
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800268 case GL_BUFFER_VARIABLE:
269 return (index < static_cast<GLuint>(programObject->getActiveBufferVariableCount()));
270
271 case GL_SHADER_STORAGE_BLOCK:
272 return (index < static_cast<GLuint>(programObject->getActiveShaderStorageBlockCount()));
273
jchen10fd7c3b52017-03-21 15:36:03 +0800274 case GL_UNIFORM_BLOCK:
jchen1058f67be2017-10-27 08:59:27 +0800275 return (index < programObject->getActiveUniformBlockCount());
276
277 case GL_ATOMIC_COUNTER_BUFFER:
278 return (index < programObject->getActiveAtomicCounterBufferCount());
279
jchen10fd7c3b52017-03-21 15:36:03 +0800280 case GL_TRANSFORM_FEEDBACK_VARYING:
jchen10910a3da2017-11-15 09:40:11 +0800281 return (index < static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()));
jchen10fd7c3b52017-03-21 15:36:03 +0800282
283 default:
284 UNREACHABLE();
285 return false;
286 }
287}
288
Jamie Madill5b772312018-03-08 20:28:32 -0500289bool ValidateProgramUniform(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +0800290 GLenum valueType,
291 GLuint program,
292 GLint location,
293 GLsizei count)
294{
295 // Check for ES31 program uniform entry points
296 if (context->getClientVersion() < Version(3, 1))
297 {
298 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
299 return false;
300 }
301
302 const LinkedUniform *uniform = nullptr;
Jamie Madill5b772312018-03-08 20:28:32 -0500303 Program *programObject = GetValidProgram(context, program);
Jiajia Qin5451d532017-11-16 17:16:34 +0800304 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
305 ValidateUniformValue(context, valueType, uniform->type);
306}
307
Jamie Madill5b772312018-03-08 20:28:32 -0500308bool ValidateProgramUniformMatrix(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +0800309 GLenum valueType,
310 GLuint program,
311 GLint location,
312 GLsizei count,
313 GLboolean transpose)
314{
315 // Check for ES31 program uniform entry points
316 if (context->getClientVersion() < Version(3, 1))
317 {
318 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
319 return false;
320 }
321
322 const LinkedUniform *uniform = nullptr;
Jamie Madill5b772312018-03-08 20:28:32 -0500323 Program *programObject = GetValidProgram(context, program);
Jiajia Qin5451d532017-11-16 17:16:34 +0800324 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
325 ValidateUniformMatrixValue(context, valueType, uniform->type);
326}
327
Jamie Madill5b772312018-03-08 20:28:32 -0500328bool ValidateVertexAttribFormatCommon(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +0800329 GLuint attribIndex,
330 GLint size,
331 GLenum type,
332 GLuint relativeOffset,
333 GLboolean pureInteger)
334{
335 if (context->getClientVersion() < ES_3_1)
336 {
337 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
338 return false;
339 }
340
341 const Caps &caps = context->getCaps();
342 if (relativeOffset > static_cast<GLuint>(caps.maxVertexAttribRelativeOffset))
343 {
344 context->handleError(
345 InvalidValue()
346 << "relativeOffset cannot be greater than MAX_VERTEX_ATTRIB_RELATIVE_OFFSET.");
347 return false;
348 }
349
350 // [OpenGL ES 3.1] Section 10.3.1 page 243:
351 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
352 if (context->getGLState().getVertexArrayId() == 0)
353 {
354 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
355 return false;
356 }
357
358 return ValidateVertexFormatBase(context, attribIndex, size, type, pureInteger);
359}
360
jchen1015015f72017-03-16 13:54:21 +0800361} // anonymous namespace
362
Martin Radev66fb8202016-07-28 11:45:20 +0300363bool ValidateGetBooleani_v(Context *context, GLenum target, GLuint index, GLboolean *data)
364{
Geoff Langeb66a6e2016-10-31 13:06:12 -0400365 if (context->getClientVersion() < ES_3_1)
Martin Radev66fb8202016-07-28 11:45:20 +0300366 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700367 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Martin Radev66fb8202016-07-28 11:45:20 +0300368 return false;
369 }
370
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400371 if (!ValidateIndexedStateQuery(context, target, index, nullptr))
372 {
373 return false;
374 }
375
376 return true;
377}
378
379bool ValidateGetBooleani_vRobustANGLE(Context *context,
380 GLenum target,
381 GLuint index,
382 GLsizei bufSize,
383 GLsizei *length,
384 GLboolean *data)
385{
Geoff Langeb66a6e2016-10-31 13:06:12 -0400386 if (context->getClientVersion() < ES_3_1)
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400387 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700388 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400389 return false;
390 }
391
392 if (!ValidateRobustEntryPoint(context, bufSize))
393 {
394 return false;
395 }
396
Brandon Jonesd1049182018-03-28 10:02:20 -0700397 GLsizei numParams = 0;
398
399 if (!ValidateIndexedStateQuery(context, target, index, &numParams))
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400400 {
401 return false;
402 }
403
Brandon Jonesd1049182018-03-28 10:02:20 -0700404 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Martin Radev66fb8202016-07-28 11:45:20 +0300405 {
406 return false;
407 }
408
Brandon Jonesd1049182018-03-28 10:02:20 -0700409 SetRobustLengthParam(length, numParams);
Martin Radev66fb8202016-07-28 11:45:20 +0300410 return true;
411}
412
Jamie Madill876429b2017-04-20 15:46:24 -0400413bool ValidateDrawIndirectBase(Context *context, GLenum mode, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800414{
415 if (context->getClientVersion() < ES_3_1)
416 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700417 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jiajia Qind9671222016-11-29 16:30:31 +0800418 return false;
419 }
420
421 // Here the third parameter 1 is only to pass the count validation.
422 if (!ValidateDrawBase(context, mode, 1))
423 {
424 return false;
425 }
426
427 const State &state = context->getGLState();
428
429 // An INVALID_OPERATION error is generated if zero is bound to VERTEX_ARRAY_BINDING,
430 // DRAW_INDIRECT_BUFFER or to any enabled vertex array.
431 if (!state.getVertexArrayId())
432 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500433 context->handleError(InvalidOperation() << "zero is bound to VERTEX_ARRAY_BINDING");
Jiajia Qind9671222016-11-29 16:30:31 +0800434 return false;
435 }
436
Jamie Madill5b772312018-03-08 20:28:32 -0500437 Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
Jiajia Qind9671222016-11-29 16:30:31 +0800438 if (!drawIndirectBuffer)
439 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500440 context->handleError(InvalidOperation() << "zero is bound to DRAW_INDIRECT_BUFFER");
Jiajia Qind9671222016-11-29 16:30:31 +0800441 return false;
442 }
443
444 // An INVALID_VALUE error is generated if indirect is not a multiple of the size, in basic
445 // machine units, of uint.
446 GLint64 offset = reinterpret_cast<GLint64>(indirect);
447 if ((static_cast<GLuint>(offset) % sizeof(GLuint)) != 0)
448 {
449 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500450 InvalidValue()
451 << "indirect is not a multiple of the size, in basic machine units, of uint");
Jiajia Qind9671222016-11-29 16:30:31 +0800452 return false;
453 }
454
Martin Radev14a26ae2017-07-24 15:56:29 +0300455 // ANGLE_multiview spec, revision 1:
456 // An INVALID_OPERATION is generated by DrawArraysIndirect and DrawElementsIndirect if the
457 // number of views in the draw framebuffer is greater than 1.
458 const Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
459 ASSERT(drawFramebuffer != nullptr);
460 if (drawFramebuffer->getNumViews() > 1)
461 {
462 context->handleError(
463 InvalidOperation()
464 << "The number of views in the active draw framebuffer is greater than 1.");
465 return false;
466 }
467
Jiajia Qind9671222016-11-29 16:30:31 +0800468 return true;
469}
470
Jamie Madill876429b2017-04-20 15:46:24 -0400471bool ValidateDrawArraysIndirect(Context *context, GLenum mode, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800472{
473 const State &state = context->getGLState();
Jamie Madill5b772312018-03-08 20:28:32 -0500474 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Jiajia Qind9671222016-11-29 16:30:31 +0800475 if (curTransformFeedback && curTransformFeedback->isActive() &&
476 !curTransformFeedback->isPaused())
477 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800478 // EXT_geometry_shader allows transform feedback to work with all draw commands.
479 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
480 if (context->getExtensions().geometryShader)
481 {
482 if (!ValidateTransformFeedbackPrimitiveMode(
483 context, curTransformFeedback->getPrimitiveMode(), mode))
484 {
485 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
486 return false;
487 }
488 }
489 else
490 {
491 // An INVALID_OPERATION error is generated if transform feedback is active and not
492 // paused.
493 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
494 UnsupportedDrawModeForTransformFeedback);
495 return false;
496 }
Jiajia Qind9671222016-11-29 16:30:31 +0800497 }
498
499 if (!ValidateDrawIndirectBase(context, mode, indirect))
500 return false;
501
Jamie Madill5b772312018-03-08 20:28:32 -0500502 Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
Jiajia Qind9671222016-11-29 16:30:31 +0800503 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
504 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawArraysIndirectCommand
505 // which's size is 4 * sizeof(uint).
506 auto checkedSum = checkedOffset + 4 * sizeof(GLuint);
507 if (!checkedSum.IsValid() ||
508 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
509 {
510 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500511 InvalidOperation()
512 << "the command would source data beyond the end of the buffer object.");
Jiajia Qind9671222016-11-29 16:30:31 +0800513 return false;
514 }
515
516 return true;
517}
518
Jamie Madill876429b2017-04-20 15:46:24 -0400519bool ValidateDrawElementsIndirect(Context *context, GLenum mode, GLenum type, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800520{
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800521 if (!ValidateDrawElementsBase(context, mode, type))
522 {
Jiajia Qind9671222016-11-29 16:30:31 +0800523 return false;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800524 }
Jiajia Qind9671222016-11-29 16:30:31 +0800525
526 const State &state = context->getGLState();
527 const VertexArray *vao = state.getVertexArray();
Jamie Madill5b772312018-03-08 20:28:32 -0500528 Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jiajia Qind9671222016-11-29 16:30:31 +0800529 if (!elementArrayBuffer)
530 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500531 context->handleError(InvalidOperation() << "zero is bound to ELEMENT_ARRAY_BUFFER");
Jiajia Qind9671222016-11-29 16:30:31 +0800532 return false;
533 }
534
535 if (!ValidateDrawIndirectBase(context, mode, indirect))
536 return false;
537
Jamie Madill5b772312018-03-08 20:28:32 -0500538 Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
Jiajia Qind9671222016-11-29 16:30:31 +0800539 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
540 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawElementsIndirectCommand
541 // which's size is 5 * sizeof(uint).
542 auto checkedSum = checkedOffset + 5 * sizeof(GLuint);
543 if (!checkedSum.IsValid() ||
544 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
545 {
546 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500547 InvalidOperation()
548 << "the command would source data beyond the end of the buffer object.");
Jiajia Qind9671222016-11-29 16:30:31 +0800549 return false;
550 }
551
552 return true;
553}
554
Jiajia Qin5451d532017-11-16 17:16:34 +0800555bool ValidateProgramUniform1i(Context *context, GLuint program, GLint location, GLint v0)
556{
557 return ValidateProgramUniform1iv(context, program, location, 1, &v0);
558}
559
560bool ValidateProgramUniform2i(Context *context, GLuint program, GLint location, GLint v0, GLint v1)
561{
562 GLint xy[2] = {v0, v1};
563 return ValidateProgramUniform2iv(context, program, location, 1, xy);
564}
565
566bool ValidateProgramUniform3i(Context *context,
567 GLuint program,
568 GLint location,
569 GLint v0,
570 GLint v1,
571 GLint v2)
572{
573 GLint xyz[3] = {v0, v1, v2};
574 return ValidateProgramUniform3iv(context, program, location, 1, xyz);
575}
576
577bool ValidateProgramUniform4i(Context *context,
578 GLuint program,
579 GLint location,
580 GLint v0,
581 GLint v1,
582 GLint v2,
583 GLint v3)
584{
585 GLint xyzw[4] = {v0, v1, v2, v3};
586 return ValidateProgramUniform4iv(context, program, location, 1, xyzw);
587}
588
589bool ValidateProgramUniform1ui(Context *context, GLuint program, GLint location, GLuint v0)
590{
591 return ValidateProgramUniform1uiv(context, program, location, 1, &v0);
592}
593
594bool ValidateProgramUniform2ui(Context *context,
595 GLuint program,
596 GLint location,
597 GLuint v0,
598 GLuint v1)
599{
600 GLuint xy[2] = {v0, v1};
601 return ValidateProgramUniform2uiv(context, program, location, 1, xy);
602}
603
604bool ValidateProgramUniform3ui(Context *context,
605 GLuint program,
606 GLint location,
607 GLuint v0,
608 GLuint v1,
609 GLuint v2)
610{
611 GLuint xyz[3] = {v0, v1, v2};
612 return ValidateProgramUniform3uiv(context, program, location, 1, xyz);
613}
614
615bool ValidateProgramUniform4ui(Context *context,
616 GLuint program,
617 GLint location,
618 GLuint v0,
619 GLuint v1,
620 GLuint v2,
621 GLuint v3)
622{
623 GLuint xyzw[4] = {v0, v1, v2, v3};
624 return ValidateProgramUniform4uiv(context, program, location, 1, xyzw);
625}
626
627bool ValidateProgramUniform1f(Context *context, GLuint program, GLint location, GLfloat v0)
628{
629 return ValidateProgramUniform1fv(context, program, location, 1, &v0);
630}
631
632bool ValidateProgramUniform2f(Context *context,
633 GLuint program,
634 GLint location,
635 GLfloat v0,
636 GLfloat v1)
637{
638 GLfloat xy[2] = {v0, v1};
639 return ValidateProgramUniform2fv(context, program, location, 1, xy);
640}
641
642bool ValidateProgramUniform3f(Context *context,
643 GLuint program,
644 GLint location,
645 GLfloat v0,
646 GLfloat v1,
647 GLfloat v2)
648{
649 GLfloat xyz[3] = {v0, v1, v2};
650 return ValidateProgramUniform3fv(context, program, location, 1, xyz);
651}
652
653bool ValidateProgramUniform4f(Context *context,
654 GLuint program,
655 GLint location,
656 GLfloat v0,
657 GLfloat v1,
658 GLfloat v2,
659 GLfloat v3)
660{
661 GLfloat xyzw[4] = {v0, v1, v2, v3};
662 return ValidateProgramUniform4fv(context, program, location, 1, xyzw);
663}
664
665bool ValidateProgramUniform1iv(Context *context,
666 GLuint program,
667 GLint location,
668 GLsizei count,
669 const GLint *value)
670{
671 // Check for ES31 program uniform entry points
672 if (context->getClientVersion() < Version(3, 1))
673 {
674 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
675 return false;
676 }
677
678 const LinkedUniform *uniform = nullptr;
Jamie Madill5b772312018-03-08 20:28:32 -0500679 Program *programObject = GetValidProgram(context, program);
Jiajia Qin5451d532017-11-16 17:16:34 +0800680 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
681 ValidateUniform1ivValue(context, uniform->type, count, value);
682}
683
684bool ValidateProgramUniform2iv(Context *context,
685 GLuint program,
686 GLint location,
687 GLsizei count,
688 const GLint *value)
689{
690 return ValidateProgramUniform(context, GL_INT_VEC2, program, location, count);
691}
692
693bool ValidateProgramUniform3iv(Context *context,
694 GLuint program,
695 GLint location,
696 GLsizei count,
697 const GLint *value)
698{
699 return ValidateProgramUniform(context, GL_INT_VEC3, program, location, count);
700}
701
702bool ValidateProgramUniform4iv(Context *context,
703 GLuint program,
704 GLint location,
705 GLsizei count,
706 const GLint *value)
707{
708 return ValidateProgramUniform(context, GL_INT_VEC4, program, location, count);
709}
710
711bool ValidateProgramUniform1uiv(Context *context,
712 GLuint program,
713 GLint location,
714 GLsizei count,
715 const GLuint *value)
716{
717 return ValidateProgramUniform(context, GL_UNSIGNED_INT, program, location, count);
718}
719
720bool ValidateProgramUniform2uiv(Context *context,
721 GLuint program,
722 GLint location,
723 GLsizei count,
724 const GLuint *value)
725{
726 return ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC2, program, location, count);
727}
728
729bool ValidateProgramUniform3uiv(Context *context,
730 GLuint program,
731 GLint location,
732 GLsizei count,
733 const GLuint *value)
734{
735 return ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC3, program, location, count);
736}
737
738bool ValidateProgramUniform4uiv(Context *context,
739 GLuint program,
740 GLint location,
741 GLsizei count,
742 const GLuint *value)
743{
744 return ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC4, program, location, count);
745}
746
747bool ValidateProgramUniform1fv(Context *context,
748 GLuint program,
749 GLint location,
750 GLsizei count,
751 const GLfloat *value)
752{
753 return ValidateProgramUniform(context, GL_FLOAT, program, location, count);
754}
755
756bool ValidateProgramUniform2fv(Context *context,
757 GLuint program,
758 GLint location,
759 GLsizei count,
760 const GLfloat *value)
761{
762 return ValidateProgramUniform(context, GL_FLOAT_VEC2, program, location, count);
763}
764
765bool ValidateProgramUniform3fv(Context *context,
766 GLuint program,
767 GLint location,
768 GLsizei count,
769 const GLfloat *value)
770{
771 return ValidateProgramUniform(context, GL_FLOAT_VEC3, program, location, count);
772}
773
774bool ValidateProgramUniform4fv(Context *context,
775 GLuint program,
776 GLint location,
777 GLsizei count,
778 const GLfloat *value)
779{
780 return ValidateProgramUniform(context, GL_FLOAT_VEC4, program, location, count);
781}
782
783bool ValidateProgramUniformMatrix2fv(Context *context,
784 GLuint program,
785 GLint location,
786 GLsizei count,
787 GLboolean transpose,
788 const GLfloat *value)
789{
790 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2, program, location, count,
791 transpose);
792}
793
794bool ValidateProgramUniformMatrix3fv(Context *context,
795 GLuint program,
796 GLint location,
797 GLsizei count,
798 GLboolean transpose,
799 const GLfloat *value)
800{
801 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3, program, location, count,
802 transpose);
803}
804
805bool ValidateProgramUniformMatrix4fv(Context *context,
806 GLuint program,
807 GLint location,
808 GLsizei count,
809 GLboolean transpose,
810 const GLfloat *value)
811{
812 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4, program, location, count,
813 transpose);
814}
815
816bool ValidateProgramUniformMatrix2x3fv(Context *context,
817 GLuint program,
818 GLint location,
819 GLsizei count,
820 GLboolean transpose,
821 const GLfloat *value)
822{
823 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2x3, program, location, count,
824 transpose);
825}
826
827bool ValidateProgramUniformMatrix3x2fv(Context *context,
828 GLuint program,
829 GLint location,
830 GLsizei count,
831 GLboolean transpose,
832 const GLfloat *value)
833{
834 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3x2, program, location, count,
835 transpose);
836}
837
838bool ValidateProgramUniformMatrix2x4fv(Context *context,
839 GLuint program,
840 GLint location,
841 GLsizei count,
842 GLboolean transpose,
843 const GLfloat *value)
844{
845 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2x4, program, location, count,
846 transpose);
847}
848
849bool ValidateProgramUniformMatrix4x2fv(Context *context,
850 GLuint program,
851 GLint location,
852 GLsizei count,
853 GLboolean transpose,
854 const GLfloat *value)
855{
856 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4x2, program, location, count,
857 transpose);
858}
859
860bool ValidateProgramUniformMatrix3x4fv(Context *context,
861 GLuint program,
862 GLint location,
863 GLsizei count,
864 GLboolean transpose,
865 const GLfloat *value)
866{
867 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3x4, program, location, count,
868 transpose);
869}
870
871bool ValidateProgramUniformMatrix4x3fv(Context *context,
872 GLuint program,
873 GLint location,
874 GLsizei count,
875 GLboolean transpose,
876 const GLfloat *value)
877{
878 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4x3, program, location, count,
879 transpose);
880}
881
He Yunchao11b038b2016-11-22 21:24:04 +0800882bool ValidateGetTexLevelParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800883 TextureTarget target,
He Yunchao11b038b2016-11-22 21:24:04 +0800884 GLint level,
885 GLenum pname,
886 GLsizei *length)
887{
888 if (context->getClientVersion() < ES_3_1)
889 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700890 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
He Yunchao11b038b2016-11-22 21:24:04 +0800891 return false;
892 }
893
894 if (length)
895 {
896 *length = 0;
897 }
898
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800899 TextureType type = TextureTargetToType(target);
900
901 if (!ValidTexLevelDestinationTarget(context, type))
He Yunchao11b038b2016-11-22 21:24:04 +0800902 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700903 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
He Yunchao11b038b2016-11-22 21:24:04 +0800904 return false;
905 }
906
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800907 if (context->getTargetTexture(type) == nullptr)
He Yunchao11b038b2016-11-22 21:24:04 +0800908 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500909 context->handleError(InvalidEnum() << "No texture bound.");
He Yunchao11b038b2016-11-22 21:24:04 +0800910 return false;
911 }
912
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800913 if (!ValidMipLevel(context, type, level))
He Yunchao11b038b2016-11-22 21:24:04 +0800914 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500915 context->handleError(InvalidValue());
He Yunchao11b038b2016-11-22 21:24:04 +0800916 return false;
917 }
918
919 switch (pname)
920 {
921 case GL_TEXTURE_RED_TYPE:
922 case GL_TEXTURE_GREEN_TYPE:
923 case GL_TEXTURE_BLUE_TYPE:
924 case GL_TEXTURE_ALPHA_TYPE:
925 case GL_TEXTURE_DEPTH_TYPE:
926 break;
927 case GL_TEXTURE_RED_SIZE:
928 case GL_TEXTURE_GREEN_SIZE:
929 case GL_TEXTURE_BLUE_SIZE:
930 case GL_TEXTURE_ALPHA_SIZE:
931 case GL_TEXTURE_DEPTH_SIZE:
932 case GL_TEXTURE_STENCIL_SIZE:
933 case GL_TEXTURE_SHARED_SIZE:
934 break;
935 case GL_TEXTURE_INTERNAL_FORMAT:
936 case GL_TEXTURE_WIDTH:
937 case GL_TEXTURE_HEIGHT:
938 case GL_TEXTURE_DEPTH:
939 break;
940 case GL_TEXTURE_SAMPLES:
941 case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
942 break;
943 case GL_TEXTURE_COMPRESSED:
944 break;
945 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700946 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
He Yunchao11b038b2016-11-22 21:24:04 +0800947 return false;
948 }
949
950 if (length)
951 {
952 *length = 1;
953 }
954 return true;
955}
956
957bool ValidateGetTexLevelParameterfv(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800958 TextureTarget target,
He Yunchao11b038b2016-11-22 21:24:04 +0800959 GLint level,
960 GLenum pname,
961 GLfloat *params)
962{
963 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
964}
965
Brandon Jonesfe4bbe62018-04-06 13:50:14 -0700966bool ValidateGetTexLevelParameterfvRobustANGLE(Context *context,
967 TextureTarget target,
968 GLint level,
969 GLenum pname,
970 GLsizei bufSize,
971 GLsizei *length,
972 GLfloat *params)
973{
974 UNIMPLEMENTED();
975 return false;
976}
977
He Yunchao11b038b2016-11-22 21:24:04 +0800978bool ValidateGetTexLevelParameteriv(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800979 TextureTarget target,
He Yunchao11b038b2016-11-22 21:24:04 +0800980 GLint level,
981 GLenum pname,
982 GLint *params)
983{
984 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
985}
986
Brandon Jonesfe4bbe62018-04-06 13:50:14 -0700987bool ValidateGetTexLevelParameterivRobustANGLE(Context *context,
988 TextureTarget target,
989 GLint level,
990 GLenum pname,
991 GLsizei bufSize,
992 GLsizei *length,
993 GLint *params)
994{
995 UNIMPLEMENTED();
996 return false;
997}
998
Jiajia Qin5451d532017-11-16 17:16:34 +0800999bool ValidateTexStorage2DMultisample(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001000 TextureType target,
JiangYizhoubddc46b2016-12-09 09:50:51 +08001001 GLsizei samples,
1002 GLint internalFormat,
1003 GLsizei width,
1004 GLsizei height,
1005 GLboolean fixedSampleLocations)
1006{
1007 if (context->getClientVersion() < ES_3_1)
1008 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001009 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhoubddc46b2016-12-09 09:50:51 +08001010 return false;
1011 }
1012
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001013 if (target != TextureType::_2DMultisample)
JiangYizhoubddc46b2016-12-09 09:50:51 +08001014 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001015 context->handleError(InvalidEnum() << "Target must be TEXTURE_2D_MULTISAMPLE.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001016 return false;
1017 }
1018
1019 if (width < 1 || height < 1)
1020 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001021 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
JiangYizhoubddc46b2016-12-09 09:50:51 +08001022 return false;
1023 }
1024
1025 const Caps &caps = context->getCaps();
1026 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1027 static_cast<GLuint>(height) > caps.max2DTextureSize)
1028 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001029 context
1030 ->handleError(InvalidValue()
1031 << "Width and height must be less than or equal to GL_MAX_TEXTURE_SIZE.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001032 return false;
1033 }
1034
1035 if (samples == 0)
1036 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001037 context->handleError(InvalidValue() << "Samples may not be zero.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001038 return false;
1039 }
1040
1041 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
1042 if (!formatCaps.renderable)
1043 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001044 context->handleError(InvalidEnum() << "SizedInternalformat must be color-renderable, "
1045 "depth-renderable, or stencil-renderable.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001046 return false;
1047 }
1048
1049 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
1050 // is one of the unsized base internalformats listed in table 8.11.
Geoff Langca271392017-04-05 12:30:00 -04001051 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
1052 if (formatInfo.internalFormat == GL_NONE)
JiangYizhoubddc46b2016-12-09 09:50:51 +08001053 {
1054 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001055 InvalidEnum()
1056 << "Internalformat is one of the unsupported unsized base internalformats.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001057 return false;
1058 }
1059
1060 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1061 {
1062 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001063 InvalidOperation()
1064 << "Samples must not be greater than maximum supported value for the format.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001065 return false;
1066 }
1067
1068 Texture *texture = context->getTargetTexture(target);
1069 if (!texture || texture->id() == 0)
1070 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001071 context->handleError(InvalidOperation() << "Zero is bound to target.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001072 return false;
1073 }
1074
1075 if (texture->getImmutableFormat())
1076 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001077 context->handleError(InvalidOperation() << "The value of TEXTURE_IMMUTABLE_FORMAT for "
1078 "the texture currently bound to target on "
1079 "the active texture unit is true.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001080 return false;
1081 }
1082
1083 return true;
1084}
1085
1086bool ValidateGetMultisamplefv(Context *context, GLenum pname, GLuint index, GLfloat *val)
1087{
1088 if (context->getClientVersion() < ES_3_1)
1089 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001090 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhoubddc46b2016-12-09 09:50:51 +08001091 return false;
1092 }
1093
1094 if (pname != GL_SAMPLE_POSITION)
1095 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001096 context->handleError(InvalidEnum() << "Pname must be SAMPLE_POSITION.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001097 return false;
1098 }
1099
JiangYizhou5b03f472017-01-09 10:22:53 +08001100 Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04001101 GLint samples = framebuffer->getSamples(context);
JiangYizhou5b03f472017-01-09 10:22:53 +08001102
Jamie Madille98b1b52018-03-08 09:47:23 -05001103 if (index >= static_cast<GLuint>(samples))
JiangYizhoubddc46b2016-12-09 09:50:51 +08001104 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001105 context->handleError(InvalidValue() << "Index must be less than the value of SAMPLES.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001106 return false;
1107 }
1108
1109 return true;
1110}
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001111
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07001112bool ValidateGetMultisamplefvRobustANGLE(Context *context,
1113 GLenum pname,
1114 GLuint index,
1115 GLsizei bufSize,
1116 GLsizei *length,
1117 GLfloat *val)
1118{
1119 UNIMPLEMENTED();
1120 return false;
1121}
1122
Jiajia Qin5451d532017-11-16 17:16:34 +08001123bool ValidateFramebufferParameteri(Context *context, GLenum target, GLenum pname, GLint param)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001124{
1125 if (context->getClientVersion() < ES_3_1)
1126 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001127 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001128 return false;
1129 }
1130
Geoff Lange8afa902017-09-27 15:00:43 -04001131 if (!ValidFramebufferTarget(context, target))
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001132 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001133 context->handleError(InvalidEnum() << "Invalid framebuffer target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001134 return false;
1135 }
1136
1137 switch (pname)
1138 {
1139 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1140 {
1141 GLint maxWidth = context->getCaps().maxFramebufferWidth;
1142 if (param < 0 || param > maxWidth)
1143 {
1144 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001145 InvalidValue()
1146 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_WIDTH.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001147 return false;
1148 }
1149 break;
1150 }
1151 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1152 {
1153 GLint maxHeight = context->getCaps().maxFramebufferHeight;
1154 if (param < 0 || param > maxHeight)
1155 {
1156 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001157 InvalidValue()
1158 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_HEIGHT.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001159 return false;
1160 }
1161 break;
1162 }
1163 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1164 {
1165 GLint maxSamples = context->getCaps().maxFramebufferSamples;
1166 if (param < 0 || param > maxSamples)
1167 {
1168 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001169 InvalidValue()
1170 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_SAMPLES.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001171 return false;
1172 }
1173 break;
1174 }
1175 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1176 {
1177 break;
1178 }
Jiawei Shaob1e91382018-05-17 14:33:55 +08001179 case GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT:
1180 {
1181 if (!context->getExtensions().geometryShader)
1182 {
1183 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
1184 return false;
1185 }
1186 GLint maxLayers = context->getCaps().maxFramebufferLayers;
1187 if (param < 0 || param > maxLayers)
1188 {
1189 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidFramebufferLayer);
1190 return false;
1191 }
1192 break;
1193 }
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001194 default:
1195 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001196 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001197 return false;
1198 }
1199 }
1200
1201 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
1202 ASSERT(framebuffer);
1203 if (framebuffer->id() == 0)
1204 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001205 context->handleError(InvalidOperation() << "Default framebuffer is bound to target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001206 return false;
1207 }
1208 return true;
1209}
1210
Jiajia Qin5451d532017-11-16 17:16:34 +08001211bool ValidateGetFramebufferParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001212{
1213 if (context->getClientVersion() < ES_3_1)
1214 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001215 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001216 return false;
1217 }
1218
Geoff Lange8afa902017-09-27 15:00:43 -04001219 if (!ValidFramebufferTarget(context, target))
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001220 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001221 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001222 return false;
1223 }
1224
1225 switch (pname)
1226 {
1227 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1228 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1229 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1230 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1231 break;
Jiawei Shaob1e91382018-05-17 14:33:55 +08001232 case GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT:
1233 if (!context->getExtensions().geometryShader)
1234 {
1235 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
1236 return false;
1237 }
1238 break;
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001239 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001240 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001241 return false;
1242 }
1243
1244 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
1245 ASSERT(framebuffer);
1246
1247 if (framebuffer->id() == 0)
1248 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001249 context->handleError(InvalidOperation() << "Default framebuffer is bound to target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001250 return false;
1251 }
1252 return true;
1253}
1254
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07001255bool ValidateGetFramebufferParameterivRobustANGLE(Context *context,
1256 GLenum target,
1257 GLenum pname,
1258 GLsizei bufSize,
1259 GLsizei *length,
1260 GLint *params)
1261{
1262 UNIMPLEMENTED();
1263 return false;
1264}
1265
jchen1015015f72017-03-16 13:54:21 +08001266bool ValidateGetProgramResourceIndex(Context *context,
1267 GLuint program,
1268 GLenum programInterface,
1269 const GLchar *name)
1270{
1271 if (context->getClientVersion() < ES_3_1)
1272 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001273 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen1015015f72017-03-16 13:54:21 +08001274 return false;
1275 }
1276
1277 Program *programObject = GetValidProgram(context, program);
1278 if (programObject == nullptr)
1279 {
1280 return false;
1281 }
1282
1283 if (!ValidateNamedProgramInterface(programInterface))
1284 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001285 context->handleError(InvalidEnum() << "Invalid program interface: 0x" << std::hex
1286 << std::uppercase << programInterface);
jchen1015015f72017-03-16 13:54:21 +08001287 return false;
1288 }
Shao80957d92017-02-20 21:25:59 +08001289
1290 return true;
1291}
1292
Jamie Madill5b772312018-03-08 20:28:32 -05001293bool ValidateBindVertexBuffer(Context *context,
Shao80957d92017-02-20 21:25:59 +08001294 GLuint bindingIndex,
1295 GLuint buffer,
1296 GLintptr offset,
1297 GLsizei stride)
1298{
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 if (!context->isBufferGenerated(buffer))
1306 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001307 context->handleError(InvalidOperation() << "Buffer is not generated.");
Shao80957d92017-02-20 21:25:59 +08001308 return false;
1309 }
1310
1311 const Caps &caps = context->getCaps();
1312 if (bindingIndex >= caps.maxVertexAttribBindings)
1313 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001314 context->handleError(InvalidValue()
1315 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08001316 return false;
1317 }
1318
1319 if (offset < 0)
1320 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001321 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Shao80957d92017-02-20 21:25:59 +08001322 return false;
1323 }
1324
1325 if (stride < 0 || stride > caps.maxVertexAttribStride)
1326 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001327 context->handleError(InvalidValue()
1328 << "stride must be between 0 and MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08001329 return false;
1330 }
1331
1332 // [OpenGL ES 3.1] Section 10.3.1 page 244:
1333 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
1334 if (context->getGLState().getVertexArrayId() == 0)
1335 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001336 context->handleError(InvalidOperation() << "Default vertex array buffer is bound.");
Shao80957d92017-02-20 21:25:59 +08001337 return false;
1338 }
1339
1340 return true;
1341}
1342
Jamie Madill5b772312018-03-08 20:28:32 -05001343bool ValidateVertexBindingDivisor(Context *context, GLuint bindingIndex, GLuint divisor)
Shao80957d92017-02-20 21:25:59 +08001344{
1345 if (context->getClientVersion() < ES_3_1)
1346 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001347 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +08001348 return false;
1349 }
1350
1351 const Caps &caps = context->getCaps();
1352 if (bindingIndex >= caps.maxVertexAttribBindings)
1353 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001354 context->handleError(InvalidValue()
1355 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08001356 return false;
1357 }
1358
1359 // [OpenGL ES 3.1] Section 10.3.1 page 243:
1360 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
1361 if (context->getGLState().getVertexArrayId() == 0)
1362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001363 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +08001364 return false;
1365 }
1366
1367 return true;
1368}
1369
Jamie Madill5b772312018-03-08 20:28:32 -05001370bool ValidateVertexAttribFormat(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08001371 GLuint attribindex,
Shao80957d92017-02-20 21:25:59 +08001372 GLint size,
1373 GLenum type,
Jiajia Qin5451d532017-11-16 17:16:34 +08001374 GLboolean normalized,
1375 GLuint relativeoffset)
Shao80957d92017-02-20 21:25:59 +08001376{
Jiajia Qin5451d532017-11-16 17:16:34 +08001377 return ValidateVertexAttribFormatCommon(context, attribindex, size, type, relativeoffset,
1378 false);
1379}
Shao80957d92017-02-20 21:25:59 +08001380
Jamie Madill5b772312018-03-08 20:28:32 -05001381bool ValidateVertexAttribIFormat(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08001382 GLuint attribindex,
1383 GLint size,
1384 GLenum type,
1385 GLuint relativeoffset)
1386{
1387 return ValidateVertexAttribFormatCommon(context, attribindex, size, type, relativeoffset, true);
Shao80957d92017-02-20 21:25:59 +08001388}
1389
Jamie Madill5b772312018-03-08 20:28:32 -05001390bool ValidateVertexAttribBinding(Context *context, GLuint attribIndex, GLuint bindingIndex)
Shao80957d92017-02-20 21:25:59 +08001391{
1392 if (context->getClientVersion() < ES_3_1)
1393 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001394 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +08001395 return false;
1396 }
1397
1398 // [OpenGL ES 3.1] Section 10.3.1 page 243:
1399 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
1400 if (context->getGLState().getVertexArrayId() == 0)
1401 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001402 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +08001403 return false;
1404 }
1405
1406 const Caps &caps = context->getCaps();
1407 if (attribIndex >= caps.maxVertexAttributes)
1408 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001409 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08001410 return false;
1411 }
1412
1413 if (bindingIndex >= caps.maxVertexAttribBindings)
1414 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001415 context->handleError(InvalidValue()
1416 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS");
Shao80957d92017-02-20 21:25:59 +08001417 return false;
1418 }
1419
jchen1015015f72017-03-16 13:54:21 +08001420 return true;
1421}
1422
jchen10fd7c3b52017-03-21 15:36:03 +08001423bool ValidateGetProgramResourceName(Context *context,
1424 GLuint program,
1425 GLenum programInterface,
1426 GLuint index,
1427 GLsizei bufSize,
1428 GLsizei *length,
1429 GLchar *name)
1430{
1431 if (context->getClientVersion() < ES_3_1)
1432 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001433 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen10fd7c3b52017-03-21 15:36:03 +08001434 return false;
1435 }
1436
1437 Program *programObject = GetValidProgram(context, program);
1438 if (programObject == nullptr)
1439 {
1440 return false;
1441 }
1442
1443 if (!ValidateNamedProgramInterface(programInterface))
1444 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001445 context->handleError(InvalidEnum() << "Invalid program interface: 0x" << std::hex
1446 << std::uppercase << programInterface);
jchen10fd7c3b52017-03-21 15:36:03 +08001447 return false;
1448 }
1449
1450 if (!ValidateProgramResourceIndex(programObject, programInterface, index))
1451 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001452 context->handleError(InvalidValue() << "Invalid index: " << index);
jchen10fd7c3b52017-03-21 15:36:03 +08001453 return false;
1454 }
1455
1456 if (bufSize < 0)
1457 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001458 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
jchen10fd7c3b52017-03-21 15:36:03 +08001459 return false;
1460 }
1461
1462 return true;
1463}
1464
Xinghua Cao2b396592017-03-29 15:36:04 +08001465bool ValidateDispatchCompute(Context *context,
1466 GLuint numGroupsX,
1467 GLuint numGroupsY,
1468 GLuint numGroupsZ)
1469{
1470 if (context->getClientVersion() < ES_3_1)
1471 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001472 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Xinghua Cao2b396592017-03-29 15:36:04 +08001473 return false;
1474 }
1475
1476 const State &state = context->getGLState();
1477 Program *program = state.getProgram();
1478
Jiawei Shao385b3e02018-03-21 09:43:28 +08001479 if (program == nullptr || !program->hasLinkedShaderStage(ShaderType::Compute))
Xinghua Cao2b396592017-03-29 15:36:04 +08001480 {
Qin Jiajia62fcf622017-11-30 16:16:12 +08001481 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveProgramWithComputeShader);
Xinghua Cao2b396592017-03-29 15:36:04 +08001482 return false;
1483 }
1484
1485 const Caps &caps = context->getCaps();
1486 if (numGroupsX > caps.maxComputeWorkGroupCount[0])
1487 {
1488 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001489 InvalidValue() << "num_groups_x cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[0]="
1490 << caps.maxComputeWorkGroupCount[0]);
Xinghua Cao2b396592017-03-29 15:36:04 +08001491 return false;
1492 }
1493 if (numGroupsY > caps.maxComputeWorkGroupCount[1])
1494 {
1495 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001496 InvalidValue() << "num_groups_y cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[1]="
1497 << caps.maxComputeWorkGroupCount[1]);
Xinghua Cao2b396592017-03-29 15:36:04 +08001498 return false;
1499 }
1500 if (numGroupsZ > caps.maxComputeWorkGroupCount[2])
1501 {
1502 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001503 InvalidValue() << "num_groups_z cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[2]="
1504 << caps.maxComputeWorkGroupCount[2]);
Xinghua Cao2b396592017-03-29 15:36:04 +08001505 return false;
1506 }
1507
1508 return true;
1509}
1510
Jiajia Qin5451d532017-11-16 17:16:34 +08001511bool ValidateDispatchComputeIndirect(Context *context, GLintptr indirect)
1512{
Qin Jiajia62fcf622017-11-30 16:16:12 +08001513 if (context->getClientVersion() < ES_3_1)
1514 {
1515 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1516 return false;
1517 }
1518
1519 const State &state = context->getGLState();
1520 Program *program = state.getProgram();
1521
Jiawei Shao385b3e02018-03-21 09:43:28 +08001522 if (program == nullptr || !program->hasLinkedShaderStage(ShaderType::Compute))
Qin Jiajia62fcf622017-11-30 16:16:12 +08001523 {
1524 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveProgramWithComputeShader);
1525 return false;
1526 }
1527
Qin Jiajia62fcf622017-11-30 16:16:12 +08001528 if (indirect < 0)
1529 {
1530 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
1531 return false;
1532 }
1533
1534 if ((indirect & (sizeof(GLuint) - 1)) != 0)
1535 {
Qin Jiajiaa4ef8432018-02-22 16:02:24 +08001536 ANGLE_VALIDATION_ERR(context, InvalidValue(), OffsetMustBeMultipleOfUint);
1537 return false;
1538 }
1539
Jamie Madill5b772312018-03-08 20:28:32 -05001540 Buffer *dispatchIndirectBuffer = state.getTargetBuffer(BufferBinding::DispatchIndirect);
Qin Jiajiaa4ef8432018-02-22 16:02:24 +08001541 if (!dispatchIndirectBuffer)
1542 {
1543 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DispatchIndirectBufferNotBound);
Qin Jiajia62fcf622017-11-30 16:16:12 +08001544 return false;
1545 }
1546
1547 CheckedNumeric<GLuint64> checkedOffset(static_cast<GLuint64>(indirect));
1548 auto checkedSum = checkedOffset + static_cast<GLuint64>(3 * sizeof(GLuint));
1549 if (!checkedSum.IsValid() ||
1550 checkedSum.ValueOrDie() > static_cast<GLuint64>(dispatchIndirectBuffer->getSize()))
1551 {
1552 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
1553 return false;
1554 }
1555
1556 return true;
Jiajia Qin5451d532017-11-16 17:16:34 +08001557}
1558
Xinghua Cao65ec0b22017-03-28 16:10:52 +08001559bool ValidateBindImageTexture(Context *context,
1560 GLuint unit,
1561 GLuint texture,
1562 GLint level,
1563 GLboolean layered,
1564 GLint layer,
1565 GLenum access,
1566 GLenum format)
1567{
1568 GLuint maxImageUnits = context->getCaps().maxImageUnits;
1569 if (unit >= maxImageUnits)
1570 {
1571 context->handleError(InvalidValue()
1572 << "unit cannot be greater than or equal than MAX_IMAGE_UNITS = "
1573 << maxImageUnits);
1574 return false;
1575 }
1576
1577 if (level < 0)
1578 {
1579 context->handleError(InvalidValue() << "level is negative.");
1580 return false;
1581 }
1582
1583 if (layer < 0)
1584 {
1585 context->handleError(InvalidValue() << "layer is negative.");
1586 return false;
1587 }
1588
1589 if (access != GL_READ_ONLY && access != GL_WRITE_ONLY && access != GL_READ_WRITE)
1590 {
1591 context->handleError(InvalidEnum() << "access is not one of the supported tokens.");
1592 return false;
1593 }
1594
1595 switch (format)
1596 {
1597 case GL_RGBA32F:
1598 case GL_RGBA16F:
1599 case GL_R32F:
1600 case GL_RGBA32UI:
1601 case GL_RGBA16UI:
1602 case GL_RGBA8UI:
1603 case GL_R32UI:
1604 case GL_RGBA32I:
1605 case GL_RGBA16I:
1606 case GL_RGBA8I:
1607 case GL_R32I:
1608 case GL_RGBA8:
1609 case GL_RGBA8_SNORM:
1610 break;
1611 default:
1612 context->handleError(InvalidValue()
1613 << "format is not one of supported image unit formats.");
1614 return false;
1615 }
1616
1617 if (texture != 0)
1618 {
1619 Texture *tex = context->getTexture(texture);
1620
1621 if (tex == nullptr)
1622 {
1623 context->handleError(InvalidValue()
1624 << "texture is not the name of an existing texture object.");
1625 return false;
1626 }
1627
1628 if (!tex->getImmutableFormat())
1629 {
1630 context->handleError(InvalidOperation()
1631 << "texture is not the name of an immutable texture object.");
1632 return false;
1633 }
1634 }
1635
1636 return true;
1637}
jchen10191381f2017-04-11 13:59:04 +08001638
1639bool ValidateGetProgramResourceLocation(Context *context,
1640 GLuint program,
1641 GLenum programInterface,
1642 const GLchar *name)
1643{
1644 if (context->getClientVersion() < ES_3_1)
1645 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001646 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen10191381f2017-04-11 13:59:04 +08001647 return false;
1648 }
1649
1650 Program *programObject = GetValidProgram(context, program);
1651 if (programObject == nullptr)
1652 {
1653 return false;
1654 }
1655
1656 if (!programObject->isLinked())
1657 {
1658 context->handleError(InvalidOperation() << "Program is not successfully linked.");
1659 return false;
1660 }
1661
1662 if (!ValidateLocationProgramInterface(programInterface))
1663 {
1664 context->handleError(InvalidEnum() << "Invalid program interface.");
1665 return false;
1666 }
1667 return true;
1668}
1669
jchen10880683b2017-04-12 16:21:55 +08001670bool ValidateGetProgramResourceiv(Context *context,
1671 GLuint program,
1672 GLenum programInterface,
1673 GLuint index,
1674 GLsizei propCount,
1675 const GLenum *props,
1676 GLsizei bufSize,
1677 GLsizei *length,
1678 GLint *params)
1679{
1680 if (context->getClientVersion() < ES_3_1)
1681 {
jchen10d9cd7b72017-08-30 15:04:25 +08001682 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen10880683b2017-04-12 16:21:55 +08001683 return false;
1684 }
1685
1686 Program *programObject = GetValidProgram(context, program);
1687 if (programObject == nullptr)
1688 {
1689 return false;
1690 }
1691 if (!ValidateProgramInterface(programInterface))
1692 {
1693 context->handleError(InvalidEnum() << "Invalid program interface.");
1694 return false;
1695 }
1696 if (propCount <= 0)
1697 {
1698 context->handleError(InvalidValue() << "Invalid propCount.");
1699 return false;
1700 }
1701 if (bufSize < 0)
1702 {
1703 context->handleError(InvalidValue() << "Invalid bufSize.");
1704 return false;
1705 }
1706 if (!ValidateProgramResourceIndex(programObject, programInterface, index))
1707 {
1708 context->handleError(InvalidValue() << "Invalid index: " << index);
1709 return false;
1710 }
1711 for (GLsizei i = 0; i < propCount; i++)
1712 {
Jiawei Shaoc6f82872018-04-24 14:14:50 +08001713 if (!ValidateProgramResourceProperty(context, props[i]))
jchen10880683b2017-04-12 16:21:55 +08001714 {
1715 context->handleError(InvalidEnum() << "Invalid prop.");
1716 return false;
1717 }
1718 if (!ValidateProgramResourcePropertyByInterface(props[i], programInterface))
1719 {
1720 context->handleError(InvalidOperation() << "Not an allowed prop for interface");
1721 return false;
1722 }
1723 }
1724 return true;
1725}
1726
jchen10d9cd7b72017-08-30 15:04:25 +08001727bool ValidateGetProgramInterfaceiv(Context *context,
1728 GLuint program,
1729 GLenum programInterface,
1730 GLenum pname,
1731 GLint *params)
1732{
1733 if (context->getClientVersion() < ES_3_1)
1734 {
1735 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1736 return false;
1737 }
1738
1739 Program *programObject = GetValidProgram(context, program);
1740 if (programObject == nullptr)
1741 {
1742 return false;
1743 }
1744
1745 if (!ValidateProgramInterface(programInterface))
1746 {
1747 context->handleError(InvalidEnum() << "Invalid program interface.");
1748 return false;
1749 }
1750
1751 switch (pname)
1752 {
1753 case GL_ACTIVE_RESOURCES:
1754 case GL_MAX_NAME_LENGTH:
1755 case GL_MAX_NUM_ACTIVE_VARIABLES:
1756 break;
1757
1758 default:
1759 context->handleError(InvalidEnum() << "Unknown property of program interface.");
1760 return false;
1761 }
1762
1763 if (pname == GL_MAX_NAME_LENGTH && programInterface == GL_ATOMIC_COUNTER_BUFFER)
1764 {
1765 context->handleError(InvalidOperation()
1766 << "Active atomic counter resources are not assigned name strings.");
1767 return false;
1768 }
1769
1770 if (pname == GL_MAX_NUM_ACTIVE_VARIABLES)
1771 {
1772 switch (programInterface)
1773 {
1774 case GL_ATOMIC_COUNTER_BUFFER:
1775 case GL_SHADER_STORAGE_BLOCK:
1776 case GL_UNIFORM_BLOCK:
1777 break;
1778
1779 default:
1780 context->handleError(
1781 InvalidOperation()
1782 << "MAX_NUM_ACTIVE_VARIABLES requires a buffer or block interface.");
1783 return false;
1784 }
1785 }
1786
1787 return true;
1788}
1789
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07001790bool ValidateGetProgramInterfaceivRobustANGLE(Context *context,
1791 GLuint program,
1792 GLenum programInterface,
1793 GLenum pname,
1794 GLsizei bufSize,
1795 GLsizei *length,
1796 GLint *params)
1797{
1798 UNIMPLEMENTED();
1799 return false;
1800}
1801
Yunchao Hea336b902017-08-02 16:05:21 +08001802static bool ValidateGenOrDeleteES31(Context *context, GLint n)
1803{
1804 if (context->getClientVersion() < ES_3_1)
1805 {
1806 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1807 return false;
1808 }
1809
1810 return ValidateGenOrDelete(context, n);
1811}
1812
1813bool ValidateGenProgramPipelines(Context *context, GLint n, GLuint *)
1814{
1815 return ValidateGenOrDeleteES31(context, n);
1816}
1817
1818bool ValidateDeleteProgramPipelines(Context *context, GLint n, const GLuint *)
1819{
1820 return ValidateGenOrDeleteES31(context, n);
1821}
1822
1823bool ValidateBindProgramPipeline(Context *context, GLuint pipeline)
1824{
1825 if (context->getClientVersion() < ES_3_1)
1826 {
1827 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1828 return false;
1829 }
1830
1831 if (!context->isProgramPipelineGenerated(pipeline))
1832 {
1833 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
1834 return false;
1835 }
1836
1837 return true;
1838}
1839
1840bool ValidateIsProgramPipeline(Context *context, GLuint pipeline)
1841{
1842 if (context->getClientVersion() < ES_3_1)
1843 {
1844 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1845 return false;
1846 }
1847
1848 return true;
1849}
1850
Jiajia Qin5451d532017-11-16 17:16:34 +08001851bool ValidateUseProgramStages(Context *context, GLuint pipeline, GLbitfield stages, GLuint program)
1852{
1853 UNIMPLEMENTED();
1854 return false;
1855}
1856
1857bool ValidateActiveShaderProgram(Context *context, GLuint pipeline, GLuint program)
1858{
1859 UNIMPLEMENTED();
1860 return false;
1861}
1862
1863bool ValidateCreateShaderProgramv(Context *context,
Jiawei Shao385b3e02018-03-21 09:43:28 +08001864 ShaderType type,
Jiajia Qin5451d532017-11-16 17:16:34 +08001865 GLsizei count,
1866 const GLchar *const *strings)
1867{
1868 UNIMPLEMENTED();
1869 return false;
1870}
1871
1872bool ValidateGetProgramPipelineiv(Context *context, GLuint pipeline, GLenum pname, GLint *params)
1873{
1874 UNIMPLEMENTED();
1875 return false;
1876}
1877
1878bool ValidateValidateProgramPipeline(Context *context, GLuint pipeline)
1879{
1880 UNIMPLEMENTED();
1881 return false;
1882}
1883
1884bool ValidateGetProgramPipelineInfoLog(Context *context,
1885 GLuint pipeline,
1886 GLsizei bufSize,
1887 GLsizei *length,
1888 GLchar *infoLog)
1889{
1890 UNIMPLEMENTED();
1891 return false;
1892}
1893
1894bool ValidateMemoryBarrier(Context *context, GLbitfield barriers)
1895{
Xinghua Cao89c422a2017-11-29 18:24:20 +08001896 if (context->getClientVersion() < ES_3_1)
1897 {
1898 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1899 return false;
1900 }
1901
1902 if (barriers == GL_ALL_BARRIER_BITS)
1903 {
1904 return true;
1905 }
1906
1907 GLbitfield supported_barrier_bits =
1908 GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT |
1909 GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT |
1910 GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT |
1911 GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT |
1912 GL_ATOMIC_COUNTER_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT;
1913 if ((barriers & ~supported_barrier_bits) != 0)
1914 {
1915 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMemoryBarrierBit);
1916 return false;
1917 }
1918
1919 return true;
Jiajia Qin5451d532017-11-16 17:16:34 +08001920}
1921
1922bool ValidateMemoryBarrierByRegion(Context *context, GLbitfield barriers)
1923{
Xinghua Cao89c422a2017-11-29 18:24:20 +08001924 if (context->getClientVersion() < ES_3_1)
1925 {
1926 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1927 return false;
1928 }
1929
1930 if (barriers == GL_ALL_BARRIER_BITS)
1931 {
1932 return true;
1933 }
1934
1935 GLbitfield supported_barrier_bits = GL_ATOMIC_COUNTER_BARRIER_BIT | GL_FRAMEBUFFER_BARRIER_BIT |
1936 GL_SHADER_IMAGE_ACCESS_BARRIER_BIT |
1937 GL_SHADER_STORAGE_BARRIER_BIT |
1938 GL_TEXTURE_FETCH_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT;
1939 if ((barriers & ~supported_barrier_bits) != 0)
1940 {
1941 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMemoryBarrierBit);
1942 return false;
1943 }
1944
1945 return true;
Jiajia Qin5451d532017-11-16 17:16:34 +08001946}
1947
1948bool ValidateSampleMaski(Context *context, GLuint maskNumber, GLbitfield mask)
Jiawei Shaodb342272017-09-27 10:21:45 +08001949{
1950 if (context->getClientVersion() < ES_3_1)
1951 {
1952 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1953 return false;
1954 }
1955
1956 if (maskNumber >= context->getCaps().maxSampleMaskWords)
1957 {
1958 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
1959 return false;
1960 }
1961
1962 return true;
1963}
1964
Martin Radev66fb8202016-07-28 11:45:20 +03001965} // namespace gl