blob: 76232fd5510cfb69e0f3c38b2a6859aa21183610 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
10#include "libANGLE/validationES2.h"
11#include "libANGLE/validationES3.h"
12#include "libANGLE/Context.h"
13#include "libANGLE/Texture.h"
14#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
16#include "libANGLE/formatutils.h"
17#include "libANGLE/Query.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050018#include "libANGLE/Program.h"
19#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/TransformFeedback.h"
21#include "libANGLE/VertexArray.h"
22#include "libANGLE/renderer/BufferImpl.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040023
24#include "common/mathutil.h"
25#include "common/utilities.h"
26
27namespace gl
28{
29
Geoff Lang0550d032014-01-30 11:29:07 -050030bool ValidCap(const Context *context, GLenum cap)
31{
32 switch (cap)
33 {
34 case GL_CULL_FACE:
35 case GL_POLYGON_OFFSET_FILL:
36 case GL_SAMPLE_ALPHA_TO_COVERAGE:
37 case GL_SAMPLE_COVERAGE:
38 case GL_SCISSOR_TEST:
39 case GL_STENCIL_TEST:
40 case GL_DEPTH_TEST:
41 case GL_BLEND:
42 case GL_DITHER:
43 return true;
44 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
45 case GL_RASTERIZER_DISCARD:
46 return (context->getClientVersion() >= 3);
47 default:
48 return false;
49 }
50}
51
Jamie Madill1fc7e2c2014-01-21 16:47:10 -050052bool ValidTextureTarget(const Context *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -040053{
Jamie Madilld7460c72014-01-21 16:38:14 -050054 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -040055 {
Jamie Madilld7460c72014-01-21 16:38:14 -050056 case GL_TEXTURE_2D:
57 case GL_TEXTURE_CUBE_MAP:
58 return true;
Jamie Madill35d15012013-10-07 10:46:37 -040059
Jamie Madilld7460c72014-01-21 16:38:14 -050060 case GL_TEXTURE_3D:
61 case GL_TEXTURE_2D_ARRAY:
62 return (context->getClientVersion() >= 3);
63
64 default:
65 return false;
66 }
Jamie Madill35d15012013-10-07 10:46:37 -040067}
68
Shannon Woods4dfed832014-03-17 20:03:39 -040069// This function differs from ValidTextureTarget in that the target must be
70// usable as the destination of a 2D operation-- so a cube face is valid, but
71// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -040072// Note: duplicate of IsInternalTextureTarget
Shannon Woods4dfed832014-03-17 20:03:39 -040073bool ValidTexture2DDestinationTarget(const Context *context, GLenum target)
74{
75 switch (target)
76 {
77 case GL_TEXTURE_2D:
78 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
79 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
80 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
81 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
82 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
83 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
84 return true;
85 case GL_TEXTURE_2D_ARRAY:
86 case GL_TEXTURE_3D:
87 return (context->getClientVersion() >= 3);
88 default:
89 return false;
90 }
91}
92
Jamie Madill1fc7e2c2014-01-21 16:47:10 -050093bool ValidFramebufferTarget(GLenum target)
94{
Geoff Langd4475812015-03-18 10:53:05 -040095 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
96 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -050097
98 switch (target)
99 {
100 case GL_FRAMEBUFFER: return true;
101 case GL_READ_FRAMEBUFFER: return true;
102 case GL_DRAW_FRAMEBUFFER: return true;
103 default: return false;
104 }
105}
106
Jamie Madill8c96d582014-03-05 15:01:23 -0500107bool ValidBufferTarget(const Context *context, GLenum target)
108{
109 switch (target)
110 {
111 case GL_ARRAY_BUFFER:
112 case GL_ELEMENT_ARRAY_BUFFER:
113 return true;
114
Jamie Madill8c96d582014-03-05 15:01:23 -0500115 case GL_PIXEL_PACK_BUFFER:
116 case GL_PIXEL_UNPACK_BUFFER:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400117 return context->getExtensions().pixelBufferObject;
Shannon Woods158c4382014-05-06 13:00:07 -0400118
Shannon Woodsb3801742014-03-27 14:59:19 -0400119 case GL_COPY_READ_BUFFER:
120 case GL_COPY_WRITE_BUFFER:
Jamie Madill8c96d582014-03-05 15:01:23 -0500121 case GL_TRANSFORM_FEEDBACK_BUFFER:
122 case GL_UNIFORM_BUFFER:
123 return (context->getClientVersion() >= 3);
124
125 default:
126 return false;
127 }
128}
129
Jamie Madill70656a62014-03-05 15:01:26 -0500130bool ValidBufferParameter(const Context *context, GLenum pname)
131{
132 switch (pname)
133 {
134 case GL_BUFFER_USAGE:
135 case GL_BUFFER_SIZE:
136 return true;
137
138 // GL_BUFFER_MAP_POINTER is a special case, and may only be
139 // queried with GetBufferPointerv
140 case GL_BUFFER_ACCESS_FLAGS:
141 case GL_BUFFER_MAPPED:
142 case GL_BUFFER_MAP_OFFSET:
143 case GL_BUFFER_MAP_LENGTH:
144 return (context->getClientVersion() >= 3);
145
146 default:
147 return false;
148 }
149}
150
Jamie Madill8c96d582014-03-05 15:01:23 -0500151bool ValidMipLevel(const Context *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400152{
Geoff Langaae65a42014-05-26 12:43:44 -0400153 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400154 switch (target)
155 {
Geoff Langaae65a42014-05-26 12:43:44 -0400156 case GL_TEXTURE_2D: maxDimension = context->getCaps().max2DTextureSize; break;
Geoff Langce635692013-09-24 13:56:32 -0400157 case GL_TEXTURE_CUBE_MAP:
158 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
159 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
160 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
161 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
162 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
Geoff Langaae65a42014-05-26 12:43:44 -0400163 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: maxDimension = context->getCaps().maxCubeMapTextureSize; break;
164 case GL_TEXTURE_3D: maxDimension = context->getCaps().max3DTextureSize; break;
165 case GL_TEXTURE_2D_ARRAY: maxDimension = context->getCaps().max2DTextureSize; break;
Geoff Langce635692013-09-24 13:56:32 -0400166 default: UNREACHABLE();
167 }
168
Geoff Langaae65a42014-05-26 12:43:44 -0400169 return level <= gl::log2(maxDimension);
Geoff Langce635692013-09-24 13:56:32 -0400170}
171
Geoff Langb1196682014-07-23 13:47:29 -0400172bool ValidImageSize(const Context *context, GLenum target, GLint level,
Jamie Madill4fd75c12014-06-23 10:53:54 -0400173 GLsizei width, GLsizei height, GLsizei depth)
Geoff Langce635692013-09-24 13:56:32 -0400174{
175 if (level < 0 || width < 0 || height < 0 || depth < 0)
176 {
177 return false;
178 }
179
Geoff Langc0b9ef42014-07-02 10:02:37 -0400180 if (!context->getExtensions().textureNPOT &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400181 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400182 {
183 return false;
184 }
185
186 if (!ValidMipLevel(context, target, level))
187 {
188 return false;
189 }
190
191 return true;
192}
193
Geoff Langb1196682014-07-23 13:47:29 -0400194bool ValidCompressedImageSize(const Context *context, GLenum internalFormat, GLsizei width, GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400195{
Geoff Lang5d601382014-07-22 15:14:06 -0400196 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
197 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400198 {
199 return false;
200 }
201
Geoff Lang5d601382014-07-22 15:14:06 -0400202 if (width < 0 || (static_cast<GLuint>(width) > formatInfo.compressedBlockWidth && width % formatInfo.compressedBlockWidth != 0) ||
203 height < 0 || (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight && height % formatInfo.compressedBlockHeight != 0))
Geoff Langd4f180b2013-09-24 13:57:44 -0400204 {
205 return false;
206 }
207
208 return true;
209}
210
Geoff Lang37dde692014-01-31 16:34:54 -0500211bool ValidQueryType(const Context *context, GLenum queryType)
212{
Geoff Langd4475812015-03-18 10:53:05 -0400213 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT, "GL extension enums not equal.");
214 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -0500215
216 switch (queryType)
217 {
218 case GL_ANY_SAMPLES_PASSED:
219 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
220 return true;
221 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
222 return (context->getClientVersion() >= 3);
223 default:
224 return false;
225 }
226}
227
Geoff Langb1196682014-07-23 13:47:29 -0400228bool ValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -0500229{
230 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the
231 // error INVALID_VALUE if the provided name is not the name of either a shader or program object and
232 // INVALID_OPERATION if the provided name identifies an object that is not the expected type."
233
234 if (context->getProgram(id) != NULL)
235 {
236 return true;
237 }
238 else if (context->getShader(id) != NULL)
239 {
240 // ID is the wrong type
Geoff Langb1196682014-07-23 13:47:29 -0400241 context->recordError(Error(GL_INVALID_OPERATION));
242 return false;
Geoff Lang48dcae72014-02-05 16:28:24 -0500243 }
244 else
245 {
246 // No shader/program object has this ID
Geoff Langb1196682014-07-23 13:47:29 -0400247 context->recordError(Error(GL_INVALID_VALUE));
248 return false;
Geoff Lang48dcae72014-02-05 16:28:24 -0500249 }
250}
251
Geoff Langb1196682014-07-23 13:47:29 -0400252bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -0400253{
254 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
255 {
256 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
257
Geoff Langaae65a42014-05-26 12:43:44 -0400258 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -0400259 {
Geoff Langb1196682014-07-23 13:47:29 -0400260 context->recordError(Error(GL_INVALID_VALUE));
261 return false;
Jamie Madillb4472272014-07-03 10:38:55 -0400262 }
263 }
264 else
265 {
266 switch (attachment)
267 {
268 case GL_DEPTH_ATTACHMENT:
269 case GL_STENCIL_ATTACHMENT:
270 break;
271
272 case GL_DEPTH_STENCIL_ATTACHMENT:
273 if (context->getClientVersion() < 3)
274 {
Geoff Langb1196682014-07-23 13:47:29 -0400275 context->recordError(Error(GL_INVALID_ENUM));
276 return false;
Jamie Madillb4472272014-07-03 10:38:55 -0400277 }
278 break;
279
280 default:
Geoff Langb1196682014-07-23 13:47:29 -0400281 context->recordError(Error(GL_INVALID_ENUM));
282 return false;
Jamie Madillb4472272014-07-03 10:38:55 -0400283 }
284 }
285
286 return true;
287}
288
Corentin Walleze0902642014-11-04 12:32:15 -0800289bool ValidateRenderbufferStorageParametersBase(gl::Context *context, GLenum target, GLsizei samples,
290 GLenum internalformat, GLsizei width, GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400291{
292 switch (target)
293 {
294 case GL_RENDERBUFFER:
295 break;
296 default:
Geoff Langb1196682014-07-23 13:47:29 -0400297 context->recordError(Error(GL_INVALID_ENUM));
298 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400299 }
300
301 if (width < 0 || height < 0 || samples < 0)
302 {
Geoff Langb1196682014-07-23 13:47:29 -0400303 context->recordError(Error(GL_INVALID_VALUE));
304 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400305 }
306
Geoff Langd87878e2014-09-19 15:42:59 -0400307 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
308 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400309 {
Geoff Langb1196682014-07-23 13:47:29 -0400310 context->recordError(Error(GL_INVALID_ENUM));
311 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400312 }
313
314 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
315 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
Corentin Walleze0902642014-11-04 12:32:15 -0800316 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -0400317 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400318 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400319 {
Geoff Langb1196682014-07-23 13:47:29 -0400320 context->recordError(Error(GL_INVALID_ENUM));
321 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400322 }
323
Geoff Langaae65a42014-05-26 12:43:44 -0400324 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400325 {
Geoff Langb1196682014-07-23 13:47:29 -0400326 context->recordError(Error(GL_INVALID_VALUE));
327 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400328 }
329
Shannon Woods53a94a82014-06-24 15:20:36 -0400330 GLuint handle = context->getState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400331 if (handle == 0)
332 {
Geoff Langb1196682014-07-23 13:47:29 -0400333 context->recordError(Error(GL_INVALID_OPERATION));
334 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400335 }
336
337 return true;
338}
339
Corentin Walleze0902642014-11-04 12:32:15 -0800340bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum target, GLsizei samples,
341 GLenum internalformat, GLsizei width, GLsizei height)
342{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -0800343 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -0800344
345 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
346 // to MAX_SAMPLES_ANGLE (Context::getExtensions().maxSamples) otherwise GL_INVALID_VALUE is
347 // generated.
348 if (static_cast<GLuint>(samples) > context->getExtensions().maxSamples)
349 {
350 context->recordError(Error(GL_INVALID_VALUE));
351 return false;
352 }
353
354 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
355 // the specified storage. This is different than ES 3.0 in which a sample number higher
356 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
357 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
358 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
359 {
360 context->recordError(Error(GL_OUT_OF_MEMORY));
361 return false;
362 }
363
364 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height);
365}
366
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500367bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
368 GLenum renderbuffertarget, GLuint renderbuffer)
369{
Shannon Woods1da3cf62014-06-27 15:32:23 -0400370 if (!ValidFramebufferTarget(target))
371 {
Geoff Langb1196682014-07-23 13:47:29 -0400372 context->recordError(Error(GL_INVALID_ENUM));
373 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -0400374 }
375
Shannon Woods53a94a82014-06-24 15:20:36 -0400376 gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
377 GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id();
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500378
379 if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0))
380 {
Geoff Langb1196682014-07-23 13:47:29 -0400381 context->recordError(Error(GL_INVALID_OPERATION));
382 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500383 }
384
Jamie Madillb4472272014-07-03 10:38:55 -0400385 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500386 {
Jamie Madillb4472272014-07-03 10:38:55 -0400387 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500388 }
389
Jamie Madillab9d82c2014-01-21 16:38:14 -0500390 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
391 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
392 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
393 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
394 if (renderbuffer != 0)
395 {
396 if (!context->getRenderbuffer(renderbuffer))
397 {
Geoff Langb1196682014-07-23 13:47:29 -0400398 context->recordError(Error(GL_INVALID_OPERATION));
399 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -0500400 }
401 }
402
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500403 return true;
404}
405
Jamie Madill3c7fa222014-06-05 13:08:51 -0400406static bool IsPartialBlit(gl::Context *context, gl::FramebufferAttachment *readBuffer, gl::FramebufferAttachment *writeBuffer,
Geoff Lang125deab2013-08-09 13:34:16 -0400407 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
408 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
409{
410 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 ||
411 dstX1 != writeBuffer->getWidth() || dstY1 != writeBuffer->getHeight() ||
412 srcX1 != readBuffer->getWidth() || srcY1 != readBuffer->getHeight())
413 {
414 return true;
415 }
Shannon Woods53a94a82014-06-24 15:20:36 -0400416 else if (context->getState().isScissorTestEnabled())
Geoff Lang125deab2013-08-09 13:34:16 -0400417 {
Shannon Woods53a94a82014-06-24 15:20:36 -0400418 const Rectangle &scissor = context->getState().getScissor();
Geoff Lang125deab2013-08-09 13:34:16 -0400419
Shannon Woods53a94a82014-06-24 15:20:36 -0400420 return scissor.x > 0 || scissor.y > 0 ||
421 scissor.width < writeBuffer->getWidth() ||
422 scissor.height < writeBuffer->getHeight();
Geoff Lang125deab2013-08-09 13:34:16 -0400423 }
424 else
425 {
426 return false;
427 }
428}
429
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400430bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400431 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask,
432 GLenum filter, bool fromAngleExtension)
433{
434 switch (filter)
435 {
436 case GL_NEAREST:
437 break;
438 case GL_LINEAR:
439 if (fromAngleExtension)
440 {
Geoff Langb1196682014-07-23 13:47:29 -0400441 context->recordError(Error(GL_INVALID_ENUM));
442 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400443 }
444 break;
445 default:
Geoff Langb1196682014-07-23 13:47:29 -0400446 context->recordError(Error(GL_INVALID_ENUM));
447 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400448 }
449
450 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
451 {
Geoff Langb1196682014-07-23 13:47:29 -0400452 context->recordError(Error(GL_INVALID_VALUE));
453 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400454 }
455
456 if (mask == 0)
457 {
458 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
459 // buffers are copied.
460 return false;
461 }
462
463 if (fromAngleExtension && (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0))
464 {
465 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation.");
Geoff Langb1196682014-07-23 13:47:29 -0400466 context->recordError(Error(GL_INVALID_OPERATION));
467 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400468 }
469
470 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
471 // color buffer, leaving only nearest being unfiltered from above
472 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
473 {
Geoff Langb1196682014-07-23 13:47:29 -0400474 context->recordError(Error(GL_INVALID_OPERATION));
475 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400476 }
477
Shannon Woods53a94a82014-06-24 15:20:36 -0400478 if (context->getState().getReadFramebuffer()->id() == context->getState().getDrawFramebuffer()->id())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400479 {
480 if (fromAngleExtension)
481 {
482 ERR("Blits with the same source and destination framebuffer are not supported by this "
483 "implementation.");
484 }
Geoff Langb1196682014-07-23 13:47:29 -0400485 context->recordError(Error(GL_INVALID_OPERATION));
486 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400487 }
488
Shannon Woods53a94a82014-06-24 15:20:36 -0400489 gl::Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
490 gl::Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -0500491
492 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400493 {
Geoff Langb1196682014-07-23 13:47:29 -0400494 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
495 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400496 }
497
Geoff Lang748f74e2014-12-01 11:25:34 -0500498 if (!readFramebuffer->checkStatus(context->getData()))
Jamie Madill48faf802014-11-06 15:27:22 -0500499 {
500 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
501 return false;
502 }
503
Geoff Lang748f74e2014-12-01 11:25:34 -0500504 if (!drawFramebuffer->checkStatus(context->getData()))
Jamie Madill48faf802014-11-06 15:27:22 -0500505 {
506 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
507 return false;
508 }
509
510 if (drawFramebuffer->getSamples(context->getData()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400511 {
Geoff Langb1196682014-07-23 13:47:29 -0400512 context->recordError(Error(GL_INVALID_OPERATION));
513 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400514 }
515
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400516 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
517
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400518 if (mask & GL_COLOR_BUFFER_BIT)
519 {
Jamie Madill3c7fa222014-06-05 13:08:51 -0400520 gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
521 gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400522
523 if (readColorBuffer && drawColorBuffer)
524 {
Geoff Langd8a22582014-12-17 15:28:23 -0500525 GLenum readInternalFormat = readColorBuffer->getInternalFormat();
Geoff Lang5d601382014-07-22 15:14:06 -0400526 const InternalFormat &readFormatInfo = GetInternalFormatInfo(readInternalFormat);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400527
Jamie Madill0af26e12015-03-05 19:54:33 -0500528 for (GLuint i = 0; i < context->getCaps().maxColorAttachments; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400529 {
530 if (drawFramebuffer->isEnabledColorAttachment(i))
531 {
Geoff Langd8a22582014-12-17 15:28:23 -0500532 GLenum drawInternalFormat = drawFramebuffer->getColorbuffer(i)->getInternalFormat();
Geoff Lang5d601382014-07-22 15:14:06 -0400533 const InternalFormat &drawFormatInfo = GetInternalFormatInfo(drawInternalFormat);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400534
Geoff Langb2f3d052013-08-13 12:49:27 -0400535 // The GL ES 3.0.2 spec (pg 193) states that:
536 // 1) If the read buffer is fixed point format, the draw buffer must be as well
537 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
538 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
Geoff Lang5d601382014-07-22 15:14:06 -0400539 if ( (readFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || readFormatInfo.componentType == GL_SIGNED_NORMALIZED) &&
540 !(drawFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || drawFormatInfo.componentType == GL_SIGNED_NORMALIZED))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400541 {
Geoff Langb1196682014-07-23 13:47:29 -0400542 context->recordError(Error(GL_INVALID_OPERATION));
543 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400544 }
545
Geoff Lang5d601382014-07-22 15:14:06 -0400546 if (readFormatInfo.componentType == GL_UNSIGNED_INT && drawFormatInfo.componentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400547 {
Geoff Langb1196682014-07-23 13:47:29 -0400548 context->recordError(Error(GL_INVALID_OPERATION));
549 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400550 }
551
Geoff Lang5d601382014-07-22 15:14:06 -0400552 if (readFormatInfo.componentType == GL_INT && drawFormatInfo.componentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400553 {
Geoff Langb1196682014-07-23 13:47:29 -0400554 context->recordError(Error(GL_INVALID_OPERATION));
555 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400556 }
557
Geoff Langb2f3d052013-08-13 12:49:27 -0400558 if (readColorBuffer->getSamples() > 0 && (readInternalFormat != drawInternalFormat || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400559 {
Geoff Langb1196682014-07-23 13:47:29 -0400560 context->recordError(Error(GL_INVALID_OPERATION));
561 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400562 }
563 }
564 }
565
Geoff Lang5d601382014-07-22 15:14:06 -0400566 if ((readFormatInfo.componentType == GL_INT || readFormatInfo.componentType == GL_UNSIGNED_INT) && filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400567 {
Geoff Langb1196682014-07-23 13:47:29 -0400568 context->recordError(Error(GL_INVALID_OPERATION));
569 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400570 }
571
572 if (fromAngleExtension)
573 {
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500574 FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
575 if (!readColorAttachment ||
576 (!(readColorAttachment->type() == GL_TEXTURE && readColorAttachment->getTextureImageIndex()->type == GL_TEXTURE_2D) &&
577 readColorAttachment->type() != GL_RENDERBUFFER &&
578 readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400579 {
Geoff Langb1196682014-07-23 13:47:29 -0400580 context->recordError(Error(GL_INVALID_OPERATION));
581 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400582 }
583
Jamie Madill0af26e12015-03-05 19:54:33 -0500584 for (GLuint colorAttachment = 0; colorAttachment < context->getCaps().maxColorAttachments; ++colorAttachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400585 {
586 if (drawFramebuffer->isEnabledColorAttachment(colorAttachment))
587 {
Jamie Madille92a3542014-07-03 10:38:58 -0400588 FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(colorAttachment);
589 ASSERT(attachment);
590
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500591 if (!(attachment->type() == GL_TEXTURE && attachment->getTextureImageIndex()->type == GL_TEXTURE_2D) &&
592 attachment->type() != GL_RENDERBUFFER &&
593 attachment->type() != GL_FRAMEBUFFER_DEFAULT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400594 {
Geoff Langb1196682014-07-23 13:47:29 -0400595 context->recordError(Error(GL_INVALID_OPERATION));
596 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400597 }
598
Jamie Madillf8f18f02014-10-02 10:44:17 -0400599 // Return an error if the destination formats do not match
600 if (attachment->getInternalFormat() != readColorBuffer->getInternalFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400601 {
Geoff Langb1196682014-07-23 13:47:29 -0400602 context->recordError(Error(GL_INVALID_OPERATION));
603 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400604 }
605 }
606 }
Jamie Madill48faf802014-11-06 15:27:22 -0500607
608 int readSamples = readFramebuffer->getSamples(context->getData());
609
610 if (readSamples != 0 && IsPartialBlit(context, readColorBuffer, drawColorBuffer,
611 srcX0, srcY0, srcX1, srcY1,
612 dstX0, dstY0, dstX1, dstY1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400613 {
Geoff Langb1196682014-07-23 13:47:29 -0400614 context->recordError(Error(GL_INVALID_OPERATION));
615 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400616 }
617 }
618 }
619 }
620
Dongseong Hwang44b422c2014-12-09 15:42:01 +0200621 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
622 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
623 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400624 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +0200625 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400626 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +0200627 gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]);
628 gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400629
Dongseong Hwang44b422c2014-12-09 15:42:01 +0200630 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400631 {
Geoff Langd8a22582014-12-17 15:28:23 -0500632 if (readBuffer->getInternalFormat() != drawBuffer->getInternalFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400633 {
Geoff Langb1196682014-07-23 13:47:29 -0400634 context->recordError(Error(GL_INVALID_OPERATION));
635 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400636 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400637
Dongseong Hwang44b422c2014-12-09 15:42:01 +0200638 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400639 {
Geoff Langb1196682014-07-23 13:47:29 -0400640 context->recordError(Error(GL_INVALID_OPERATION));
641 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400642 }
Dongseong Hwang44b422c2014-12-09 15:42:01 +0200643
644 if (fromAngleExtension)
645 {
646 if (IsPartialBlit(context, readBuffer, drawBuffer,
647 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
648 {
649 ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
650 context->recordError(Error(GL_INVALID_OPERATION)); // only whole-buffer copies are permitted
651 return false;
652 }
653
654 if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
655 {
656 context->recordError(Error(GL_INVALID_OPERATION));
657 return false;
658 }
659 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400660 }
661 }
662 }
663
664 return true;
665}
666
Geoff Langb1196682014-07-23 13:47:29 -0400667bool ValidateGetVertexAttribParameters(Context *context, GLenum pname)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400668{
669 switch (pname)
670 {
671 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
672 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
673 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
674 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
675 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
676 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
677 case GL_CURRENT_VERTEX_ATTRIB:
678 return true;
679
680 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
681 // Don't verify ES3 context because GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE uses
682 // the same constant.
Geoff Langd4475812015-03-18 10:53:05 -0400683 static_assert(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
684 "ANGLE extension enums not equal to GL enums.");
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400685 return true;
686
687 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Geoff Langb1196682014-07-23 13:47:29 -0400688 if (context->getClientVersion() < 3)
689 {
690 context->recordError(Error(GL_INVALID_ENUM));
691 return false;
692 }
693 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400694
695 default:
Geoff Langb1196682014-07-23 13:47:29 -0400696 context->recordError(Error(GL_INVALID_ENUM));
697 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400698 }
699}
700
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400701bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400702{
703 switch (pname)
704 {
705 case GL_TEXTURE_WRAP_R:
706 case GL_TEXTURE_SWIZZLE_R:
707 case GL_TEXTURE_SWIZZLE_G:
708 case GL_TEXTURE_SWIZZLE_B:
709 case GL_TEXTURE_SWIZZLE_A:
710 case GL_TEXTURE_BASE_LEVEL:
711 case GL_TEXTURE_MAX_LEVEL:
712 case GL_TEXTURE_COMPARE_MODE:
713 case GL_TEXTURE_COMPARE_FUNC:
714 case GL_TEXTURE_MIN_LOD:
715 case GL_TEXTURE_MAX_LOD:
716 if (context->getClientVersion() < 3)
717 {
Geoff Langb1196682014-07-23 13:47:29 -0400718 context->recordError(Error(GL_INVALID_ENUM));
719 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400720 }
721 break;
722
723 default: break;
724 }
725
726 switch (pname)
727 {
728 case GL_TEXTURE_WRAP_S:
729 case GL_TEXTURE_WRAP_T:
730 case GL_TEXTURE_WRAP_R:
731 switch (param)
732 {
733 case GL_REPEAT:
734 case GL_CLAMP_TO_EDGE:
735 case GL_MIRRORED_REPEAT:
736 return true;
737 default:
Geoff Langb1196682014-07-23 13:47:29 -0400738 context->recordError(Error(GL_INVALID_ENUM));
739 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400740 }
741
742 case GL_TEXTURE_MIN_FILTER:
743 switch (param)
744 {
745 case GL_NEAREST:
746 case GL_LINEAR:
747 case GL_NEAREST_MIPMAP_NEAREST:
748 case GL_LINEAR_MIPMAP_NEAREST:
749 case GL_NEAREST_MIPMAP_LINEAR:
750 case GL_LINEAR_MIPMAP_LINEAR:
751 return true;
752 default:
Geoff Langb1196682014-07-23 13:47:29 -0400753 context->recordError(Error(GL_INVALID_ENUM));
754 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400755 }
756 break;
757
758 case GL_TEXTURE_MAG_FILTER:
759 switch (param)
760 {
761 case GL_NEAREST:
762 case GL_LINEAR:
763 return true;
764 default:
Geoff Langb1196682014-07-23 13:47:29 -0400765 context->recordError(Error(GL_INVALID_ENUM));
766 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400767 }
768 break;
769
770 case GL_TEXTURE_USAGE_ANGLE:
771 switch (param)
772 {
773 case GL_NONE:
774 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
775 return true;
776 default:
Geoff Langb1196682014-07-23 13:47:29 -0400777 context->recordError(Error(GL_INVALID_ENUM));
778 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400779 }
780 break;
781
782 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Geoff Langc0b9ef42014-07-02 10:02:37 -0400783 if (!context->getExtensions().textureFilterAnisotropic)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400784 {
Geoff Langb1196682014-07-23 13:47:29 -0400785 context->recordError(Error(GL_INVALID_ENUM));
786 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400787 }
788
789 // we assume the parameter passed to this validation method is truncated, not rounded
790 if (param < 1)
791 {
Geoff Langb1196682014-07-23 13:47:29 -0400792 context->recordError(Error(GL_INVALID_VALUE));
793 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400794 }
795 return true;
796
797 case GL_TEXTURE_MIN_LOD:
798 case GL_TEXTURE_MAX_LOD:
799 // any value is permissible
800 return true;
801
802 case GL_TEXTURE_COMPARE_MODE:
Geoff Lang63b5f1f2013-09-23 14:52:14 -0400803 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400804 switch (param)
805 {
806 case GL_NONE:
807 case GL_COMPARE_REF_TO_TEXTURE:
808 return true;
809 default:
Geoff Langb1196682014-07-23 13:47:29 -0400810 context->recordError(Error(GL_INVALID_ENUM));
811 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400812 }
813 break;
814
815 case GL_TEXTURE_COMPARE_FUNC:
Geoff Lang63b5f1f2013-09-23 14:52:14 -0400816 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400817 switch (param)
818 {
819 case GL_LEQUAL:
820 case GL_GEQUAL:
821 case GL_LESS:
822 case GL_GREATER:
823 case GL_EQUAL:
824 case GL_NOTEQUAL:
825 case GL_ALWAYS:
826 case GL_NEVER:
827 return true;
828 default:
Geoff Langb1196682014-07-23 13:47:29 -0400829 context->recordError(Error(GL_INVALID_ENUM));
830 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400831 }
832 break;
833
834 case GL_TEXTURE_SWIZZLE_R:
835 case GL_TEXTURE_SWIZZLE_G:
836 case GL_TEXTURE_SWIZZLE_B:
837 case GL_TEXTURE_SWIZZLE_A:
Geoff Langbc90a482013-09-17 16:51:27 -0400838 switch (param)
839 {
840 case GL_RED:
841 case GL_GREEN:
842 case GL_BLUE:
843 case GL_ALPHA:
844 case GL_ZERO:
845 case GL_ONE:
846 return true;
847 default:
Geoff Langb1196682014-07-23 13:47:29 -0400848 context->recordError(Error(GL_INVALID_ENUM));
849 return false;
Geoff Langbc90a482013-09-17 16:51:27 -0400850 }
851 break;
852
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400853 case GL_TEXTURE_BASE_LEVEL:
854 case GL_TEXTURE_MAX_LEVEL:
Nicolas Capens8de68282014-04-04 11:10:27 -0400855 if (param < 0)
856 {
Geoff Langb1196682014-07-23 13:47:29 -0400857 context->recordError(Error(GL_INVALID_VALUE));
858 return false;
Nicolas Capens8de68282014-04-04 11:10:27 -0400859 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400860 return true;
861
862 default:
Geoff Langb1196682014-07-23 13:47:29 -0400863 context->recordError(Error(GL_INVALID_ENUM));
864 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400865 }
866}
867
Geoff Langb1196682014-07-23 13:47:29 -0400868bool ValidateSamplerObjectParameter(gl::Context *context, GLenum pname)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400869{
870 switch (pname)
871 {
872 case GL_TEXTURE_MIN_FILTER:
873 case GL_TEXTURE_MAG_FILTER:
874 case GL_TEXTURE_WRAP_S:
875 case GL_TEXTURE_WRAP_T:
876 case GL_TEXTURE_WRAP_R:
877 case GL_TEXTURE_MIN_LOD:
878 case GL_TEXTURE_MAX_LOD:
879 case GL_TEXTURE_COMPARE_MODE:
880 case GL_TEXTURE_COMPARE_FUNC:
881 return true;
882
883 default:
Geoff Langb1196682014-07-23 13:47:29 -0400884 context->recordError(Error(GL_INVALID_ENUM));
885 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400886 }
887}
888
Jamie Madill26e91952014-03-05 15:01:27 -0500889bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsizei width, GLsizei height,
890 GLenum format, GLenum type, GLsizei *bufSize, GLvoid *pixels)
891{
Shannon Woods53a94a82014-06-24 15:20:36 -0400892 gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
Jamie Madill893ab082014-05-16 16:56:10 -0400893 ASSERT(framebuffer);
Jamie Madill26e91952014-03-05 15:01:27 -0500894
Geoff Lang748f74e2014-12-01 11:25:34 -0500895 if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill26e91952014-03-05 15:01:27 -0500896 {
Geoff Langb1196682014-07-23 13:47:29 -0400897 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
898 return false;
Jamie Madill26e91952014-03-05 15:01:27 -0500899 }
900
Jamie Madill48faf802014-11-06 15:27:22 -0500901 if (context->getState().getReadFramebuffer()->id() != 0 &&
902 framebuffer->getSamples(context->getData()) != 0)
Jamie Madill26e91952014-03-05 15:01:27 -0500903 {
Geoff Langb1196682014-07-23 13:47:29 -0400904 context->recordError(Error(GL_INVALID_OPERATION));
905 return false;
Jamie Madill26e91952014-03-05 15:01:27 -0500906 }
907
Geoff Langbce529e2014-12-01 12:48:41 -0500908 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
909 if (!readBuffer)
Jamie Madill893ab082014-05-16 16:56:10 -0400910 {
Geoff Langb1196682014-07-23 13:47:29 -0400911 context->recordError(Error(GL_INVALID_OPERATION));
912 return false;
Jamie Madill893ab082014-05-16 16:56:10 -0400913 }
914
Geoff Langbce529e2014-12-01 12:48:41 -0500915 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
916 GLenum currentType = framebuffer->getImplementationColorReadType();
Geoff Langd8a22582014-12-17 15:28:23 -0500917 GLenum currentInternalFormat = readBuffer->getInternalFormat();
Geoff Lange4a492b2014-06-19 14:14:41 -0400918 GLuint clientVersion = context->getClientVersion();
Jamie Madill26e91952014-03-05 15:01:27 -0500919
Geoff Langbdc9b2f2014-04-16 14:41:54 -0400920 bool validReadFormat = (clientVersion < 3) ? ValidES2ReadFormatType(context, format, type) :
921 ValidES3ReadFormatType(context, currentInternalFormat, format, type);
Jamie Madill26e91952014-03-05 15:01:27 -0500922
923 if (!(currentFormat == format && currentType == type) && !validReadFormat)
924 {
Geoff Langb1196682014-07-23 13:47:29 -0400925 context->recordError(Error(GL_INVALID_OPERATION));
926 return false;
Jamie Madill26e91952014-03-05 15:01:27 -0500927 }
928
Geoff Lang5d601382014-07-22 15:14:06 -0400929 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
930 const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat);
Jamie Madill26e91952014-03-05 15:01:27 -0500931
Minmin Gongb8aee3b2015-01-27 14:42:36 -0800932 GLsizei outputPitch = sizedFormatInfo.computeRowPitch(type, width, context->getState().getPackAlignment(), 0);
Jamie Madill26e91952014-03-05 15:01:27 -0500933 // sized query sanity check
934 if (bufSize)
935 {
936 int requiredSize = outputPitch * height;
937 if (requiredSize > *bufSize)
938 {
Geoff Langb1196682014-07-23 13:47:29 -0400939 context->recordError(Error(GL_INVALID_OPERATION));
940 return false;
Jamie Madill26e91952014-03-05 15:01:27 -0500941 }
942 }
943
944 return true;
945}
946
Jamie Madilldb2f14c2014-05-13 13:56:30 -0400947bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
948{
949 if (!ValidQueryType(context, target))
950 {
Geoff Langb1196682014-07-23 13:47:29 -0400951 context->recordError(Error(GL_INVALID_ENUM));
952 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -0400953 }
954
955 if (id == 0)
956 {
Geoff Langb1196682014-07-23 13:47:29 -0400957 context->recordError(Error(GL_INVALID_OPERATION));
958 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -0400959 }
960
961 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
962 // of zero, if the active query object name for <target> is non-zero (for the
963 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
964 // the active query for either target is non-zero), if <id> is the name of an
965 // existing query object whose type does not match <target>, or if <id> is the
966 // active query object name for any query type, the error INVALID_OPERATION is
967 // generated.
968
969 // Ensure no other queries are active
970 // NOTE: If other queries than occlusion are supported, we will need to check
971 // separately that:
972 // a) The query ID passed is not the current active query for any target/type
973 // b) There are no active queries for the requested target (and in the case
974 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
975 // no query may be active for either if glBeginQuery targets either.
Shannon Woods53a94a82014-06-24 15:20:36 -0400976 if (context->getState().isQueryActive())
Jamie Madilldb2f14c2014-05-13 13:56:30 -0400977 {
Geoff Langb1196682014-07-23 13:47:29 -0400978 context->recordError(Error(GL_INVALID_OPERATION));
979 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -0400980 }
981
982 Query *queryObject = context->getQuery(id, true, target);
983
984 // check that name was obtained with glGenQueries
985 if (!queryObject)
986 {
Geoff Langb1196682014-07-23 13:47:29 -0400987 context->recordError(Error(GL_INVALID_OPERATION));
988 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -0400989 }
990
991 // check for type mismatch
992 if (queryObject->getType() != target)
993 {
Geoff Langb1196682014-07-23 13:47:29 -0400994 context->recordError(Error(GL_INVALID_OPERATION));
995 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -0400996 }
997
998 return true;
999}
1000
Jamie Madill45c785d2014-05-13 14:09:34 -04001001bool ValidateEndQuery(gl::Context *context, GLenum target)
1002{
1003 if (!ValidQueryType(context, target))
1004 {
Geoff Langb1196682014-07-23 13:47:29 -04001005 context->recordError(Error(GL_INVALID_ENUM));
1006 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001007 }
1008
Shannon Woods53a94a82014-06-24 15:20:36 -04001009 const Query *queryObject = context->getState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001010
1011 if (queryObject == NULL)
1012 {
Geoff Langb1196682014-07-23 13:47:29 -04001013 context->recordError(Error(GL_INVALID_OPERATION));
1014 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001015 }
1016
Jamie Madill45c785d2014-05-13 14:09:34 -04001017 return true;
1018}
1019
Jamie Madill36398922014-05-20 14:51:53 -04001020static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniformType,
1021 GLint location, GLsizei count, LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001022{
1023 if (count < 0)
1024 {
Geoff Langb1196682014-07-23 13:47:29 -04001025 context->recordError(Error(GL_INVALID_VALUE));
1026 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001027 }
1028
Geoff Lang7dd2e102014-11-10 15:19:26 -05001029 gl::Program *program = context->getState().getProgram();
1030 if (!program)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001031 {
Geoff Langb1196682014-07-23 13:47:29 -04001032 context->recordError(Error(GL_INVALID_OPERATION));
1033 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001034 }
1035
1036 if (location == -1)
1037 {
1038 // Silently ignore the uniform command
1039 return false;
1040 }
1041
Geoff Lang7dd2e102014-11-10 15:19:26 -05001042 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04001043 {
Geoff Langb1196682014-07-23 13:47:29 -04001044 context->recordError(Error(GL_INVALID_OPERATION));
1045 return false;
Jamie Madill36398922014-05-20 14:51:53 -04001046 }
1047
Geoff Lang7dd2e102014-11-10 15:19:26 -05001048 LinkedUniform *uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04001049
1050 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
1051 if (uniform->elementCount() == 1 && count > 1)
1052 {
Geoff Langb1196682014-07-23 13:47:29 -04001053 context->recordError(Error(GL_INVALID_OPERATION));
1054 return false;
Jamie Madill36398922014-05-20 14:51:53 -04001055 }
1056
1057 *uniformOut = uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04001058 return true;
1059}
1060
Jamie Madillaa981bd2014-05-20 10:55:55 -04001061bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
1062{
1063 // Check for ES3 uniform entry points
Jamie Madillf2575982014-06-25 16:04:54 -04001064 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT && context->getClientVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04001065 {
Geoff Langb1196682014-07-23 13:47:29 -04001066 context->recordError(Error(GL_INVALID_OPERATION));
1067 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001068 }
1069
Jamie Madill36398922014-05-20 14:51:53 -04001070 LinkedUniform *uniform = NULL;
1071 if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
1072 {
1073 return false;
1074 }
1075
Jamie Madillf2575982014-06-25 16:04:54 -04001076 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05001077 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04001078 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
1079 {
Geoff Langb1196682014-07-23 13:47:29 -04001080 context->recordError(Error(GL_INVALID_OPERATION));
1081 return false;
Jamie Madill36398922014-05-20 14:51:53 -04001082 }
1083
1084 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001085}
1086
1087bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count,
1088 GLboolean transpose)
1089{
1090 // Check for ES3 uniform entry points
1091 int rows = VariableRowCount(matrixType);
1092 int cols = VariableColumnCount(matrixType);
1093 if (rows != cols && context->getClientVersion() < 3)
1094 {
Geoff Langb1196682014-07-23 13:47:29 -04001095 context->recordError(Error(GL_INVALID_OPERATION));
1096 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001097 }
1098
1099 if (transpose != GL_FALSE && context->getClientVersion() < 3)
1100 {
Geoff Langb1196682014-07-23 13:47:29 -04001101 context->recordError(Error(GL_INVALID_VALUE));
1102 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001103 }
1104
Jamie Madill36398922014-05-20 14:51:53 -04001105 LinkedUniform *uniform = NULL;
1106 if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
1107 {
1108 return false;
1109 }
1110
1111 if (uniform->type != matrixType)
1112 {
Geoff Langb1196682014-07-23 13:47:29 -04001113 context->recordError(Error(GL_INVALID_OPERATION));
1114 return false;
Jamie Madill36398922014-05-20 14:51:53 -04001115 }
1116
1117 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04001118}
1119
Jamie Madill893ab082014-05-16 16:56:10 -04001120bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
1121{
1122 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
1123 {
Geoff Langb1196682014-07-23 13:47:29 -04001124 context->recordError(Error(GL_INVALID_ENUM));
1125 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001126 }
1127
Jamie Madill0af26e12015-03-05 19:54:33 -05001128 const Caps &caps = context->getCaps();
1129
Jamie Madill893ab082014-05-16 16:56:10 -04001130 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
1131 {
1132 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
1133
Jamie Madill0af26e12015-03-05 19:54:33 -05001134 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04001135 {
Geoff Langb1196682014-07-23 13:47:29 -04001136 context->recordError(Error(GL_INVALID_OPERATION));
1137 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001138 }
1139 }
1140
1141 switch (pname)
1142 {
1143 case GL_TEXTURE_BINDING_2D:
1144 case GL_TEXTURE_BINDING_CUBE_MAP:
1145 case GL_TEXTURE_BINDING_3D:
1146 case GL_TEXTURE_BINDING_2D_ARRAY:
Jamie Madill0af26e12015-03-05 19:54:33 -05001147 if (context->getState().getActiveSampler() >= caps.maxCombinedTextureImageUnits)
Jamie Madill893ab082014-05-16 16:56:10 -04001148 {
Geoff Langb1196682014-07-23 13:47:29 -04001149 context->recordError(Error(GL_INVALID_OPERATION));
1150 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001151 }
1152 break;
1153
1154 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1155 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1156 {
Shannon Woods53a94a82014-06-24 15:20:36 -04001157 Framebuffer *framebuffer = context->getState().getReadFramebuffer();
Jamie Madill893ab082014-05-16 16:56:10 -04001158 ASSERT(framebuffer);
Geoff Lang748f74e2014-12-01 11:25:34 -05001159 if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04001160 {
Geoff Langb1196682014-07-23 13:47:29 -04001161 context->recordError(Error(GL_INVALID_OPERATION));
1162 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001163 }
1164
Jamie Madill3c7fa222014-06-05 13:08:51 -04001165 FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
1166 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04001167 {
Geoff Langb1196682014-07-23 13:47:29 -04001168 context->recordError(Error(GL_INVALID_OPERATION));
1169 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04001170 }
1171 }
1172 break;
1173
1174 default:
1175 break;
1176 }
1177
1178 // pname is valid, but there are no parameters to return
1179 if (numParams == 0)
1180 {
1181 return false;
1182 }
1183
1184 return true;
1185}
1186
Jamie Madill560a8d82014-05-21 13:06:20 -04001187bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage,
1188 GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height,
1189 GLint border, GLenum *textureFormatOut)
1190{
1191
1192 if (!ValidTexture2DDestinationTarget(context, target))
1193 {
Geoff Langb1196682014-07-23 13:47:29 -04001194 context->recordError(Error(GL_INVALID_ENUM));
1195 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001196 }
1197
1198 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
1199 {
Geoff Langb1196682014-07-23 13:47:29 -04001200 context->recordError(Error(GL_INVALID_VALUE));
1201 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001202 }
1203
1204 if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1205 {
Geoff Langb1196682014-07-23 13:47:29 -04001206 context->recordError(Error(GL_INVALID_VALUE));
1207 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001208 }
1209
1210 if (border != 0)
1211 {
Geoff Langb1196682014-07-23 13:47:29 -04001212 context->recordError(Error(GL_INVALID_VALUE));
1213 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001214 }
1215
1216 if (!ValidMipLevel(context, target, level))
1217 {
Geoff Langb1196682014-07-23 13:47:29 -04001218 context->recordError(Error(GL_INVALID_VALUE));
1219 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001220 }
1221
Shannon Woods53a94a82014-06-24 15:20:36 -04001222 gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
Geoff Lang748f74e2014-12-01 11:25:34 -05001223 if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04001224 {
Geoff Langb1196682014-07-23 13:47:29 -04001225 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
1226 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001227 }
1228
Jamie Madill48faf802014-11-06 15:27:22 -05001229 if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples(context->getData()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04001230 {
Geoff Langb1196682014-07-23 13:47:29 -04001231 context->recordError(Error(GL_INVALID_OPERATION));
1232 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001233 }
1234
Geoff Langaae65a42014-05-26 12:43:44 -04001235 const gl::Caps &caps = context->getCaps();
1236
Geoff Langaae65a42014-05-26 12:43:44 -04001237 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04001238 switch (target)
1239 {
1240 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05001241 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04001242 break;
1243
1244 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1245 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1246 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1247 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1248 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1249 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -05001250 maxDimension = caps.maxCubeMapTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04001251 break;
1252
1253 case GL_TEXTURE_2D_ARRAY:
Geoff Langa9be0dc2014-12-17 12:34:40 -05001254 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04001255 break;
1256
1257 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05001258 maxDimension = caps.max3DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04001259 break;
1260
1261 default:
Geoff Langb1196682014-07-23 13:47:29 -04001262 context->recordError(Error(GL_INVALID_ENUM));
1263 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001264 }
1265
Geoff Lang691e58c2014-12-19 17:03:25 -05001266 gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04001267 if (!texture)
1268 {
Geoff Langb1196682014-07-23 13:47:29 -04001269 context->recordError(Error(GL_INVALID_OPERATION));
1270 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001271 }
1272
1273 if (texture->isImmutable() && !isSubImage)
1274 {
Geoff Langb1196682014-07-23 13:47:29 -04001275 context->recordError(Error(GL_INVALID_OPERATION));
1276 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001277 }
1278
Geoff Lang5d601382014-07-22 15:14:06 -04001279 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1280
1281 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04001282 {
Geoff Langb1196682014-07-23 13:47:29 -04001283 context->recordError(Error(GL_INVALID_OPERATION));
1284 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001285 }
1286
Geoff Langa9be0dc2014-12-17 12:34:40 -05001287 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04001288 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05001289 context->recordError(Error(GL_INVALID_OPERATION));
1290 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001291 }
1292
1293 if (isSubImage)
1294 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05001295 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
1296 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
1297 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04001298 {
Geoff Langb1196682014-07-23 13:47:29 -04001299 context->recordError(Error(GL_INVALID_VALUE));
1300 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04001301 }
1302 }
Jamie Madill6f38f822014-06-06 17:12:20 -04001303 else
1304 {
Geoff Lang691e58c2014-12-19 17:03:25 -05001305 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04001306 {
Geoff Langb1196682014-07-23 13:47:29 -04001307 context->recordError(Error(GL_INVALID_VALUE));
1308 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04001309 }
1310
Geoff Lang5d601382014-07-22 15:14:06 -04001311 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04001312 {
Geoff Langb1196682014-07-23 13:47:29 -04001313 context->recordError(Error(GL_INVALID_ENUM));
1314 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04001315 }
1316
1317 int maxLevelDimension = (maxDimension >> level);
1318 if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension)
1319 {
Geoff Langb1196682014-07-23 13:47:29 -04001320 context->recordError(Error(GL_INVALID_VALUE));
1321 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04001322 }
1323 }
Jamie Madill560a8d82014-05-21 13:06:20 -04001324
Geoff Langa9be0dc2014-12-17 12:34:40 -05001325 *textureFormatOut = texture->getInternalFormat(target, level);
Jamie Madill560a8d82014-05-21 13:06:20 -04001326 return true;
1327}
1328
Geoff Langb1196682014-07-23 13:47:29 -04001329static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsizei maxVertex, GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04001330{
Jamie Madill1aeb1312014-06-20 13:21:25 -04001331 switch (mode)
1332 {
1333 case GL_POINTS:
1334 case GL_LINES:
1335 case GL_LINE_LOOP:
1336 case GL_LINE_STRIP:
1337 case GL_TRIANGLES:
1338 case GL_TRIANGLE_STRIP:
1339 case GL_TRIANGLE_FAN:
1340 break;
1341 default:
Geoff Langb1196682014-07-23 13:47:29 -04001342 context->recordError(Error(GL_INVALID_ENUM));
1343 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04001344 }
1345
Jamie Madill250d33f2014-06-06 17:09:03 -04001346 if (count < 0)
1347 {
Geoff Langb1196682014-07-23 13:47:29 -04001348 context->recordError(Error(GL_INVALID_VALUE));
1349 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04001350 }
1351
Geoff Langb1196682014-07-23 13:47:29 -04001352 const State &state = context->getState();
1353
Jamie Madill250d33f2014-06-06 17:09:03 -04001354 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04001355 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04001356 {
Geoff Langb1196682014-07-23 13:47:29 -04001357 context->recordError(Error(GL_INVALID_OPERATION));
1358 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04001359 }
1360
Jamie Madilld9ba4f72014-08-04 10:47:59 -04001361 const gl::DepthStencilState &depthStencilState = state.getDepthStencilState();
Jamie Madillac528012014-06-20 13:21:23 -04001362 if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask ||
Jamie Madilld9ba4f72014-08-04 10:47:59 -04001363 state.getStencilRef() != state.getStencilBackRef() ||
Jamie Madillac528012014-06-20 13:21:23 -04001364 depthStencilState.stencilMask != depthStencilState.stencilBackMask)
1365 {
1366 // Note: these separate values are not supported in WebGL, due to D3D's limitations.
1367 // See Section 6.10 of the WebGL 1.0 spec
1368 ERR("This ANGLE implementation does not support separate front/back stencil "
1369 "writemasks, reference values, or stencil mask values.");
Geoff Langb1196682014-07-23 13:47:29 -04001370 context->recordError(Error(GL_INVALID_OPERATION));
1371 return false;
Jamie Madillac528012014-06-20 13:21:23 -04001372 }
1373
Jamie Madilld9ba4f72014-08-04 10:47:59 -04001374 const gl::Framebuffer *fbo = state.getDrawFramebuffer();
Geoff Lang748f74e2014-12-01 11:25:34 -05001375 if (!fbo || fbo->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001376 {
Geoff Langb1196682014-07-23 13:47:29 -04001377 context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
1378 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001379 }
1380
Geoff Lang7dd2e102014-11-10 15:19:26 -05001381 gl::Program *program = state.getProgram();
1382 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04001383 {
Geoff Langb1196682014-07-23 13:47:29 -04001384 context->recordError(Error(GL_INVALID_OPERATION));
1385 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04001386 }
1387
Geoff Lang7dd2e102014-11-10 15:19:26 -05001388 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04001389 {
Geoff Langb1196682014-07-23 13:47:29 -04001390 context->recordError(Error(GL_INVALID_OPERATION));
1391 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04001392 }
1393
Jamie Madill2b976812014-08-25 15:47:49 -04001394 // Buffer validations
1395 const VertexArray *vao = state.getVertexArray();
1396 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
1397 {
1398 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Geoff Lang7dd2e102014-11-10 15:19:26 -05001399 bool attribActive = (program->getSemanticIndex(attributeIndex) != -1);
Jamie Madill2b976812014-08-25 15:47:49 -04001400 if (attribActive && attrib.enabled)
1401 {
1402 gl::Buffer *buffer = attrib.buffer.get();
1403
1404 if (buffer)
1405 {
1406 GLint64 attribStride = static_cast<GLint64>(ComputeVertexAttributeStride(attrib));
1407 GLint64 maxVertexElement = 0;
1408
1409 if (attrib.divisor > 0)
1410 {
1411 maxVertexElement = static_cast<GLint64>(primcount) / static_cast<GLint64>(attrib.divisor);
1412 }
1413 else
1414 {
1415 maxVertexElement = static_cast<GLint64>(maxVertex);
1416 }
1417
1418 GLint64 attribDataSize = maxVertexElement * attribStride;
1419
1420 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
1421 // We can return INVALID_OPERATION if our vertex attribute does not have
1422 // enough backing data.
1423 if (attribDataSize > buffer->getSize())
1424 {
Geoff Langb1196682014-07-23 13:47:29 -04001425 context->recordError(Error(GL_INVALID_OPERATION));
1426 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04001427 }
1428 }
1429 else if (attrib.pointer == NULL)
1430 {
1431 // This is an application error that would normally result in a crash,
1432 // but we catch it and return an error
Geoff Langb1196682014-07-23 13:47:29 -04001433 context->recordError(Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer."));
1434 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04001435 }
1436 }
1437 }
1438
Jamie Madill250d33f2014-06-06 17:09:03 -04001439 // No-op if zero count
1440 return (count > 0);
1441}
1442
Geoff Langb1196682014-07-23 13:47:29 -04001443bool ValidateDrawArrays(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04001444{
Jamie Madillfd716582014-06-06 17:09:04 -04001445 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04001446 {
Geoff Langb1196682014-07-23 13:47:29 -04001447 context->recordError(Error(GL_INVALID_VALUE));
1448 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04001449 }
1450
Jamie Madilld9ba4f72014-08-04 10:47:59 -04001451 const State &state = context->getState();
1452 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Jamie Madillfd716582014-06-06 17:09:04 -04001453 if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused() &&
1454 curTransformFeedback->getDrawMode() != mode)
1455 {
1456 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
1457 // that does not match the current transform feedback object's draw mode (if transform feedback
1458 // is active), (3.0.2, section 2.14, pg 86)
Geoff Langb1196682014-07-23 13:47:29 -04001459 context->recordError(Error(GL_INVALID_OPERATION));
1460 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04001461 }
1462
Geoff Langb1196682014-07-23 13:47:29 -04001463 if (!ValidateDrawBase(context, mode, count, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04001464 {
1465 return false;
1466 }
1467
1468 return true;
1469}
1470
Geoff Langb1196682014-07-23 13:47:29 -04001471bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04001472{
1473 if (primcount < 0)
1474 {
Geoff Langb1196682014-07-23 13:47:29 -04001475 context->recordError(Error(GL_INVALID_VALUE));
1476 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04001477 }
1478
Jamie Madill2b976812014-08-25 15:47:49 -04001479 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04001480 {
1481 return false;
1482 }
1483
1484 // No-op if zero primitive count
1485 return (primcount > 0);
1486}
1487
Geoff Lang87a93302014-09-16 13:29:43 -04001488static bool ValidateDrawInstancedANGLE(Context *context)
1489{
1490 // Verify there is at least one active attribute with a divisor of zero
1491 const gl::State& state = context->getState();
1492
Geoff Lang7dd2e102014-11-10 15:19:26 -05001493 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04001494
1495 const VertexArray *vao = state.getVertexArray();
1496 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
1497 {
1498 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Geoff Lang7dd2e102014-11-10 15:19:26 -05001499 bool active = (program->getSemanticIndex(attributeIndex) != -1);
Geoff Lang87a93302014-09-16 13:29:43 -04001500 if (active && attrib.divisor == 0)
1501 {
1502 return true;
1503 }
1504 }
1505
1506 context->recordError(Error(GL_INVALID_OPERATION, "ANGLE_instanced_arrays requires that at least one active attribute"
1507 "has a divisor of zero."));
1508 return false;
1509}
1510
1511bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
1512{
1513 if (!ValidateDrawInstancedANGLE(context))
1514 {
1515 return false;
1516 }
1517
1518 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
1519}
1520
Geoff Langb1196682014-07-23 13:47:29 -04001521bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum type,
Jamie Madill2b976812014-08-25 15:47:49 -04001522 const GLvoid* indices, GLsizei primcount, rx::RangeUI *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04001523{
Jamie Madill250d33f2014-06-06 17:09:03 -04001524 switch (type)
1525 {
1526 case GL_UNSIGNED_BYTE:
1527 case GL_UNSIGNED_SHORT:
1528 break;
1529 case GL_UNSIGNED_INT:
Geoff Langc0b9ef42014-07-02 10:02:37 -04001530 if (!context->getExtensions().elementIndexUint)
Jamie Madill250d33f2014-06-06 17:09:03 -04001531 {
Geoff Langb1196682014-07-23 13:47:29 -04001532 context->recordError(Error(GL_INVALID_ENUM));
1533 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04001534 }
1535 break;
1536 default:
Geoff Langb1196682014-07-23 13:47:29 -04001537 context->recordError(Error(GL_INVALID_ENUM));
1538 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04001539 }
1540
Jamie Madilld9ba4f72014-08-04 10:47:59 -04001541 const State &state = context->getState();
1542
1543 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Jamie Madill250d33f2014-06-06 17:09:03 -04001544 if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused())
1545 {
1546 // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
1547 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Geoff Langb1196682014-07-23 13:47:29 -04001548 context->recordError(Error(GL_INVALID_OPERATION));
1549 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04001550 }
1551
1552 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04001553 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04001554 {
Geoff Langb1196682014-07-23 13:47:29 -04001555 context->recordError(Error(GL_INVALID_OPERATION));
1556 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04001557 }
1558
Jamie Madill2b976812014-08-25 15:47:49 -04001559 const gl::VertexArray *vao = state.getVertexArray();
1560 const gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
1561 if (!indices && !elementArrayBuffer)
Jamie Madilld4cfa572014-07-08 10:00:32 -04001562 {
Geoff Langb1196682014-07-23 13:47:29 -04001563 context->recordError(Error(GL_INVALID_OPERATION));
1564 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04001565 }
1566
Jamie Madillae3000b2014-08-25 15:47:51 -04001567 if (elementArrayBuffer)
1568 {
1569 const gl::Type &typeInfo = gl::GetTypeInfo(type);
1570
1571 GLint64 offset = reinterpret_cast<GLint64>(indices);
1572 GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset;
1573
1574 // check for integer overflows
1575 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
1576 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
1577 {
Geoff Langb1196682014-07-23 13:47:29 -04001578 context->recordError(Error(GL_OUT_OF_MEMORY));
1579 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04001580 }
1581
1582 // Check for reading past the end of the bound buffer object
1583 if (byteCount > elementArrayBuffer->getSize())
1584 {
Geoff Langb1196682014-07-23 13:47:29 -04001585 context->recordError(Error(GL_INVALID_OPERATION));
1586 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04001587 }
1588 }
1589 else if (!indices)
1590 {
1591 // Catch this programming error here
Geoff Langb1196682014-07-23 13:47:29 -04001592 context->recordError(Error(GL_INVALID_OPERATION));
1593 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04001594 }
1595
Jamie Madill2b976812014-08-25 15:47:49 -04001596 // Use max index to validate if our vertex buffers are large enough for the pull.
1597 // TODO: offer fast path, with disabled index validation.
1598 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
1599 if (elementArrayBuffer)
1600 {
Jacek Cabana5521de2014-10-01 17:23:46 +02001601 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Jamie Madill2b976812014-08-25 15:47:49 -04001602 if (!elementArrayBuffer->getIndexRangeCache()->findRange(type, offset, count, indexRangeOut, NULL))
1603 {
Jamie Madill72468832015-01-05 15:03:18 -05001604 rx::BufferImpl *bufferImpl = elementArrayBuffer->getImplementation();
Geoff Langc8d297a2014-09-19 11:09:08 -04001605 const uint8_t *dataPointer = NULL;
Jamie Madill72468832015-01-05 15:03:18 -05001606 Error error = bufferImpl->getData(&dataPointer);
Geoff Langc8d297a2014-09-19 11:09:08 -04001607 if (error.isError())
1608 {
1609 context->recordError(error);
1610 return false;
1611 }
1612
1613 const uint8_t *offsetPointer = dataPointer + offset;
Jamie Madill2b976812014-08-25 15:47:49 -04001614 *indexRangeOut = rx::IndexRangeCache::ComputeRange(type, offsetPointer, count);
1615 }
1616 }
1617 else
1618 {
1619 *indexRangeOut = rx::IndexRangeCache::ComputeRange(type, indices, count);
1620 }
1621
Geoff Langb1196682014-07-23 13:47:29 -04001622 if (!ValidateDrawBase(context, mode, count, static_cast<GLsizei>(indexRangeOut->end), primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04001623 {
1624 return false;
1625 }
1626
1627 return true;
1628}
1629
Geoff Langb1196682014-07-23 13:47:29 -04001630bool ValidateDrawElementsInstanced(Context *context,
Jamie Madill2b976812014-08-25 15:47:49 -04001631 GLenum mode, GLsizei count, GLenum type,
1632 const GLvoid *indices, GLsizei primcount,
1633 rx::RangeUI *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04001634{
1635 if (primcount < 0)
1636 {
Geoff Langb1196682014-07-23 13:47:29 -04001637 context->recordError(Error(GL_INVALID_VALUE));
1638 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04001639 }
1640
Jamie Madill2b976812014-08-25 15:47:49 -04001641 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04001642 {
1643 return false;
1644 }
1645
1646 // No-op zero primitive count
1647 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04001648}
1649
Geoff Lang87a93302014-09-16 13:29:43 -04001650bool ValidateDrawElementsInstancedANGLE(Context *context, GLenum mode, GLsizei count, GLenum type,
1651 const GLvoid *indices, GLsizei primcount, rx::RangeUI *indexRangeOut)
1652{
1653 if (!ValidateDrawInstancedANGLE(context))
1654 {
1655 return false;
1656 }
1657
1658 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut);
1659}
1660
Geoff Langb1196682014-07-23 13:47:29 -04001661bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04001662 GLuint texture, GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04001663{
Jamie Madill55ec3b12014-07-03 10:38:57 -04001664 if (!ValidFramebufferTarget(target))
1665 {
Geoff Langb1196682014-07-23 13:47:29 -04001666 context->recordError(Error(GL_INVALID_ENUM));
1667 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001668 }
1669
1670 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04001671 {
1672 return false;
1673 }
1674
Jamie Madill55ec3b12014-07-03 10:38:57 -04001675 if (texture != 0)
1676 {
1677 gl::Texture *tex = context->getTexture(texture);
1678
1679 if (tex == NULL)
1680 {
Geoff Langb1196682014-07-23 13:47:29 -04001681 context->recordError(Error(GL_INVALID_OPERATION));
1682 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001683 }
1684
1685 if (level < 0)
1686 {
Geoff Langb1196682014-07-23 13:47:29 -04001687 context->recordError(Error(GL_INVALID_VALUE));
1688 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001689 }
1690 }
1691
Shannon Woods53a94a82014-06-24 15:20:36 -04001692 const gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
1693 GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id();
Jamie Madill55ec3b12014-07-03 10:38:57 -04001694
1695 if (framebufferHandle == 0 || !framebuffer)
1696 {
Geoff Langb1196682014-07-23 13:47:29 -04001697 context->recordError(Error(GL_INVALID_OPERATION));
1698 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001699 }
1700
1701 return true;
1702}
1703
Geoff Langb1196682014-07-23 13:47:29 -04001704bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04001705 GLenum textarget, GLuint texture, GLint level)
1706{
1707 // Attachments are required to be bound to level 0 in ES2
1708 if (context->getClientVersion() < 3 && level != 0)
1709 {
Geoff Langb1196682014-07-23 13:47:29 -04001710 context->recordError(Error(GL_INVALID_VALUE));
1711 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001712 }
1713
1714 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04001715 {
1716 return false;
1717 }
1718
Jamie Madill55ec3b12014-07-03 10:38:57 -04001719 if (texture != 0)
1720 {
1721 gl::Texture *tex = context->getTexture(texture);
1722 ASSERT(tex);
1723
Jamie Madill2a6564e2014-07-11 09:53:19 -04001724 const gl::Caps &caps = context->getCaps();
1725
Jamie Madill55ec3b12014-07-03 10:38:57 -04001726 switch (textarget)
1727 {
1728 case GL_TEXTURE_2D:
1729 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04001730 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04001731 {
Geoff Langb1196682014-07-23 13:47:29 -04001732 context->recordError(Error(GL_INVALID_VALUE));
1733 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001734 }
1735 if (tex->getTarget() != GL_TEXTURE_2D)
1736 {
Geoff Langb1196682014-07-23 13:47:29 -04001737 context->recordError(Error(GL_INVALID_OPERATION));
1738 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001739 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001740 }
1741 break;
1742
1743 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1744 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1745 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1746 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1747 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1748 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1749 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04001750 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04001751 {
Geoff Langb1196682014-07-23 13:47:29 -04001752 context->recordError(Error(GL_INVALID_VALUE));
1753 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001754 }
1755 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
1756 {
Geoff Langb1196682014-07-23 13:47:29 -04001757 context->recordError(Error(GL_INVALID_OPERATION));
1758 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001759 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001760 }
1761 break;
1762
1763 default:
Geoff Langb1196682014-07-23 13:47:29 -04001764 context->recordError(Error(GL_INVALID_ENUM));
1765 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001766 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001767
1768 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(textarget, level));
1769 if (internalFormatInfo.compressed)
1770 {
1771 context->recordError(Error(GL_INVALID_OPERATION));
1772 return false;
1773 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001774 }
1775
Jamie Madill570f7c82014-07-03 10:38:54 -04001776 return true;
1777}
1778
Geoff Langb1196682014-07-23 13:47:29 -04001779bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04001780{
1781 if (program == 0)
1782 {
Geoff Langb1196682014-07-23 13:47:29 -04001783 context->recordError(Error(GL_INVALID_VALUE));
1784 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001785 }
1786
Shannon Woods4de4fd62014-11-07 16:22:02 -05001787 if (!ValidProgram(context, program))
1788 {
1789 return false;
1790 }
1791
Jamie Madill0063c512014-08-25 15:47:53 -04001792 gl::Program *programObject = context->getProgram(program);
1793
1794 if (!programObject || !programObject->isLinked())
1795 {
Geoff Langb1196682014-07-23 13:47:29 -04001796 context->recordError(Error(GL_INVALID_OPERATION));
1797 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001798 }
1799
Geoff Lang7dd2e102014-11-10 15:19:26 -05001800 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04001801 {
Geoff Langb1196682014-07-23 13:47:29 -04001802 context->recordError(Error(GL_INVALID_OPERATION));
1803 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04001804 }
1805
Jamie Madill0063c512014-08-25 15:47:53 -04001806 return true;
1807}
1808
Geoff Langb1196682014-07-23 13:47:29 -04001809bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params)
Jamie Madill78f41802014-08-25 15:47:55 -04001810{
1811 return ValidateGetUniformBase(context, program, location);
1812}
1813
Geoff Langb1196682014-07-23 13:47:29 -04001814bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001815{
Jamie Madill78f41802014-08-25 15:47:55 -04001816 return ValidateGetUniformBase(context, program, location);
1817}
1818
Geoff Langb1196682014-07-23 13:47:29 -04001819static bool ValidateSizedGetUniform(Context *context, GLuint program, GLint location, GLsizei bufSize)
Jamie Madill78f41802014-08-25 15:47:55 -04001820{
1821 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04001822 {
Jamie Madill78f41802014-08-25 15:47:55 -04001823 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001824 }
1825
Jamie Madilla502c742014-08-28 17:19:13 -04001826 gl::Program *programObject = context->getProgram(program);
1827 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04001828
Jamie Madill78f41802014-08-25 15:47:55 -04001829 // sized queries -- ensure the provided buffer is large enough
Geoff Lang7dd2e102014-11-10 15:19:26 -05001830 LinkedUniform *uniform = programObject->getUniformByLocation(location);
Jamie Madill78f41802014-08-25 15:47:55 -04001831 size_t requiredBytes = VariableExternalSize(uniform->type);
1832 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04001833 {
Geoff Langb1196682014-07-23 13:47:29 -04001834 context->recordError(Error(GL_INVALID_OPERATION));
1835 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001836 }
1837
1838 return true;
1839}
1840
Geoff Langb1196682014-07-23 13:47:29 -04001841bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001842{
Jamie Madill78f41802014-08-25 15:47:55 -04001843 return ValidateSizedGetUniform(context, program, location, bufSize);
Jamie Madill0063c512014-08-25 15:47:53 -04001844}
1845
Geoff Langb1196682014-07-23 13:47:29 -04001846bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04001847{
Jamie Madill78f41802014-08-25 15:47:55 -04001848 return ValidateSizedGetUniform(context, program, location, bufSize);
Jamie Madill0063c512014-08-25 15:47:53 -04001849}
1850
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001851}