blob: 8ae760b6efd6f359d4425c51340353ad97b6595d [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
Jamie Madill778bf092018-11-14 09:54:36 -05009#include "libANGLE/validationES31_autogen.h"
Martin Radev66fb8202016-07-28 11:45:20 +030010
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"
Jamie Madill778bf092018-11-14 09:54:36 -050016#include "libANGLE/validationES2_autogen.h"
17#include "libANGLE/validationES3_autogen.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{
Jamie Madille0472f32018-11-27 16:32:45 -050025using namespace err;
Martin Radev66fb8202016-07-28 11:45:20 +030026
jchen1015015f72017-03-16 13:54:21 +080027namespace
28{
29
30bool ValidateNamedProgramInterface(GLenum programInterface)
31{
32 switch (programInterface)
33 {
34 case GL_UNIFORM:
35 case GL_UNIFORM_BLOCK:
36 case GL_PROGRAM_INPUT:
37 case GL_PROGRAM_OUTPUT:
38 case GL_TRANSFORM_FEEDBACK_VARYING:
39 case GL_BUFFER_VARIABLE:
40 case GL_SHADER_STORAGE_BLOCK:
41 return true;
42 default:
43 return false;
44 }
45}
46
jchen10191381f2017-04-11 13:59:04 +080047bool ValidateLocationProgramInterface(GLenum programInterface)
48{
49 switch (programInterface)
50 {
51 case GL_UNIFORM:
52 case GL_PROGRAM_INPUT:
53 case GL_PROGRAM_OUTPUT:
54 return true;
55 default:
56 return false;
57 }
58}
59
jchen10880683b2017-04-12 16:21:55 +080060bool ValidateProgramInterface(GLenum programInterface)
61{
62 return (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
63 ValidateNamedProgramInterface(programInterface));
64}
65
Jiawei Shaoc6f82872018-04-24 14:14:50 +080066bool ValidateProgramResourceProperty(const Context *context, GLenum prop)
jchen10880683b2017-04-12 16:21:55 +080067{
Jiawei Shaoc6f82872018-04-24 14:14:50 +080068 ASSERT(context);
jchen10880683b2017-04-12 16:21:55 +080069 switch (prop)
70 {
71 case GL_ACTIVE_VARIABLES:
72 case GL_BUFFER_BINDING:
73 case GL_NUM_ACTIVE_VARIABLES:
74
75 case GL_ARRAY_SIZE:
76
77 case GL_ARRAY_STRIDE:
78 case GL_BLOCK_INDEX:
79 case GL_IS_ROW_MAJOR:
80 case GL_MATRIX_STRIDE:
81
82 case GL_ATOMIC_COUNTER_BUFFER_INDEX:
83
84 case GL_BUFFER_DATA_SIZE:
85
86 case GL_LOCATION:
87
88 case GL_NAME_LENGTH:
89
90 case GL_OFFSET:
91
92 case GL_REFERENCED_BY_VERTEX_SHADER:
93 case GL_REFERENCED_BY_FRAGMENT_SHADER:
94 case GL_REFERENCED_BY_COMPUTE_SHADER:
95
96 case GL_TOP_LEVEL_ARRAY_SIZE:
97 case GL_TOP_LEVEL_ARRAY_STRIDE:
98
99 case GL_TYPE:
100 return true;
101
Jiawei Shaoc6f82872018-04-24 14:14:50 +0800102 case GL_REFERENCED_BY_GEOMETRY_SHADER_EXT:
103 return context->getExtensions().geometryShader;
104
Olli Etuaho0ca09752018-09-24 11:00:50 +0300105 case GL_LOCATION_INDEX_EXT:
106 return context->getExtensions().blendFuncExtended;
107
jchen10880683b2017-04-12 16:21:55 +0800108 default:
109 return false;
110 }
111}
112
113// GLES 3.10 spec: Page 82 -- Table 7.2
114bool ValidateProgramResourcePropertyByInterface(GLenum prop, GLenum programInterface)
115{
116 switch (prop)
117 {
118 case GL_ACTIVE_VARIABLES:
119 case GL_BUFFER_BINDING:
120 case GL_NUM_ACTIVE_VARIABLES:
121 {
122 switch (programInterface)
123 {
124 case GL_ATOMIC_COUNTER_BUFFER:
125 case GL_SHADER_STORAGE_BLOCK:
126 case GL_UNIFORM_BLOCK:
127 return true;
128 default:
129 return false;
130 }
131 }
132
133 case GL_ARRAY_SIZE:
134 {
135 switch (programInterface)
136 {
137 case GL_BUFFER_VARIABLE:
138 case GL_PROGRAM_INPUT:
139 case GL_PROGRAM_OUTPUT:
140 case GL_TRANSFORM_FEEDBACK_VARYING:
141 case GL_UNIFORM:
142 return true;
143 default:
144 return false;
145 }
146 }
147
148 case GL_ARRAY_STRIDE:
149 case GL_BLOCK_INDEX:
150 case GL_IS_ROW_MAJOR:
151 case GL_MATRIX_STRIDE:
152 {
153 switch (programInterface)
154 {
155 case GL_BUFFER_VARIABLE:
156 case GL_UNIFORM:
157 return true;
158 default:
159 return false;
160 }
161 }
162
163 case GL_ATOMIC_COUNTER_BUFFER_INDEX:
164 {
165 if (programInterface == GL_UNIFORM)
166 {
167 return true;
168 }
169 return false;
170 }
171
172 case GL_BUFFER_DATA_SIZE:
173 {
174 switch (programInterface)
175 {
176 case GL_ATOMIC_COUNTER_BUFFER:
177 case GL_SHADER_STORAGE_BLOCK:
178 case GL_UNIFORM_BLOCK:
179 return true;
180 default:
181 return false;
182 }
183 }
184
185 case GL_LOCATION:
186 {
187 return ValidateLocationProgramInterface(programInterface);
188 }
189
Olli Etuaho0ca09752018-09-24 11:00:50 +0300190 case GL_LOCATION_INDEX_EXT:
191 {
192 // EXT_blend_func_extended
193 return (programInterface == GL_PROGRAM_OUTPUT);
194 }
195
jchen10880683b2017-04-12 16:21:55 +0800196 case GL_NAME_LENGTH:
197 {
198 return ValidateNamedProgramInterface(programInterface);
199 }
200
201 case GL_OFFSET:
202 {
203 switch (programInterface)
204 {
205 case GL_BUFFER_VARIABLE:
206 case GL_UNIFORM:
207 return true;
208 default:
209 return false;
210 }
211 }
212
213 case GL_REFERENCED_BY_VERTEX_SHADER:
214 case GL_REFERENCED_BY_FRAGMENT_SHADER:
215 case GL_REFERENCED_BY_COMPUTE_SHADER:
Jiawei Shaoc6f82872018-04-24 14:14:50 +0800216 case GL_REFERENCED_BY_GEOMETRY_SHADER_EXT:
jchen10880683b2017-04-12 16:21:55 +0800217 {
218 switch (programInterface)
219 {
220 case GL_ATOMIC_COUNTER_BUFFER:
221 case GL_BUFFER_VARIABLE:
222 case GL_PROGRAM_INPUT:
223 case GL_PROGRAM_OUTPUT:
224 case GL_SHADER_STORAGE_BLOCK:
225 case GL_UNIFORM:
226 case GL_UNIFORM_BLOCK:
227 return true;
228 default:
229 return false;
230 }
231 }
232
233 case GL_TOP_LEVEL_ARRAY_SIZE:
234 case GL_TOP_LEVEL_ARRAY_STRIDE:
235 {
236 if (programInterface == GL_BUFFER_VARIABLE)
237 {
238 return true;
239 }
240 return false;
241 }
242
243 case GL_TYPE:
244 {
245 switch (programInterface)
246 {
247 case GL_BUFFER_VARIABLE:
248 case GL_PROGRAM_INPUT:
249 case GL_PROGRAM_OUTPUT:
250 case GL_TRANSFORM_FEEDBACK_VARYING:
251 case GL_UNIFORM:
252 return true;
253 default:
254 return false;
255 }
256 }
257
258 default:
259 return false;
260 }
261}
262
jchen10fd7c3b52017-03-21 15:36:03 +0800263bool ValidateProgramResourceIndex(const Program *programObject,
264 GLenum programInterface,
265 GLuint index)
266{
267 switch (programInterface)
268 {
269 case GL_PROGRAM_INPUT:
270 return (index < static_cast<GLuint>(programObject->getActiveAttributeCount()));
271
272 case GL_PROGRAM_OUTPUT:
273 return (index < static_cast<GLuint>(programObject->getOutputResourceCount()));
274
jchen10fd7c3b52017-03-21 15:36:03 +0800275 case GL_UNIFORM:
jchen10baf5d942017-08-28 20:45:48 +0800276 return (index < static_cast<GLuint>(programObject->getActiveUniformCount()));
277
Jiajia Qin3a9090f2017-09-27 14:37:04 +0800278 case GL_BUFFER_VARIABLE:
279 return (index < static_cast<GLuint>(programObject->getActiveBufferVariableCount()));
280
281 case GL_SHADER_STORAGE_BLOCK:
282 return (index < static_cast<GLuint>(programObject->getActiveShaderStorageBlockCount()));
283
jchen10fd7c3b52017-03-21 15:36:03 +0800284 case GL_UNIFORM_BLOCK:
jchen1058f67be2017-10-27 08:59:27 +0800285 return (index < programObject->getActiveUniformBlockCount());
286
287 case GL_ATOMIC_COUNTER_BUFFER:
288 return (index < programObject->getActiveAtomicCounterBufferCount());
289
jchen10fd7c3b52017-03-21 15:36:03 +0800290 case GL_TRANSFORM_FEEDBACK_VARYING:
jchen10910a3da2017-11-15 09:40:11 +0800291 return (index < static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()));
jchen10fd7c3b52017-03-21 15:36:03 +0800292
293 default:
294 UNREACHABLE();
295 return false;
296 }
297}
298
Jamie Madill5b772312018-03-08 20:28:32 -0500299bool ValidateProgramUniform(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +0800300 GLenum valueType,
301 GLuint program,
302 GLint location,
303 GLsizei count)
304{
305 // Check for ES31 program uniform entry points
306 if (context->getClientVersion() < Version(3, 1))
307 {
Jamie Madille0472f32018-11-27 16:32:45 -0500308 context->validationError(GL_INVALID_OPERATION, kES31Required);
Jiajia Qin5451d532017-11-16 17:16:34 +0800309 return false;
310 }
311
312 const LinkedUniform *uniform = nullptr;
Jamie Madill5b772312018-03-08 20:28:32 -0500313 Program *programObject = GetValidProgram(context, program);
Jiajia Qin5451d532017-11-16 17:16:34 +0800314 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
315 ValidateUniformValue(context, valueType, uniform->type);
316}
317
Jamie Madill5b772312018-03-08 20:28:32 -0500318bool ValidateProgramUniformMatrix(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +0800319 GLenum valueType,
320 GLuint program,
321 GLint location,
322 GLsizei count,
323 GLboolean transpose)
324{
325 // Check for ES31 program uniform entry points
326 if (context->getClientVersion() < Version(3, 1))
327 {
Jamie Madille0472f32018-11-27 16:32:45 -0500328 context->validationError(GL_INVALID_OPERATION, kES31Required);
Jiajia Qin5451d532017-11-16 17:16:34 +0800329 return false;
330 }
331
332 const LinkedUniform *uniform = nullptr;
Jamie Madill5b772312018-03-08 20:28:32 -0500333 Program *programObject = GetValidProgram(context, program);
Jiajia Qin5451d532017-11-16 17:16:34 +0800334 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
335 ValidateUniformMatrixValue(context, valueType, uniform->type);
336}
337
Jamie Madill5b772312018-03-08 20:28:32 -0500338bool ValidateVertexAttribFormatCommon(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +0800339 GLuint attribIndex,
340 GLint size,
341 GLenum type,
342 GLuint relativeOffset,
343 GLboolean pureInteger)
344{
345 if (context->getClientVersion() < ES_3_1)
346 {
Jamie Madille0472f32018-11-27 16:32:45 -0500347 context->validationError(GL_INVALID_OPERATION, kES31Required);
Jiajia Qin5451d532017-11-16 17:16:34 +0800348 return false;
349 }
350
351 const Caps &caps = context->getCaps();
352 if (relativeOffset > static_cast<GLuint>(caps.maxVertexAttribRelativeOffset))
353 {
Jamie Madille0472f32018-11-27 16:32:45 -0500354 context->validationError(GL_INVALID_VALUE, kRelativeOffsetTooLarge);
Jiajia Qin5451d532017-11-16 17:16:34 +0800355 return false;
356 }
357
358 // [OpenGL ES 3.1] Section 10.3.1 page 243:
359 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
360 if (context->getGLState().getVertexArrayId() == 0)
361 {
Jamie Madille0472f32018-11-27 16:32:45 -0500362 context->validationError(GL_INVALID_OPERATION, kDefaultVertexArray);
Jiajia Qin5451d532017-11-16 17:16:34 +0800363 return false;
364 }
365
366 return ValidateVertexFormatBase(context, attribIndex, size, type, pureInteger);
367}
368
jchen1015015f72017-03-16 13:54:21 +0800369} // anonymous namespace
370
Martin Radev66fb8202016-07-28 11:45:20 +0300371bool ValidateGetBooleani_v(Context *context, GLenum target, GLuint index, GLboolean *data)
372{
Geoff Langeb66a6e2016-10-31 13:06:12 -0400373 if (context->getClientVersion() < ES_3_1)
Martin Radev66fb8202016-07-28 11:45:20 +0300374 {
Jamie Madille0472f32018-11-27 16:32:45 -0500375 context->validationError(GL_INVALID_OPERATION, kES31Required);
Martin Radev66fb8202016-07-28 11:45:20 +0300376 return false;
377 }
378
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400379 if (!ValidateIndexedStateQuery(context, target, index, nullptr))
380 {
381 return false;
382 }
383
384 return true;
385}
386
387bool ValidateGetBooleani_vRobustANGLE(Context *context,
388 GLenum target,
389 GLuint index,
390 GLsizei bufSize,
391 GLsizei *length,
392 GLboolean *data)
393{
Geoff Langeb66a6e2016-10-31 13:06:12 -0400394 if (context->getClientVersion() < ES_3_1)
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400395 {
Jamie Madille0472f32018-11-27 16:32:45 -0500396 context->validationError(GL_INVALID_OPERATION, kES31Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400397 return false;
398 }
399
400 if (!ValidateRobustEntryPoint(context, bufSize))
401 {
402 return false;
403 }
404
Brandon Jonesd1049182018-03-28 10:02:20 -0700405 GLsizei numParams = 0;
406
407 if (!ValidateIndexedStateQuery(context, target, index, &numParams))
Geoff Lang2e43dbb2016-10-14 12:27:35 -0400408 {
409 return false;
410 }
411
Brandon Jonesd1049182018-03-28 10:02:20 -0700412 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Martin Radev66fb8202016-07-28 11:45:20 +0300413 {
414 return false;
415 }
416
Brandon Jonesd1049182018-03-28 10:02:20 -0700417 SetRobustLengthParam(length, numParams);
Martin Radev66fb8202016-07-28 11:45:20 +0300418 return true;
419}
420
Jamie Madill493f9572018-05-24 19:52:15 -0400421bool ValidateDrawIndirectBase(Context *context, PrimitiveMode mode, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800422{
423 if (context->getClientVersion() < ES_3_1)
424 {
Jamie Madille0472f32018-11-27 16:32:45 -0500425 context->validationError(GL_INVALID_OPERATION, kES31Required);
Jiajia Qind9671222016-11-29 16:30:31 +0800426 return false;
427 }
428
429 // Here the third parameter 1 is only to pass the count validation.
430 if (!ValidateDrawBase(context, mode, 1))
431 {
432 return false;
433 }
434
435 const State &state = context->getGLState();
436
437 // An INVALID_OPERATION error is generated if zero is bound to VERTEX_ARRAY_BINDING,
438 // DRAW_INDIRECT_BUFFER or to any enabled vertex array.
439 if (!state.getVertexArrayId())
440 {
Jamie Madille0472f32018-11-27 16:32:45 -0500441 context->validationError(GL_INVALID_OPERATION, kDefaultVertexArray);
Jiajia Qind9671222016-11-29 16:30:31 +0800442 return false;
443 }
444
Jamie Madill5b772312018-03-08 20:28:32 -0500445 Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
Jiajia Qind9671222016-11-29 16:30:31 +0800446 if (!drawIndirectBuffer)
447 {
Jamie Madille0472f32018-11-27 16:32:45 -0500448 context->validationError(GL_INVALID_OPERATION, kDrawIndirectBufferNotBound);
Jiajia Qind9671222016-11-29 16:30:31 +0800449 return false;
450 }
451
452 // An INVALID_VALUE error is generated if indirect is not a multiple of the size, in basic
453 // machine units, of uint.
454 GLint64 offset = reinterpret_cast<GLint64>(indirect);
455 if ((static_cast<GLuint>(offset) % sizeof(GLuint)) != 0)
456 {
Jamie Madille0472f32018-11-27 16:32:45 -0500457 context->validationError(GL_INVALID_VALUE, kInvalidIndirectOffset);
Jiajia Qind9671222016-11-29 16:30:31 +0800458 return false;
459 }
460
Martin Radev14a26ae2017-07-24 15:56:29 +0300461 // ANGLE_multiview spec, revision 1:
462 // An INVALID_OPERATION is generated by DrawArraysIndirect and DrawElementsIndirect if the
463 // number of views in the draw framebuffer is greater than 1.
464 const Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
465 ASSERT(drawFramebuffer != nullptr);
466 if (drawFramebuffer->getNumViews() > 1)
467 {
Jamie Madille0472f32018-11-27 16:32:45 -0500468 context->validationError(GL_INVALID_OPERATION, kMultiviewActive);
Martin Radev14a26ae2017-07-24 15:56:29 +0300469 return false;
470 }
471
Jiajia Qind9671222016-11-29 16:30:31 +0800472 return true;
473}
474
Jamie Madill493f9572018-05-24 19:52:15 -0400475bool ValidateDrawArraysIndirect(Context *context, PrimitiveMode mode, const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800476{
Jamie Madill493f9572018-05-24 19:52:15 -0400477 const State &state = context->getGLState();
478 TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Jiajia Qind9671222016-11-29 16:30:31 +0800479 if (curTransformFeedback && curTransformFeedback->isActive() &&
480 !curTransformFeedback->isPaused())
481 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800482 // EXT_geometry_shader allows transform feedback to work with all draw commands.
483 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
484 if (context->getExtensions().geometryShader)
485 {
486 if (!ValidateTransformFeedbackPrimitiveMode(
487 context, curTransformFeedback->getPrimitiveMode(), mode))
488 {
Jamie Madille0472f32018-11-27 16:32:45 -0500489 context->validationError(GL_INVALID_OPERATION, kInvalidDrawModeTransformFeedback);
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800490 return false;
491 }
492 }
493 else
494 {
495 // An INVALID_OPERATION error is generated if transform feedback is active and not
496 // paused.
Jamie Madill610640f2018-11-21 17:28:41 -0500497 context->validationError(GL_INVALID_OPERATION,
Jamie Madille0472f32018-11-27 16:32:45 -0500498 kUnsupportedDrawModeForTransformFeedback);
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800499 return false;
500 }
Jiajia Qind9671222016-11-29 16:30:31 +0800501 }
502
503 if (!ValidateDrawIndirectBase(context, mode, indirect))
504 return false;
505
Jamie Madill5b772312018-03-08 20:28:32 -0500506 Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
Jiajia Qind9671222016-11-29 16:30:31 +0800507 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
508 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawArraysIndirectCommand
509 // which's size is 4 * sizeof(uint).
510 auto checkedSum = checkedOffset + 4 * sizeof(GLuint);
511 if (!checkedSum.IsValid() ||
512 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
513 {
Jamie Madille0472f32018-11-27 16:32:45 -0500514 context->validationError(GL_INVALID_OPERATION, kParamOverflow);
Jiajia Qind9671222016-11-29 16:30:31 +0800515 return false;
516 }
517
518 return true;
519}
520
Jamie Madill493f9572018-05-24 19:52:15 -0400521bool ValidateDrawElementsIndirect(Context *context,
522 PrimitiveMode mode,
523 GLenum type,
524 const void *indirect)
Jiajia Qind9671222016-11-29 16:30:31 +0800525{
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800526 if (!ValidateDrawElementsBase(context, mode, type))
527 {
Jiajia Qind9671222016-11-29 16:30:31 +0800528 return false;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800529 }
Jiajia Qind9671222016-11-29 16:30:31 +0800530
Jamie Madill493f9572018-05-24 19:52:15 -0400531 const State &state = context->getGLState();
532 const VertexArray *vao = state.getVertexArray();
Jamie Madillcd0a0a32018-10-18 18:41:57 -0400533 Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
Jiajia Qind9671222016-11-29 16:30:31 +0800534 if (!elementArrayBuffer)
535 {
Jamie Madille0472f32018-11-27 16:32:45 -0500536 context->validationError(GL_INVALID_OPERATION, kMustHaveElementArrayBinding);
Jiajia Qind9671222016-11-29 16:30:31 +0800537 return false;
538 }
539
540 if (!ValidateDrawIndirectBase(context, mode, indirect))
541 return false;
542
Jamie Madill5b772312018-03-08 20:28:32 -0500543 Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
Jiajia Qind9671222016-11-29 16:30:31 +0800544 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
545 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawElementsIndirectCommand
546 // which's size is 5 * sizeof(uint).
547 auto checkedSum = checkedOffset + 5 * sizeof(GLuint);
548 if (!checkedSum.IsValid() ||
549 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
550 {
Jamie Madill610640f2018-11-21 17:28:41 -0500551 context->validationError(
552 GL_INVALID_OPERATION,
553 "the command would source data beyond the end of the buffer object.");
Jiajia Qind9671222016-11-29 16:30:31 +0800554 return false;
555 }
556
557 return true;
558}
559
Jiajia Qin5451d532017-11-16 17:16:34 +0800560bool ValidateProgramUniform1i(Context *context, GLuint program, GLint location, GLint v0)
561{
562 return ValidateProgramUniform1iv(context, program, location, 1, &v0);
563}
564
565bool ValidateProgramUniform2i(Context *context, GLuint program, GLint location, GLint v0, GLint v1)
566{
567 GLint xy[2] = {v0, v1};
568 return ValidateProgramUniform2iv(context, program, location, 1, xy);
569}
570
571bool ValidateProgramUniform3i(Context *context,
572 GLuint program,
573 GLint location,
574 GLint v0,
575 GLint v1,
576 GLint v2)
577{
578 GLint xyz[3] = {v0, v1, v2};
579 return ValidateProgramUniform3iv(context, program, location, 1, xyz);
580}
581
582bool ValidateProgramUniform4i(Context *context,
583 GLuint program,
584 GLint location,
585 GLint v0,
586 GLint v1,
587 GLint v2,
588 GLint v3)
589{
590 GLint xyzw[4] = {v0, v1, v2, v3};
591 return ValidateProgramUniform4iv(context, program, location, 1, xyzw);
592}
593
594bool ValidateProgramUniform1ui(Context *context, GLuint program, GLint location, GLuint v0)
595{
596 return ValidateProgramUniform1uiv(context, program, location, 1, &v0);
597}
598
599bool ValidateProgramUniform2ui(Context *context,
600 GLuint program,
601 GLint location,
602 GLuint v0,
603 GLuint v1)
604{
605 GLuint xy[2] = {v0, v1};
606 return ValidateProgramUniform2uiv(context, program, location, 1, xy);
607}
608
609bool ValidateProgramUniform3ui(Context *context,
610 GLuint program,
611 GLint location,
612 GLuint v0,
613 GLuint v1,
614 GLuint v2)
615{
616 GLuint xyz[3] = {v0, v1, v2};
617 return ValidateProgramUniform3uiv(context, program, location, 1, xyz);
618}
619
620bool ValidateProgramUniform4ui(Context *context,
621 GLuint program,
622 GLint location,
623 GLuint v0,
624 GLuint v1,
625 GLuint v2,
626 GLuint v3)
627{
628 GLuint xyzw[4] = {v0, v1, v2, v3};
629 return ValidateProgramUniform4uiv(context, program, location, 1, xyzw);
630}
631
632bool ValidateProgramUniform1f(Context *context, GLuint program, GLint location, GLfloat v0)
633{
634 return ValidateProgramUniform1fv(context, program, location, 1, &v0);
635}
636
637bool ValidateProgramUniform2f(Context *context,
638 GLuint program,
639 GLint location,
640 GLfloat v0,
641 GLfloat v1)
642{
643 GLfloat xy[2] = {v0, v1};
644 return ValidateProgramUniform2fv(context, program, location, 1, xy);
645}
646
647bool ValidateProgramUniform3f(Context *context,
648 GLuint program,
649 GLint location,
650 GLfloat v0,
651 GLfloat v1,
652 GLfloat v2)
653{
654 GLfloat xyz[3] = {v0, v1, v2};
655 return ValidateProgramUniform3fv(context, program, location, 1, xyz);
656}
657
658bool ValidateProgramUniform4f(Context *context,
659 GLuint program,
660 GLint location,
661 GLfloat v0,
662 GLfloat v1,
663 GLfloat v2,
664 GLfloat v3)
665{
666 GLfloat xyzw[4] = {v0, v1, v2, v3};
667 return ValidateProgramUniform4fv(context, program, location, 1, xyzw);
668}
669
670bool ValidateProgramUniform1iv(Context *context,
671 GLuint program,
672 GLint location,
673 GLsizei count,
674 const GLint *value)
675{
676 // Check for ES31 program uniform entry points
677 if (context->getClientVersion() < Version(3, 1))
678 {
Jamie Madille0472f32018-11-27 16:32:45 -0500679 context->validationError(GL_INVALID_OPERATION, kES31Required);
Jiajia Qin5451d532017-11-16 17:16:34 +0800680 return false;
681 }
682
683 const LinkedUniform *uniform = nullptr;
Jamie Madill5b772312018-03-08 20:28:32 -0500684 Program *programObject = GetValidProgram(context, program);
Jiajia Qin5451d532017-11-16 17:16:34 +0800685 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
686 ValidateUniform1ivValue(context, uniform->type, count, value);
687}
688
689bool ValidateProgramUniform2iv(Context *context,
690 GLuint program,
691 GLint location,
692 GLsizei count,
693 const GLint *value)
694{
695 return ValidateProgramUniform(context, GL_INT_VEC2, program, location, count);
696}
697
698bool ValidateProgramUniform3iv(Context *context,
699 GLuint program,
700 GLint location,
701 GLsizei count,
702 const GLint *value)
703{
704 return ValidateProgramUniform(context, GL_INT_VEC3, program, location, count);
705}
706
707bool ValidateProgramUniform4iv(Context *context,
708 GLuint program,
709 GLint location,
710 GLsizei count,
711 const GLint *value)
712{
713 return ValidateProgramUniform(context, GL_INT_VEC4, program, location, count);
714}
715
716bool ValidateProgramUniform1uiv(Context *context,
717 GLuint program,
718 GLint location,
719 GLsizei count,
720 const GLuint *value)
721{
722 return ValidateProgramUniform(context, GL_UNSIGNED_INT, program, location, count);
723}
724
725bool ValidateProgramUniform2uiv(Context *context,
726 GLuint program,
727 GLint location,
728 GLsizei count,
729 const GLuint *value)
730{
731 return ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC2, program, location, count);
732}
733
734bool ValidateProgramUniform3uiv(Context *context,
735 GLuint program,
736 GLint location,
737 GLsizei count,
738 const GLuint *value)
739{
740 return ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC3, program, location, count);
741}
742
743bool ValidateProgramUniform4uiv(Context *context,
744 GLuint program,
745 GLint location,
746 GLsizei count,
747 const GLuint *value)
748{
749 return ValidateProgramUniform(context, GL_UNSIGNED_INT_VEC4, program, location, count);
750}
751
752bool ValidateProgramUniform1fv(Context *context,
753 GLuint program,
754 GLint location,
755 GLsizei count,
756 const GLfloat *value)
757{
758 return ValidateProgramUniform(context, GL_FLOAT, program, location, count);
759}
760
761bool ValidateProgramUniform2fv(Context *context,
762 GLuint program,
763 GLint location,
764 GLsizei count,
765 const GLfloat *value)
766{
767 return ValidateProgramUniform(context, GL_FLOAT_VEC2, program, location, count);
768}
769
770bool ValidateProgramUniform3fv(Context *context,
771 GLuint program,
772 GLint location,
773 GLsizei count,
774 const GLfloat *value)
775{
776 return ValidateProgramUniform(context, GL_FLOAT_VEC3, program, location, count);
777}
778
779bool ValidateProgramUniform4fv(Context *context,
780 GLuint program,
781 GLint location,
782 GLsizei count,
783 const GLfloat *value)
784{
785 return ValidateProgramUniform(context, GL_FLOAT_VEC4, program, location, count);
786}
787
788bool ValidateProgramUniformMatrix2fv(Context *context,
789 GLuint program,
790 GLint location,
791 GLsizei count,
792 GLboolean transpose,
793 const GLfloat *value)
794{
795 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2, program, location, count,
796 transpose);
797}
798
799bool ValidateProgramUniformMatrix3fv(Context *context,
800 GLuint program,
801 GLint location,
802 GLsizei count,
803 GLboolean transpose,
804 const GLfloat *value)
805{
806 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3, program, location, count,
807 transpose);
808}
809
810bool ValidateProgramUniformMatrix4fv(Context *context,
811 GLuint program,
812 GLint location,
813 GLsizei count,
814 GLboolean transpose,
815 const GLfloat *value)
816{
817 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4, program, location, count,
818 transpose);
819}
820
821bool ValidateProgramUniformMatrix2x3fv(Context *context,
822 GLuint program,
823 GLint location,
824 GLsizei count,
825 GLboolean transpose,
826 const GLfloat *value)
827{
828 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2x3, program, location, count,
829 transpose);
830}
831
832bool ValidateProgramUniformMatrix3x2fv(Context *context,
833 GLuint program,
834 GLint location,
835 GLsizei count,
836 GLboolean transpose,
837 const GLfloat *value)
838{
839 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3x2, program, location, count,
840 transpose);
841}
842
843bool ValidateProgramUniformMatrix2x4fv(Context *context,
844 GLuint program,
845 GLint location,
846 GLsizei count,
847 GLboolean transpose,
848 const GLfloat *value)
849{
850 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT2x4, program, location, count,
851 transpose);
852}
853
854bool ValidateProgramUniformMatrix4x2fv(Context *context,
855 GLuint program,
856 GLint location,
857 GLsizei count,
858 GLboolean transpose,
859 const GLfloat *value)
860{
861 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4x2, program, location, count,
862 transpose);
863}
864
865bool ValidateProgramUniformMatrix3x4fv(Context *context,
866 GLuint program,
867 GLint location,
868 GLsizei count,
869 GLboolean transpose,
870 const GLfloat *value)
871{
872 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT3x4, program, location, count,
873 transpose);
874}
875
876bool ValidateProgramUniformMatrix4x3fv(Context *context,
877 GLuint program,
878 GLint location,
879 GLsizei count,
880 GLboolean transpose,
881 const GLfloat *value)
882{
883 return ValidateProgramUniformMatrix(context, GL_FLOAT_MAT4x3, program, location, count,
884 transpose);
885}
886
Yizhou Jiangc0b6c632018-09-06 15:02:04 +0800887bool ValidateGetTexLevelParameterfv(Context *context,
888 TextureTarget target,
889 GLint level,
890 GLenum pname,
891 GLfloat *params)
He Yunchao11b038b2016-11-22 21:24:04 +0800892{
893 if (context->getClientVersion() < ES_3_1)
894 {
Jamie Madille0472f32018-11-27 16:32:45 -0500895 context->validationError(GL_INVALID_OPERATION, kES31Required);
He Yunchao11b038b2016-11-22 21:24:04 +0800896 return false;
897 }
898
He Yunchao11b038b2016-11-22 21:24:04 +0800899 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
900}
901
Brandon Jonesfe4bbe62018-04-06 13:50:14 -0700902bool ValidateGetTexLevelParameterfvRobustANGLE(Context *context,
903 TextureTarget target,
904 GLint level,
905 GLenum pname,
906 GLsizei bufSize,
907 GLsizei *length,
908 GLfloat *params)
909{
910 UNIMPLEMENTED();
911 return false;
912}
913
He Yunchao11b038b2016-11-22 21:24:04 +0800914bool ValidateGetTexLevelParameteriv(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800915 TextureTarget target,
He Yunchao11b038b2016-11-22 21:24:04 +0800916 GLint level,
917 GLenum pname,
918 GLint *params)
919{
Yizhou Jiangc0b6c632018-09-06 15:02:04 +0800920 if (context->getClientVersion() < ES_3_1)
921 {
Jamie Madille0472f32018-11-27 16:32:45 -0500922 context->validationError(GL_INVALID_OPERATION, kES31Required);
Yizhou Jiangc0b6c632018-09-06 15:02:04 +0800923 return false;
924 }
925
He Yunchao11b038b2016-11-22 21:24:04 +0800926 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
927}
928
Brandon Jonesfe4bbe62018-04-06 13:50:14 -0700929bool ValidateGetTexLevelParameterivRobustANGLE(Context *context,
930 TextureTarget target,
931 GLint level,
932 GLenum pname,
933 GLsizei bufSize,
934 GLsizei *length,
935 GLint *params)
936{
937 UNIMPLEMENTED();
938 return false;
939}
940
Jiajia Qin5451d532017-11-16 17:16:34 +0800941bool ValidateTexStorage2DMultisample(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800942 TextureType target,
JiangYizhoubddc46b2016-12-09 09:50:51 +0800943 GLsizei samples,
Jamie Madill778bf092018-11-14 09:54:36 -0500944 GLenum internalFormat,
JiangYizhoubddc46b2016-12-09 09:50:51 +0800945 GLsizei width,
946 GLsizei height,
947 GLboolean fixedSampleLocations)
948{
949 if (context->getClientVersion() < ES_3_1)
950 {
Jamie Madille0472f32018-11-27 16:32:45 -0500951 context->validationError(GL_INVALID_OPERATION, kES31Required);
JiangYizhoubddc46b2016-12-09 09:50:51 +0800952 return false;
953 }
954
Yizhou Jiang7818a852018-09-06 15:02:04 +0800955 return ValidateTexStorage2DMultisampleBase(context, target, samples, internalFormat, width,
956 height);
JiangYizhoubddc46b2016-12-09 09:50:51 +0800957}
958
959bool ValidateGetMultisamplefv(Context *context, GLenum pname, GLuint index, GLfloat *val)
960{
961 if (context->getClientVersion() < ES_3_1)
962 {
Jamie Madille0472f32018-11-27 16:32:45 -0500963 context->validationError(GL_INVALID_OPERATION, kES31Required);
JiangYizhoubddc46b2016-12-09 09:50:51 +0800964 return false;
965 }
966
967 if (pname != GL_SAMPLE_POSITION)
968 {
Jamie Madille0472f32018-11-27 16:32:45 -0500969 context->validationError(GL_INVALID_ENUM, kInvalidPname);
JiangYizhoubddc46b2016-12-09 09:50:51 +0800970 return false;
971 }
972
JiangYizhou5b03f472017-01-09 10:22:53 +0800973 Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -0400974 GLint samples = framebuffer->getSamples(context);
JiangYizhou5b03f472017-01-09 10:22:53 +0800975
Jamie Madille98b1b52018-03-08 09:47:23 -0500976 if (index >= static_cast<GLuint>(samples))
JiangYizhoubddc46b2016-12-09 09:50:51 +0800977 {
Jamie Madille0472f32018-11-27 16:32:45 -0500978 context->validationError(GL_INVALID_VALUE, kIndexExceedsSamples);
JiangYizhoubddc46b2016-12-09 09:50:51 +0800979 return false;
980 }
981
982 return true;
983}
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800984
Brandon Jonesfe4bbe62018-04-06 13:50:14 -0700985bool ValidateGetMultisamplefvRobustANGLE(Context *context,
986 GLenum pname,
987 GLuint index,
988 GLsizei bufSize,
989 GLsizei *length,
990 GLfloat *val)
991{
992 UNIMPLEMENTED();
993 return false;
994}
995
Jiajia Qin5451d532017-11-16 17:16:34 +0800996bool ValidateFramebufferParameteri(Context *context, GLenum target, GLenum pname, GLint param)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800997{
998 if (context->getClientVersion() < ES_3_1)
999 {
Jamie Madille0472f32018-11-27 16:32:45 -05001000 context->validationError(GL_INVALID_OPERATION, kES31Required);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001001 return false;
1002 }
1003
Geoff Lange8afa902017-09-27 15:00:43 -04001004 if (!ValidFramebufferTarget(context, target))
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001005 {
Jamie Madille0472f32018-11-27 16:32:45 -05001006 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001007 return false;
1008 }
1009
1010 switch (pname)
1011 {
1012 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1013 {
1014 GLint maxWidth = context->getCaps().maxFramebufferWidth;
1015 if (param < 0 || param > maxWidth)
1016 {
Jamie Madill610640f2018-11-21 17:28:41 -05001017 context->validationError(
1018 GL_INVALID_VALUE,
1019 "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_WIDTH.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001020 return false;
1021 }
1022 break;
1023 }
1024 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1025 {
1026 GLint maxHeight = context->getCaps().maxFramebufferHeight;
1027 if (param < 0 || param > maxHeight)
1028 {
Jamie Madill610640f2018-11-21 17:28:41 -05001029 context->validationError(
1030 GL_INVALID_VALUE,
1031 "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_HEIGHT.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001032 return false;
1033 }
1034 break;
1035 }
1036 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1037 {
1038 GLint maxSamples = context->getCaps().maxFramebufferSamples;
1039 if (param < 0 || param > maxSamples)
1040 {
Jamie Madill610640f2018-11-21 17:28:41 -05001041 context->validationError(
1042 GL_INVALID_VALUE,
1043 "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_SAMPLES.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001044 return false;
1045 }
1046 break;
1047 }
1048 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1049 {
1050 break;
1051 }
Jiawei Shaob1e91382018-05-17 14:33:55 +08001052 case GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT:
1053 {
1054 if (!context->getExtensions().geometryShader)
1055 {
Jamie Madille0472f32018-11-27 16:32:45 -05001056 context->validationError(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
Jiawei Shaob1e91382018-05-17 14:33:55 +08001057 return false;
1058 }
1059 GLint maxLayers = context->getCaps().maxFramebufferLayers;
1060 if (param < 0 || param > maxLayers)
1061 {
Jamie Madille0472f32018-11-27 16:32:45 -05001062 context->validationError(GL_INVALID_VALUE, kInvalidFramebufferLayer);
Jiawei Shaob1e91382018-05-17 14:33:55 +08001063 return false;
1064 }
1065 break;
1066 }
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001067 default:
1068 {
Jamie Madille0472f32018-11-27 16:32:45 -05001069 context->validationError(GL_INVALID_ENUM, kInvalidPname);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001070 return false;
1071 }
1072 }
1073
1074 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
1075 ASSERT(framebuffer);
1076 if (framebuffer->id() == 0)
1077 {
Jamie Madill610640f2018-11-21 17:28:41 -05001078 context->validationError(GL_INVALID_OPERATION, "Default framebuffer is bound to target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001079 return false;
1080 }
1081 return true;
1082}
1083
Jiajia Qin5451d532017-11-16 17:16:34 +08001084bool ValidateGetFramebufferParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001085{
1086 if (context->getClientVersion() < ES_3_1)
1087 {
Jamie Madille0472f32018-11-27 16:32:45 -05001088 context->validationError(GL_INVALID_OPERATION, kES31Required);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001089 return false;
1090 }
1091
Geoff Lange8afa902017-09-27 15:00:43 -04001092 if (!ValidFramebufferTarget(context, target))
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001093 {
Jamie Madille0472f32018-11-27 16:32:45 -05001094 context->validationError(GL_INVALID_ENUM, kInvalidFramebufferTarget);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001095 return false;
1096 }
1097
1098 switch (pname)
1099 {
1100 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
1101 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
1102 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
1103 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
1104 break;
Jiawei Shaob1e91382018-05-17 14:33:55 +08001105 case GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT:
1106 if (!context->getExtensions().geometryShader)
1107 {
Jamie Madille0472f32018-11-27 16:32:45 -05001108 context->validationError(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
Jiawei Shaob1e91382018-05-17 14:33:55 +08001109 return false;
1110 }
1111 break;
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001112 default:
Jamie Madille0472f32018-11-27 16:32:45 -05001113 context->validationError(GL_INVALID_ENUM, kInvalidPname);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001114 return false;
1115 }
1116
1117 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
1118 ASSERT(framebuffer);
1119
1120 if (framebuffer->id() == 0)
1121 {
Jamie Madill610640f2018-11-21 17:28:41 -05001122 context->validationError(GL_INVALID_OPERATION, "Default framebuffer is bound to target.");
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001123 return false;
1124 }
1125 return true;
1126}
1127
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07001128bool ValidateGetFramebufferParameterivRobustANGLE(Context *context,
1129 GLenum target,
1130 GLenum pname,
1131 GLsizei bufSize,
1132 GLsizei *length,
1133 GLint *params)
1134{
1135 UNIMPLEMENTED();
1136 return false;
1137}
1138
jchen1015015f72017-03-16 13:54:21 +08001139bool ValidateGetProgramResourceIndex(Context *context,
1140 GLuint program,
1141 GLenum programInterface,
1142 const GLchar *name)
1143{
1144 if (context->getClientVersion() < ES_3_1)
1145 {
Jamie Madille0472f32018-11-27 16:32:45 -05001146 context->validationError(GL_INVALID_OPERATION, kES31Required);
jchen1015015f72017-03-16 13:54:21 +08001147 return false;
1148 }
1149
1150 Program *programObject = GetValidProgram(context, program);
1151 if (programObject == nullptr)
1152 {
1153 return false;
1154 }
1155
1156 if (!ValidateNamedProgramInterface(programInterface))
1157 {
Jamie Madill610640f2018-11-21 17:28:41 -05001158 context->validationError(GL_INVALID_ENUM, "Invalid program interface");
jchen1015015f72017-03-16 13:54:21 +08001159 return false;
1160 }
Shao80957d92017-02-20 21:25:59 +08001161
1162 return true;
1163}
1164
Jamie Madill5b772312018-03-08 20:28:32 -05001165bool ValidateBindVertexBuffer(Context *context,
Shao80957d92017-02-20 21:25:59 +08001166 GLuint bindingIndex,
1167 GLuint buffer,
1168 GLintptr offset,
1169 GLsizei stride)
1170{
1171 if (context->getClientVersion() < ES_3_1)
1172 {
Jamie Madille0472f32018-11-27 16:32:45 -05001173 context->validationError(GL_INVALID_OPERATION, kES31Required);
Shao80957d92017-02-20 21:25:59 +08001174 return false;
1175 }
1176
1177 if (!context->isBufferGenerated(buffer))
1178 {
Jamie Madill610640f2018-11-21 17:28:41 -05001179 context->validationError(GL_INVALID_OPERATION, "Buffer is not generated.");
Shao80957d92017-02-20 21:25:59 +08001180 return false;
1181 }
1182
1183 const Caps &caps = context->getCaps();
1184 if (bindingIndex >= caps.maxVertexAttribBindings)
1185 {
Jamie Madill610640f2018-11-21 17:28:41 -05001186 context->validationError(GL_INVALID_VALUE,
1187 "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08001188 return false;
1189 }
1190
1191 if (offset < 0)
1192 {
Jamie Madille0472f32018-11-27 16:32:45 -05001193 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
Shao80957d92017-02-20 21:25:59 +08001194 return false;
1195 }
1196
1197 if (stride < 0 || stride > caps.maxVertexAttribStride)
1198 {
Jamie Madill610640f2018-11-21 17:28:41 -05001199 context->validationError(GL_INVALID_VALUE,
1200 "stride must be between 0 and MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08001201 return false;
1202 }
1203
1204 // [OpenGL ES 3.1] Section 10.3.1 page 244:
1205 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
1206 if (context->getGLState().getVertexArrayId() == 0)
1207 {
Jamie Madill610640f2018-11-21 17:28:41 -05001208 context->validationError(GL_INVALID_OPERATION, "Default vertex array buffer is bound.");
Shao80957d92017-02-20 21:25:59 +08001209 return false;
1210 }
1211
1212 return true;
1213}
1214
Jamie Madill5b772312018-03-08 20:28:32 -05001215bool ValidateVertexBindingDivisor(Context *context, GLuint bindingIndex, GLuint divisor)
Shao80957d92017-02-20 21:25:59 +08001216{
1217 if (context->getClientVersion() < ES_3_1)
1218 {
Jamie Madille0472f32018-11-27 16:32:45 -05001219 context->validationError(GL_INVALID_OPERATION, kES31Required);
Shao80957d92017-02-20 21:25:59 +08001220 return false;
1221 }
1222
1223 const Caps &caps = context->getCaps();
1224 if (bindingIndex >= caps.maxVertexAttribBindings)
1225 {
Jamie Madill610640f2018-11-21 17:28:41 -05001226 context->validationError(GL_INVALID_VALUE,
1227 "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08001228 return false;
1229 }
1230
1231 // [OpenGL ES 3.1] Section 10.3.1 page 243:
1232 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
1233 if (context->getGLState().getVertexArrayId() == 0)
1234 {
Jamie Madill610640f2018-11-21 17:28:41 -05001235 context->validationError(GL_INVALID_OPERATION, "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +08001236 return false;
1237 }
1238
1239 return true;
1240}
1241
Jamie Madill5b772312018-03-08 20:28:32 -05001242bool ValidateVertexAttribFormat(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08001243 GLuint attribindex,
Shao80957d92017-02-20 21:25:59 +08001244 GLint size,
1245 GLenum type,
Jiajia Qin5451d532017-11-16 17:16:34 +08001246 GLboolean normalized,
1247 GLuint relativeoffset)
Shao80957d92017-02-20 21:25:59 +08001248{
Jiajia Qin5451d532017-11-16 17:16:34 +08001249 return ValidateVertexAttribFormatCommon(context, attribindex, size, type, relativeoffset,
1250 false);
1251}
Shao80957d92017-02-20 21:25:59 +08001252
Jamie Madill5b772312018-03-08 20:28:32 -05001253bool ValidateVertexAttribIFormat(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08001254 GLuint attribindex,
1255 GLint size,
1256 GLenum type,
1257 GLuint relativeoffset)
1258{
1259 return ValidateVertexAttribFormatCommon(context, attribindex, size, type, relativeoffset, true);
Shao80957d92017-02-20 21:25:59 +08001260}
1261
Jamie Madill5b772312018-03-08 20:28:32 -05001262bool ValidateVertexAttribBinding(Context *context, GLuint attribIndex, GLuint bindingIndex)
Shao80957d92017-02-20 21:25:59 +08001263{
1264 if (context->getClientVersion() < ES_3_1)
1265 {
Jamie Madille0472f32018-11-27 16:32:45 -05001266 context->validationError(GL_INVALID_OPERATION, kES31Required);
Shao80957d92017-02-20 21:25:59 +08001267 return false;
1268 }
1269
1270 // [OpenGL ES 3.1] Section 10.3.1 page 243:
1271 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
1272 if (context->getGLState().getVertexArrayId() == 0)
1273 {
Jamie Madill610640f2018-11-21 17:28:41 -05001274 context->validationError(GL_INVALID_OPERATION, "Default vertex array object is bound.");
Shao80957d92017-02-20 21:25:59 +08001275 return false;
1276 }
1277
1278 const Caps &caps = context->getCaps();
1279 if (attribIndex >= caps.maxVertexAttributes)
1280 {
Jamie Madille0472f32018-11-27 16:32:45 -05001281 context->validationError(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08001282 return false;
1283 }
1284
1285 if (bindingIndex >= caps.maxVertexAttribBindings)
1286 {
Jamie Madill610640f2018-11-21 17:28:41 -05001287 context->validationError(GL_INVALID_VALUE,
1288 "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS");
Shao80957d92017-02-20 21:25:59 +08001289 return false;
1290 }
1291
jchen1015015f72017-03-16 13:54:21 +08001292 return true;
1293}
1294
jchen10fd7c3b52017-03-21 15:36:03 +08001295bool ValidateGetProgramResourceName(Context *context,
1296 GLuint program,
1297 GLenum programInterface,
1298 GLuint index,
1299 GLsizei bufSize,
1300 GLsizei *length,
1301 GLchar *name)
1302{
1303 if (context->getClientVersion() < ES_3_1)
1304 {
Jamie Madille0472f32018-11-27 16:32:45 -05001305 context->validationError(GL_INVALID_OPERATION, kES31Required);
jchen10fd7c3b52017-03-21 15:36:03 +08001306 return false;
1307 }
1308
1309 Program *programObject = GetValidProgram(context, program);
1310 if (programObject == nullptr)
1311 {
1312 return false;
1313 }
1314
1315 if (!ValidateNamedProgramInterface(programInterface))
1316 {
Jamie Madill610640f2018-11-21 17:28:41 -05001317 context->validationError(GL_INVALID_ENUM, "Invalid program interface");
jchen10fd7c3b52017-03-21 15:36:03 +08001318 return false;
1319 }
1320
1321 if (!ValidateProgramResourceIndex(programObject, programInterface, index))
1322 {
Jamie Madill610640f2018-11-21 17:28:41 -05001323 context->validationError(GL_INVALID_VALUE, "Invalid index");
jchen10fd7c3b52017-03-21 15:36:03 +08001324 return false;
1325 }
1326
1327 if (bufSize < 0)
1328 {
Jamie Madille0472f32018-11-27 16:32:45 -05001329 context->validationError(GL_INVALID_VALUE, kNegativeBufferSize);
jchen10fd7c3b52017-03-21 15:36:03 +08001330 return false;
1331 }
1332
1333 return true;
1334}
1335
Xinghua Cao2b396592017-03-29 15:36:04 +08001336bool ValidateDispatchCompute(Context *context,
1337 GLuint numGroupsX,
1338 GLuint numGroupsY,
1339 GLuint numGroupsZ)
1340{
1341 if (context->getClientVersion() < ES_3_1)
1342 {
Jamie Madille0472f32018-11-27 16:32:45 -05001343 context->validationError(GL_INVALID_OPERATION, kES31Required);
Xinghua Cao2b396592017-03-29 15:36:04 +08001344 return false;
1345 }
1346
1347 const State &state = context->getGLState();
Jamie Madill785e8a02018-10-04 17:42:00 -04001348 Program *program = state.getLinkedProgram(context);
Xinghua Cao2b396592017-03-29 15:36:04 +08001349
Jiawei Shao385b3e02018-03-21 09:43:28 +08001350 if (program == nullptr || !program->hasLinkedShaderStage(ShaderType::Compute))
Xinghua Cao2b396592017-03-29 15:36:04 +08001351 {
Jamie Madille0472f32018-11-27 16:32:45 -05001352 context->validationError(GL_INVALID_OPERATION, kNoActiveProgramWithComputeShader);
Xinghua Cao2b396592017-03-29 15:36:04 +08001353 return false;
1354 }
1355
1356 const Caps &caps = context->getCaps();
1357 if (numGroupsX > caps.maxComputeWorkGroupCount[0])
1358 {
Jamie Madill610640f2018-11-21 17:28:41 -05001359 context->validationError(
1360 GL_INVALID_VALUE,
1361 "num_groups_x cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[0]");
Xinghua Cao2b396592017-03-29 15:36:04 +08001362 return false;
1363 }
1364 if (numGroupsY > caps.maxComputeWorkGroupCount[1])
1365 {
Jamie Madill610640f2018-11-21 17:28:41 -05001366 context->validationError(
1367 GL_INVALID_VALUE,
1368 "num_groups_y cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[1]");
Xinghua Cao2b396592017-03-29 15:36:04 +08001369 return false;
1370 }
1371 if (numGroupsZ > caps.maxComputeWorkGroupCount[2])
1372 {
Jamie Madill610640f2018-11-21 17:28:41 -05001373 context->validationError(
1374 GL_INVALID_VALUE,
1375 "num_groups_z cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[2]");
Xinghua Cao2b396592017-03-29 15:36:04 +08001376 return false;
1377 }
1378
1379 return true;
1380}
1381
Jiajia Qin5451d532017-11-16 17:16:34 +08001382bool ValidateDispatchComputeIndirect(Context *context, GLintptr indirect)
1383{
Qin Jiajia62fcf622017-11-30 16:16:12 +08001384 if (context->getClientVersion() < ES_3_1)
1385 {
Jamie Madille0472f32018-11-27 16:32:45 -05001386 context->validationError(GL_INVALID_OPERATION, kES31Required);
Qin Jiajia62fcf622017-11-30 16:16:12 +08001387 return false;
1388 }
1389
1390 const State &state = context->getGLState();
Jamie Madill785e8a02018-10-04 17:42:00 -04001391 Program *program = state.getLinkedProgram(context);
Qin Jiajia62fcf622017-11-30 16:16:12 +08001392
Jiawei Shao385b3e02018-03-21 09:43:28 +08001393 if (program == nullptr || !program->hasLinkedShaderStage(ShaderType::Compute))
Qin Jiajia62fcf622017-11-30 16:16:12 +08001394 {
Jamie Madille0472f32018-11-27 16:32:45 -05001395 context->validationError(GL_INVALID_OPERATION, kNoActiveProgramWithComputeShader);
Qin Jiajia62fcf622017-11-30 16:16:12 +08001396 return false;
1397 }
1398
Qin Jiajia62fcf622017-11-30 16:16:12 +08001399 if (indirect < 0)
1400 {
Jamie Madille0472f32018-11-27 16:32:45 -05001401 context->validationError(GL_INVALID_VALUE, kNegativeOffset);
Qin Jiajia62fcf622017-11-30 16:16:12 +08001402 return false;
1403 }
1404
1405 if ((indirect & (sizeof(GLuint) - 1)) != 0)
1406 {
Jamie Madille0472f32018-11-27 16:32:45 -05001407 context->validationError(GL_INVALID_VALUE, kOffsetMustBeMultipleOfUint);
Qin Jiajiaa4ef8432018-02-22 16:02:24 +08001408 return false;
1409 }
1410
Jamie Madill5b772312018-03-08 20:28:32 -05001411 Buffer *dispatchIndirectBuffer = state.getTargetBuffer(BufferBinding::DispatchIndirect);
Qin Jiajiaa4ef8432018-02-22 16:02:24 +08001412 if (!dispatchIndirectBuffer)
1413 {
Jamie Madille0472f32018-11-27 16:32:45 -05001414 context->validationError(GL_INVALID_OPERATION, kDispatchIndirectBufferNotBound);
Qin Jiajia62fcf622017-11-30 16:16:12 +08001415 return false;
1416 }
1417
1418 CheckedNumeric<GLuint64> checkedOffset(static_cast<GLuint64>(indirect));
1419 auto checkedSum = checkedOffset + static_cast<GLuint64>(3 * sizeof(GLuint));
1420 if (!checkedSum.IsValid() ||
1421 checkedSum.ValueOrDie() > static_cast<GLuint64>(dispatchIndirectBuffer->getSize()))
1422 {
Jamie Madille0472f32018-11-27 16:32:45 -05001423 context->validationError(GL_INVALID_OPERATION, kInsufficientBufferSize);
Qin Jiajia62fcf622017-11-30 16:16:12 +08001424 return false;
1425 }
1426
1427 return true;
Jiajia Qin5451d532017-11-16 17:16:34 +08001428}
1429
Xinghua Cao65ec0b22017-03-28 16:10:52 +08001430bool ValidateBindImageTexture(Context *context,
1431 GLuint unit,
1432 GLuint texture,
1433 GLint level,
1434 GLboolean layered,
1435 GLint layer,
1436 GLenum access,
1437 GLenum format)
1438{
1439 GLuint maxImageUnits = context->getCaps().maxImageUnits;
1440 if (unit >= maxImageUnits)
1441 {
Jamie Madill610640f2018-11-21 17:28:41 -05001442 context->validationError(GL_INVALID_VALUE,
1443 "unit cannot be greater than or equal than MAX_IMAGE_UNITS");
Xinghua Cao65ec0b22017-03-28 16:10:52 +08001444 return false;
1445 }
1446
1447 if (level < 0)
1448 {
Jamie Madill610640f2018-11-21 17:28:41 -05001449 context->validationError(GL_INVALID_VALUE, "level is negative.");
Xinghua Cao65ec0b22017-03-28 16:10:52 +08001450 return false;
1451 }
1452
1453 if (layer < 0)
1454 {
Jamie Madill610640f2018-11-21 17:28:41 -05001455 context->validationError(GL_INVALID_VALUE, "layer is negative.");
Xinghua Cao65ec0b22017-03-28 16:10:52 +08001456 return false;
1457 }
1458
1459 if (access != GL_READ_ONLY && access != GL_WRITE_ONLY && access != GL_READ_WRITE)
1460 {
Jamie Madill610640f2018-11-21 17:28:41 -05001461 context->validationError(GL_INVALID_ENUM, "access is not one of the supported tokens.");
Xinghua Cao65ec0b22017-03-28 16:10:52 +08001462 return false;
1463 }
1464
1465 switch (format)
1466 {
1467 case GL_RGBA32F:
1468 case GL_RGBA16F:
1469 case GL_R32F:
1470 case GL_RGBA32UI:
1471 case GL_RGBA16UI:
1472 case GL_RGBA8UI:
1473 case GL_R32UI:
1474 case GL_RGBA32I:
1475 case GL_RGBA16I:
1476 case GL_RGBA8I:
1477 case GL_R32I:
1478 case GL_RGBA8:
1479 case GL_RGBA8_SNORM:
1480 break;
1481 default:
Jamie Madill610640f2018-11-21 17:28:41 -05001482 context->validationError(GL_INVALID_VALUE,
1483 "format is not one of supported image unit formats.");
Xinghua Cao65ec0b22017-03-28 16:10:52 +08001484 return false;
1485 }
1486
1487 if (texture != 0)
1488 {
1489 Texture *tex = context->getTexture(texture);
1490
1491 if (tex == nullptr)
1492 {
Jamie Madill610640f2018-11-21 17:28:41 -05001493 context->validationError(GL_INVALID_VALUE,
1494 "texture is not the name of an existing texture object.");
Xinghua Cao65ec0b22017-03-28 16:10:52 +08001495 return false;
1496 }
1497
1498 if (!tex->getImmutableFormat())
1499 {
Jamie Madill610640f2018-11-21 17:28:41 -05001500 context->validationError(GL_INVALID_OPERATION,
1501 "texture is not the name of an immutable texture object.");
Xinghua Cao65ec0b22017-03-28 16:10:52 +08001502 return false;
1503 }
1504 }
1505
1506 return true;
1507}
jchen10191381f2017-04-11 13:59:04 +08001508
1509bool ValidateGetProgramResourceLocation(Context *context,
1510 GLuint program,
1511 GLenum programInterface,
1512 const GLchar *name)
1513{
1514 if (context->getClientVersion() < ES_3_1)
1515 {
Jamie Madille0472f32018-11-27 16:32:45 -05001516 context->validationError(GL_INVALID_OPERATION, kES31Required);
jchen10191381f2017-04-11 13:59:04 +08001517 return false;
1518 }
1519
1520 Program *programObject = GetValidProgram(context, program);
1521 if (programObject == nullptr)
1522 {
1523 return false;
1524 }
1525
1526 if (!programObject->isLinked())
1527 {
Jamie Madill610640f2018-11-21 17:28:41 -05001528 context->validationError(GL_INVALID_OPERATION, "Program is not successfully linked.");
jchen10191381f2017-04-11 13:59:04 +08001529 return false;
1530 }
1531
1532 if (!ValidateLocationProgramInterface(programInterface))
1533 {
Jamie Madill610640f2018-11-21 17:28:41 -05001534 context->validationError(GL_INVALID_ENUM, "Invalid program interface.");
jchen10191381f2017-04-11 13:59:04 +08001535 return false;
1536 }
1537 return true;
1538}
1539
jchen10880683b2017-04-12 16:21:55 +08001540bool ValidateGetProgramResourceiv(Context *context,
1541 GLuint program,
1542 GLenum programInterface,
1543 GLuint index,
1544 GLsizei propCount,
1545 const GLenum *props,
1546 GLsizei bufSize,
1547 GLsizei *length,
1548 GLint *params)
1549{
1550 if (context->getClientVersion() < ES_3_1)
1551 {
Jamie Madille0472f32018-11-27 16:32:45 -05001552 context->validationError(GL_INVALID_OPERATION, kES31Required);
jchen10880683b2017-04-12 16:21:55 +08001553 return false;
1554 }
1555
1556 Program *programObject = GetValidProgram(context, program);
1557 if (programObject == nullptr)
1558 {
1559 return false;
1560 }
1561 if (!ValidateProgramInterface(programInterface))
1562 {
Jamie Madill610640f2018-11-21 17:28:41 -05001563 context->validationError(GL_INVALID_ENUM, "Invalid program interface.");
jchen10880683b2017-04-12 16:21:55 +08001564 return false;
1565 }
1566 if (propCount <= 0)
1567 {
Jamie Madill610640f2018-11-21 17:28:41 -05001568 context->validationError(GL_INVALID_VALUE, "Invalid propCount.");
jchen10880683b2017-04-12 16:21:55 +08001569 return false;
1570 }
1571 if (bufSize < 0)
1572 {
Jamie Madill610640f2018-11-21 17:28:41 -05001573 context->validationError(GL_INVALID_VALUE, "Invalid bufSize.");
jchen10880683b2017-04-12 16:21:55 +08001574 return false;
1575 }
1576 if (!ValidateProgramResourceIndex(programObject, programInterface, index))
1577 {
Jamie Madill610640f2018-11-21 17:28:41 -05001578 context->validationError(GL_INVALID_VALUE, "Invalid index");
jchen10880683b2017-04-12 16:21:55 +08001579 return false;
1580 }
1581 for (GLsizei i = 0; i < propCount; i++)
1582 {
Jiawei Shaoc6f82872018-04-24 14:14:50 +08001583 if (!ValidateProgramResourceProperty(context, props[i]))
jchen10880683b2017-04-12 16:21:55 +08001584 {
Jamie Madill610640f2018-11-21 17:28:41 -05001585 context->validationError(GL_INVALID_ENUM, "Invalid prop.");
jchen10880683b2017-04-12 16:21:55 +08001586 return false;
1587 }
1588 if (!ValidateProgramResourcePropertyByInterface(props[i], programInterface))
1589 {
Jamie Madill610640f2018-11-21 17:28:41 -05001590 context->validationError(GL_INVALID_OPERATION, "Not an allowed prop for interface");
jchen10880683b2017-04-12 16:21:55 +08001591 return false;
1592 }
1593 }
1594 return true;
1595}
1596
jchen10d9cd7b72017-08-30 15:04:25 +08001597bool ValidateGetProgramInterfaceiv(Context *context,
1598 GLuint program,
1599 GLenum programInterface,
1600 GLenum pname,
1601 GLint *params)
1602{
1603 if (context->getClientVersion() < ES_3_1)
1604 {
Jamie Madille0472f32018-11-27 16:32:45 -05001605 context->validationError(GL_INVALID_OPERATION, kES31Required);
jchen10d9cd7b72017-08-30 15:04:25 +08001606 return false;
1607 }
1608
1609 Program *programObject = GetValidProgram(context, program);
1610 if (programObject == nullptr)
1611 {
1612 return false;
1613 }
1614
1615 if (!ValidateProgramInterface(programInterface))
1616 {
Jamie Madill610640f2018-11-21 17:28:41 -05001617 context->validationError(GL_INVALID_ENUM, "Invalid program interface.");
jchen10d9cd7b72017-08-30 15:04:25 +08001618 return false;
1619 }
1620
1621 switch (pname)
1622 {
1623 case GL_ACTIVE_RESOURCES:
1624 case GL_MAX_NAME_LENGTH:
1625 case GL_MAX_NUM_ACTIVE_VARIABLES:
1626 break;
1627
1628 default:
Jamie Madill610640f2018-11-21 17:28:41 -05001629 context->validationError(GL_INVALID_ENUM, "Unknown property of program interface.");
jchen10d9cd7b72017-08-30 15:04:25 +08001630 return false;
1631 }
1632
1633 if (pname == GL_MAX_NAME_LENGTH && programInterface == GL_ATOMIC_COUNTER_BUFFER)
1634 {
Jamie Madill610640f2018-11-21 17:28:41 -05001635 context->validationError(GL_INVALID_OPERATION,
1636 "Active atomic counter resources are not assigned name strings.");
jchen10d9cd7b72017-08-30 15:04:25 +08001637 return false;
1638 }
1639
1640 if (pname == GL_MAX_NUM_ACTIVE_VARIABLES)
1641 {
1642 switch (programInterface)
1643 {
1644 case GL_ATOMIC_COUNTER_BUFFER:
1645 case GL_SHADER_STORAGE_BLOCK:
1646 case GL_UNIFORM_BLOCK:
1647 break;
1648
1649 default:
Jamie Madill610640f2018-11-21 17:28:41 -05001650 context->validationError(
1651 GL_INVALID_OPERATION,
1652 "MAX_NUM_ACTIVE_VARIABLES requires a buffer or block interface.");
jchen10d9cd7b72017-08-30 15:04:25 +08001653 return false;
1654 }
1655 }
1656
1657 return true;
1658}
1659
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07001660bool ValidateGetProgramInterfaceivRobustANGLE(Context *context,
1661 GLuint program,
1662 GLenum programInterface,
1663 GLenum pname,
1664 GLsizei bufSize,
1665 GLsizei *length,
1666 GLint *params)
1667{
1668 UNIMPLEMENTED();
1669 return false;
1670}
1671
Yunchao Hea336b902017-08-02 16:05:21 +08001672static bool ValidateGenOrDeleteES31(Context *context, GLint n)
1673{
1674 if (context->getClientVersion() < ES_3_1)
1675 {
Jamie Madille0472f32018-11-27 16:32:45 -05001676 context->validationError(GL_INVALID_OPERATION, kES31Required);
Yunchao Hea336b902017-08-02 16:05:21 +08001677 return false;
1678 }
1679
1680 return ValidateGenOrDelete(context, n);
1681}
1682
1683bool ValidateGenProgramPipelines(Context *context, GLint n, GLuint *)
1684{
1685 return ValidateGenOrDeleteES31(context, n);
1686}
1687
1688bool ValidateDeleteProgramPipelines(Context *context, GLint n, const GLuint *)
1689{
1690 return ValidateGenOrDeleteES31(context, n);
1691}
1692
1693bool ValidateBindProgramPipeline(Context *context, GLuint pipeline)
1694{
1695 if (context->getClientVersion() < ES_3_1)
1696 {
Jamie Madille0472f32018-11-27 16:32:45 -05001697 context->validationError(GL_INVALID_OPERATION, kES31Required);
Yunchao Hea336b902017-08-02 16:05:21 +08001698 return false;
1699 }
1700
1701 if (!context->isProgramPipelineGenerated(pipeline))
1702 {
Jamie Madille0472f32018-11-27 16:32:45 -05001703 context->validationError(GL_INVALID_OPERATION, kObjectNotGenerated);
Yunchao Hea336b902017-08-02 16:05:21 +08001704 return false;
1705 }
1706
1707 return true;
1708}
1709
1710bool ValidateIsProgramPipeline(Context *context, GLuint pipeline)
1711{
1712 if (context->getClientVersion() < ES_3_1)
1713 {
Jamie Madille0472f32018-11-27 16:32:45 -05001714 context->validationError(GL_INVALID_OPERATION, kES31Required);
Yunchao Hea336b902017-08-02 16:05:21 +08001715 return false;
1716 }
1717
1718 return true;
1719}
1720
Jiajia Qin5451d532017-11-16 17:16:34 +08001721bool ValidateUseProgramStages(Context *context, GLuint pipeline, GLbitfield stages, GLuint program)
1722{
1723 UNIMPLEMENTED();
1724 return false;
1725}
1726
1727bool ValidateActiveShaderProgram(Context *context, GLuint pipeline, GLuint program)
1728{
1729 UNIMPLEMENTED();
1730 return false;
1731}
1732
1733bool ValidateCreateShaderProgramv(Context *context,
Jiawei Shao385b3e02018-03-21 09:43:28 +08001734 ShaderType type,
Jiajia Qin5451d532017-11-16 17:16:34 +08001735 GLsizei count,
1736 const GLchar *const *strings)
1737{
1738 UNIMPLEMENTED();
1739 return false;
1740}
1741
1742bool ValidateGetProgramPipelineiv(Context *context, GLuint pipeline, GLenum pname, GLint *params)
1743{
1744 UNIMPLEMENTED();
1745 return false;
1746}
1747
1748bool ValidateValidateProgramPipeline(Context *context, GLuint pipeline)
1749{
1750 UNIMPLEMENTED();
1751 return false;
1752}
1753
1754bool ValidateGetProgramPipelineInfoLog(Context *context,
1755 GLuint pipeline,
1756 GLsizei bufSize,
1757 GLsizei *length,
1758 GLchar *infoLog)
1759{
1760 UNIMPLEMENTED();
1761 return false;
1762}
1763
1764bool ValidateMemoryBarrier(Context *context, GLbitfield barriers)
1765{
Xinghua Cao89c422a2017-11-29 18:24:20 +08001766 if (context->getClientVersion() < ES_3_1)
1767 {
Jamie Madille0472f32018-11-27 16:32:45 -05001768 context->validationError(GL_INVALID_OPERATION, kES31Required);
Xinghua Cao89c422a2017-11-29 18:24:20 +08001769 return false;
1770 }
1771
1772 if (barriers == GL_ALL_BARRIER_BITS)
1773 {
1774 return true;
1775 }
1776
1777 GLbitfield supported_barrier_bits =
1778 GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT |
1779 GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT |
1780 GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT |
1781 GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT |
1782 GL_ATOMIC_COUNTER_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT;
1783 if ((barriers & ~supported_barrier_bits) != 0)
1784 {
Jamie Madille0472f32018-11-27 16:32:45 -05001785 context->validationError(GL_INVALID_VALUE, kInvalidMemoryBarrierBit);
Xinghua Cao89c422a2017-11-29 18:24:20 +08001786 return false;
1787 }
1788
1789 return true;
Jiajia Qin5451d532017-11-16 17:16:34 +08001790}
1791
1792bool ValidateMemoryBarrierByRegion(Context *context, GLbitfield barriers)
1793{
Xinghua Cao89c422a2017-11-29 18:24:20 +08001794 if (context->getClientVersion() < ES_3_1)
1795 {
Jamie Madille0472f32018-11-27 16:32:45 -05001796 context->validationError(GL_INVALID_OPERATION, kES31Required);
Xinghua Cao89c422a2017-11-29 18:24:20 +08001797 return false;
1798 }
1799
1800 if (barriers == GL_ALL_BARRIER_BITS)
1801 {
1802 return true;
1803 }
1804
1805 GLbitfield supported_barrier_bits = GL_ATOMIC_COUNTER_BARRIER_BIT | GL_FRAMEBUFFER_BARRIER_BIT |
1806 GL_SHADER_IMAGE_ACCESS_BARRIER_BIT |
1807 GL_SHADER_STORAGE_BARRIER_BIT |
1808 GL_TEXTURE_FETCH_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT;
1809 if ((barriers & ~supported_barrier_bits) != 0)
1810 {
Jamie Madille0472f32018-11-27 16:32:45 -05001811 context->validationError(GL_INVALID_VALUE, kInvalidMemoryBarrierBit);
Xinghua Cao89c422a2017-11-29 18:24:20 +08001812 return false;
1813 }
1814
1815 return true;
Jiajia Qin5451d532017-11-16 17:16:34 +08001816}
1817
1818bool ValidateSampleMaski(Context *context, GLuint maskNumber, GLbitfield mask)
Jiawei Shaodb342272017-09-27 10:21:45 +08001819{
1820 if (context->getClientVersion() < ES_3_1)
1821 {
Jamie Madille0472f32018-11-27 16:32:45 -05001822 context->validationError(GL_INVALID_OPERATION, kES31Required);
Jiawei Shaodb342272017-09-27 10:21:45 +08001823 return false;
1824 }
1825
1826 if (maskNumber >= context->getCaps().maxSampleMaskWords)
1827 {
Jamie Madille0472f32018-11-27 16:32:45 -05001828 context->validationError(GL_INVALID_VALUE, kInvalidSampleMaskNumber);
Jiawei Shaodb342272017-09-27 10:21:45 +08001829 return false;
1830 }
1831
1832 return true;
1833}
1834
Jiawei Shao5f9482f2018-05-18 09:00:09 +08001835bool ValidateFramebufferTextureEXT(Context *context,
1836 GLenum target,
1837 GLenum attachment,
1838 GLuint texture,
1839 GLint level)
1840{
1841 if (!context->getExtensions().geometryShader)
1842 {
Jamie Madille0472f32018-11-27 16:32:45 -05001843 context->validationError(GL_INVALID_OPERATION, kGeometryShaderExtensionNotEnabled);
Jiawei Shao5f9482f2018-05-18 09:00:09 +08001844 return false;
1845 }
1846
1847 if (texture != 0)
1848 {
1849 gl::Texture *tex = context->getTexture(texture);
1850
1851 // [EXT_geometry_shader] Section 9.2.8 "Attaching Texture Images to a Framebuffer"
1852 // An INVALID_VALUE error is generated if <texture> is not the name of a texture object.
1853 // We put this validation before ValidateFramebufferTextureBase because it is an
1854 // INVALID_OPERATION error for both FramebufferTexture2D and FramebufferTextureLayer:
1855 // [OpenGL ES 3.1] Chapter 9.2.8 (FramebufferTexture2D)
1856 // An INVALID_OPERATION error is generated if texture is not zero, and does not name an
1857 // existing texture object of type matching textarget.
1858 // [OpenGL ES 3.1 Chapter 9.2.8 (FramebufferTextureLayer)
1859 // An INVALID_OPERATION error is generated if texture is non-zero and is not the name of a
1860 // three-dimensional or two-dimensional array texture.
1861 if (tex == nullptr)
1862 {
Jamie Madille0472f32018-11-27 16:32:45 -05001863 context->validationError(GL_INVALID_VALUE, kInvalidTextureName);
Jiawei Shao5f9482f2018-05-18 09:00:09 +08001864 return false;
1865 }
1866
1867 if (!ValidMipLevel(context, tex->getType(), level))
1868 {
Jamie Madille0472f32018-11-27 16:32:45 -05001869 context->validationError(GL_INVALID_VALUE, kInvalidMipLevel);
Jiawei Shao5f9482f2018-05-18 09:00:09 +08001870 return false;
1871 }
1872 }
1873
1874 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1875 {
1876 return false;
1877 }
1878
1879 return true;
1880}
1881
Olli Etuaho064458a2018-08-30 14:02:02 +03001882// GL_OES_texture_storage_multisample_2d_array
1883bool ValidateTexStorage3DMultisampleOES(Context *context,
1884 TextureType target,
1885 GLsizei samples,
Jamie Madill778bf092018-11-14 09:54:36 -05001886 GLenum sizedinternalformat,
Olli Etuaho064458a2018-08-30 14:02:02 +03001887 GLsizei width,
1888 GLsizei height,
1889 GLsizei depth,
1890 GLboolean fixedsamplelocations)
Olli Etuaho89664842018-08-24 14:45:36 +03001891{
Olli Etuaho064458a2018-08-30 14:02:02 +03001892 if (!context->getExtensions().textureStorageMultisample2DArray)
Olli Etuahod310a432018-08-24 15:40:23 +03001893 {
Jamie Madille0472f32018-11-27 16:32:45 -05001894 context->validationError(GL_INVALID_ENUM, kMultisampleArrayExtensionRequired);
Olli Etuahod310a432018-08-24 15:40:23 +03001895 return false;
1896 }
1897
1898 if (target != TextureType::_2DMultisampleArray)
1899 {
Jamie Madille0472f32018-11-27 16:32:45 -05001900 context->validationError(GL_INVALID_ENUM, kTargetMustBeTexture2DMultisampleArrayOES);
Olli Etuahod310a432018-08-24 15:40:23 +03001901 return false;
1902 }
1903
1904 if (width < 1 || height < 1 || depth < 1)
1905 {
Jamie Madille0472f32018-11-27 16:32:45 -05001906 context->validationError(GL_INVALID_VALUE, kNegativeSize);
Olli Etuahod310a432018-08-24 15:40:23 +03001907 return false;
1908 }
1909
1910 return ValidateTexStorageMultisample(context, target, samples, sizedinternalformat, width,
1911 height);
Olli Etuaho89664842018-08-24 14:45:36 +03001912}
1913
Olli Etuaho0ca09752018-09-24 11:00:50 +03001914bool ValidateGetProgramResourceLocationIndexEXT(Context *context,
1915 GLuint program,
1916 GLenum programInterface,
1917 const char *name)
1918{
1919 if (!context->getExtensions().blendFuncExtended)
1920 {
Jamie Madille0472f32018-11-27 16:32:45 -05001921 context->validationError(GL_INVALID_OPERATION, kExtensionNotEnabled);
Olli Etuaho0ca09752018-09-24 11:00:50 +03001922 return false;
1923 }
1924 if (context->getClientVersion() < ES_3_1)
1925 {
Jamie Madille0472f32018-11-27 16:32:45 -05001926 context->validationError(GL_INVALID_OPERATION, kES31Required);
Olli Etuaho0ca09752018-09-24 11:00:50 +03001927 return false;
1928 }
1929 if (programInterface != GL_PROGRAM_OUTPUT)
1930 {
Jamie Madille0472f32018-11-27 16:32:45 -05001931 context->validationError(GL_INVALID_ENUM, kProgramInterfaceMustBeProgramOutput);
Olli Etuaho0ca09752018-09-24 11:00:50 +03001932 return false;
1933 }
1934 Program *programObject = GetValidProgram(context, program);
1935 if (!programObject)
1936 {
1937 return false;
1938 }
1939 if (!programObject->isLinked())
1940 {
Jamie Madille0472f32018-11-27 16:32:45 -05001941 context->validationError(GL_INVALID_OPERATION, kProgramNotLinked);
Olli Etuaho0ca09752018-09-24 11:00:50 +03001942 return false;
1943 }
1944 return true;
1945}
1946
Martin Radev66fb8202016-07-28 11:45:20 +03001947} // namespace gl