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