blob: c688fcd7934c26d55fdee375d821f0db0b156f09 [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
Jamie Madill1fc7e2c2014-01-21 16:47:10 -050024bool ValidTextureTarget(const Context *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -040025{
26 if (context->getClientVersion() < 3)
27 {
28 if (target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY)
29 {
30 return false;
31 }
32 }
33
34 return true;
35}
36
Jamie Madill1fc7e2c2014-01-21 16:47:10 -050037bool ValidFramebufferTarget(GLenum target)
38{
39 META_ASSERT(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER);
40
41 switch (target)
42 {
43 case GL_FRAMEBUFFER: return true;
44 case GL_READ_FRAMEBUFFER: return true;
45 case GL_DRAW_FRAMEBUFFER: return true;
46 default: return false;
47 }
48}
49
Geoff Langce635692013-09-24 13:56:32 -040050bool ValidMipLevel(const gl::Context *context, GLenum target, GLint level)
51{
52 int maxLevel = 0;
53 switch (target)
54 {
55 case GL_TEXTURE_2D: maxLevel = context->getMaximum2DTextureLevel(); break;
56 case GL_TEXTURE_CUBE_MAP:
57 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
58 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
59 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
60 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
61 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
62 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: maxLevel = context->getMaximumCubeTextureLevel(); break;
63 case GL_TEXTURE_3D: maxLevel = context->getMaximum3DTextureLevel(); break;
64 case GL_TEXTURE_2D_ARRAY: maxLevel = context->getMaximum2DArrayTextureLevel(); break;
65 default: UNREACHABLE();
66 }
67
68 return level < maxLevel;
69}
70
71bool ValidImageSize(const gl::Context *context, GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth)
72{
73 if (level < 0 || width < 0 || height < 0 || depth < 0)
74 {
75 return false;
76 }
77
78 if (!context->supportsNonPower2Texture() && (level != 0 || !gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth)))
79 {
80 return false;
81 }
82
83 if (!ValidMipLevel(context, target, level))
84 {
85 return false;
86 }
87
88 return true;
89}
90
Geoff Lang005df412013-10-16 14:12:50 -040091bool ValidCompressedImageSize(const gl::Context *context, GLenum internalFormat, GLsizei width, GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -040092{
93 GLuint clientVersion = context->getClientVersion();
94 if (!IsFormatCompressed(internalFormat, clientVersion))
95 {
96 return false;
97 }
98
99 GLint blockWidth = GetCompressedBlockWidth(internalFormat, clientVersion);
100 GLint blockHeight = GetCompressedBlockHeight(internalFormat, clientVersion);
101 if (width < 0 || (width > blockWidth && width % blockWidth != 0) ||
102 height < 0 || (height > blockHeight && height % blockHeight != 0))
103 {
104 return false;
105 }
106
107 return true;
108}
109
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400110bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum target, GLsizei samples,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400111 GLenum internalformat, GLsizei width, GLsizei height,
112 bool angleExtension)
113{
114 switch (target)
115 {
116 case GL_RENDERBUFFER:
117 break;
118 default:
119 return gl::error(GL_INVALID_ENUM, false);
120 }
121
122 if (width < 0 || height < 0 || samples < 0)
123 {
124 return gl::error(GL_INVALID_VALUE, false);
125 }
126
127 if (!gl::IsValidInternalFormat(internalformat, context))
128 {
129 return gl::error(GL_INVALID_ENUM, false);
130 }
131
132 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
133 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
134 // only sized internal formats. The ES3 spec (section 4.4.2) does, however, state that the
135 // internal format must be sized and not an integer format if samples is greater than zero.
136 if (!gl::IsSizedInternalFormat(internalformat, context->getClientVersion()))
137 {
138 return gl::error(GL_INVALID_ENUM, false);
139 }
140
Geoff Langb2f3d052013-08-13 12:49:27 -0400141 GLenum componentType = gl::GetComponentType(internalformat, context->getClientVersion());
142 if ((componentType == GL_UNSIGNED_INT || componentType == GL_INT) && samples > 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400143 {
144 return gl::error(GL_INVALID_OPERATION, false);
145 }
146
147 if (!gl::IsColorRenderingSupported(internalformat, context) &&
148 !gl::IsDepthRenderingSupported(internalformat, context) &&
149 !gl::IsStencilRenderingSupported(internalformat, context))
150 {
151 return gl::error(GL_INVALID_ENUM, false);
152 }
153
154 if (std::max(width, height) > context->getMaximumRenderbufferDimension())
155 {
156 return gl::error(GL_INVALID_VALUE, false);
157 }
158
159 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
160 // to MAX_SAMPLES_ANGLE (Context::getMaxSupportedSamples) while the ES3.0 spec (section 4.4.2)
161 // states that samples must be less than or equal to the maximum samples for the specified
162 // internal format.
163 if (angleExtension)
164 {
165 if (samples > context->getMaxSupportedSamples())
166 {
167 return gl::error(GL_INVALID_VALUE, false);
168 }
169 }
170 else
171 {
172 if (samples > context->getMaxSupportedFormatSamples(internalformat))
173 {
174 return gl::error(GL_INVALID_VALUE, false);
175 }
176 }
177
178 GLuint handle = context->getRenderbufferHandle();
179 if (handle == 0)
180 {
181 return gl::error(GL_INVALID_OPERATION, false);
182 }
183
184 return true;
185}
186
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500187bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
188 GLenum renderbuffertarget, GLuint renderbuffer)
189{
190 gl::Framebuffer *framebuffer = context->getTargetFramebuffer(target);
191 GLuint framebufferHandle = context->getTargetFramebufferHandle(target);
192
193 if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0))
194 {
195 return gl::error(GL_INVALID_OPERATION, false);
196 }
197
198 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
199 {
200 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
201
202 if (colorAttachment >= context->getMaximumRenderTargets())
203 {
204 return gl::error(GL_INVALID_VALUE, false);
205 }
206 }
207 else
208 {
209 switch (attachment)
210 {
211 case GL_DEPTH_ATTACHMENT:
212 break;
213 case GL_STENCIL_ATTACHMENT:
214 break;
215 case GL_DEPTH_STENCIL_ATTACHMENT:
216 if (context->getClientVersion() < 3)
217 {
218 return gl::error(GL_INVALID_ENUM, false);
219 }
220 break;
221 default:
222 return gl::error(GL_INVALID_ENUM, false);
223 }
224 }
225
226 return true;
227}
228
Geoff Lang125deab2013-08-09 13:34:16 -0400229static bool IsPartialBlit(gl::Context *context, gl::Renderbuffer *readBuffer, gl::Renderbuffer *writeBuffer,
230 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
231 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
232{
233 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 ||
234 dstX1 != writeBuffer->getWidth() || dstY1 != writeBuffer->getHeight() ||
235 srcX1 != readBuffer->getWidth() || srcY1 != readBuffer->getHeight())
236 {
237 return true;
238 }
239 else if (context->isScissorTestEnabled())
240 {
241 int scissorX, scissorY, scissorWidth, scissorHeight;
242 context->getScissorParams(&scissorX, &scissorY, &scissorWidth, &scissorHeight);
243
244 return scissorX > 0 || scissorY > 0 ||
245 scissorWidth < writeBuffer->getWidth() ||
246 scissorHeight < writeBuffer->getHeight();
247 }
248 else
249 {
250 return false;
251 }
252}
253
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400254bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400255 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask,
256 GLenum filter, bool fromAngleExtension)
257{
258 switch (filter)
259 {
260 case GL_NEAREST:
261 break;
262 case GL_LINEAR:
263 if (fromAngleExtension)
264 {
265 return gl::error(GL_INVALID_ENUM, false);
266 }
267 break;
268 default:
269 return gl::error(GL_INVALID_ENUM, false);
270 }
271
272 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
273 {
274 return gl::error(GL_INVALID_VALUE, false);
275 }
276
277 if (mask == 0)
278 {
279 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
280 // buffers are copied.
281 return false;
282 }
283
284 if (fromAngleExtension && (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0))
285 {
286 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation.");
287 return gl::error(GL_INVALID_OPERATION, false);
288 }
289
290 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
291 // color buffer, leaving only nearest being unfiltered from above
292 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
293 {
294 return gl::error(GL_INVALID_OPERATION, false);
295 }
296
297 if (context->getReadFramebufferHandle() == context->getDrawFramebufferHandle())
298 {
299 if (fromAngleExtension)
300 {
301 ERR("Blits with the same source and destination framebuffer are not supported by this "
302 "implementation.");
303 }
304 return gl::error(GL_INVALID_OPERATION, false);
305 }
306
307 gl::Framebuffer *readFramebuffer = context->getReadFramebuffer();
308 gl::Framebuffer *drawFramebuffer = context->getDrawFramebuffer();
309 if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE ||
310 !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
311 {
312 return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
313 }
314
315 if (drawFramebuffer->getSamples() != 0)
316 {
317 return gl::error(GL_INVALID_OPERATION, false);
318 }
319
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400320 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
321
322 GLuint clientVersion = context->getClientVersion();
323
324 if (mask & GL_COLOR_BUFFER_BIT)
325 {
326 gl::Renderbuffer *readColorBuffer = readFramebuffer->getReadColorbuffer();
327 gl::Renderbuffer *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
328
329 if (readColorBuffer && drawColorBuffer)
330 {
Geoff Lang005df412013-10-16 14:12:50 -0400331 GLenum readInternalFormat = readColorBuffer->getActualFormat();
Geoff Langb2f3d052013-08-13 12:49:27 -0400332 GLenum readComponentType = gl::GetComponentType(readInternalFormat, clientVersion);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400333
334 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; i++)
335 {
336 if (drawFramebuffer->isEnabledColorAttachment(i))
337 {
Geoff Lang005df412013-10-16 14:12:50 -0400338 GLenum drawInternalFormat = drawFramebuffer->getColorbuffer(i)->getActualFormat();
Geoff Langb2f3d052013-08-13 12:49:27 -0400339 GLenum drawComponentType = gl::GetComponentType(drawInternalFormat, clientVersion);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400340
Geoff Langb2f3d052013-08-13 12:49:27 -0400341 // The GL ES 3.0.2 spec (pg 193) states that:
342 // 1) If the read buffer is fixed point format, the draw buffer must be as well
343 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
344 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
345 if ( (readComponentType == GL_UNSIGNED_NORMALIZED || readComponentType == GL_SIGNED_NORMALIZED) &&
346 !(drawComponentType == GL_UNSIGNED_NORMALIZED || drawComponentType == GL_SIGNED_NORMALIZED))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400347 {
348 return gl::error(GL_INVALID_OPERATION, false);
349 }
350
Geoff Langb2f3d052013-08-13 12:49:27 -0400351 if (readComponentType == GL_UNSIGNED_INT && drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400352 {
353 return gl::error(GL_INVALID_OPERATION, false);
354 }
355
Geoff Langb2f3d052013-08-13 12:49:27 -0400356 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400357 {
358 return gl::error(GL_INVALID_OPERATION, false);
359 }
360
Geoff Langb2f3d052013-08-13 12:49:27 -0400361 if (readColorBuffer->getSamples() > 0 && (readInternalFormat != drawInternalFormat || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400362 {
363 return gl::error(GL_INVALID_OPERATION, false);
364 }
365 }
366 }
367
Geoff Langb2f3d052013-08-13 12:49:27 -0400368 if ((readComponentType == GL_INT || readComponentType == GL_UNSIGNED_INT) && filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400369 {
370 return gl::error(GL_INVALID_OPERATION, false);
371 }
372
373 if (fromAngleExtension)
374 {
375 const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType();
376 if (readColorbufferType != GL_TEXTURE_2D && readColorbufferType != GL_RENDERBUFFER)
377 {
378 return gl::error(GL_INVALID_OPERATION, false);
379 }
380
381 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
382 {
383 if (drawFramebuffer->isEnabledColorAttachment(colorAttachment))
384 {
385 if (drawFramebuffer->getColorbufferType(colorAttachment) != GL_TEXTURE_2D &&
386 drawFramebuffer->getColorbufferType(colorAttachment) != GL_RENDERBUFFER)
387 {
388 return gl::error(GL_INVALID_OPERATION, false);
389 }
390
391 if (drawFramebuffer->getColorbuffer(colorAttachment)->getActualFormat() != readColorBuffer->getActualFormat())
392 {
393 return gl::error(GL_INVALID_OPERATION, false);
394 }
395 }
396 }
Geoff Lang125deab2013-08-09 13:34:16 -0400397 if (readFramebuffer->getSamples() != 0 && IsPartialBlit(context, readColorBuffer, drawColorBuffer,
398 srcX0, srcY0, srcX1, srcY1,
399 dstX0, dstY0, dstX1, dstY1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400400 {
401 return gl::error(GL_INVALID_OPERATION, false);
402 }
403 }
404 }
405 }
406
407 if (mask & GL_DEPTH_BUFFER_BIT)
408 {
409 gl::Renderbuffer *readDepthBuffer = readFramebuffer->getDepthbuffer();
410 gl::Renderbuffer *drawDepthBuffer = drawFramebuffer->getDepthbuffer();
411
412 if (readDepthBuffer && drawDepthBuffer)
413 {
414 if (readDepthBuffer->getActualFormat() != drawDepthBuffer->getActualFormat())
415 {
416 return gl::error(GL_INVALID_OPERATION, false);
417 }
418
419 if (readDepthBuffer->getSamples() > 0 && !sameBounds)
420 {
421 return gl::error(GL_INVALID_OPERATION, false);
422 }
423
424 if (fromAngleExtension)
425 {
Geoff Lang125deab2013-08-09 13:34:16 -0400426 if (IsPartialBlit(context, readDepthBuffer, drawDepthBuffer,
427 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400428 {
429 ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
430 return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted
431 }
432
433 if (readDepthBuffer->getSamples() != 0 || drawDepthBuffer->getSamples() != 0)
434 {
435 return gl::error(GL_INVALID_OPERATION, false);
436 }
437 }
438 }
439 }
440
441 if (mask & GL_STENCIL_BUFFER_BIT)
442 {
443 gl::Renderbuffer *readStencilBuffer = readFramebuffer->getStencilbuffer();
444 gl::Renderbuffer *drawStencilBuffer = drawFramebuffer->getStencilbuffer();
445
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400446 if (readStencilBuffer && drawStencilBuffer)
447 {
448 if (readStencilBuffer->getActualFormat() != drawStencilBuffer->getActualFormat())
449 {
450 return gl::error(GL_INVALID_OPERATION, false);
451 }
452
453 if (readStencilBuffer->getSamples() > 0 && !sameBounds)
454 {
455 return gl::error(GL_INVALID_OPERATION, false);
456 }
457
458 if (fromAngleExtension)
459 {
Geoff Lang125deab2013-08-09 13:34:16 -0400460 if (IsPartialBlit(context, readStencilBuffer, drawStencilBuffer,
461 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400462 {
463 ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
464 return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted
465 }
466
467 if (readStencilBuffer->getSamples() != 0 || drawStencilBuffer->getSamples() != 0)
468 {
469 return gl::error(GL_INVALID_OPERATION, false);
470 }
471 }
472 }
473 }
474
475 return true;
476}
477
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400478bool ValidateGetVertexAttribParameters(GLenum pname, int clientVersion)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400479{
480 switch (pname)
481 {
482 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
483 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
484 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
485 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
486 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
487 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
488 case GL_CURRENT_VERTEX_ATTRIB:
489 return true;
490
491 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
492 // Don't verify ES3 context because GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE uses
493 // the same constant.
494 META_ASSERT(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE);
495 return true;
496
497 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
498 return ((clientVersion >= 3) ? true : gl::error(GL_INVALID_ENUM, false));
499
500 default:
501 return gl::error(GL_INVALID_ENUM, false);
502 }
503}
504
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400505bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400506{
507 switch (pname)
508 {
509 case GL_TEXTURE_WRAP_R:
510 case GL_TEXTURE_SWIZZLE_R:
511 case GL_TEXTURE_SWIZZLE_G:
512 case GL_TEXTURE_SWIZZLE_B:
513 case GL_TEXTURE_SWIZZLE_A:
514 case GL_TEXTURE_BASE_LEVEL:
515 case GL_TEXTURE_MAX_LEVEL:
516 case GL_TEXTURE_COMPARE_MODE:
517 case GL_TEXTURE_COMPARE_FUNC:
518 case GL_TEXTURE_MIN_LOD:
519 case GL_TEXTURE_MAX_LOD:
520 if (context->getClientVersion() < 3)
521 {
522 return gl::error(GL_INVALID_ENUM, false);
523 }
524 break;
525
526 default: break;
527 }
528
529 switch (pname)
530 {
531 case GL_TEXTURE_WRAP_S:
532 case GL_TEXTURE_WRAP_T:
533 case GL_TEXTURE_WRAP_R:
534 switch (param)
535 {
536 case GL_REPEAT:
537 case GL_CLAMP_TO_EDGE:
538 case GL_MIRRORED_REPEAT:
539 return true;
540 default:
541 return gl::error(GL_INVALID_ENUM, false);
542 }
543
544 case GL_TEXTURE_MIN_FILTER:
545 switch (param)
546 {
547 case GL_NEAREST:
548 case GL_LINEAR:
549 case GL_NEAREST_MIPMAP_NEAREST:
550 case GL_LINEAR_MIPMAP_NEAREST:
551 case GL_NEAREST_MIPMAP_LINEAR:
552 case GL_LINEAR_MIPMAP_LINEAR:
553 return true;
554 default:
555 return gl::error(GL_INVALID_ENUM, false);
556 }
557 break;
558
559 case GL_TEXTURE_MAG_FILTER:
560 switch (param)
561 {
562 case GL_NEAREST:
563 case GL_LINEAR:
564 return true;
565 default:
566 return gl::error(GL_INVALID_ENUM, false);
567 }
568 break;
569
570 case GL_TEXTURE_USAGE_ANGLE:
571 switch (param)
572 {
573 case GL_NONE:
574 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
575 return true;
576 default:
577 return gl::error(GL_INVALID_ENUM, false);
578 }
579 break;
580
581 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
582 if (!context->supportsTextureFilterAnisotropy())
583 {
584 return gl::error(GL_INVALID_ENUM, false);
585 }
586
587 // we assume the parameter passed to this validation method is truncated, not rounded
588 if (param < 1)
589 {
590 return gl::error(GL_INVALID_VALUE, false);
591 }
592 return true;
593
594 case GL_TEXTURE_MIN_LOD:
595 case GL_TEXTURE_MAX_LOD:
596 // any value is permissible
597 return true;
598
599 case GL_TEXTURE_COMPARE_MODE:
Geoff Lang63b5f1f2013-09-23 14:52:14 -0400600 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400601 switch (param)
602 {
603 case GL_NONE:
604 case GL_COMPARE_REF_TO_TEXTURE:
605 return true;
606 default:
607 return gl::error(GL_INVALID_ENUM, false);
608 }
609 break;
610
611 case GL_TEXTURE_COMPARE_FUNC:
Geoff Lang63b5f1f2013-09-23 14:52:14 -0400612 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400613 switch (param)
614 {
615 case GL_LEQUAL:
616 case GL_GEQUAL:
617 case GL_LESS:
618 case GL_GREATER:
619 case GL_EQUAL:
620 case GL_NOTEQUAL:
621 case GL_ALWAYS:
622 case GL_NEVER:
623 return true;
624 default:
625 return gl::error(GL_INVALID_ENUM, false);
626 }
627 break;
628
629 case GL_TEXTURE_SWIZZLE_R:
630 case GL_TEXTURE_SWIZZLE_G:
631 case GL_TEXTURE_SWIZZLE_B:
632 case GL_TEXTURE_SWIZZLE_A:
Geoff Langbc90a482013-09-17 16:51:27 -0400633 switch (param)
634 {
635 case GL_RED:
636 case GL_GREEN:
637 case GL_BLUE:
638 case GL_ALPHA:
639 case GL_ZERO:
640 case GL_ONE:
641 return true;
642 default:
643 return gl::error(GL_INVALID_ENUM, false);
644 }
645 break;
646
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400647 case GL_TEXTURE_BASE_LEVEL:
648 case GL_TEXTURE_MAX_LEVEL:
649 UNIMPLEMENTED();
650 return true;
651
652 default:
653 return gl::error(GL_INVALID_ENUM, false);
654 }
655}
656
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400657bool ValidateSamplerObjectParameter(GLenum pname)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400658{
659 switch (pname)
660 {
661 case GL_TEXTURE_MIN_FILTER:
662 case GL_TEXTURE_MAG_FILTER:
663 case GL_TEXTURE_WRAP_S:
664 case GL_TEXTURE_WRAP_T:
665 case GL_TEXTURE_WRAP_R:
666 case GL_TEXTURE_MIN_LOD:
667 case GL_TEXTURE_MAX_LOD:
668 case GL_TEXTURE_COMPARE_MODE:
669 case GL_TEXTURE_COMPARE_FUNC:
670 return true;
671
672 default:
673 return gl::error(GL_INVALID_ENUM, false);
674 }
675}
676
677}