blob: 9f62b95ccd9cc79ac542fc8aafdac8f55dbe50e8 [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
230 return true;
231}
232
Geoff Lang125deab2013-08-09 13:34:16 -0400233static bool IsPartialBlit(gl::Context *context, gl::Renderbuffer *readBuffer, gl::Renderbuffer *writeBuffer,
234 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
235 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
236{
237 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 ||
238 dstX1 != writeBuffer->getWidth() || dstY1 != writeBuffer->getHeight() ||
239 srcX1 != readBuffer->getWidth() || srcY1 != readBuffer->getHeight())
240 {
241 return true;
242 }
243 else if (context->isScissorTestEnabled())
244 {
245 int scissorX, scissorY, scissorWidth, scissorHeight;
246 context->getScissorParams(&scissorX, &scissorY, &scissorWidth, &scissorHeight);
247
248 return scissorX > 0 || scissorY > 0 ||
249 scissorWidth < writeBuffer->getWidth() ||
250 scissorHeight < writeBuffer->getHeight();
251 }
252 else
253 {
254 return false;
255 }
256}
257
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400258bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400259 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask,
260 GLenum filter, bool fromAngleExtension)
261{
262 switch (filter)
263 {
264 case GL_NEAREST:
265 break;
266 case GL_LINEAR:
267 if (fromAngleExtension)
268 {
269 return gl::error(GL_INVALID_ENUM, false);
270 }
271 break;
272 default:
273 return gl::error(GL_INVALID_ENUM, false);
274 }
275
276 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
277 {
278 return gl::error(GL_INVALID_VALUE, false);
279 }
280
281 if (mask == 0)
282 {
283 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
284 // buffers are copied.
285 return false;
286 }
287
288 if (fromAngleExtension && (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0))
289 {
290 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation.");
291 return gl::error(GL_INVALID_OPERATION, false);
292 }
293
294 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
295 // color buffer, leaving only nearest being unfiltered from above
296 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
297 {
298 return gl::error(GL_INVALID_OPERATION, false);
299 }
300
301 if (context->getReadFramebufferHandle() == context->getDrawFramebufferHandle())
302 {
303 if (fromAngleExtension)
304 {
305 ERR("Blits with the same source and destination framebuffer are not supported by this "
306 "implementation.");
307 }
308 return gl::error(GL_INVALID_OPERATION, false);
309 }
310
311 gl::Framebuffer *readFramebuffer = context->getReadFramebuffer();
312 gl::Framebuffer *drawFramebuffer = context->getDrawFramebuffer();
313 if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE ||
314 !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
315 {
316 return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
317 }
318
319 if (drawFramebuffer->getSamples() != 0)
320 {
321 return gl::error(GL_INVALID_OPERATION, false);
322 }
323
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400324 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
325
326 GLuint clientVersion = context->getClientVersion();
327
328 if (mask & GL_COLOR_BUFFER_BIT)
329 {
330 gl::Renderbuffer *readColorBuffer = readFramebuffer->getReadColorbuffer();
331 gl::Renderbuffer *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
332
333 if (readColorBuffer && drawColorBuffer)
334 {
Geoff Lang005df412013-10-16 14:12:50 -0400335 GLenum readInternalFormat = readColorBuffer->getActualFormat();
Geoff Langb2f3d052013-08-13 12:49:27 -0400336 GLenum readComponentType = gl::GetComponentType(readInternalFormat, clientVersion);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400337
338 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; i++)
339 {
340 if (drawFramebuffer->isEnabledColorAttachment(i))
341 {
Geoff Lang005df412013-10-16 14:12:50 -0400342 GLenum drawInternalFormat = drawFramebuffer->getColorbuffer(i)->getActualFormat();
Geoff Langb2f3d052013-08-13 12:49:27 -0400343 GLenum drawComponentType = gl::GetComponentType(drawInternalFormat, clientVersion);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400344
Geoff Langb2f3d052013-08-13 12:49:27 -0400345 // The GL ES 3.0.2 spec (pg 193) states that:
346 // 1) If the read buffer is fixed point format, the draw buffer must be as well
347 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
348 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
349 if ( (readComponentType == GL_UNSIGNED_NORMALIZED || readComponentType == GL_SIGNED_NORMALIZED) &&
350 !(drawComponentType == GL_UNSIGNED_NORMALIZED || drawComponentType == GL_SIGNED_NORMALIZED))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400351 {
352 return gl::error(GL_INVALID_OPERATION, false);
353 }
354
Geoff Langb2f3d052013-08-13 12:49:27 -0400355 if (readComponentType == GL_UNSIGNED_INT && drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400356 {
357 return gl::error(GL_INVALID_OPERATION, false);
358 }
359
Geoff Langb2f3d052013-08-13 12:49:27 -0400360 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400361 {
362 return gl::error(GL_INVALID_OPERATION, false);
363 }
364
Geoff Langb2f3d052013-08-13 12:49:27 -0400365 if (readColorBuffer->getSamples() > 0 && (readInternalFormat != drawInternalFormat || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400366 {
367 return gl::error(GL_INVALID_OPERATION, false);
368 }
369 }
370 }
371
Geoff Langb2f3d052013-08-13 12:49:27 -0400372 if ((readComponentType == GL_INT || readComponentType == GL_UNSIGNED_INT) && filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400373 {
374 return gl::error(GL_INVALID_OPERATION, false);
375 }
376
377 if (fromAngleExtension)
378 {
379 const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType();
380 if (readColorbufferType != GL_TEXTURE_2D && readColorbufferType != GL_RENDERBUFFER)
381 {
382 return gl::error(GL_INVALID_OPERATION, false);
383 }
384
385 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
386 {
387 if (drawFramebuffer->isEnabledColorAttachment(colorAttachment))
388 {
389 if (drawFramebuffer->getColorbufferType(colorAttachment) != GL_TEXTURE_2D &&
390 drawFramebuffer->getColorbufferType(colorAttachment) != GL_RENDERBUFFER)
391 {
392 return gl::error(GL_INVALID_OPERATION, false);
393 }
394
395 if (drawFramebuffer->getColorbuffer(colorAttachment)->getActualFormat() != readColorBuffer->getActualFormat())
396 {
397 return gl::error(GL_INVALID_OPERATION, false);
398 }
399 }
400 }
Geoff Lang125deab2013-08-09 13:34:16 -0400401 if (readFramebuffer->getSamples() != 0 && IsPartialBlit(context, readColorBuffer, drawColorBuffer,
402 srcX0, srcY0, srcX1, srcY1,
403 dstX0, dstY0, dstX1, dstY1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400404 {
405 return gl::error(GL_INVALID_OPERATION, false);
406 }
407 }
408 }
409 }
410
411 if (mask & GL_DEPTH_BUFFER_BIT)
412 {
413 gl::Renderbuffer *readDepthBuffer = readFramebuffer->getDepthbuffer();
414 gl::Renderbuffer *drawDepthBuffer = drawFramebuffer->getDepthbuffer();
415
416 if (readDepthBuffer && drawDepthBuffer)
417 {
418 if (readDepthBuffer->getActualFormat() != drawDepthBuffer->getActualFormat())
419 {
420 return gl::error(GL_INVALID_OPERATION, false);
421 }
422
423 if (readDepthBuffer->getSamples() > 0 && !sameBounds)
424 {
425 return gl::error(GL_INVALID_OPERATION, false);
426 }
427
428 if (fromAngleExtension)
429 {
Geoff Lang125deab2013-08-09 13:34:16 -0400430 if (IsPartialBlit(context, readDepthBuffer, drawDepthBuffer,
431 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400432 {
433 ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
434 return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted
435 }
436
437 if (readDepthBuffer->getSamples() != 0 || drawDepthBuffer->getSamples() != 0)
438 {
439 return gl::error(GL_INVALID_OPERATION, false);
440 }
441 }
442 }
443 }
444
445 if (mask & GL_STENCIL_BUFFER_BIT)
446 {
447 gl::Renderbuffer *readStencilBuffer = readFramebuffer->getStencilbuffer();
448 gl::Renderbuffer *drawStencilBuffer = drawFramebuffer->getStencilbuffer();
449
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400450 if (readStencilBuffer && drawStencilBuffer)
451 {
452 if (readStencilBuffer->getActualFormat() != drawStencilBuffer->getActualFormat())
453 {
454 return gl::error(GL_INVALID_OPERATION, false);
455 }
456
457 if (readStencilBuffer->getSamples() > 0 && !sameBounds)
458 {
459 return gl::error(GL_INVALID_OPERATION, false);
460 }
461
462 if (fromAngleExtension)
463 {
Geoff Lang125deab2013-08-09 13:34:16 -0400464 if (IsPartialBlit(context, readStencilBuffer, drawStencilBuffer,
465 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400466 {
467 ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
468 return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted
469 }
470
471 if (readStencilBuffer->getSamples() != 0 || drawStencilBuffer->getSamples() != 0)
472 {
473 return gl::error(GL_INVALID_OPERATION, false);
474 }
475 }
476 }
477 }
478
479 return true;
480}
481
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400482bool ValidateGetVertexAttribParameters(GLenum pname, int clientVersion)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400483{
484 switch (pname)
485 {
486 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
487 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
488 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
489 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
490 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
491 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
492 case GL_CURRENT_VERTEX_ATTRIB:
493 return true;
494
495 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
496 // Don't verify ES3 context because GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE uses
497 // the same constant.
498 META_ASSERT(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE);
499 return true;
500
501 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
502 return ((clientVersion >= 3) ? true : gl::error(GL_INVALID_ENUM, false));
503
504 default:
505 return gl::error(GL_INVALID_ENUM, false);
506 }
507}
508
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400509bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400510{
511 switch (pname)
512 {
513 case GL_TEXTURE_WRAP_R:
514 case GL_TEXTURE_SWIZZLE_R:
515 case GL_TEXTURE_SWIZZLE_G:
516 case GL_TEXTURE_SWIZZLE_B:
517 case GL_TEXTURE_SWIZZLE_A:
518 case GL_TEXTURE_BASE_LEVEL:
519 case GL_TEXTURE_MAX_LEVEL:
520 case GL_TEXTURE_COMPARE_MODE:
521 case GL_TEXTURE_COMPARE_FUNC:
522 case GL_TEXTURE_MIN_LOD:
523 case GL_TEXTURE_MAX_LOD:
524 if (context->getClientVersion() < 3)
525 {
526 return gl::error(GL_INVALID_ENUM, false);
527 }
528 break;
529
530 default: break;
531 }
532
533 switch (pname)
534 {
535 case GL_TEXTURE_WRAP_S:
536 case GL_TEXTURE_WRAP_T:
537 case GL_TEXTURE_WRAP_R:
538 switch (param)
539 {
540 case GL_REPEAT:
541 case GL_CLAMP_TO_EDGE:
542 case GL_MIRRORED_REPEAT:
543 return true;
544 default:
545 return gl::error(GL_INVALID_ENUM, false);
546 }
547
548 case GL_TEXTURE_MIN_FILTER:
549 switch (param)
550 {
551 case GL_NEAREST:
552 case GL_LINEAR:
553 case GL_NEAREST_MIPMAP_NEAREST:
554 case GL_LINEAR_MIPMAP_NEAREST:
555 case GL_NEAREST_MIPMAP_LINEAR:
556 case GL_LINEAR_MIPMAP_LINEAR:
557 return true;
558 default:
559 return gl::error(GL_INVALID_ENUM, false);
560 }
561 break;
562
563 case GL_TEXTURE_MAG_FILTER:
564 switch (param)
565 {
566 case GL_NEAREST:
567 case GL_LINEAR:
568 return true;
569 default:
570 return gl::error(GL_INVALID_ENUM, false);
571 }
572 break;
573
574 case GL_TEXTURE_USAGE_ANGLE:
575 switch (param)
576 {
577 case GL_NONE:
578 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
579 return true;
580 default:
581 return gl::error(GL_INVALID_ENUM, false);
582 }
583 break;
584
585 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
586 if (!context->supportsTextureFilterAnisotropy())
587 {
588 return gl::error(GL_INVALID_ENUM, false);
589 }
590
591 // we assume the parameter passed to this validation method is truncated, not rounded
592 if (param < 1)
593 {
594 return gl::error(GL_INVALID_VALUE, false);
595 }
596 return true;
597
598 case GL_TEXTURE_MIN_LOD:
599 case GL_TEXTURE_MAX_LOD:
600 // any value is permissible
601 return true;
602
603 case GL_TEXTURE_COMPARE_MODE:
Geoff Lang63b5f1f2013-09-23 14:52:14 -0400604 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400605 switch (param)
606 {
607 case GL_NONE:
608 case GL_COMPARE_REF_TO_TEXTURE:
609 return true;
610 default:
611 return gl::error(GL_INVALID_ENUM, false);
612 }
613 break;
614
615 case GL_TEXTURE_COMPARE_FUNC:
Geoff Lang63b5f1f2013-09-23 14:52:14 -0400616 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400617 switch (param)
618 {
619 case GL_LEQUAL:
620 case GL_GEQUAL:
621 case GL_LESS:
622 case GL_GREATER:
623 case GL_EQUAL:
624 case GL_NOTEQUAL:
625 case GL_ALWAYS:
626 case GL_NEVER:
627 return true;
628 default:
629 return gl::error(GL_INVALID_ENUM, false);
630 }
631 break;
632
633 case GL_TEXTURE_SWIZZLE_R:
634 case GL_TEXTURE_SWIZZLE_G:
635 case GL_TEXTURE_SWIZZLE_B:
636 case GL_TEXTURE_SWIZZLE_A:
Geoff Langbc90a482013-09-17 16:51:27 -0400637 switch (param)
638 {
639 case GL_RED:
640 case GL_GREEN:
641 case GL_BLUE:
642 case GL_ALPHA:
643 case GL_ZERO:
644 case GL_ONE:
645 return true;
646 default:
647 return gl::error(GL_INVALID_ENUM, false);
648 }
649 break;
650
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400651 case GL_TEXTURE_BASE_LEVEL:
652 case GL_TEXTURE_MAX_LEVEL:
653 UNIMPLEMENTED();
654 return true;
655
656 default:
657 return gl::error(GL_INVALID_ENUM, false);
658 }
659}
660
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400661bool ValidateSamplerObjectParameter(GLenum pname)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400662{
663 switch (pname)
664 {
665 case GL_TEXTURE_MIN_FILTER:
666 case GL_TEXTURE_MAG_FILTER:
667 case GL_TEXTURE_WRAP_S:
668 case GL_TEXTURE_WRAP_T:
669 case GL_TEXTURE_WRAP_R:
670 case GL_TEXTURE_MIN_LOD:
671 case GL_TEXTURE_MAX_LOD:
672 case GL_TEXTURE_COMPARE_MODE:
673 case GL_TEXTURE_COMPARE_FUNC:
674 return true;
675
676 default:
677 return gl::error(GL_INVALID_ENUM, false);
678 }
679}
680
681}