blob: 840758c91783bdb498a979a41eae970c3c2fccbd [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001#include "precompiled.h"
2//
3// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style license that can be
5// found in the LICENSE file.
6//
7
8// validationES.h: Validation functions for generic OpenGL ES entry point parameters
9
10#include "libGLESv2/validationES.h"
11#include "libGLESv2/Context.h"
12#include "libGLESv2/Texture.h"
13#include "libGLESv2/Framebuffer.h"
14#include "libGLESv2/Renderbuffer.h"
15#include "libGLESv2/formatutils.h"
16#include "libGLESv2/main.h"
17
18#include "common/mathutil.h"
19#include "common/utilities.h"
20
21namespace gl
22{
23
Geoff Lang0550d032014-01-30 11:29:07 -050024bool ValidCap(const Context *context, GLenum cap)
25{
26 switch (cap)
27 {
28 case GL_CULL_FACE:
29 case GL_POLYGON_OFFSET_FILL:
30 case GL_SAMPLE_ALPHA_TO_COVERAGE:
31 case GL_SAMPLE_COVERAGE:
32 case GL_SCISSOR_TEST:
33 case GL_STENCIL_TEST:
34 case GL_DEPTH_TEST:
35 case GL_BLEND:
36 case GL_DITHER:
37 return true;
38 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
39 case GL_RASTERIZER_DISCARD:
40 return (context->getClientVersion() >= 3);
41 default:
42 return false;
43 }
44}
45
Jamie Madill1fc7e2c2014-01-21 16:47:10 -050046bool ValidTextureTarget(const Context *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -040047{
Jamie Madilld7460c72014-01-21 16:38:14 -050048 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -040049 {
Jamie Madilld7460c72014-01-21 16:38:14 -050050 case GL_TEXTURE_2D:
51 case GL_TEXTURE_CUBE_MAP:
52 return true;
Jamie Madill35d15012013-10-07 10:46:37 -040053
Jamie Madilld7460c72014-01-21 16:38:14 -050054 case GL_TEXTURE_3D:
55 case GL_TEXTURE_2D_ARRAY:
56 return (context->getClientVersion() >= 3);
57
58 default:
59 return false;
60 }
Jamie Madill35d15012013-10-07 10:46:37 -040061}
62
Jamie Madill1fc7e2c2014-01-21 16:47:10 -050063bool ValidFramebufferTarget(GLenum target)
64{
65 META_ASSERT(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER);
66
67 switch (target)
68 {
69 case GL_FRAMEBUFFER: return true;
70 case GL_READ_FRAMEBUFFER: return true;
71 case GL_DRAW_FRAMEBUFFER: return true;
72 default: return false;
73 }
74}
75
Geoff Langce635692013-09-24 13:56:32 -040076bool ValidMipLevel(const gl::Context *context, GLenum target, GLint level)
77{
78 int maxLevel = 0;
79 switch (target)
80 {
81 case GL_TEXTURE_2D: maxLevel = context->getMaximum2DTextureLevel(); break;
82 case GL_TEXTURE_CUBE_MAP:
83 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
84 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
85 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
86 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
87 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
88 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: maxLevel = context->getMaximumCubeTextureLevel(); break;
89 case GL_TEXTURE_3D: maxLevel = context->getMaximum3DTextureLevel(); break;
90 case GL_TEXTURE_2D_ARRAY: maxLevel = context->getMaximum2DArrayTextureLevel(); break;
91 default: UNREACHABLE();
92 }
93
94 return level < maxLevel;
95}
96
97bool ValidImageSize(const gl::Context *context, GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth)
98{
99 if (level < 0 || width < 0 || height < 0 || depth < 0)
100 {
101 return false;
102 }
103
104 if (!context->supportsNonPower2Texture() && (level != 0 || !gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth)))
105 {
106 return false;
107 }
108
109 if (!ValidMipLevel(context, target, level))
110 {
111 return false;
112 }
113
114 return true;
115}
116
Geoff Lang005df412013-10-16 14:12:50 -0400117bool ValidCompressedImageSize(const gl::Context *context, GLenum internalFormat, GLsizei width, GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400118{
119 GLuint clientVersion = context->getClientVersion();
120 if (!IsFormatCompressed(internalFormat, clientVersion))
121 {
122 return false;
123 }
124
125 GLint blockWidth = GetCompressedBlockWidth(internalFormat, clientVersion);
126 GLint blockHeight = GetCompressedBlockHeight(internalFormat, clientVersion);
127 if (width < 0 || (width > blockWidth && width % blockWidth != 0) ||
128 height < 0 || (height > blockHeight && height % blockHeight != 0))
129 {
130 return false;
131 }
132
133 return true;
134}
135
Geoff Lang37dde692014-01-31 16:34:54 -0500136bool ValidQueryType(const Context *context, GLenum queryType)
137{
138 META_ASSERT(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT);
139 META_ASSERT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT);
140
141 switch (queryType)
142 {
143 case GL_ANY_SAMPLES_PASSED:
144 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
145 return true;
146 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
147 return (context->getClientVersion() >= 3);
148 default:
149 return false;
150 }
151}
152
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400153bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum target, GLsizei samples,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400154 GLenum internalformat, GLsizei width, GLsizei height,
155 bool angleExtension)
156{
157 switch (target)
158 {
159 case GL_RENDERBUFFER:
160 break;
161 default:
162 return gl::error(GL_INVALID_ENUM, false);
163 }
164
165 if (width < 0 || height < 0 || samples < 0)
166 {
167 return gl::error(GL_INVALID_VALUE, false);
168 }
169
170 if (!gl::IsValidInternalFormat(internalformat, context))
171 {
172 return gl::error(GL_INVALID_ENUM, false);
173 }
174
175 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
176 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
177 // only sized internal formats. The ES3 spec (section 4.4.2) does, however, state that the
178 // internal format must be sized and not an integer format if samples is greater than zero.
179 if (!gl::IsSizedInternalFormat(internalformat, context->getClientVersion()))
180 {
181 return gl::error(GL_INVALID_ENUM, false);
182 }
183
Geoff Langb2f3d052013-08-13 12:49:27 -0400184 GLenum componentType = gl::GetComponentType(internalformat, context->getClientVersion());
185 if ((componentType == GL_UNSIGNED_INT || componentType == GL_INT) && samples > 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400186 {
187 return gl::error(GL_INVALID_OPERATION, false);
188 }
189
190 if (!gl::IsColorRenderingSupported(internalformat, context) &&
191 !gl::IsDepthRenderingSupported(internalformat, context) &&
192 !gl::IsStencilRenderingSupported(internalformat, context))
193 {
194 return gl::error(GL_INVALID_ENUM, false);
195 }
196
197 if (std::max(width, height) > context->getMaximumRenderbufferDimension())
198 {
199 return gl::error(GL_INVALID_VALUE, false);
200 }
201
202 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
203 // to MAX_SAMPLES_ANGLE (Context::getMaxSupportedSamples) while the ES3.0 spec (section 4.4.2)
204 // states that samples must be less than or equal to the maximum samples for the specified
205 // internal format.
206 if (angleExtension)
207 {
208 if (samples > context->getMaxSupportedSamples())
209 {
210 return gl::error(GL_INVALID_VALUE, false);
211 }
212 }
213 else
214 {
215 if (samples > context->getMaxSupportedFormatSamples(internalformat))
216 {
217 return gl::error(GL_INVALID_VALUE, false);
218 }
219 }
220
221 GLuint handle = context->getRenderbufferHandle();
222 if (handle == 0)
223 {
224 return gl::error(GL_INVALID_OPERATION, false);
225 }
226
227 return true;
228}
229
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500230bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
231 GLenum renderbuffertarget, GLuint renderbuffer)
232{
233 gl::Framebuffer *framebuffer = context->getTargetFramebuffer(target);
234 GLuint framebufferHandle = context->getTargetFramebufferHandle(target);
235
236 if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0))
237 {
238 return gl::error(GL_INVALID_OPERATION, false);
239 }
240
241 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
242 {
243 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
244
245 if (colorAttachment >= context->getMaximumRenderTargets())
246 {
247 return gl::error(GL_INVALID_VALUE, false);
248 }
249 }
250 else
251 {
252 switch (attachment)
253 {
254 case GL_DEPTH_ATTACHMENT:
255 break;
256 case GL_STENCIL_ATTACHMENT:
257 break;
258 case GL_DEPTH_STENCIL_ATTACHMENT:
259 if (context->getClientVersion() < 3)
260 {
261 return gl::error(GL_INVALID_ENUM, false);
262 }
263 break;
264 default:
265 return gl::error(GL_INVALID_ENUM, false);
266 }
267 }
268
Jamie Madillab9d82c2014-01-21 16:38:14 -0500269 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
270 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
271 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
272 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
273 if (renderbuffer != 0)
274 {
275 if (!context->getRenderbuffer(renderbuffer))
276 {
277 return gl::error(GL_INVALID_OPERATION, false);
278 }
279 }
280
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500281 return true;
282}
283
Geoff Lang125deab2013-08-09 13:34:16 -0400284static bool IsPartialBlit(gl::Context *context, gl::Renderbuffer *readBuffer, gl::Renderbuffer *writeBuffer,
285 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
286 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
287{
288 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 ||
289 dstX1 != writeBuffer->getWidth() || dstY1 != writeBuffer->getHeight() ||
290 srcX1 != readBuffer->getWidth() || srcY1 != readBuffer->getHeight())
291 {
292 return true;
293 }
294 else if (context->isScissorTestEnabled())
295 {
296 int scissorX, scissorY, scissorWidth, scissorHeight;
297 context->getScissorParams(&scissorX, &scissorY, &scissorWidth, &scissorHeight);
298
299 return scissorX > 0 || scissorY > 0 ||
300 scissorWidth < writeBuffer->getWidth() ||
301 scissorHeight < writeBuffer->getHeight();
302 }
303 else
304 {
305 return false;
306 }
307}
308
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400309bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400310 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask,
311 GLenum filter, bool fromAngleExtension)
312{
313 switch (filter)
314 {
315 case GL_NEAREST:
316 break;
317 case GL_LINEAR:
318 if (fromAngleExtension)
319 {
320 return gl::error(GL_INVALID_ENUM, false);
321 }
322 break;
323 default:
324 return gl::error(GL_INVALID_ENUM, false);
325 }
326
327 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
328 {
329 return gl::error(GL_INVALID_VALUE, false);
330 }
331
332 if (mask == 0)
333 {
334 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
335 // buffers are copied.
336 return false;
337 }
338
339 if (fromAngleExtension && (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0))
340 {
341 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation.");
342 return gl::error(GL_INVALID_OPERATION, false);
343 }
344
345 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
346 // color buffer, leaving only nearest being unfiltered from above
347 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
348 {
349 return gl::error(GL_INVALID_OPERATION, false);
350 }
351
352 if (context->getReadFramebufferHandle() == context->getDrawFramebufferHandle())
353 {
354 if (fromAngleExtension)
355 {
356 ERR("Blits with the same source and destination framebuffer are not supported by this "
357 "implementation.");
358 }
359 return gl::error(GL_INVALID_OPERATION, false);
360 }
361
362 gl::Framebuffer *readFramebuffer = context->getReadFramebuffer();
363 gl::Framebuffer *drawFramebuffer = context->getDrawFramebuffer();
364 if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE ||
365 !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
366 {
367 return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
368 }
369
370 if (drawFramebuffer->getSamples() != 0)
371 {
372 return gl::error(GL_INVALID_OPERATION, false);
373 }
374
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400375 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
376
377 GLuint clientVersion = context->getClientVersion();
378
379 if (mask & GL_COLOR_BUFFER_BIT)
380 {
381 gl::Renderbuffer *readColorBuffer = readFramebuffer->getReadColorbuffer();
382 gl::Renderbuffer *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
383
384 if (readColorBuffer && drawColorBuffer)
385 {
Geoff Lang005df412013-10-16 14:12:50 -0400386 GLenum readInternalFormat = readColorBuffer->getActualFormat();
Geoff Langb2f3d052013-08-13 12:49:27 -0400387 GLenum readComponentType = gl::GetComponentType(readInternalFormat, clientVersion);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400388
389 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; i++)
390 {
391 if (drawFramebuffer->isEnabledColorAttachment(i))
392 {
Geoff Lang005df412013-10-16 14:12:50 -0400393 GLenum drawInternalFormat = drawFramebuffer->getColorbuffer(i)->getActualFormat();
Geoff Langb2f3d052013-08-13 12:49:27 -0400394 GLenum drawComponentType = gl::GetComponentType(drawInternalFormat, clientVersion);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400395
Geoff Langb2f3d052013-08-13 12:49:27 -0400396 // The GL ES 3.0.2 spec (pg 193) states that:
397 // 1) If the read buffer is fixed point format, the draw buffer must be as well
398 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
399 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
400 if ( (readComponentType == GL_UNSIGNED_NORMALIZED || readComponentType == GL_SIGNED_NORMALIZED) &&
401 !(drawComponentType == GL_UNSIGNED_NORMALIZED || drawComponentType == GL_SIGNED_NORMALIZED))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400402 {
403 return gl::error(GL_INVALID_OPERATION, false);
404 }
405
Geoff Langb2f3d052013-08-13 12:49:27 -0400406 if (readComponentType == GL_UNSIGNED_INT && drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400407 {
408 return gl::error(GL_INVALID_OPERATION, false);
409 }
410
Geoff Langb2f3d052013-08-13 12:49:27 -0400411 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400412 {
413 return gl::error(GL_INVALID_OPERATION, false);
414 }
415
Geoff Langb2f3d052013-08-13 12:49:27 -0400416 if (readColorBuffer->getSamples() > 0 && (readInternalFormat != drawInternalFormat || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400417 {
418 return gl::error(GL_INVALID_OPERATION, false);
419 }
420 }
421 }
422
Geoff Langb2f3d052013-08-13 12:49:27 -0400423 if ((readComponentType == GL_INT || readComponentType == GL_UNSIGNED_INT) && filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400424 {
425 return gl::error(GL_INVALID_OPERATION, false);
426 }
427
428 if (fromAngleExtension)
429 {
430 const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType();
431 if (readColorbufferType != GL_TEXTURE_2D && readColorbufferType != GL_RENDERBUFFER)
432 {
433 return gl::error(GL_INVALID_OPERATION, false);
434 }
435
436 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
437 {
438 if (drawFramebuffer->isEnabledColorAttachment(colorAttachment))
439 {
440 if (drawFramebuffer->getColorbufferType(colorAttachment) != GL_TEXTURE_2D &&
441 drawFramebuffer->getColorbufferType(colorAttachment) != GL_RENDERBUFFER)
442 {
443 return gl::error(GL_INVALID_OPERATION, false);
444 }
445
446 if (drawFramebuffer->getColorbuffer(colorAttachment)->getActualFormat() != readColorBuffer->getActualFormat())
447 {
448 return gl::error(GL_INVALID_OPERATION, false);
449 }
450 }
451 }
Geoff Lang125deab2013-08-09 13:34:16 -0400452 if (readFramebuffer->getSamples() != 0 && IsPartialBlit(context, readColorBuffer, drawColorBuffer,
453 srcX0, srcY0, srcX1, srcY1,
454 dstX0, dstY0, dstX1, dstY1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400455 {
456 return gl::error(GL_INVALID_OPERATION, false);
457 }
458 }
459 }
460 }
461
462 if (mask & GL_DEPTH_BUFFER_BIT)
463 {
464 gl::Renderbuffer *readDepthBuffer = readFramebuffer->getDepthbuffer();
465 gl::Renderbuffer *drawDepthBuffer = drawFramebuffer->getDepthbuffer();
466
467 if (readDepthBuffer && drawDepthBuffer)
468 {
469 if (readDepthBuffer->getActualFormat() != drawDepthBuffer->getActualFormat())
470 {
471 return gl::error(GL_INVALID_OPERATION, false);
472 }
473
474 if (readDepthBuffer->getSamples() > 0 && !sameBounds)
475 {
476 return gl::error(GL_INVALID_OPERATION, false);
477 }
478
479 if (fromAngleExtension)
480 {
Geoff Lang125deab2013-08-09 13:34:16 -0400481 if (IsPartialBlit(context, readDepthBuffer, drawDepthBuffer,
482 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400483 {
484 ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
485 return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted
486 }
487
488 if (readDepthBuffer->getSamples() != 0 || drawDepthBuffer->getSamples() != 0)
489 {
490 return gl::error(GL_INVALID_OPERATION, false);
491 }
492 }
493 }
494 }
495
496 if (mask & GL_STENCIL_BUFFER_BIT)
497 {
498 gl::Renderbuffer *readStencilBuffer = readFramebuffer->getStencilbuffer();
499 gl::Renderbuffer *drawStencilBuffer = drawFramebuffer->getStencilbuffer();
500
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400501 if (readStencilBuffer && drawStencilBuffer)
502 {
503 if (readStencilBuffer->getActualFormat() != drawStencilBuffer->getActualFormat())
504 {
505 return gl::error(GL_INVALID_OPERATION, false);
506 }
507
508 if (readStencilBuffer->getSamples() > 0 && !sameBounds)
509 {
510 return gl::error(GL_INVALID_OPERATION, false);
511 }
512
513 if (fromAngleExtension)
514 {
Geoff Lang125deab2013-08-09 13:34:16 -0400515 if (IsPartialBlit(context, readStencilBuffer, drawStencilBuffer,
516 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400517 {
518 ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
519 return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted
520 }
521
522 if (readStencilBuffer->getSamples() != 0 || drawStencilBuffer->getSamples() != 0)
523 {
524 return gl::error(GL_INVALID_OPERATION, false);
525 }
526 }
527 }
528 }
529
530 return true;
531}
532
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400533bool ValidateGetVertexAttribParameters(GLenum pname, int clientVersion)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400534{
535 switch (pname)
536 {
537 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
538 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
539 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
540 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
541 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
542 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
543 case GL_CURRENT_VERTEX_ATTRIB:
544 return true;
545
546 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
547 // Don't verify ES3 context because GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE uses
548 // the same constant.
549 META_ASSERT(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE);
550 return true;
551
552 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
553 return ((clientVersion >= 3) ? true : gl::error(GL_INVALID_ENUM, false));
554
555 default:
556 return gl::error(GL_INVALID_ENUM, false);
557 }
558}
559
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400560bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400561{
562 switch (pname)
563 {
564 case GL_TEXTURE_WRAP_R:
565 case GL_TEXTURE_SWIZZLE_R:
566 case GL_TEXTURE_SWIZZLE_G:
567 case GL_TEXTURE_SWIZZLE_B:
568 case GL_TEXTURE_SWIZZLE_A:
569 case GL_TEXTURE_BASE_LEVEL:
570 case GL_TEXTURE_MAX_LEVEL:
571 case GL_TEXTURE_COMPARE_MODE:
572 case GL_TEXTURE_COMPARE_FUNC:
573 case GL_TEXTURE_MIN_LOD:
574 case GL_TEXTURE_MAX_LOD:
575 if (context->getClientVersion() < 3)
576 {
577 return gl::error(GL_INVALID_ENUM, false);
578 }
579 break;
580
581 default: break;
582 }
583
584 switch (pname)
585 {
586 case GL_TEXTURE_WRAP_S:
587 case GL_TEXTURE_WRAP_T:
588 case GL_TEXTURE_WRAP_R:
589 switch (param)
590 {
591 case GL_REPEAT:
592 case GL_CLAMP_TO_EDGE:
593 case GL_MIRRORED_REPEAT:
594 return true;
595 default:
596 return gl::error(GL_INVALID_ENUM, false);
597 }
598
599 case GL_TEXTURE_MIN_FILTER:
600 switch (param)
601 {
602 case GL_NEAREST:
603 case GL_LINEAR:
604 case GL_NEAREST_MIPMAP_NEAREST:
605 case GL_LINEAR_MIPMAP_NEAREST:
606 case GL_NEAREST_MIPMAP_LINEAR:
607 case GL_LINEAR_MIPMAP_LINEAR:
608 return true;
609 default:
610 return gl::error(GL_INVALID_ENUM, false);
611 }
612 break;
613
614 case GL_TEXTURE_MAG_FILTER:
615 switch (param)
616 {
617 case GL_NEAREST:
618 case GL_LINEAR:
619 return true;
620 default:
621 return gl::error(GL_INVALID_ENUM, false);
622 }
623 break;
624
625 case GL_TEXTURE_USAGE_ANGLE:
626 switch (param)
627 {
628 case GL_NONE:
629 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
630 return true;
631 default:
632 return gl::error(GL_INVALID_ENUM, false);
633 }
634 break;
635
636 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
637 if (!context->supportsTextureFilterAnisotropy())
638 {
639 return gl::error(GL_INVALID_ENUM, false);
640 }
641
642 // we assume the parameter passed to this validation method is truncated, not rounded
643 if (param < 1)
644 {
645 return gl::error(GL_INVALID_VALUE, false);
646 }
647 return true;
648
649 case GL_TEXTURE_MIN_LOD:
650 case GL_TEXTURE_MAX_LOD:
651 // any value is permissible
652 return true;
653
654 case GL_TEXTURE_COMPARE_MODE:
Geoff Lang63b5f1f2013-09-23 14:52:14 -0400655 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400656 switch (param)
657 {
658 case GL_NONE:
659 case GL_COMPARE_REF_TO_TEXTURE:
660 return true;
661 default:
662 return gl::error(GL_INVALID_ENUM, false);
663 }
664 break;
665
666 case GL_TEXTURE_COMPARE_FUNC:
Geoff Lang63b5f1f2013-09-23 14:52:14 -0400667 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400668 switch (param)
669 {
670 case GL_LEQUAL:
671 case GL_GEQUAL:
672 case GL_LESS:
673 case GL_GREATER:
674 case GL_EQUAL:
675 case GL_NOTEQUAL:
676 case GL_ALWAYS:
677 case GL_NEVER:
678 return true;
679 default:
680 return gl::error(GL_INVALID_ENUM, false);
681 }
682 break;
683
684 case GL_TEXTURE_SWIZZLE_R:
685 case GL_TEXTURE_SWIZZLE_G:
686 case GL_TEXTURE_SWIZZLE_B:
687 case GL_TEXTURE_SWIZZLE_A:
Geoff Langbc90a482013-09-17 16:51:27 -0400688 switch (param)
689 {
690 case GL_RED:
691 case GL_GREEN:
692 case GL_BLUE:
693 case GL_ALPHA:
694 case GL_ZERO:
695 case GL_ONE:
696 return true;
697 default:
698 return gl::error(GL_INVALID_ENUM, false);
699 }
700 break;
701
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400702 case GL_TEXTURE_BASE_LEVEL:
703 case GL_TEXTURE_MAX_LEVEL:
704 UNIMPLEMENTED();
705 return true;
706
707 default:
708 return gl::error(GL_INVALID_ENUM, false);
709 }
710}
711
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400712bool ValidateSamplerObjectParameter(GLenum pname)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400713{
714 switch (pname)
715 {
716 case GL_TEXTURE_MIN_FILTER:
717 case GL_TEXTURE_MAG_FILTER:
718 case GL_TEXTURE_WRAP_S:
719 case GL_TEXTURE_WRAP_T:
720 case GL_TEXTURE_WRAP_R:
721 case GL_TEXTURE_MIN_LOD:
722 case GL_TEXTURE_MAX_LOD:
723 case GL_TEXTURE_COMPARE_MODE:
724 case GL_TEXTURE_COMPARE_FUNC:
725 return true;
726
727 default:
728 return gl::error(GL_INVALID_ENUM, false);
729 }
730}
731
732}