blob: 4cc705d6bc8a6c0917994efa6b545f8e393ae2ad [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"
Geoff Lang2e43dbb2016-10-14 12:27:35 -040012#include "libANGLE/validationES.h"
13#include "libANGLE/validationES3.h"
Jiajia Qind9671222016-11-29 16:30:31 +080014#include "libANGLE/VertexArray.h"
Martin Radev66fb8202016-07-28 11:45:20 +030015
16using namespace angle;
17
18namespace gl
19{
20
21bool ValidateGetBooleani_v(Context *context, GLenum target, GLuint index, GLboolean *data)
22{
Geoff Langeb66a6e2016-10-31 13:06:12 -040023 if (context->getClientVersion() < ES_3_1)
Martin Radev66fb8202016-07-28 11:45:20 +030024 {
25 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1"));
26 return false;
27 }
28
Geoff Lang2e43dbb2016-10-14 12:27:35 -040029 if (!ValidateIndexedStateQuery(context, target, index, nullptr))
30 {
31 return false;
32 }
33
34 return true;
35}
36
37bool ValidateGetBooleani_vRobustANGLE(Context *context,
38 GLenum target,
39 GLuint index,
40 GLsizei bufSize,
41 GLsizei *length,
42 GLboolean *data)
43{
Geoff Langeb66a6e2016-10-31 13:06:12 -040044 if (context->getClientVersion() < ES_3_1)
Geoff Lang2e43dbb2016-10-14 12:27:35 -040045 {
46 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1"));
47 return false;
48 }
49
50 if (!ValidateRobustEntryPoint(context, bufSize))
51 {
52 return false;
53 }
54
55 if (!ValidateIndexedStateQuery(context, target, index, length))
56 {
57 return false;
58 }
59
60 if (!ValidateRobustBufferSize(context, bufSize, *length))
Martin Radev66fb8202016-07-28 11:45:20 +030061 {
62 return false;
63 }
64
65 return true;
66}
67
Jiajia Qind9671222016-11-29 16:30:31 +080068bool ValidateDrawIndirectBase(Context *context, GLenum mode, const GLvoid *indirect)
69{
70 if (context->getClientVersion() < ES_3_1)
71 {
72 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1"));
73 return false;
74 }
75
76 // Here the third parameter 1 is only to pass the count validation.
77 if (!ValidateDrawBase(context, mode, 1))
78 {
79 return false;
80 }
81
82 const State &state = context->getGLState();
83
84 // An INVALID_OPERATION error is generated if zero is bound to VERTEX_ARRAY_BINDING,
85 // DRAW_INDIRECT_BUFFER or to any enabled vertex array.
86 if (!state.getVertexArrayId())
87 {
88 context->handleError(Error(GL_INVALID_OPERATION, "zero is bound to VERTEX_ARRAY_BINDING"));
89 return false;
90 }
91
92 gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
93 if (!drawIndirectBuffer)
94 {
95 context->handleError(Error(GL_INVALID_OPERATION, "zero is bound to DRAW_INDIRECT_BUFFER"));
96 return false;
97 }
98
99 // An INVALID_VALUE error is generated if indirect is not a multiple of the size, in basic
100 // machine units, of uint.
101 GLint64 offset = reinterpret_cast<GLint64>(indirect);
102 if ((static_cast<GLuint>(offset) % sizeof(GLuint)) != 0)
103 {
104 context->handleError(
105 Error(GL_INVALID_VALUE,
106 "indirect is not a multiple of the size, in basic machine units, of uint"));
107 return false;
108 }
109
110 return true;
111}
112
113bool ValidateDrawArraysIndirect(Context *context, GLenum mode, const GLvoid *indirect)
114{
115 const State &state = context->getGLState();
116 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
117 if (curTransformFeedback && curTransformFeedback->isActive() &&
118 !curTransformFeedback->isPaused())
119 {
120 // An INVALID_OPERATION error is generated if transform feedback is active and not paused.
121 context->handleError(
122 Error(GL_INVALID_OPERATION, "transform feedback is active and not paused."));
123 return false;
124 }
125
126 if (!ValidateDrawIndirectBase(context, mode, indirect))
127 return false;
128
129 gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
130 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
131 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawArraysIndirectCommand
132 // which's size is 4 * sizeof(uint).
133 auto checkedSum = checkedOffset + 4 * sizeof(GLuint);
134 if (!checkedSum.IsValid() ||
135 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
136 {
137 context->handleError(
138 Error(GL_INVALID_OPERATION,
139 "the command would source data beyond the end of the buffer object."));
140 return false;
141 }
142
143 return true;
144}
145
146bool ValidateDrawElementsIndirect(Context *context,
147 GLenum mode,
148 GLenum type,
149 const GLvoid *indirect)
150{
151 if (!ValidateDrawElementsBase(context, type))
152 return false;
153
154 const State &state = context->getGLState();
155 const VertexArray *vao = state.getVertexArray();
156 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
157 if (!elementArrayBuffer)
158 {
159 context->handleError(Error(GL_INVALID_OPERATION, "zero is bound to ELEMENT_ARRAY_BUFFER"));
160 return false;
161 }
162
163 if (!ValidateDrawIndirectBase(context, mode, indirect))
164 return false;
165
166 gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
167 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
168 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawElementsIndirectCommand
169 // which's size is 5 * sizeof(uint).
170 auto checkedSum = checkedOffset + 5 * sizeof(GLuint);
171 if (!checkedSum.IsValid() ||
172 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
173 {
174 context->handleError(
175 Error(GL_INVALID_OPERATION,
176 "the command would source data beyond the end of the buffer object."));
177 return false;
178 }
179
180 return true;
181}
182
Martin Radev66fb8202016-07-28 11:45:20 +0300183} // namespace gl