blob: b128f3a3a4d0c72a9a19941e8808a8b490c6e3f9 [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"
JiangYizhouf7bbc8a2016-11-16 09:57:22 +080012#include "libANGLE/Framebuffer.h"
Geoff Lang2e43dbb2016-10-14 12:27:35 -040013#include "libANGLE/validationES.h"
14#include "libANGLE/validationES3.h"
Jiajia Qind9671222016-11-29 16:30:31 +080015#include "libANGLE/VertexArray.h"
Martin Radev66fb8202016-07-28 11:45:20 +030016
He Yunchao11b038b2016-11-22 21:24:04 +080017#include "common/utilities.h"
18
Martin Radev66fb8202016-07-28 11:45:20 +030019using namespace angle;
20
21namespace gl
22{
23
jchen1015015f72017-03-16 13:54:21 +080024namespace
25{
26
27bool ValidateNamedProgramInterface(GLenum programInterface)
28{
29 switch (programInterface)
30 {
31 case GL_UNIFORM:
32 case GL_UNIFORM_BLOCK:
33 case GL_PROGRAM_INPUT:
34 case GL_PROGRAM_OUTPUT:
35 case GL_TRANSFORM_FEEDBACK_VARYING:
36 case GL_BUFFER_VARIABLE:
37 case GL_SHADER_STORAGE_BLOCK:
38 return true;
39 default:
40 return false;
41 }
42}
43
jchen10fd7c3b52017-03-21 15:36:03 +080044bool ValidateProgramResourceIndex(const Program *programObject,
45 GLenum programInterface,
46 GLuint index)
47{
48 switch (programInterface)
49 {
50 case GL_PROGRAM_INPUT:
51 return (index < static_cast<GLuint>(programObject->getActiveAttributeCount()));
52
53 case GL_PROGRAM_OUTPUT:
54 return (index < static_cast<GLuint>(programObject->getOutputResourceCount()));
55
56 // TODO(Jie): more interfaces.
57 case GL_UNIFORM:
58 case GL_UNIFORM_BLOCK:
59 case GL_TRANSFORM_FEEDBACK_VARYING:
60 case GL_BUFFER_VARIABLE:
61 case GL_SHADER_STORAGE_BLOCK:
62 UNIMPLEMENTED();
63 return false;
64
65 default:
66 UNREACHABLE();
67 return false;
68 }
69}
70
jchen1015015f72017-03-16 13:54:21 +080071} // anonymous namespace
72
Martin Radev66fb8202016-07-28 11:45:20 +030073bool ValidateGetBooleani_v(Context *context, GLenum target, GLuint index, GLboolean *data)
74{
Geoff Langeb66a6e2016-10-31 13:06:12 -040075 if (context->getClientVersion() < ES_3_1)
Martin Radev66fb8202016-07-28 11:45:20 +030076 {
77 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1"));
78 return false;
79 }
80
Geoff Lang2e43dbb2016-10-14 12:27:35 -040081 if (!ValidateIndexedStateQuery(context, target, index, nullptr))
82 {
83 return false;
84 }
85
86 return true;
87}
88
89bool ValidateGetBooleani_vRobustANGLE(Context *context,
90 GLenum target,
91 GLuint index,
92 GLsizei bufSize,
93 GLsizei *length,
94 GLboolean *data)
95{
Geoff Langeb66a6e2016-10-31 13:06:12 -040096 if (context->getClientVersion() < ES_3_1)
Geoff Lang2e43dbb2016-10-14 12:27:35 -040097 {
98 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1"));
99 return false;
100 }
101
102 if (!ValidateRobustEntryPoint(context, bufSize))
103 {
104 return false;
105 }
106
107 if (!ValidateIndexedStateQuery(context, target, index, length))
108 {
109 return false;
110 }
111
112 if (!ValidateRobustBufferSize(context, bufSize, *length))
Martin Radev66fb8202016-07-28 11:45:20 +0300113 {
114 return false;
115 }
116
117 return true;
118}
119
Jiajia Qind9671222016-11-29 16:30:31 +0800120bool ValidateDrawIndirectBase(Context *context, GLenum mode, const GLvoid *indirect)
121{
122 if (context->getClientVersion() < ES_3_1)
123 {
124 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1"));
125 return false;
126 }
127
128 // Here the third parameter 1 is only to pass the count validation.
129 if (!ValidateDrawBase(context, mode, 1))
130 {
131 return false;
132 }
133
134 const State &state = context->getGLState();
135
136 // An INVALID_OPERATION error is generated if zero is bound to VERTEX_ARRAY_BINDING,
137 // DRAW_INDIRECT_BUFFER or to any enabled vertex array.
138 if (!state.getVertexArrayId())
139 {
140 context->handleError(Error(GL_INVALID_OPERATION, "zero is bound to VERTEX_ARRAY_BINDING"));
141 return false;
142 }
143
144 gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
145 if (!drawIndirectBuffer)
146 {
147 context->handleError(Error(GL_INVALID_OPERATION, "zero is bound to DRAW_INDIRECT_BUFFER"));
148 return false;
149 }
150
151 // An INVALID_VALUE error is generated if indirect is not a multiple of the size, in basic
152 // machine units, of uint.
153 GLint64 offset = reinterpret_cast<GLint64>(indirect);
154 if ((static_cast<GLuint>(offset) % sizeof(GLuint)) != 0)
155 {
156 context->handleError(
157 Error(GL_INVALID_VALUE,
158 "indirect is not a multiple of the size, in basic machine units, of uint"));
159 return false;
160 }
161
162 return true;
163}
164
165bool ValidateDrawArraysIndirect(Context *context, GLenum mode, const GLvoid *indirect)
166{
167 const State &state = context->getGLState();
168 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
169 if (curTransformFeedback && curTransformFeedback->isActive() &&
170 !curTransformFeedback->isPaused())
171 {
172 // An INVALID_OPERATION error is generated if transform feedback is active and not paused.
173 context->handleError(
174 Error(GL_INVALID_OPERATION, "transform feedback is active and not paused."));
175 return false;
176 }
177
178 if (!ValidateDrawIndirectBase(context, mode, indirect))
179 return false;
180
181 gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
182 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
183 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawArraysIndirectCommand
184 // which's size is 4 * sizeof(uint).
185 auto checkedSum = checkedOffset + 4 * sizeof(GLuint);
186 if (!checkedSum.IsValid() ||
187 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
188 {
189 context->handleError(
190 Error(GL_INVALID_OPERATION,
191 "the command would source data beyond the end of the buffer object."));
192 return false;
193 }
194
195 return true;
196}
197
198bool ValidateDrawElementsIndirect(Context *context,
199 GLenum mode,
200 GLenum type,
201 const GLvoid *indirect)
202{
203 if (!ValidateDrawElementsBase(context, type))
204 return false;
205
206 const State &state = context->getGLState();
207 const VertexArray *vao = state.getVertexArray();
208 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
209 if (!elementArrayBuffer)
210 {
211 context->handleError(Error(GL_INVALID_OPERATION, "zero is bound to ELEMENT_ARRAY_BUFFER"));
212 return false;
213 }
214
215 if (!ValidateDrawIndirectBase(context, mode, indirect))
216 return false;
217
218 gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
219 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
220 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawElementsIndirectCommand
221 // which's size is 5 * sizeof(uint).
222 auto checkedSum = checkedOffset + 5 * sizeof(GLuint);
223 if (!checkedSum.IsValid() ||
224 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
225 {
226 context->handleError(
227 Error(GL_INVALID_OPERATION,
228 "the command would source data beyond the end of the buffer object."));
229 return false;
230 }
231
232 return true;
233}
234
He Yunchao11b038b2016-11-22 21:24:04 +0800235bool ValidateGetTexLevelParameterBase(Context *context,
236 GLenum target,
237 GLint level,
238 GLenum pname,
239 GLsizei *length)
240{
241 if (context->getClientVersion() < ES_3_1)
242 {
243 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1"));
244 return false;
245 }
246
247 if (length)
248 {
249 *length = 0;
250 }
251
252 if (!ValidTexLevelDestinationTarget(context, target))
253 {
254 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
255 return false;
256 }
257
258 if (context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target) ==
259 nullptr)
260 {
261 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
262 return false;
263 }
264
265 if (!ValidMipLevel(context, target, level))
266 {
267 context->handleError(Error(GL_INVALID_VALUE));
268 return false;
269 }
270
271 switch (pname)
272 {
273 case GL_TEXTURE_RED_TYPE:
274 case GL_TEXTURE_GREEN_TYPE:
275 case GL_TEXTURE_BLUE_TYPE:
276 case GL_TEXTURE_ALPHA_TYPE:
277 case GL_TEXTURE_DEPTH_TYPE:
278 break;
279 case GL_TEXTURE_RED_SIZE:
280 case GL_TEXTURE_GREEN_SIZE:
281 case GL_TEXTURE_BLUE_SIZE:
282 case GL_TEXTURE_ALPHA_SIZE:
283 case GL_TEXTURE_DEPTH_SIZE:
284 case GL_TEXTURE_STENCIL_SIZE:
285 case GL_TEXTURE_SHARED_SIZE:
286 break;
287 case GL_TEXTURE_INTERNAL_FORMAT:
288 case GL_TEXTURE_WIDTH:
289 case GL_TEXTURE_HEIGHT:
290 case GL_TEXTURE_DEPTH:
291 break;
292 case GL_TEXTURE_SAMPLES:
293 case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
294 break;
295 case GL_TEXTURE_COMPRESSED:
296 break;
297 default:
298 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
299 return false;
300 }
301
302 if (length)
303 {
304 *length = 1;
305 }
306 return true;
307}
308
309bool ValidateGetTexLevelParameterfv(Context *context,
310 GLenum target,
311 GLint level,
312 GLenum pname,
313 GLfloat *params)
314{
315 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
316}
317
318bool ValidateGetTexLevelParameteriv(Context *context,
319 GLenum target,
320 GLint level,
321 GLenum pname,
322 GLint *params)
323{
324 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
325}
326
JiangYizhoubddc46b2016-12-09 09:50:51 +0800327bool ValidateTexStorage2DMultiSample(Context *context,
328 GLenum target,
329 GLsizei samples,
330 GLint internalFormat,
331 GLsizei width,
332 GLsizei height,
333 GLboolean fixedSampleLocations)
334{
335 if (context->getClientVersion() < ES_3_1)
336 {
337 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
338 return false;
339 }
340
341 if (target != GL_TEXTURE_2D_MULTISAMPLE)
342 {
343 context->handleError(Error(GL_INVALID_ENUM, "Target must be TEXTURE_2D_MULTISAMPLE."));
344 return false;
345 }
346
347 if (width < 1 || height < 1)
348 {
349 context->handleError(Error(GL_INVALID_VALUE, "Width and height must be positive."));
350 return false;
351 }
352
353 const Caps &caps = context->getCaps();
354 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
355 static_cast<GLuint>(height) > caps.max2DTextureSize)
356 {
357 context->handleError(
358 Error(GL_INVALID_VALUE,
359 "Width and height must be less than or equal to GL_MAX_TEXTURE_SIZE."));
360 return false;
361 }
362
363 if (samples == 0)
364 {
365 context->handleError(Error(GL_INVALID_VALUE, "Samples may not be zero."));
366 return false;
367 }
368
369 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
370 if (!formatCaps.renderable)
371 {
372 context->handleError(
373 Error(GL_INVALID_ENUM,
374 "SizedInternalformat must be color-renderable, depth-renderable, "
375 "or stencil-renderable."));
376 return false;
377 }
378
379 // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
380 // is one of the unsized base internalformats listed in table 8.11.
381 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
382 if (formatInfo.pixelBytes == 0)
383 {
384 context->handleError(
385 Error(GL_INVALID_ENUM,
386 "Internalformat is one of the unsupported unsized base internalformats."));
387 return false;
388 }
389
390 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
391 {
392 context->handleError(
393 Error(GL_INVALID_OPERATION,
394 "Samples must not be greater than maximum supported value for the format."));
395 return false;
396 }
397
398 Texture *texture = context->getTargetTexture(target);
399 if (!texture || texture->id() == 0)
400 {
401 context->handleError(Error(GL_INVALID_OPERATION, "Zero is bound to target."));
402 return false;
403 }
404
405 if (texture->getImmutableFormat())
406 {
407 context->handleError(
408 Error(GL_INVALID_OPERATION,
409 "The value of TEXTURE_IMMUTABLE_FORMAT for the texture "
410 "currently bound to target on the active texture unit is true."));
411 return false;
412 }
413
414 return true;
415}
416
417bool ValidateGetMultisamplefv(Context *context, GLenum pname, GLuint index, GLfloat *val)
418{
419 if (context->getClientVersion() < ES_3_1)
420 {
421 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
422 return false;
423 }
424
425 if (pname != GL_SAMPLE_POSITION)
426 {
427 context->handleError(Error(GL_INVALID_ENUM, "Pname must be SAMPLE_POSITION."));
428 return false;
429 }
430
431 GLint maxSamples = context->getCaps().maxSamples;
432 if (index >= static_cast<GLuint>(maxSamples))
433 {
434 context->handleError(
435 Error(GL_INVALID_VALUE, "Index must be less than the value of SAMPLES."));
436 return false;
437 }
438
439 return true;
440}
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800441
442bool ValidationFramebufferParameteri(Context *context, GLenum target, GLenum pname, GLint param)
443{
444 if (context->getClientVersion() < ES_3_1)
445 {
446 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
447 return false;
448 }
449
450 if (!ValidFramebufferTarget(target))
451 {
452 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target."));
453 return false;
454 }
455
456 switch (pname)
457 {
458 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
459 {
460 GLint maxWidth = context->getCaps().maxFramebufferWidth;
461 if (param < 0 || param > maxWidth)
462 {
463 context->handleError(
464 Error(GL_INVALID_VALUE,
465 "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_WIDTH."));
466 return false;
467 }
468 break;
469 }
470 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
471 {
472 GLint maxHeight = context->getCaps().maxFramebufferHeight;
473 if (param < 0 || param > maxHeight)
474 {
475 context->handleError(
476 Error(GL_INVALID_VALUE,
477 "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_HEIGHT."));
478 return false;
479 }
480 break;
481 }
482 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
483 {
484 GLint maxSamples = context->getCaps().maxFramebufferSamples;
485 if (param < 0 || param > maxSamples)
486 {
487 context->handleError(
488 Error(GL_INVALID_VALUE,
489 "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_SAMPLES."));
490 return false;
491 }
492 break;
493 }
494 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
495 {
496 break;
497 }
498 default:
499 {
500 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
501 return false;
502 }
503 }
504
505 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
506 ASSERT(framebuffer);
507 if (framebuffer->id() == 0)
508 {
509 context->handleError(
510 Error(GL_INVALID_OPERATION, "Default framebuffer is bound to target."));
511 return false;
512 }
513 return true;
514}
515
516bool ValidationGetFramebufferParameteri(Context *context,
517 GLenum target,
518 GLenum pname,
519 GLint *params)
520{
521 if (context->getClientVersion() < ES_3_1)
522 {
523 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
524 return false;
525 }
526
527 if (!ValidFramebufferTarget(target))
528 {
529 context->handleError(Error(GL_INVALID_ENUM, "Invalid framebuffer target."));
530 return false;
531 }
532
533 switch (pname)
534 {
535 case GL_FRAMEBUFFER_DEFAULT_WIDTH:
536 case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
537 case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
538 case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
539 break;
540 default:
541 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname));
542 return false;
543 }
544
545 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
546 ASSERT(framebuffer);
547
548 if (framebuffer->id() == 0)
549 {
550 context->handleError(
551 Error(GL_INVALID_OPERATION, "Default framebuffer is bound to target."));
552 return false;
553 }
554 return true;
555}
556
jchen1015015f72017-03-16 13:54:21 +0800557bool ValidateGetProgramResourceIndex(Context *context,
558 GLuint program,
559 GLenum programInterface,
560 const GLchar *name)
561{
562 if (context->getClientVersion() < ES_3_1)
563 {
564 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES 3.1."));
565 return false;
566 }
567
568 Program *programObject = GetValidProgram(context, program);
569 if (programObject == nullptr)
570 {
571 return false;
572 }
573
574 if (!ValidateNamedProgramInterface(programInterface))
575 {
576 context->handleError(
577 Error(GL_INVALID_ENUM, "Invalid program interface: 0x%X", programInterface));
578 return false;
579 }
Shao80957d92017-02-20 21:25:59 +0800580
581 return true;
582}
583
584bool ValidateBindVertexBuffer(ValidationContext *context,
585 GLuint bindingIndex,
586 GLuint buffer,
587 GLintptr offset,
588 GLsizei stride)
589{
590 if (context->getClientVersion() < ES_3_1)
591 {
592 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
593 return false;
594 }
595
596 if (!context->isBufferGenerated(buffer))
597 {
598 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is not generated."));
599 return false;
600 }
601
602 const Caps &caps = context->getCaps();
603 if (bindingIndex >= caps.maxVertexAttribBindings)
604 {
605 context->handleError(Error(
606 GL_INVALID_VALUE, "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
607 return false;
608 }
609
610 if (offset < 0)
611 {
612 context->handleError(Error(GL_INVALID_VALUE, "offset cannot be negative."));
613 return false;
614 }
615
616 if (stride < 0 || stride > caps.maxVertexAttribStride)
617 {
618 context->handleError(
619 Error(GL_INVALID_VALUE, "stride must be between 0 and MAX_VERTEX_ATTRIB_STRIDE."));
620 return false;
621 }
622
623 // [OpenGL ES 3.1] Section 10.3.1 page 244:
624 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
625 if (context->getGLState().getVertexArrayId() == 0)
626 {
627 context->handleError(Error(GL_INVALID_OPERATION, "Default vertex array buffer is bound."));
628 return false;
629 }
630
631 return true;
632}
633
634bool ValidateVertexBindingDivisor(ValidationContext *context, GLuint bindingIndex, GLuint divisor)
635{
636 if (context->getClientVersion() < ES_3_1)
637 {
638 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
639 return false;
640 }
641
642 const Caps &caps = context->getCaps();
643 if (bindingIndex >= caps.maxVertexAttribBindings)
644 {
645 context->handleError(Error(
646 GL_INVALID_VALUE, "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS."));
647 return false;
648 }
649
650 // [OpenGL ES 3.1] Section 10.3.1 page 243:
651 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
652 if (context->getGLState().getVertexArrayId() == 0)
653 {
654 context->handleError(Error(GL_INVALID_OPERATION, "Default vertex array object is bound."));
655 return false;
656 }
657
658 return true;
659}
660
661bool ValidateVertexAttribFormat(ValidationContext *context,
662 GLuint attribIndex,
663 GLint size,
664 GLenum type,
665 GLuint relativeOffset,
666 GLboolean pureInteger)
667{
668 if (context->getClientVersion() < ES_3_1)
669 {
670 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
671 return false;
672 }
673
674 const Caps &caps = context->getCaps();
675 if (relativeOffset > static_cast<GLuint>(caps.maxVertexAttribRelativeOffset))
676 {
677 context->handleError(
678 Error(GL_INVALID_VALUE,
679 "relativeOffset cannot be greater than MAX_VERTEX_ATTRIB_RELATIVE_OFFSET."));
680 return false;
681 }
682
683 // [OpenGL ES 3.1] Section 10.3.1 page 243:
684 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
685 if (context->getGLState().getVertexArrayId() == 0)
686 {
687 context->handleError(Error(GL_INVALID_OPERATION, "Default vertex array object is bound."));
688 return false;
689 }
690
691 return ValidateVertexFormatBase(context, attribIndex, size, type, pureInteger);
692}
693
694bool ValidateVertexAttribBinding(ValidationContext *context,
695 GLuint attribIndex,
696 GLuint bindingIndex)
697{
698 if (context->getClientVersion() < ES_3_1)
699 {
700 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
701 return false;
702 }
703
704 // [OpenGL ES 3.1] Section 10.3.1 page 243:
705 // An INVALID_OPERATION error is generated if the default vertex array object is bound.
706 if (context->getGLState().getVertexArrayId() == 0)
707 {
708 context->handleError(Error(GL_INVALID_OPERATION, "Default vertex array object is bound."));
709 return false;
710 }
711
712 const Caps &caps = context->getCaps();
713 if (attribIndex >= caps.maxVertexAttributes)
714 {
715 context->handleError(
716 Error(GL_INVALID_VALUE, "attribindex must be smaller than MAX_VERTEX_ATTRIBS."));
717 return false;
718 }
719
720 if (bindingIndex >= caps.maxVertexAttribBindings)
721 {
722 context->handleError(Error(GL_INVALID_VALUE,
723 "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS"));
724 return false;
725 }
726
jchen1015015f72017-03-16 13:54:21 +0800727 return true;
728}
729
jchen10fd7c3b52017-03-21 15:36:03 +0800730bool ValidateGetProgramResourceName(Context *context,
731 GLuint program,
732 GLenum programInterface,
733 GLuint index,
734 GLsizei bufSize,
735 GLsizei *length,
736 GLchar *name)
737{
738 if (context->getClientVersion() < ES_3_1)
739 {
740 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
741 return false;
742 }
743
744 Program *programObject = GetValidProgram(context, program);
745 if (programObject == nullptr)
746 {
747 return false;
748 }
749
750 if (!ValidateNamedProgramInterface(programInterface))
751 {
752 context->handleError(
753 Error(GL_INVALID_ENUM, "Invalid program interface: 0x%X", programInterface));
754 return false;
755 }
756
757 if (!ValidateProgramResourceIndex(programObject, programInterface, index))
758 {
759 context->handleError(Error(GL_INVALID_VALUE, "Invalid index: %d", index));
760 return false;
761 }
762
763 if (bufSize < 0)
764 {
765 context->handleError(Error(GL_INVALID_VALUE, "Invalid bufSize: %d", bufSize));
766 return false;
767 }
768
769 return true;
770}
771
Xinghua Cao2b396592017-03-29 15:36:04 +0800772bool ValidateDispatchCompute(Context *context,
773 GLuint numGroupsX,
774 GLuint numGroupsY,
775 GLuint numGroupsZ)
776{
777 if (context->getClientVersion() < ES_3_1)
778 {
779 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1."));
780 return false;
781 }
782
783 const State &state = context->getGLState();
784 Program *program = state.getProgram();
785
786 if (program == nullptr)
787 {
788 context->handleError(
789 Error(GL_INVALID_OPERATION, "No active program object for the compute shader stage."));
790 return false;
791 }
792
793 if (program->isLinked() == false || program->getAttachedComputeShader() == nullptr)
794 {
795 context->handleError(Error(
796 GL_INVALID_OPERATION,
797 "Program has not been successfully linked, or program contains no compute shaders."));
798 return false;
799 }
800
801 const Caps &caps = context->getCaps();
802 if (numGroupsX > caps.maxComputeWorkGroupCount[0])
803 {
804 context->handleError(
805 Error(GL_INVALID_VALUE,
806 "num_groups_x cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[0](%u).",
807 caps.maxComputeWorkGroupCount[0]));
808 return false;
809 }
810 if (numGroupsY > caps.maxComputeWorkGroupCount[1])
811 {
812 context->handleError(
813 Error(GL_INVALID_VALUE,
814 "num_groups_y cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[1](%u).",
815 caps.maxComputeWorkGroupCount[1]));
816 return false;
817 }
818 if (numGroupsZ > caps.maxComputeWorkGroupCount[2])
819 {
820 context->handleError(
821 Error(GL_INVALID_VALUE,
822 "num_groups_z cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[2](%u).",
823 caps.maxComputeWorkGroupCount[2]));
824 return false;
825 }
826
827 return true;
828}
829
Martin Radev66fb8202016-07-28 11:45:20 +0300830} // namespace gl