blob: b2883f2131a44416c38ee36234f7152512af4753 [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
Jamie Madill8c96d582014-03-05 15:01:23 -050076bool ValidBufferTarget(const Context *context, GLenum target)
77{
78 switch (target)
79 {
80 case GL_ARRAY_BUFFER:
81 case GL_ELEMENT_ARRAY_BUFFER:
82 return true;
83
84 case GL_COPY_READ_BUFFER:
85 case GL_COPY_WRITE_BUFFER:
86 case GL_PIXEL_PACK_BUFFER:
87 case GL_PIXEL_UNPACK_BUFFER:
88 case GL_TRANSFORM_FEEDBACK_BUFFER:
89 case GL_UNIFORM_BUFFER:
90 return (context->getClientVersion() >= 3);
91
92 default:
93 return false;
94 }
95}
96
97bool ValidMipLevel(const Context *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -040098{
99 int maxLevel = 0;
100 switch (target)
101 {
102 case GL_TEXTURE_2D: maxLevel = context->getMaximum2DTextureLevel(); break;
103 case GL_TEXTURE_CUBE_MAP:
104 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
105 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
106 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
107 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
108 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
109 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: maxLevel = context->getMaximumCubeTextureLevel(); break;
110 case GL_TEXTURE_3D: maxLevel = context->getMaximum3DTextureLevel(); break;
111 case GL_TEXTURE_2D_ARRAY: maxLevel = context->getMaximum2DArrayTextureLevel(); break;
112 default: UNREACHABLE();
113 }
114
115 return level < maxLevel;
116}
117
118bool ValidImageSize(const gl::Context *context, GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth)
119{
120 if (level < 0 || width < 0 || height < 0 || depth < 0)
121 {
122 return false;
123 }
124
125 if (!context->supportsNonPower2Texture() && (level != 0 || !gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth)))
126 {
127 return false;
128 }
129
130 if (!ValidMipLevel(context, target, level))
131 {
132 return false;
133 }
134
135 return true;
136}
137
Geoff Lang005df412013-10-16 14:12:50 -0400138bool ValidCompressedImageSize(const gl::Context *context, GLenum internalFormat, GLsizei width, GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400139{
140 GLuint clientVersion = context->getClientVersion();
141 if (!IsFormatCompressed(internalFormat, clientVersion))
142 {
143 return false;
144 }
145
146 GLint blockWidth = GetCompressedBlockWidth(internalFormat, clientVersion);
147 GLint blockHeight = GetCompressedBlockHeight(internalFormat, clientVersion);
148 if (width < 0 || (width > blockWidth && width % blockWidth != 0) ||
149 height < 0 || (height > blockHeight && height % blockHeight != 0))
150 {
151 return false;
152 }
153
154 return true;
155}
156
Geoff Lang37dde692014-01-31 16:34:54 -0500157bool ValidQueryType(const Context *context, GLenum queryType)
158{
159 META_ASSERT(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT);
160 META_ASSERT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT);
161
162 switch (queryType)
163 {
164 case GL_ANY_SAMPLES_PASSED:
165 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
166 return true;
167 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
168 return (context->getClientVersion() >= 3);
169 default:
170 return false;
171 }
172}
173
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400174bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum target, GLsizei samples,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400175 GLenum internalformat, GLsizei width, GLsizei height,
176 bool angleExtension)
177{
178 switch (target)
179 {
180 case GL_RENDERBUFFER:
181 break;
182 default:
183 return gl::error(GL_INVALID_ENUM, false);
184 }
185
186 if (width < 0 || height < 0 || samples < 0)
187 {
188 return gl::error(GL_INVALID_VALUE, false);
189 }
190
191 if (!gl::IsValidInternalFormat(internalformat, context))
192 {
193 return gl::error(GL_INVALID_ENUM, false);
194 }
195
196 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
197 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
198 // only sized internal formats. The ES3 spec (section 4.4.2) does, however, state that the
199 // internal format must be sized and not an integer format if samples is greater than zero.
200 if (!gl::IsSizedInternalFormat(internalformat, context->getClientVersion()))
201 {
202 return gl::error(GL_INVALID_ENUM, false);
203 }
204
Geoff Langb2f3d052013-08-13 12:49:27 -0400205 GLenum componentType = gl::GetComponentType(internalformat, context->getClientVersion());
206 if ((componentType == GL_UNSIGNED_INT || componentType == GL_INT) && samples > 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400207 {
208 return gl::error(GL_INVALID_OPERATION, false);
209 }
210
211 if (!gl::IsColorRenderingSupported(internalformat, context) &&
212 !gl::IsDepthRenderingSupported(internalformat, context) &&
213 !gl::IsStencilRenderingSupported(internalformat, context))
214 {
215 return gl::error(GL_INVALID_ENUM, false);
216 }
217
218 if (std::max(width, height) > context->getMaximumRenderbufferDimension())
219 {
220 return gl::error(GL_INVALID_VALUE, false);
221 }
222
223 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
224 // to MAX_SAMPLES_ANGLE (Context::getMaxSupportedSamples) while the ES3.0 spec (section 4.4.2)
225 // states that samples must be less than or equal to the maximum samples for the specified
226 // internal format.
227 if (angleExtension)
228 {
229 if (samples > context->getMaxSupportedSamples())
230 {
231 return gl::error(GL_INVALID_VALUE, false);
232 }
233 }
234 else
235 {
236 if (samples > context->getMaxSupportedFormatSamples(internalformat))
237 {
238 return gl::error(GL_INVALID_VALUE, false);
239 }
240 }
241
242 GLuint handle = context->getRenderbufferHandle();
243 if (handle == 0)
244 {
245 return gl::error(GL_INVALID_OPERATION, false);
246 }
247
248 return true;
249}
250
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500251bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
252 GLenum renderbuffertarget, GLuint renderbuffer)
253{
254 gl::Framebuffer *framebuffer = context->getTargetFramebuffer(target);
255 GLuint framebufferHandle = context->getTargetFramebufferHandle(target);
256
257 if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0))
258 {
259 return gl::error(GL_INVALID_OPERATION, false);
260 }
261
262 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
263 {
264 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
265
266 if (colorAttachment >= context->getMaximumRenderTargets())
267 {
268 return gl::error(GL_INVALID_VALUE, false);
269 }
270 }
271 else
272 {
273 switch (attachment)
274 {
275 case GL_DEPTH_ATTACHMENT:
276 break;
277 case GL_STENCIL_ATTACHMENT:
278 break;
279 case GL_DEPTH_STENCIL_ATTACHMENT:
280 if (context->getClientVersion() < 3)
281 {
282 return gl::error(GL_INVALID_ENUM, false);
283 }
284 break;
285 default:
286 return gl::error(GL_INVALID_ENUM, false);
287 }
288 }
289
Jamie Madillab9d82c2014-01-21 16:38:14 -0500290 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
291 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
292 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
293 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
294 if (renderbuffer != 0)
295 {
296 if (!context->getRenderbuffer(renderbuffer))
297 {
298 return gl::error(GL_INVALID_OPERATION, false);
299 }
300 }
301
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500302 return true;
303}
304
Geoff Lang125deab2013-08-09 13:34:16 -0400305static bool IsPartialBlit(gl::Context *context, gl::Renderbuffer *readBuffer, gl::Renderbuffer *writeBuffer,
306 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
307 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
308{
309 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 ||
310 dstX1 != writeBuffer->getWidth() || dstY1 != writeBuffer->getHeight() ||
311 srcX1 != readBuffer->getWidth() || srcY1 != readBuffer->getHeight())
312 {
313 return true;
314 }
315 else if (context->isScissorTestEnabled())
316 {
317 int scissorX, scissorY, scissorWidth, scissorHeight;
318 context->getScissorParams(&scissorX, &scissorY, &scissorWidth, &scissorHeight);
319
320 return scissorX > 0 || scissorY > 0 ||
321 scissorWidth < writeBuffer->getWidth() ||
322 scissorHeight < writeBuffer->getHeight();
323 }
324 else
325 {
326 return false;
327 }
328}
329
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400330bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400331 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask,
332 GLenum filter, bool fromAngleExtension)
333{
334 switch (filter)
335 {
336 case GL_NEAREST:
337 break;
338 case GL_LINEAR:
339 if (fromAngleExtension)
340 {
341 return gl::error(GL_INVALID_ENUM, false);
342 }
343 break;
344 default:
345 return gl::error(GL_INVALID_ENUM, false);
346 }
347
348 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
349 {
350 return gl::error(GL_INVALID_VALUE, false);
351 }
352
353 if (mask == 0)
354 {
355 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
356 // buffers are copied.
357 return false;
358 }
359
360 if (fromAngleExtension && (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0))
361 {
362 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation.");
363 return gl::error(GL_INVALID_OPERATION, false);
364 }
365
366 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
367 // color buffer, leaving only nearest being unfiltered from above
368 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
369 {
370 return gl::error(GL_INVALID_OPERATION, false);
371 }
372
373 if (context->getReadFramebufferHandle() == context->getDrawFramebufferHandle())
374 {
375 if (fromAngleExtension)
376 {
377 ERR("Blits with the same source and destination framebuffer are not supported by this "
378 "implementation.");
379 }
380 return gl::error(GL_INVALID_OPERATION, false);
381 }
382
383 gl::Framebuffer *readFramebuffer = context->getReadFramebuffer();
384 gl::Framebuffer *drawFramebuffer = context->getDrawFramebuffer();
385 if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE ||
386 !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
387 {
388 return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
389 }
390
391 if (drawFramebuffer->getSamples() != 0)
392 {
393 return gl::error(GL_INVALID_OPERATION, false);
394 }
395
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400396 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
397
398 GLuint clientVersion = context->getClientVersion();
399
400 if (mask & GL_COLOR_BUFFER_BIT)
401 {
402 gl::Renderbuffer *readColorBuffer = readFramebuffer->getReadColorbuffer();
403 gl::Renderbuffer *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
404
405 if (readColorBuffer && drawColorBuffer)
406 {
Geoff Lang005df412013-10-16 14:12:50 -0400407 GLenum readInternalFormat = readColorBuffer->getActualFormat();
Geoff Langb2f3d052013-08-13 12:49:27 -0400408 GLenum readComponentType = gl::GetComponentType(readInternalFormat, clientVersion);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400409
410 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; i++)
411 {
412 if (drawFramebuffer->isEnabledColorAttachment(i))
413 {
Geoff Lang005df412013-10-16 14:12:50 -0400414 GLenum drawInternalFormat = drawFramebuffer->getColorbuffer(i)->getActualFormat();
Geoff Langb2f3d052013-08-13 12:49:27 -0400415 GLenum drawComponentType = gl::GetComponentType(drawInternalFormat, clientVersion);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400416
Geoff Langb2f3d052013-08-13 12:49:27 -0400417 // The GL ES 3.0.2 spec (pg 193) states that:
418 // 1) If the read buffer is fixed point format, the draw buffer must be as well
419 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
420 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
421 if ( (readComponentType == GL_UNSIGNED_NORMALIZED || readComponentType == GL_SIGNED_NORMALIZED) &&
422 !(drawComponentType == GL_UNSIGNED_NORMALIZED || drawComponentType == GL_SIGNED_NORMALIZED))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400423 {
424 return gl::error(GL_INVALID_OPERATION, false);
425 }
426
Geoff Langb2f3d052013-08-13 12:49:27 -0400427 if (readComponentType == GL_UNSIGNED_INT && drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400428 {
429 return gl::error(GL_INVALID_OPERATION, false);
430 }
431
Geoff Langb2f3d052013-08-13 12:49:27 -0400432 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400433 {
434 return gl::error(GL_INVALID_OPERATION, false);
435 }
436
Geoff Langb2f3d052013-08-13 12:49:27 -0400437 if (readColorBuffer->getSamples() > 0 && (readInternalFormat != drawInternalFormat || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400438 {
439 return gl::error(GL_INVALID_OPERATION, false);
440 }
441 }
442 }
443
Geoff Langb2f3d052013-08-13 12:49:27 -0400444 if ((readComponentType == GL_INT || readComponentType == GL_UNSIGNED_INT) && filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400445 {
446 return gl::error(GL_INVALID_OPERATION, false);
447 }
448
449 if (fromAngleExtension)
450 {
451 const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType();
452 if (readColorbufferType != GL_TEXTURE_2D && readColorbufferType != GL_RENDERBUFFER)
453 {
454 return gl::error(GL_INVALID_OPERATION, false);
455 }
456
457 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
458 {
459 if (drawFramebuffer->isEnabledColorAttachment(colorAttachment))
460 {
461 if (drawFramebuffer->getColorbufferType(colorAttachment) != GL_TEXTURE_2D &&
462 drawFramebuffer->getColorbufferType(colorAttachment) != GL_RENDERBUFFER)
463 {
464 return gl::error(GL_INVALID_OPERATION, false);
465 }
466
467 if (drawFramebuffer->getColorbuffer(colorAttachment)->getActualFormat() != readColorBuffer->getActualFormat())
468 {
469 return gl::error(GL_INVALID_OPERATION, false);
470 }
471 }
472 }
Geoff Lang125deab2013-08-09 13:34:16 -0400473 if (readFramebuffer->getSamples() != 0 && IsPartialBlit(context, readColorBuffer, drawColorBuffer,
474 srcX0, srcY0, srcX1, srcY1,
475 dstX0, dstY0, dstX1, dstY1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400476 {
477 return gl::error(GL_INVALID_OPERATION, false);
478 }
479 }
480 }
481 }
482
483 if (mask & GL_DEPTH_BUFFER_BIT)
484 {
485 gl::Renderbuffer *readDepthBuffer = readFramebuffer->getDepthbuffer();
486 gl::Renderbuffer *drawDepthBuffer = drawFramebuffer->getDepthbuffer();
487
488 if (readDepthBuffer && drawDepthBuffer)
489 {
490 if (readDepthBuffer->getActualFormat() != drawDepthBuffer->getActualFormat())
491 {
492 return gl::error(GL_INVALID_OPERATION, false);
493 }
494
495 if (readDepthBuffer->getSamples() > 0 && !sameBounds)
496 {
497 return gl::error(GL_INVALID_OPERATION, false);
498 }
499
500 if (fromAngleExtension)
501 {
Geoff Lang125deab2013-08-09 13:34:16 -0400502 if (IsPartialBlit(context, readDepthBuffer, drawDepthBuffer,
503 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400504 {
505 ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
506 return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted
507 }
508
509 if (readDepthBuffer->getSamples() != 0 || drawDepthBuffer->getSamples() != 0)
510 {
511 return gl::error(GL_INVALID_OPERATION, false);
512 }
513 }
514 }
515 }
516
517 if (mask & GL_STENCIL_BUFFER_BIT)
518 {
519 gl::Renderbuffer *readStencilBuffer = readFramebuffer->getStencilbuffer();
520 gl::Renderbuffer *drawStencilBuffer = drawFramebuffer->getStencilbuffer();
521
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400522 if (readStencilBuffer && drawStencilBuffer)
523 {
524 if (readStencilBuffer->getActualFormat() != drawStencilBuffer->getActualFormat())
525 {
526 return gl::error(GL_INVALID_OPERATION, false);
527 }
528
529 if (readStencilBuffer->getSamples() > 0 && !sameBounds)
530 {
531 return gl::error(GL_INVALID_OPERATION, false);
532 }
533
534 if (fromAngleExtension)
535 {
Geoff Lang125deab2013-08-09 13:34:16 -0400536 if (IsPartialBlit(context, readStencilBuffer, drawStencilBuffer,
537 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400538 {
539 ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
540 return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted
541 }
542
543 if (readStencilBuffer->getSamples() != 0 || drawStencilBuffer->getSamples() != 0)
544 {
545 return gl::error(GL_INVALID_OPERATION, false);
546 }
547 }
548 }
549 }
550
551 return true;
552}
553
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400554bool ValidateGetVertexAttribParameters(GLenum pname, int clientVersion)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400555{
556 switch (pname)
557 {
558 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
559 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
560 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
561 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
562 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
563 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
564 case GL_CURRENT_VERTEX_ATTRIB:
565 return true;
566
567 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
568 // Don't verify ES3 context because GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE uses
569 // the same constant.
570 META_ASSERT(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE);
571 return true;
572
573 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
574 return ((clientVersion >= 3) ? true : gl::error(GL_INVALID_ENUM, false));
575
576 default:
577 return gl::error(GL_INVALID_ENUM, false);
578 }
579}
580
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400581bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400582{
583 switch (pname)
584 {
585 case GL_TEXTURE_WRAP_R:
586 case GL_TEXTURE_SWIZZLE_R:
587 case GL_TEXTURE_SWIZZLE_G:
588 case GL_TEXTURE_SWIZZLE_B:
589 case GL_TEXTURE_SWIZZLE_A:
590 case GL_TEXTURE_BASE_LEVEL:
591 case GL_TEXTURE_MAX_LEVEL:
592 case GL_TEXTURE_COMPARE_MODE:
593 case GL_TEXTURE_COMPARE_FUNC:
594 case GL_TEXTURE_MIN_LOD:
595 case GL_TEXTURE_MAX_LOD:
596 if (context->getClientVersion() < 3)
597 {
598 return gl::error(GL_INVALID_ENUM, false);
599 }
600 break;
601
602 default: break;
603 }
604
605 switch (pname)
606 {
607 case GL_TEXTURE_WRAP_S:
608 case GL_TEXTURE_WRAP_T:
609 case GL_TEXTURE_WRAP_R:
610 switch (param)
611 {
612 case GL_REPEAT:
613 case GL_CLAMP_TO_EDGE:
614 case GL_MIRRORED_REPEAT:
615 return true;
616 default:
617 return gl::error(GL_INVALID_ENUM, false);
618 }
619
620 case GL_TEXTURE_MIN_FILTER:
621 switch (param)
622 {
623 case GL_NEAREST:
624 case GL_LINEAR:
625 case GL_NEAREST_MIPMAP_NEAREST:
626 case GL_LINEAR_MIPMAP_NEAREST:
627 case GL_NEAREST_MIPMAP_LINEAR:
628 case GL_LINEAR_MIPMAP_LINEAR:
629 return true;
630 default:
631 return gl::error(GL_INVALID_ENUM, false);
632 }
633 break;
634
635 case GL_TEXTURE_MAG_FILTER:
636 switch (param)
637 {
638 case GL_NEAREST:
639 case GL_LINEAR:
640 return true;
641 default:
642 return gl::error(GL_INVALID_ENUM, false);
643 }
644 break;
645
646 case GL_TEXTURE_USAGE_ANGLE:
647 switch (param)
648 {
649 case GL_NONE:
650 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
651 return true;
652 default:
653 return gl::error(GL_INVALID_ENUM, false);
654 }
655 break;
656
657 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
658 if (!context->supportsTextureFilterAnisotropy())
659 {
660 return gl::error(GL_INVALID_ENUM, false);
661 }
662
663 // we assume the parameter passed to this validation method is truncated, not rounded
664 if (param < 1)
665 {
666 return gl::error(GL_INVALID_VALUE, false);
667 }
668 return true;
669
670 case GL_TEXTURE_MIN_LOD:
671 case GL_TEXTURE_MAX_LOD:
672 // any value is permissible
673 return true;
674
675 case GL_TEXTURE_COMPARE_MODE:
Geoff Lang63b5f1f2013-09-23 14:52:14 -0400676 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400677 switch (param)
678 {
679 case GL_NONE:
680 case GL_COMPARE_REF_TO_TEXTURE:
681 return true;
682 default:
683 return gl::error(GL_INVALID_ENUM, false);
684 }
685 break;
686
687 case GL_TEXTURE_COMPARE_FUNC:
Geoff Lang63b5f1f2013-09-23 14:52:14 -0400688 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400689 switch (param)
690 {
691 case GL_LEQUAL:
692 case GL_GEQUAL:
693 case GL_LESS:
694 case GL_GREATER:
695 case GL_EQUAL:
696 case GL_NOTEQUAL:
697 case GL_ALWAYS:
698 case GL_NEVER:
699 return true;
700 default:
701 return gl::error(GL_INVALID_ENUM, false);
702 }
703 break;
704
705 case GL_TEXTURE_SWIZZLE_R:
706 case GL_TEXTURE_SWIZZLE_G:
707 case GL_TEXTURE_SWIZZLE_B:
708 case GL_TEXTURE_SWIZZLE_A:
Geoff Langbc90a482013-09-17 16:51:27 -0400709 switch (param)
710 {
711 case GL_RED:
712 case GL_GREEN:
713 case GL_BLUE:
714 case GL_ALPHA:
715 case GL_ZERO:
716 case GL_ONE:
717 return true;
718 default:
719 return gl::error(GL_INVALID_ENUM, false);
720 }
721 break;
722
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400723 case GL_TEXTURE_BASE_LEVEL:
724 case GL_TEXTURE_MAX_LEVEL:
725 UNIMPLEMENTED();
726 return true;
727
728 default:
729 return gl::error(GL_INVALID_ENUM, false);
730 }
731}
732
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400733bool ValidateSamplerObjectParameter(GLenum pname)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400734{
735 switch (pname)
736 {
737 case GL_TEXTURE_MIN_FILTER:
738 case GL_TEXTURE_MAG_FILTER:
739 case GL_TEXTURE_WRAP_S:
740 case GL_TEXTURE_WRAP_T:
741 case GL_TEXTURE_WRAP_R:
742 case GL_TEXTURE_MIN_LOD:
743 case GL_TEXTURE_MAX_LOD:
744 case GL_TEXTURE_COMPARE_MODE:
745 case GL_TEXTURE_COMPARE_FUNC:
746 return true;
747
748 default:
749 return gl::error(GL_INVALID_ENUM, false);
750 }
751}
752
753}