blob: 39ee40463420d4372a8b4ba6aee77fcd246ae88b [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
He Yunchao11b038b2016-11-22 21:24:04 +080016#include "common/utilities.h"
17
Martin Radev66fb8202016-07-28 11:45:20 +030018using namespace angle;
19
20namespace gl
21{
22
23bool ValidateGetBooleani_v(Context *context, GLenum target, GLuint index, GLboolean *data)
24{
Geoff Langeb66a6e2016-10-31 13:06:12 -040025 if (context->getClientVersion() < ES_3_1)
Martin Radev66fb8202016-07-28 11:45:20 +030026 {
27 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1"));
28 return false;
29 }
30
Geoff Lang2e43dbb2016-10-14 12:27:35 -040031 if (!ValidateIndexedStateQuery(context, target, index, nullptr))
32 {
33 return false;
34 }
35
36 return true;
37}
38
39bool ValidateGetBooleani_vRobustANGLE(Context *context,
40 GLenum target,
41 GLuint index,
42 GLsizei bufSize,
43 GLsizei *length,
44 GLboolean *data)
45{
Geoff Langeb66a6e2016-10-31 13:06:12 -040046 if (context->getClientVersion() < ES_3_1)
Geoff Lang2e43dbb2016-10-14 12:27:35 -040047 {
48 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1"));
49 return false;
50 }
51
52 if (!ValidateRobustEntryPoint(context, bufSize))
53 {
54 return false;
55 }
56
57 if (!ValidateIndexedStateQuery(context, target, index, length))
58 {
59 return false;
60 }
61
62 if (!ValidateRobustBufferSize(context, bufSize, *length))
Martin Radev66fb8202016-07-28 11:45:20 +030063 {
64 return false;
65 }
66
67 return true;
68}
69
Jiajia Qind9671222016-11-29 16:30:31 +080070bool ValidateDrawIndirectBase(Context *context, GLenum mode, const GLvoid *indirect)
71{
72 if (context->getClientVersion() < ES_3_1)
73 {
74 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1"));
75 return false;
76 }
77
78 // Here the third parameter 1 is only to pass the count validation.
79 if (!ValidateDrawBase(context, mode, 1))
80 {
81 return false;
82 }
83
84 const State &state = context->getGLState();
85
86 // An INVALID_OPERATION error is generated if zero is bound to VERTEX_ARRAY_BINDING,
87 // DRAW_INDIRECT_BUFFER or to any enabled vertex array.
88 if (!state.getVertexArrayId())
89 {
90 context->handleError(Error(GL_INVALID_OPERATION, "zero is bound to VERTEX_ARRAY_BINDING"));
91 return false;
92 }
93
94 gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
95 if (!drawIndirectBuffer)
96 {
97 context->handleError(Error(GL_INVALID_OPERATION, "zero is bound to DRAW_INDIRECT_BUFFER"));
98 return false;
99 }
100
101 // An INVALID_VALUE error is generated if indirect is not a multiple of the size, in basic
102 // machine units, of uint.
103 GLint64 offset = reinterpret_cast<GLint64>(indirect);
104 if ((static_cast<GLuint>(offset) % sizeof(GLuint)) != 0)
105 {
106 context->handleError(
107 Error(GL_INVALID_VALUE,
108 "indirect is not a multiple of the size, in basic machine units, of uint"));
109 return false;
110 }
111
112 return true;
113}
114
115bool ValidateDrawArraysIndirect(Context *context, GLenum mode, const GLvoid *indirect)
116{
117 const State &state = context->getGLState();
118 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
119 if (curTransformFeedback && curTransformFeedback->isActive() &&
120 !curTransformFeedback->isPaused())
121 {
122 // An INVALID_OPERATION error is generated if transform feedback is active and not paused.
123 context->handleError(
124 Error(GL_INVALID_OPERATION, "transform feedback is active and not paused."));
125 return false;
126 }
127
128 if (!ValidateDrawIndirectBase(context, mode, indirect))
129 return false;
130
131 gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
132 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
133 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawArraysIndirectCommand
134 // which's size is 4 * sizeof(uint).
135 auto checkedSum = checkedOffset + 4 * sizeof(GLuint);
136 if (!checkedSum.IsValid() ||
137 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
138 {
139 context->handleError(
140 Error(GL_INVALID_OPERATION,
141 "the command would source data beyond the end of the buffer object."));
142 return false;
143 }
144
145 return true;
146}
147
148bool ValidateDrawElementsIndirect(Context *context,
149 GLenum mode,
150 GLenum type,
151 const GLvoid *indirect)
152{
153 if (!ValidateDrawElementsBase(context, type))
154 return false;
155
156 const State &state = context->getGLState();
157 const VertexArray *vao = state.getVertexArray();
158 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
159 if (!elementArrayBuffer)
160 {
161 context->handleError(Error(GL_INVALID_OPERATION, "zero is bound to ELEMENT_ARRAY_BUFFER"));
162 return false;
163 }
164
165 if (!ValidateDrawIndirectBase(context, mode, indirect))
166 return false;
167
168 gl::Buffer *drawIndirectBuffer = state.getDrawIndirectBuffer();
169 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
170 // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawElementsIndirectCommand
171 // which's size is 5 * sizeof(uint).
172 auto checkedSum = checkedOffset + 5 * sizeof(GLuint);
173 if (!checkedSum.IsValid() ||
174 checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
175 {
176 context->handleError(
177 Error(GL_INVALID_OPERATION,
178 "the command would source data beyond the end of the buffer object."));
179 return false;
180 }
181
182 return true;
183}
184
He Yunchao11b038b2016-11-22 21:24:04 +0800185bool ValidateGetTexLevelParameterBase(Context *context,
186 GLenum target,
187 GLint level,
188 GLenum pname,
189 GLsizei *length)
190{
191 if (context->getClientVersion() < ES_3_1)
192 {
193 context->handleError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.1"));
194 return false;
195 }
196
197 if (length)
198 {
199 *length = 0;
200 }
201
202 if (!ValidTexLevelDestinationTarget(context, target))
203 {
204 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
205 return false;
206 }
207
208 if (context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target) ==
209 nullptr)
210 {
211 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
212 return false;
213 }
214
215 if (!ValidMipLevel(context, target, level))
216 {
217 context->handleError(Error(GL_INVALID_VALUE));
218 return false;
219 }
220
221 switch (pname)
222 {
223 case GL_TEXTURE_RED_TYPE:
224 case GL_TEXTURE_GREEN_TYPE:
225 case GL_TEXTURE_BLUE_TYPE:
226 case GL_TEXTURE_ALPHA_TYPE:
227 case GL_TEXTURE_DEPTH_TYPE:
228 break;
229 case GL_TEXTURE_RED_SIZE:
230 case GL_TEXTURE_GREEN_SIZE:
231 case GL_TEXTURE_BLUE_SIZE:
232 case GL_TEXTURE_ALPHA_SIZE:
233 case GL_TEXTURE_DEPTH_SIZE:
234 case GL_TEXTURE_STENCIL_SIZE:
235 case GL_TEXTURE_SHARED_SIZE:
236 break;
237 case GL_TEXTURE_INTERNAL_FORMAT:
238 case GL_TEXTURE_WIDTH:
239 case GL_TEXTURE_HEIGHT:
240 case GL_TEXTURE_DEPTH:
241 break;
242 case GL_TEXTURE_SAMPLES:
243 case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
244 break;
245 case GL_TEXTURE_COMPRESSED:
246 break;
247 default:
248 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
249 return false;
250 }
251
252 if (length)
253 {
254 *length = 1;
255 }
256 return true;
257}
258
259bool ValidateGetTexLevelParameterfv(Context *context,
260 GLenum target,
261 GLint level,
262 GLenum pname,
263 GLfloat *params)
264{
265 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
266}
267
268bool ValidateGetTexLevelParameteriv(Context *context,
269 GLenum target,
270 GLint level,
271 GLenum pname,
272 GLint *params)
273{
274 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
275}
276
Martin Radev66fb8202016-07-28 11:45:20 +0300277} // namespace gl