blob: 86d0b552722fa9febaa95ed5b506a51375856a52 [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 Madill493f9572018-05-24 19:52:15 -0400413bool ValidateDrawIndirectBase(Context *context, PrimitiveMode 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 Madill493f9572018-05-24 19:52:15 -0400471bool ValidateDrawArraysIndirect(Context *context, PrimitiveMode mode, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800472{
Jamie Madill493f9572018-05-24 19:52:15 -0400473 const State &state = context->getGLState();
474 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 Madill493f9572018-05-24 19:52:15 -0400519bool ValidateDrawElementsIndirect(Context *context,
520 PrimitiveMode mode,
521 GLenum type,
522 const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800523{
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800524 if (!ValidateDrawElementsBase(context, mode, type))
525 {
Jiajia Qind9671222016-11-29 16:30:31 +0800526 return false;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800527 }
Jiajia Qind9671222016-11-29 16:30:31 +0800528
Jamie Madill493f9572018-05-24 19:52:15 -0400529 const State &state = context->getGLState();
530 const VertexArray *vao = state.getVertexArray();
531 Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jiajia Qind9671222016-11-29 16:30:31 +0800532 if (!elementArrayBuffer)
533 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500534 context->handleError(InvalidOperation() << "zero is bound to ELEMENT_ARRAY_BUFFER");
Jiajia Qind9671222016-11-29 16:30:31 +0800535 return false;
536 }
537
538 if (!ValidateDrawIndirectBase(context, mode, indirect))
539 return false;
540
Jamie Madill5b772312018-03-08 20:28:32 -0500541 Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
Jiajia Qind9671222016-11-29 16:30:31 +0800542 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
543 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawElementsIndirectCommand
544 // which's size is 5 * sizeof(uint).
545 auto checkedSum = checkedOffset + 5 * sizeof(GLuint);
546 if (!checkedSum.IsValid() ||
547 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
548 {
549 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500550 InvalidOperation()
551 << "the command would source data beyond the end of the buffer object.");
Jiajia Qind9671222016-11-29 16:30:31 +0800552 return false;
553 }
554
555 return true;
556}
557
Jiajia Qin5451d532017-11-16 17:16:34 +0800558bool ValidateProgramUniform1i(Context *context, GLuint program, GLint location, GLint v0)
559{
560 return ValidateProgramUniform1iv(context, program, location, 1, &v0);
561}
562
563bool ValidateProgramUniform2i(Context *context, GLuint program, GLint location, GLint v0, GLint v1)
564{
565 GLint xy[2] = {v0, v1};
566 return ValidateProgramUniform2iv(context, program, location, 1, xy);
567}
568
569bool ValidateProgramUniform3i(Context *context,
570 GLuint program,
571 GLint location,
572 GLint v0,
573 GLint v1,
574 GLint v2)
575{
576 GLint xyz[3] = {v0, v1, v2};
577 return ValidateProgramUniform3iv(context, program, location, 1, xyz);
578}
579
580bool ValidateProgramUniform4i(Context *context,
581 GLuint program,
582 GLint location,
583 GLint v0,
584 GLint v1,
585 GLint v2,
586 GLint v3)
587{
588 GLint xyzw[4] = {v0, v1, v2, v3};
589 return ValidateProgramUniform4iv(context, program, location, 1, xyzw);
590}
591
592bool ValidateProgramUniform1ui(Context *context, GLuint program, GLint location, GLuint v0)
593{
594 return ValidateProgramUniform1uiv(context, program, location, 1, &v0);
595}
596
597bool ValidateProgramUniform2ui(Context *context,
598 GLuint program,
599 GLint location,
600 GLuint v0,
601 GLuint v1)
602{
603 GLuint xy[2] = {v0, v1};
604 return ValidateProgramUniform2uiv(context, program, location, 1, xy);
605}
606
607bool ValidateProgramUniform3ui(Context *context,
608 GLuint program,
609 GLint location,
610 GLuint v0,
611 GLuint v1,
612 GLuint v2)
613{
614 GLuint xyz[3] = {v0, v1, v2};
615 return ValidateProgramUniform3uiv(context, program, location, 1, xyz);
616}
617
618bool ValidateProgramUniform4ui(Context *context,
619 GLuint program,
620 GLint location,
621 GLuint v0,
622 GLuint v1,
623 GLuint v2,
624 GLuint v3)
625{
626 GLuint xyzw[4] = {v0, v1, v2, v3};
627 return ValidateProgramUniform4uiv(context, program, location, 1, xyzw);
628}
629
630bool ValidateProgramUniform1f(Context *context, GLuint program, GLint location, GLfloat v0)
631{
632 return ValidateProgramUniform1fv(context, program, location, 1, &v0);
633}
634
635bool ValidateProgramUniform2f(Context *context,
636 GLuint program,
637 GLint location,
638 GLfloat v0,
639 GLfloat v1)
640{
641 GLfloat xy[2] = {v0, v1};
642 return ValidateProgramUniform2fv(context, program, location, 1, xy);
643}
644
645bool ValidateProgramUniform3f(Context *context,
646 GLuint program,
647 GLint location,
648 GLfloat v0,
649 GLfloat v1,
650 GLfloat v2)
651{
652 GLfloat xyz[3] = {v0, v1, v2};
653 return ValidateProgramUniform3fv(context, program, location, 1, xyz);
654}
655
656bool ValidateProgramUniform4f(Context *context,
657 GLuint program,
658 GLint location,
659 GLfloat v0,
660 GLfloat v1,
661 GLfloat v2,
662 GLfloat v3)
663{
664 GLfloat xyzw[4] = {v0, v1, v2, v3};
665 return ValidateProgramUniform4fv(context, program, location, 1, xyzw);
666}
667
668bool ValidateProgramUniform1iv(Context *context,
669 GLuint program,
670 GLint location,
671 GLsizei count,
672 const GLint *value)
673{
674 // Check for ES31 program uniform entry points
675 if (context->getClientVersion() < Version(3, 1))
676 {
677 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
678 return false;
679 }
680
681 const LinkedUniform *uniform = nullptr;
Jamie Madill5b772312018-03-08 20:28:32 -0500682 Program *programObject = GetValidProgram(context, program);
Jiajia Qin5451d532017-11-16 17:16:34 +0800683 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
684 ValidateUniform1ivValue(context, uniform->type, count, value);
685}
686
687bool ValidateProgramUniform2iv(Context *context,
688 GLuint program,
689 GLint location,
690 GLsizei count,
691 const GLint *value)
692{
693 return ValidateProgramUniform(context, GL_INT_VEC2, program, location, count);
694}
695
696bool ValidateProgramUniform3iv(Context *context,
697 GLuint program,
698 GLint location,
699 GLsizei count,
700 const GLint *value)
701{
702 return ValidateProgramUniform(context, GL_INT_VEC3, program, location, count);
703}
704
705bool ValidateProgramUniform4iv(Context *context,
706 GLuint program,
707 GLint location,
708 GLsizei count,
709 const GLint *value)
710{
711 return ValidateProgramUniform(context, GL_INT_VEC4, program, location, count);
712}
713
714bool ValidateProgramUniform1uiv(Context *context,
715 GLuint program,
716 GLint location,
717 GLsizei count,
718 const GLuint *value)
719{
720 return ValidateProgramUniform(context, GL_UNSIGNED_INT, program, location, count);
721}
722
723bool ValidateProgramUniform2uiv(Context *context,
724 GLuint program,
725 GLint location,
726 GLsizei count,
727 const GLuint *value)
728{
729 return ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC2, program, location, count);
730}
731
732bool ValidateProgramUniform3uiv(Context *context,
733 GLuint program,
734 GLint location,
735 GLsizei count,
736 const GLuint *value)
737{
738 return ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC3, program, location, count);
739}
740
741bool ValidateProgramUniform4uiv(Context *context,
742 GLuint program,
743 GLint location,
744 GLsizei count,
745 const GLuint *value)
746{
747 return ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC4, program, location, count);
748}
749
750bool ValidateProgramUniform1fv(Context *context,
751 GLuint program,
752 GLint location,
753 GLsizei count,
754 const GLfloat *value)
755{
756 return ValidateProgramUniform(context, GL_FLOAT, program, location, count);
757}
758
759bool ValidateProgramUniform2fv(Context *context,
760 GLuint program,
761 GLint location,
762 GLsizei count,
763 const GLfloat *value)
764{
765 return ValidateProgramUniform(context, GL_FLOAT_VEC2, program, location, count);
766}
767
768bool ValidateProgramUniform3fv(Context *context,
769 GLuint program,
770 GLint location,
771 GLsizei count,
772 const GLfloat *value)
773{
774 return ValidateProgramUniform(context, GL_FLOAT_VEC3, program, location, count);
775}
776
777bool ValidateProgramUniform4fv(Context *context,
778 GLuint program,
779 GLint location,
780 GLsizei count,
781 const GLfloat *value)
782{
783 return ValidateProgramUniform(context, GL_FLOAT_VEC4, program, location, count);
784}
785
786bool ValidateProgramUniformMatrix2fv(Context *context,
787 GLuint program,
788 GLint location,
789 GLsizei count,
790 GLboolean transpose,
791 const GLfloat *value)
792{
793 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2, program, location, count,
794 transpose);
795}
796
797bool ValidateProgramUniformMatrix3fv(Context *context,
798 GLuint program,
799 GLint location,
800 GLsizei count,
801 GLboolean transpose,
802 const GLfloat *value)
803{
804 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3, program, location, count,
805 transpose);
806}
807
808bool ValidateProgramUniformMatrix4fv(Context *context,
809 GLuint program,
810 GLint location,
811 GLsizei count,
812 GLboolean transpose,
813 const GLfloat *value)
814{
815 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4, program, location, count,
816 transpose);
817}
818
819bool ValidateProgramUniformMatrix2x3fv(Context *context,
820 GLuint program,
821 GLint location,
822 GLsizei count,
823 GLboolean transpose,
824 const GLfloat *value)
825{
826 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2x3, program, location, count,
827 transpose);
828}
829
830bool ValidateProgramUniformMatrix3x2fv(Context *context,
831 GLuint program,
832 GLint location,
833 GLsizei count,
834 GLboolean transpose,
835 const GLfloat *value)
836{
837 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3x2, program, location, count,
838 transpose);
839}
840
841bool ValidateProgramUniformMatrix2x4fv(Context *context,
842 GLuint program,
843 GLint location,
844 GLsizei count,
845 GLboolean transpose,
846 const GLfloat *value)
847{
848 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2x4, program, location, count,
849 transpose);
850}
851
852bool ValidateProgramUniformMatrix4x2fv(Context *context,
853 GLuint program,
854 GLint location,
855 GLsizei count,
856 GLboolean transpose,
857 const GLfloat *value)
858{
859 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4x2, program, location, count,
860 transpose);
861}
862
863bool ValidateProgramUniformMatrix3x4fv(Context *context,
864 GLuint program,
865 GLint location,
866 GLsizei count,
867 GLboolean transpose,
868 const GLfloat *value)
869{
870 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3x4, program, location, count,
871 transpose);
872}
873
874bool ValidateProgramUniformMatrix4x3fv(Context *context,
875 GLuint program,
876 GLint location,
877 GLsizei count,
878 GLboolean transpose,
879 const GLfloat *value)
880{
881 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4x3, program, location, count,
882 transpose);
883}
884
He Yunchao11b038b2016-11-22 21:24:04 +0800885bool ValidateGetTexLevelParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800886 TextureTarget target,
He Yunchao11b038b2016-11-22 21:24:04 +0800887 GLint level,
888 GLenum pname,
889 GLsizei *length)
890{
891 if (context->getClientVersion() < ES_3_1)
892 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700893 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
He Yunchao11b038b2016-11-22 21:24:04 +0800894 return false;
895 }
896
897 if (length)
898 {
899 *length = 0;
900 }
901
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800902 TextureType type = TextureTargetToType(target);
903
904 if (!ValidTexLevelDestinationTarget(context, type))
He Yunchao11b038b2016-11-22 21:24:04 +0800905 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700906 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
He Yunchao11b038b2016-11-22 21:24:04 +0800907 return false;
908 }
909
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800910 if (context->getTargetTexture(type) == nullptr)
He Yunchao11b038b2016-11-22 21:24:04 +0800911 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500912 context->handleError(InvalidEnum() << "No texture bound.");
He Yunchao11b038b2016-11-22 21:24:04 +0800913 return false;
914 }
915
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800916 if (!ValidMipLevel(context, type, level))
He Yunchao11b038b2016-11-22 21:24:04 +0800917 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500918 context->handleError(InvalidValue());
He Yunchao11b038b2016-11-22 21:24:04 +0800919 return false;
920 }
921
922 switch (pname)
923 {
924 case GL_TEXTURE_RED_TYPE:
925 case GL_TEXTURE_GREEN_TYPE:
926 case GL_TEXTURE_BLUE_TYPE:
927 case GL_TEXTURE_ALPHA_TYPE:
928 case GL_TEXTURE_DEPTH_TYPE:
929 break;
930 case GL_TEXTURE_RED_SIZE:
931 case GL_TEXTURE_GREEN_SIZE:
932 case GL_TEXTURE_BLUE_SIZE:
933 case GL_TEXTURE_ALPHA_SIZE:
934 case GL_TEXTURE_DEPTH_SIZE:
935 case GL_TEXTURE_STENCIL_SIZE:
936 case GL_TEXTURE_SHARED_SIZE:
937 break;
938 case GL_TEXTURE_INTERNAL_FORMAT:
939 case GL_TEXTURE_WIDTH:
940 case GL_TEXTURE_HEIGHT:
941 case GL_TEXTURE_DEPTH:
942 break;
943 case GL_TEXTURE_SAMPLES:
944 case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
945 break;
946 case GL_TEXTURE_COMPRESSED:
947 break;
948 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700949 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
He Yunchao11b038b2016-11-22 21:24:04 +0800950 return false;
951 }
952
953 if (length)
954 {
955 *length = 1;
956 }
957 return true;
958}
959
960bool ValidateGetTexLevelParameterfv(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800961 TextureTarget target,
He Yunchao11b038b2016-11-22 21:24:04 +0800962 GLint level,
963 GLenum pname,
964 GLfloat *params)
965{
966 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
967}
968
Brandon Jonesfe4bbe62018-04-06 13:50:14 -0700969bool ValidateGetTexLevelParameterfvRobustANGLE(Context *context,
970 TextureTarget target,
971 GLint level,
972 GLenum pname,
973 GLsizei bufSize,
974 GLsizei *length,
975 GLfloat *params)
976{
977 UNIMPLEMENTED();
978 return false;
979}
980
He Yunchao11b038b2016-11-22 21:24:04 +0800981bool ValidateGetTexLevelParameteriv(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800982 TextureTarget target,
He Yunchao11b038b2016-11-22 21:24:04 +0800983 GLint level,
984 GLenum pname,
985 GLint *params)
986{
987 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
988}
989
Brandon Jonesfe4bbe62018-04-06 13:50:14 -0700990bool ValidateGetTexLevelParameterivRobustANGLE(Context *context,
991 TextureTarget target,
992 GLint level,
993 GLenum pname,
994 GLsizei bufSize,
995 GLsizei *length,
996 GLint *params)
997{
998 UNIMPLEMENTED();
999 return false;
1000}
1001
Jiajia Qin5451d532017-11-16 17:16:34 +08001002bool ValidateTexStorage2DMultisample(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001003 TextureType target,
JiangYizhoubddc46b2016-12-09 09:50:51 +08001004 GLsizei samples,
1005 GLint internalFormat,
1006 GLsizei width,
1007 GLsizei height,
1008 GLboolean fixedSampleLocations)
1009{
1010 if (context->getClientVersion() < ES_3_1)
1011 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001012 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhoubddc46b2016-12-09 09:50:51 +08001013 return false;
1014 }
1015
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001016 if (target != TextureType::_2DMultisample)
JiangYizhoubddc46b2016-12-09 09:50:51 +08001017 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001018 context->handleError(InvalidEnum() << "Target must be TEXTURE_2D_MULTISAMPLE.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001019 return false;
1020 }
1021
1022 if (width < 1 || height < 1)
1023 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001024 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
JiangYizhoubddc46b2016-12-09 09:50:51 +08001025 return false;
1026 }
1027
1028 const Caps &caps = context->getCaps();
1029 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1030 static_cast<GLuint>(height) > caps.max2DTextureSize)
1031 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001032 context
1033 ->handleError(InvalidValue()
1034 << "Width and height must be less than or equal to GL_MAX_TEXTURE_SIZE.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001035 return false;
1036 }
1037
1038 if (samples == 0)
1039 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001040 context->handleError(InvalidValue() << "Samples may not be zero.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001041 return false;
1042 }
1043
1044 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
1045 if (!formatCaps.renderable)
1046 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001047 context->handleError(InvalidEnum() << "SizedInternalformat must be color-renderable, "
1048 "depth-renderable, or stencil-renderable.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001049 return false;
1050 }
1051
1052 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
1053 // is one of the unsized base internalformats listed in table 8.11.
Geoff Langca271392017-04-05 12:30:00 -04001054 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
1055 if (formatInfo.internalFormat == GL_NONE)
JiangYizhoubddc46b2016-12-09 09:50:51 +08001056 {
1057 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001058 InvalidEnum()
1059 << "Internalformat is one of the unsupported unsized base internalformats.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001060 return false;
1061 }
1062
1063 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1064 {
1065 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001066 InvalidOperation()
1067 << "Samples must not be greater than maximum supported value for the format.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001068 return false;
1069 }
1070
1071 Texture *texture = context->getTargetTexture(target);
1072 if (!texture || texture->id() == 0)
1073 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001074 context->handleError(InvalidOperation() << "Zero is bound to target.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001075 return false;
1076 }
1077
1078 if (texture->getImmutableFormat())
1079 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001080 context->handleError(InvalidOperation() << "The value of TEXTURE_IMMUTABLE_FORMAT for "
1081 "the texture currently bound to target on "
1082 "the active texture unit is true.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001083 return false;
1084 }
1085
1086 return true;
1087}
1088
1089bool ValidateGetMultisamplefv(Context *context, GLenum pname, GLuint index, GLfloat *val)
1090{
1091 if (context->getClientVersion() < ES_3_1)
1092 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001093 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhoubddc46b2016-12-09 09:50:51 +08001094 return false;
1095 }
1096
1097 if (pname != GL_SAMPLE_POSITION)
1098 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001099 context->handleError(InvalidEnum() << "Pname must be SAMPLE_POSITION.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001100 return false;
1101 }
1102
JiangYizhou5b03f472017-01-09 10:22:53 +08001103 Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04001104 GLint samples = framebuffer->getSamples(context);
JiangYizhou5b03f472017-01-09 10:22:53 +08001105
Jamie Madille98b1b52018-03-08 09:47:23 -05001106 if (index >= static_cast<GLuint>(samples))
JiangYizhoubddc46b2016-12-09 09:50:51 +08001107 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001108 context->handleError(InvalidValue() << "Index must be less than the value of SAMPLES.");
JiangYizhoubddc46b2016-12-09 09:50:51 +08001109 return false;
1110 }
1111
1112 return true;
1113}
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001114
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07001115bool ValidateGetMultisamplefvRobustANGLE(Context *context,
1116 GLenum pname,
1117 GLuint index,
1118 GLsizei bufSize,
1119 GLsizei *length,
1120 GLfloat *val)
1121{
1122 UNIMPLEMENTED();
1123 return false;
1124}
1125
Jiajia Qin5451d532017-11-16 17:16:34 +08001126bool ValidateFramebufferParameteri(Context *context, GLenum target, GLenum pname, GLint param)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001127{
1128 if (context->getClientVersion() < ES_3_1)
1129 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001130 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001131 return false;
1132 }
1133
Geoff Lange8afa902017-09-27 15:00:43 -04001134 if (!ValidFramebufferTarget(context, target))
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001135 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001136 context->handleError(InvalidEnum() << "Invalid framebuffer target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001137 return false;
1138 }
1139
1140 switch (pname)
1141 {
1142 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1143 {
1144 GLint maxWidth = context->getCaps().maxFramebufferWidth;
1145 if (param < 0 || param > maxWidth)
1146 {
1147 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001148 InvalidValue()
1149 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_WIDTH.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001150 return false;
1151 }
1152 break;
1153 }
1154 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1155 {
1156 GLint maxHeight = context->getCaps().maxFramebufferHeight;
1157 if (param < 0 || param > maxHeight)
1158 {
1159 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001160 InvalidValue()
1161 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_HEIGHT.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001162 return false;
1163 }
1164 break;
1165 }
1166 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1167 {
1168 GLint maxSamples = context->getCaps().maxFramebufferSamples;
1169 if (param < 0 || param > maxSamples)
1170 {
1171 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001172 InvalidValue()
1173 << "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_SAMPLES.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001174 return false;
1175 }
1176 break;
1177 }
1178 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1179 {
1180 break;
1181 }
Jiawei Shaob1e91382018-05-17 14:33:55 +08001182 case GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT:
1183 {
1184 if (!context->getExtensions().geometryShader)
1185 {
1186 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
1187 return false;
1188 }
1189 GLint maxLayers = context->getCaps().maxFramebufferLayers;
1190 if (param < 0 || param > maxLayers)
1191 {
1192 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidFramebufferLayer);
1193 return false;
1194 }
1195 break;
1196 }
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001197 default:
1198 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001199 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001200 return false;
1201 }
1202 }
1203
1204 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
1205 ASSERT(framebuffer);
1206 if (framebuffer->id() == 0)
1207 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001208 context->handleError(InvalidOperation() << "Default framebuffer is bound to target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001209 return false;
1210 }
1211 return true;
1212}
1213
Jiajia Qin5451d532017-11-16 17:16:34 +08001214bool ValidateGetFramebufferParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001215{
1216 if (context->getClientVersion() < ES_3_1)
1217 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001218 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001219 return false;
1220 }
1221
Geoff Lange8afa902017-09-27 15:00:43 -04001222 if (!ValidFramebufferTarget(context, target))
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001223 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001224 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001225 return false;
1226 }
1227
1228 switch (pname)
1229 {
1230 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1231 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1232 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1233 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1234 break;
Jiawei Shaob1e91382018-05-17 14:33:55 +08001235 case GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT:
1236 if (!context->getExtensions().geometryShader)
1237 {
1238 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
1239 return false;
1240 }
1241 break;
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001242 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001243 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001244 return false;
1245 }
1246
1247 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
1248 ASSERT(framebuffer);
1249
1250 if (framebuffer->id() == 0)
1251 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001252 context->handleError(InvalidOperation() << "Default framebuffer is bound to target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001253 return false;
1254 }
1255 return true;
1256}
1257
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07001258bool ValidateGetFramebufferParameterivRobustANGLE(Context *context,
1259 GLenum target,
1260 GLenum pname,
1261 GLsizei bufSize,
1262 GLsizei *length,
1263 GLint *params)
1264{
1265 UNIMPLEMENTED();
1266 return false;
1267}
1268
jchen1015015f72017-03-16 13:54:21 +08001269bool ValidateGetProgramResourceIndex(Context *context,
1270 GLuint program,
1271 GLenum programInterface,
1272 const GLchar *name)
1273{
1274 if (context->getClientVersion() < ES_3_1)
1275 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001276 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen1015015f72017-03-16 13:54:21 +08001277 return false;
1278 }
1279
1280 Program *programObject = GetValidProgram(context, program);
1281 if (programObject == nullptr)
1282 {
1283 return false;
1284 }
1285
1286 if (!ValidateNamedProgramInterface(programInterface))
1287 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001288 context->handleError(InvalidEnum() << "Invalid program interface: 0x" << std::hex
1289 << std::uppercase << programInterface);
jchen1015015f72017-03-16 13:54:21 +08001290 return false;
1291 }
Shao80957d92017-02-20 21:25:59 +08001292
1293 return true;
1294}
1295
Jamie Madill5b772312018-03-08 20:28:32 -05001296bool ValidateBindVertexBuffer(Context *context,
Shao80957d92017-02-20 21:25:59 +08001297 GLuint bindingIndex,
1298 GLuint buffer,
1299 GLintptr offset,
1300 GLsizei stride)
1301{
1302 if (context->getClientVersion() < ES_3_1)
1303 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001304 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +08001305 return false;
1306 }
1307
1308 if (!context->isBufferGenerated(buffer))
1309 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001310 context->handleError(InvalidOperation() << "Buffer is not generated.");
Shao80957d92017-02-20 21:25:59 +08001311 return false;
1312 }
1313
1314 const Caps &caps = context->getCaps();
1315 if (bindingIndex >= caps.maxVertexAttribBindings)
1316 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001317 context->handleError(InvalidValue()
1318 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08001319 return false;
1320 }
1321
1322 if (offset < 0)
1323 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001324 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Shao80957d92017-02-20 21:25:59 +08001325 return false;
1326 }
1327
1328 if (stride < 0 || stride > caps.maxVertexAttribStride)
1329 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001330 context->handleError(InvalidValue()
1331 << "stride must be between 0 and MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08001332 return false;
1333 }
1334
1335 // [OpenGL ES 3.1] Section 10.3.1 page 244:
1336 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
1337 if (context->getGLState().getVertexArrayId() == 0)
1338 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001339 context->handleError(InvalidOperation() << "Default vertex array buffer is bound.");
Shao80957d92017-02-20 21:25:59 +08001340 return false;
1341 }
1342
1343 return true;
1344}
1345
Jamie Madill5b772312018-03-08 20:28:32 -05001346bool ValidateVertexBindingDivisor(Context *context, GLuint bindingIndex, GLuint divisor)
Shao80957d92017-02-20 21:25:59 +08001347{
1348 if (context->getClientVersion() < ES_3_1)
1349 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001350 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +08001351 return false;
1352 }
1353
1354 const Caps &caps = context->getCaps();
1355 if (bindingIndex >= caps.maxVertexAttribBindings)
1356 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001357 context->handleError(InvalidValue()
1358 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08001359 return false;
1360 }
1361
1362 // [OpenGL ES 3.1] Section 10.3.1 page 243:
1363 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
1364 if (context->getGLState().getVertexArrayId() == 0)
1365 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001366 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +08001367 return false;
1368 }
1369
1370 return true;
1371}
1372
Jamie Madill5b772312018-03-08 20:28:32 -05001373bool ValidateVertexAttribFormat(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08001374 GLuint attribindex,
Shao80957d92017-02-20 21:25:59 +08001375 GLint size,
1376 GLenum type,
Jiajia Qin5451d532017-11-16 17:16:34 +08001377 GLboolean normalized,
1378 GLuint relativeoffset)
Shao80957d92017-02-20 21:25:59 +08001379{
Jiajia Qin5451d532017-11-16 17:16:34 +08001380 return ValidateVertexAttribFormatCommon(context, attribindex, size, type, relativeoffset,
1381 false);
1382}
Shao80957d92017-02-20 21:25:59 +08001383
Jamie Madill5b772312018-03-08 20:28:32 -05001384bool ValidateVertexAttribIFormat(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08001385 GLuint attribindex,
1386 GLint size,
1387 GLenum type,
1388 GLuint relativeoffset)
1389{
1390 return ValidateVertexAttribFormatCommon(context, attribindex, size, type, relativeoffset, true);
Shao80957d92017-02-20 21:25:59 +08001391}
1392
Jamie Madill5b772312018-03-08 20:28:32 -05001393bool ValidateVertexAttribBinding(Context *context, GLuint attribIndex, GLuint bindingIndex)
Shao80957d92017-02-20 21:25:59 +08001394{
1395 if (context->getClientVersion() < ES_3_1)
1396 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001397 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Shao80957d92017-02-20 21:25:59 +08001398 return false;
1399 }
1400
1401 // [OpenGL ES 3.1] Section 10.3.1 page 243:
1402 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
1403 if (context->getGLState().getVertexArrayId() == 0)
1404 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001405 context->handleError(InvalidOperation() << "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +08001406 return false;
1407 }
1408
1409 const Caps &caps = context->getCaps();
1410 if (attribIndex >= caps.maxVertexAttributes)
1411 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001412 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08001413 return false;
1414 }
1415
1416 if (bindingIndex >= caps.maxVertexAttribBindings)
1417 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001418 context->handleError(InvalidValue()
1419 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS");
Shao80957d92017-02-20 21:25:59 +08001420 return false;
1421 }
1422
jchen1015015f72017-03-16 13:54:21 +08001423 return true;
1424}
1425
jchen10fd7c3b52017-03-21 15:36:03 +08001426bool ValidateGetProgramResourceName(Context *context,
1427 GLuint program,
1428 GLenum programInterface,
1429 GLuint index,
1430 GLsizei bufSize,
1431 GLsizei *length,
1432 GLchar *name)
1433{
1434 if (context->getClientVersion() < ES_3_1)
1435 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001436 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen10fd7c3b52017-03-21 15:36:03 +08001437 return false;
1438 }
1439
1440 Program *programObject = GetValidProgram(context, program);
1441 if (programObject == nullptr)
1442 {
1443 return false;
1444 }
1445
1446 if (!ValidateNamedProgramInterface(programInterface))
1447 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001448 context->handleError(InvalidEnum() << "Invalid program interface: 0x" << std::hex
1449 << std::uppercase << programInterface);
jchen10fd7c3b52017-03-21 15:36:03 +08001450 return false;
1451 }
1452
1453 if (!ValidateProgramResourceIndex(programObject, programInterface, index))
1454 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001455 context->handleError(InvalidValue() << "Invalid index: " << index);
jchen10fd7c3b52017-03-21 15:36:03 +08001456 return false;
1457 }
1458
1459 if (bufSize < 0)
1460 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001461 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
jchen10fd7c3b52017-03-21 15:36:03 +08001462 return false;
1463 }
1464
1465 return true;
1466}
1467
Xinghua Cao2b396592017-03-29 15:36:04 +08001468bool ValidateDispatchCompute(Context *context,
1469 GLuint numGroupsX,
1470 GLuint numGroupsY,
1471 GLuint numGroupsZ)
1472{
1473 if (context->getClientVersion() < ES_3_1)
1474 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001475 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Xinghua Cao2b396592017-03-29 15:36:04 +08001476 return false;
1477 }
1478
1479 const State &state = context->getGLState();
1480 Program *program = state.getProgram();
1481
Jiawei Shao385b3e02018-03-21 09:43:28 +08001482 if (program == nullptr || !program->hasLinkedShaderStage(ShaderType::Compute))
Xinghua Cao2b396592017-03-29 15:36:04 +08001483 {
Qin Jiajia62fcf622017-11-30 16:16:12 +08001484 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveProgramWithComputeShader);
Xinghua Cao2b396592017-03-29 15:36:04 +08001485 return false;
1486 }
1487
1488 const Caps &caps = context->getCaps();
1489 if (numGroupsX > caps.maxComputeWorkGroupCount[0])
1490 {
1491 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001492 InvalidValue() << "num_groups_x cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[0]="
1493 << caps.maxComputeWorkGroupCount[0]);
Xinghua Cao2b396592017-03-29 15:36:04 +08001494 return false;
1495 }
1496 if (numGroupsY > caps.maxComputeWorkGroupCount[1])
1497 {
1498 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001499 InvalidValue() << "num_groups_y cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[1]="
1500 << caps.maxComputeWorkGroupCount[1]);
Xinghua Cao2b396592017-03-29 15:36:04 +08001501 return false;
1502 }
1503 if (numGroupsZ > caps.maxComputeWorkGroupCount[2])
1504 {
1505 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001506 InvalidValue() << "num_groups_z cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[2]="
1507 << caps.maxComputeWorkGroupCount[2]);
Xinghua Cao2b396592017-03-29 15:36:04 +08001508 return false;
1509 }
1510
1511 return true;
1512}
1513
Jiajia Qin5451d532017-11-16 17:16:34 +08001514bool ValidateDispatchComputeIndirect(Context *context, GLintptr indirect)
1515{
Qin Jiajia62fcf622017-11-30 16:16:12 +08001516 if (context->getClientVersion() < ES_3_1)
1517 {
1518 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1519 return false;
1520 }
1521
1522 const State &state = context->getGLState();
1523 Program *program = state.getProgram();
1524
Jiawei Shao385b3e02018-03-21 09:43:28 +08001525 if (program == nullptr || !program->hasLinkedShaderStage(ShaderType::Compute))
Qin Jiajia62fcf622017-11-30 16:16:12 +08001526 {
1527 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveProgramWithComputeShader);
1528 return false;
1529 }
1530
Qin Jiajia62fcf622017-11-30 16:16:12 +08001531 if (indirect < 0)
1532 {
1533 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
1534 return false;
1535 }
1536
1537 if ((indirect & (sizeof(GLuint) - 1)) != 0)
1538 {
Qin Jiajiaa4ef8432018-02-22 16:02:24 +08001539 ANGLE_VALIDATION_ERR(context, InvalidValue(), OffsetMustBeMultipleOfUint);
1540 return false;
1541 }
1542
Jamie Madill5b772312018-03-08 20:28:32 -05001543 Buffer *dispatchIndirectBuffer = state.getTargetBuffer(BufferBinding::DispatchIndirect);
Qin Jiajiaa4ef8432018-02-22 16:02:24 +08001544 if (!dispatchIndirectBuffer)
1545 {
1546 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DispatchIndirectBufferNotBound);
Qin Jiajia62fcf622017-11-30 16:16:12 +08001547 return false;
1548 }
1549
1550 CheckedNumeric<GLuint64> checkedOffset(static_cast<GLuint64>(indirect));
1551 auto checkedSum = checkedOffset + static_cast<GLuint64>(3 * sizeof(GLuint));
1552 if (!checkedSum.IsValid() ||
1553 checkedSum.ValueOrDie() > static_cast<GLuint64>(dispatchIndirectBuffer->getSize()))
1554 {
1555 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
1556 return false;
1557 }
1558
1559 return true;
Jiajia Qin5451d532017-11-16 17:16:34 +08001560}
1561
Xinghua Cao65ec0b22017-03-28 16:10:52 +08001562bool ValidateBindImageTexture(Context *context,
1563 GLuint unit,
1564 GLuint texture,
1565 GLint level,
1566 GLboolean layered,
1567 GLint layer,
1568 GLenum access,
1569 GLenum format)
1570{
1571 GLuint maxImageUnits = context->getCaps().maxImageUnits;
1572 if (unit >= maxImageUnits)
1573 {
1574 context->handleError(InvalidValue()
1575 << "unit cannot be greater than or equal than MAX_IMAGE_UNITS = "
1576 << maxImageUnits);
1577 return false;
1578 }
1579
1580 if (level < 0)
1581 {
1582 context->handleError(InvalidValue() << "level is negative.");
1583 return false;
1584 }
1585
1586 if (layer < 0)
1587 {
1588 context->handleError(InvalidValue() << "layer is negative.");
1589 return false;
1590 }
1591
1592 if (access != GL_READ_ONLY && access != GL_WRITE_ONLY && access != GL_READ_WRITE)
1593 {
1594 context->handleError(InvalidEnum() << "access is not one of the supported tokens.");
1595 return false;
1596 }
1597
1598 switch (format)
1599 {
1600 case GL_RGBA32F:
1601 case GL_RGBA16F:
1602 case GL_R32F:
1603 case GL_RGBA32UI:
1604 case GL_RGBA16UI:
1605 case GL_RGBA8UI:
1606 case GL_R32UI:
1607 case GL_RGBA32I:
1608 case GL_RGBA16I:
1609 case GL_RGBA8I:
1610 case GL_R32I:
1611 case GL_RGBA8:
1612 case GL_RGBA8_SNORM:
1613 break;
1614 default:
1615 context->handleError(InvalidValue()
1616 << "format is not one of supported image unit formats.");
1617 return false;
1618 }
1619
1620 if (texture != 0)
1621 {
1622 Texture *tex = context->getTexture(texture);
1623
1624 if (tex == nullptr)
1625 {
1626 context->handleError(InvalidValue()
1627 << "texture is not the name of an existing texture object.");
1628 return false;
1629 }
1630
1631 if (!tex->getImmutableFormat())
1632 {
1633 context->handleError(InvalidOperation()
1634 << "texture is not the name of an immutable texture object.");
1635 return false;
1636 }
1637 }
1638
1639 return true;
1640}
jchen10191381f2017-04-11 13:59:04 +08001641
1642bool ValidateGetProgramResourceLocation(Context *context,
1643 GLuint program,
1644 GLenum programInterface,
1645 const GLchar *name)
1646{
1647 if (context->getClientVersion() < ES_3_1)
1648 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001649 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen10191381f2017-04-11 13:59:04 +08001650 return false;
1651 }
1652
1653 Program *programObject = GetValidProgram(context, program);
1654 if (programObject == nullptr)
1655 {
1656 return false;
1657 }
1658
1659 if (!programObject->isLinked())
1660 {
1661 context->handleError(InvalidOperation() << "Program is not successfully linked.");
1662 return false;
1663 }
1664
1665 if (!ValidateLocationProgramInterface(programInterface))
1666 {
1667 context->handleError(InvalidEnum() << "Invalid program interface.");
1668 return false;
1669 }
1670 return true;
1671}
1672
jchen10880683b2017-04-12 16:21:55 +08001673bool ValidateGetProgramResourceiv(Context *context,
1674 GLuint program,
1675 GLenum programInterface,
1676 GLuint index,
1677 GLsizei propCount,
1678 const GLenum *props,
1679 GLsizei bufSize,
1680 GLsizei *length,
1681 GLint *params)
1682{
1683 if (context->getClientVersion() < ES_3_1)
1684 {
jchen10d9cd7b72017-08-30 15:04:25 +08001685 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
jchen10880683b2017-04-12 16:21:55 +08001686 return false;
1687 }
1688
1689 Program *programObject = GetValidProgram(context, program);
1690 if (programObject == nullptr)
1691 {
1692 return false;
1693 }
1694 if (!ValidateProgramInterface(programInterface))
1695 {
1696 context->handleError(InvalidEnum() << "Invalid program interface.");
1697 return false;
1698 }
1699 if (propCount <= 0)
1700 {
1701 context->handleError(InvalidValue() << "Invalid propCount.");
1702 return false;
1703 }
1704 if (bufSize < 0)
1705 {
1706 context->handleError(InvalidValue() << "Invalid bufSize.");
1707 return false;
1708 }
1709 if (!ValidateProgramResourceIndex(programObject, programInterface, index))
1710 {
1711 context->handleError(InvalidValue() << "Invalid index: " << index);
1712 return false;
1713 }
1714 for (GLsizei i = 0; i < propCount; i++)
1715 {
Jiawei Shaoc6f82872018-04-24 14:14:50 +08001716 if (!ValidateProgramResourceProperty(context, props[i]))
jchen10880683b2017-04-12 16:21:55 +08001717 {
1718 context->handleError(InvalidEnum() << "Invalid prop.");
1719 return false;
1720 }
1721 if (!ValidateProgramResourcePropertyByInterface(props[i], programInterface))
1722 {
1723 context->handleError(InvalidOperation() << "Not an allowed prop for interface");
1724 return false;
1725 }
1726 }
1727 return true;
1728}
1729
jchen10d9cd7b72017-08-30 15:04:25 +08001730bool ValidateGetProgramInterfaceiv(Context *context,
1731 GLuint program,
1732 GLenum programInterface,
1733 GLenum pname,
1734 GLint *params)
1735{
1736 if (context->getClientVersion() < ES_3_1)
1737 {
1738 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1739 return false;
1740 }
1741
1742 Program *programObject = GetValidProgram(context, program);
1743 if (programObject == nullptr)
1744 {
1745 return false;
1746 }
1747
1748 if (!ValidateProgramInterface(programInterface))
1749 {
1750 context->handleError(InvalidEnum() << "Invalid program interface.");
1751 return false;
1752 }
1753
1754 switch (pname)
1755 {
1756 case GL_ACTIVE_RESOURCES:
1757 case GL_MAX_NAME_LENGTH:
1758 case GL_MAX_NUM_ACTIVE_VARIABLES:
1759 break;
1760
1761 default:
1762 context->handleError(InvalidEnum() << "Unknown property of program interface.");
1763 return false;
1764 }
1765
1766 if (pname == GL_MAX_NAME_LENGTH && programInterface == GL_ATOMIC_COUNTER_BUFFER)
1767 {
1768 context->handleError(InvalidOperation()
1769 << "Active atomic counter resources are not assigned name strings.");
1770 return false;
1771 }
1772
1773 if (pname == GL_MAX_NUM_ACTIVE_VARIABLES)
1774 {
1775 switch (programInterface)
1776 {
1777 case GL_ATOMIC_COUNTER_BUFFER:
1778 case GL_SHADER_STORAGE_BLOCK:
1779 case GL_UNIFORM_BLOCK:
1780 break;
1781
1782 default:
1783 context->handleError(
1784 InvalidOperation()
1785 << "MAX_NUM_ACTIVE_VARIABLES requires a buffer or block interface.");
1786 return false;
1787 }
1788 }
1789
1790 return true;
1791}
1792
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07001793bool ValidateGetProgramInterfaceivRobustANGLE(Context *context,
1794 GLuint program,
1795 GLenum programInterface,
1796 GLenum pname,
1797 GLsizei bufSize,
1798 GLsizei *length,
1799 GLint *params)
1800{
1801 UNIMPLEMENTED();
1802 return false;
1803}
1804
Yunchao Hea336b902017-08-02 16:05:21 +08001805static bool ValidateGenOrDeleteES31(Context *context, GLint n)
1806{
1807 if (context->getClientVersion() < ES_3_1)
1808 {
1809 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1810 return false;
1811 }
1812
1813 return ValidateGenOrDelete(context, n);
1814}
1815
1816bool ValidateGenProgramPipelines(Context *context, GLint n, GLuint *)
1817{
1818 return ValidateGenOrDeleteES31(context, n);
1819}
1820
1821bool ValidateDeleteProgramPipelines(Context *context, GLint n, const GLuint *)
1822{
1823 return ValidateGenOrDeleteES31(context, n);
1824}
1825
1826bool ValidateBindProgramPipeline(Context *context, GLuint pipeline)
1827{
1828 if (context->getClientVersion() < ES_3_1)
1829 {
1830 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1831 return false;
1832 }
1833
1834 if (!context->isProgramPipelineGenerated(pipeline))
1835 {
1836 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
1837 return false;
1838 }
1839
1840 return true;
1841}
1842
1843bool ValidateIsProgramPipeline(Context *context, GLuint pipeline)
1844{
1845 if (context->getClientVersion() < ES_3_1)
1846 {
1847 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1848 return false;
1849 }
1850
1851 return true;
1852}
1853
Jiajia Qin5451d532017-11-16 17:16:34 +08001854bool ValidateUseProgramStages(Context *context, GLuint pipeline, GLbitfield stages, GLuint program)
1855{
1856 UNIMPLEMENTED();
1857 return false;
1858}
1859
1860bool ValidateActiveShaderProgram(Context *context, GLuint pipeline, GLuint program)
1861{
1862 UNIMPLEMENTED();
1863 return false;
1864}
1865
1866bool ValidateCreateShaderProgramv(Context *context,
Jiawei Shao385b3e02018-03-21 09:43:28 +08001867 ShaderType type,
Jiajia Qin5451d532017-11-16 17:16:34 +08001868 GLsizei count,
1869 const GLchar *const *strings)
1870{
1871 UNIMPLEMENTED();
1872 return false;
1873}
1874
1875bool ValidateGetProgramPipelineiv(Context *context, GLuint pipeline, GLenum pname, GLint *params)
1876{
1877 UNIMPLEMENTED();
1878 return false;
1879}
1880
1881bool ValidateValidateProgramPipeline(Context *context, GLuint pipeline)
1882{
1883 UNIMPLEMENTED();
1884 return false;
1885}
1886
1887bool ValidateGetProgramPipelineInfoLog(Context *context,
1888 GLuint pipeline,
1889 GLsizei bufSize,
1890 GLsizei *length,
1891 GLchar *infoLog)
1892{
1893 UNIMPLEMENTED();
1894 return false;
1895}
1896
1897bool ValidateMemoryBarrier(Context *context, GLbitfield barriers)
1898{
Xinghua Cao89c422a2017-11-29 18:24:20 +08001899 if (context->getClientVersion() < ES_3_1)
1900 {
1901 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1902 return false;
1903 }
1904
1905 if (barriers == GL_ALL_BARRIER_BITS)
1906 {
1907 return true;
1908 }
1909
1910 GLbitfield supported_barrier_bits =
1911 GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT |
1912 GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT |
1913 GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT |
1914 GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT |
1915 GL_ATOMIC_COUNTER_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT;
1916 if ((barriers & ~supported_barrier_bits) != 0)
1917 {
1918 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMemoryBarrierBit);
1919 return false;
1920 }
1921
1922 return true;
Jiajia Qin5451d532017-11-16 17:16:34 +08001923}
1924
1925bool ValidateMemoryBarrierByRegion(Context *context, GLbitfield barriers)
1926{
Xinghua Cao89c422a2017-11-29 18:24:20 +08001927 if (context->getClientVersion() < ES_3_1)
1928 {
1929 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1930 return false;
1931 }
1932
1933 if (barriers == GL_ALL_BARRIER_BITS)
1934 {
1935 return true;
1936 }
1937
1938 GLbitfield supported_barrier_bits = GL_ATOMIC_COUNTER_BARRIER_BIT | GL_FRAMEBUFFER_BARRIER_BIT |
1939 GL_SHADER_IMAGE_ACCESS_BARRIER_BIT |
1940 GL_SHADER_STORAGE_BARRIER_BIT |
1941 GL_TEXTURE_FETCH_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT;
1942 if ((barriers & ~supported_barrier_bits) != 0)
1943 {
1944 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMemoryBarrierBit);
1945 return false;
1946 }
1947
1948 return true;
Jiajia Qin5451d532017-11-16 17:16:34 +08001949}
1950
1951bool ValidateSampleMaski(Context *context, GLuint maskNumber, GLbitfield mask)
Jiawei Shaodb342272017-09-27 10:21:45 +08001952{
1953 if (context->getClientVersion() < ES_3_1)
1954 {
1955 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
1956 return false;
1957 }
1958
1959 if (maskNumber >= context->getCaps().maxSampleMaskWords)
1960 {
1961 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
1962 return false;
1963 }
1964
1965 return true;
1966}
1967
Jiawei Shao5f9482f2018-05-18 09:00:09 +08001968bool ValidateFramebufferTextureEXT(Context *context,
1969 GLenum target,
1970 GLenum attachment,
1971 GLuint texture,
1972 GLint level)
1973{
1974 if (!context->getExtensions().geometryShader)
1975 {
1976 ANGLE_VALIDATION_ERR(context, InvalidOperation(), GeometryShaderExtensionNotEnabled);
1977 return false;
1978 }
1979
1980 if (texture != 0)
1981 {
1982 gl::Texture *tex = context->getTexture(texture);
1983
1984 // [EXT_geometry_shader] Section 9.2.8 "Attaching Texture Images to a Framebuffer"
1985 // An INVALID_VALUE error is generated if <texture> is not the name of a texture object.
1986 // We put this validation before ValidateFramebufferTextureBase because it is an
1987 // INVALID_OPERATION error for both FramebufferTexture2D and FramebufferTextureLayer:
1988 // [OpenGL ES 3.1] Chapter 9.2.8 (FramebufferTexture2D)
1989 // An INVALID_OPERATION error is generated if texture is not zero, and does not name an
1990 // existing texture object of type matching textarget.
1991 // [OpenGL ES 3.1 Chapter 9.2.8 (FramebufferTextureLayer)
1992 // An INVALID_OPERATION error is generated if texture is non-zero and is not the name of a
1993 // three-dimensional or two-dimensional array texture.
1994 if (tex == nullptr)
1995 {
1996 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidTextureName);
1997 return false;
1998 }
1999
2000 if (!ValidMipLevel(context, tex->getType(), level))
2001 {
2002 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
2003 return false;
2004 }
2005 }
2006
2007 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
2008 {
2009 return false;
2010 }
2011
2012 return true;
2013}
2014
Martin Radev66fb8202016-07-28 11:45:20 +03002015} // namespace gl