blob: b3f8d90d63f2dfc0b1737ab5642f256b66fab97c [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 Madill35d15012013-10-07 10:46:37 -040024bool ValidTextureTarget(gl::Context *context, GLenum target)
25{
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
Geoff Langce635692013-09-24 13:56:32 -040037bool ValidMipLevel(const gl::Context *context, GLenum target, GLint level)
38{
39 int maxLevel = 0;
40 switch (target)
41 {
42 case GL_TEXTURE_2D: maxLevel = context->getMaximum2DTextureLevel(); break;
43 case GL_TEXTURE_CUBE_MAP:
44 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
45 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
46 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
47 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
48 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
49 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: maxLevel = context->getMaximumCubeTextureLevel(); break;
50 case GL_TEXTURE_3D: maxLevel = context->getMaximum3DTextureLevel(); break;
51 case GL_TEXTURE_2D_ARRAY: maxLevel = context->getMaximum2DArrayTextureLevel(); break;
52 default: UNREACHABLE();
53 }
54
55 return level < maxLevel;
56}
57
58bool ValidImageSize(const gl::Context *context, GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth)
59{
60 if (level < 0 || width < 0 || height < 0 || depth < 0)
61 {
62 return false;
63 }
64
65 if (!context->supportsNonPower2Texture() && (level != 0 || !gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth)))
66 {
67 return false;
68 }
69
70 if (!ValidMipLevel(context, target, level))
71 {
72 return false;
73 }
74
75 return true;
76}
77
Geoff Lang005df412013-10-16 14:12:50 -040078bool ValidCompressedImageSize(const gl::Context *context, GLenum internalFormat, GLsizei width, GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -040079{
80 GLuint clientVersion = context->getClientVersion();
81 if (!IsFormatCompressed(internalFormat, clientVersion))
82 {
83 return false;
84 }
85
86 GLint blockWidth = GetCompressedBlockWidth(internalFormat, clientVersion);
87 GLint blockHeight = GetCompressedBlockHeight(internalFormat, clientVersion);
88 if (width < 0 || (width > blockWidth && width % blockWidth != 0) ||
89 height < 0 || (height > blockHeight && height % blockHeight != 0))
90 {
91 return false;
92 }
93
94 return true;
95}
96
Geoff Lang34dbb6f2013-08-05 15:05:47 -040097bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum target, GLsizei samples,
Geoff Lange8ebe7f2013-08-05 15:03:13 -040098 GLenum internalformat, GLsizei width, GLsizei height,
99 bool angleExtension)
100{
101 switch (target)
102 {
103 case GL_RENDERBUFFER:
104 break;
105 default:
106 return gl::error(GL_INVALID_ENUM, false);
107 }
108
109 if (width < 0 || height < 0 || samples < 0)
110 {
111 return gl::error(GL_INVALID_VALUE, false);
112 }
113
114 if (!gl::IsValidInternalFormat(internalformat, context))
115 {
116 return gl::error(GL_INVALID_ENUM, false);
117 }
118
119 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
120 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
121 // only sized internal formats. The ES3 spec (section 4.4.2) does, however, state that the
122 // internal format must be sized and not an integer format if samples is greater than zero.
123 if (!gl::IsSizedInternalFormat(internalformat, context->getClientVersion()))
124 {
125 return gl::error(GL_INVALID_ENUM, false);
126 }
127
Geoff Langb2f3d052013-08-13 12:49:27 -0400128 GLenum componentType = gl::GetComponentType(internalformat, context->getClientVersion());
129 if ((componentType == GL_UNSIGNED_INT || componentType == GL_INT) && samples > 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400130 {
131 return gl::error(GL_INVALID_OPERATION, false);
132 }
133
134 if (!gl::IsColorRenderingSupported(internalformat, context) &&
135 !gl::IsDepthRenderingSupported(internalformat, context) &&
136 !gl::IsStencilRenderingSupported(internalformat, context))
137 {
138 return gl::error(GL_INVALID_ENUM, false);
139 }
140
141 if (std::max(width, height) > context->getMaximumRenderbufferDimension())
142 {
143 return gl::error(GL_INVALID_VALUE, false);
144 }
145
146 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
147 // to MAX_SAMPLES_ANGLE (Context::getMaxSupportedSamples) while the ES3.0 spec (section 4.4.2)
148 // states that samples must be less than or equal to the maximum samples for the specified
149 // internal format.
150 if (angleExtension)
151 {
152 if (samples > context->getMaxSupportedSamples())
153 {
154 return gl::error(GL_INVALID_VALUE, false);
155 }
156 }
157 else
158 {
159 if (samples > context->getMaxSupportedFormatSamples(internalformat))
160 {
161 return gl::error(GL_INVALID_VALUE, false);
162 }
163 }
164
165 GLuint handle = context->getRenderbufferHandle();
166 if (handle == 0)
167 {
168 return gl::error(GL_INVALID_OPERATION, false);
169 }
170
171 return true;
172}
173
Geoff Lang125deab2013-08-09 13:34:16 -0400174static bool IsPartialBlit(gl::Context *context, gl::Renderbuffer *readBuffer, gl::Renderbuffer *writeBuffer,
175 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
176 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
177{
178 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 ||
179 dstX1 != writeBuffer->getWidth() || dstY1 != writeBuffer->getHeight() ||
180 srcX1 != readBuffer->getWidth() || srcY1 != readBuffer->getHeight())
181 {
182 return true;
183 }
184 else if (context->isScissorTestEnabled())
185 {
186 int scissorX, scissorY, scissorWidth, scissorHeight;
187 context->getScissorParams(&scissorX, &scissorY, &scissorWidth, &scissorHeight);
188
189 return scissorX > 0 || scissorY > 0 ||
190 scissorWidth < writeBuffer->getWidth() ||
191 scissorHeight < writeBuffer->getHeight();
192 }
193 else
194 {
195 return false;
196 }
197}
198
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400199bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400200 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask,
201 GLenum filter, bool fromAngleExtension)
202{
203 switch (filter)
204 {
205 case GL_NEAREST:
206 break;
207 case GL_LINEAR:
208 if (fromAngleExtension)
209 {
210 return gl::error(GL_INVALID_ENUM, false);
211 }
212 break;
213 default:
214 return gl::error(GL_INVALID_ENUM, false);
215 }
216
217 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
218 {
219 return gl::error(GL_INVALID_VALUE, false);
220 }
221
222 if (mask == 0)
223 {
224 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
225 // buffers are copied.
226 return false;
227 }
228
229 if (fromAngleExtension && (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0))
230 {
231 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation.");
232 return gl::error(GL_INVALID_OPERATION, false);
233 }
234
235 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
236 // color buffer, leaving only nearest being unfiltered from above
237 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
238 {
239 return gl::error(GL_INVALID_OPERATION, false);
240 }
241
242 if (context->getReadFramebufferHandle() == context->getDrawFramebufferHandle())
243 {
244 if (fromAngleExtension)
245 {
246 ERR("Blits with the same source and destination framebuffer are not supported by this "
247 "implementation.");
248 }
249 return gl::error(GL_INVALID_OPERATION, false);
250 }
251
252 gl::Framebuffer *readFramebuffer = context->getReadFramebuffer();
253 gl::Framebuffer *drawFramebuffer = context->getDrawFramebuffer();
254 if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE ||
255 !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
256 {
257 return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
258 }
259
260 if (drawFramebuffer->getSamples() != 0)
261 {
262 return gl::error(GL_INVALID_OPERATION, false);
263 }
264
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400265 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
266
267 GLuint clientVersion = context->getClientVersion();
268
269 if (mask & GL_COLOR_BUFFER_BIT)
270 {
271 gl::Renderbuffer *readColorBuffer = readFramebuffer->getReadColorbuffer();
272 gl::Renderbuffer *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
273
274 if (readColorBuffer && drawColorBuffer)
275 {
Geoff Lang005df412013-10-16 14:12:50 -0400276 GLenum readInternalFormat = readColorBuffer->getActualFormat();
Geoff Langb2f3d052013-08-13 12:49:27 -0400277 GLenum readComponentType = gl::GetComponentType(readInternalFormat, clientVersion);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400278
279 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; i++)
280 {
281 if (drawFramebuffer->isEnabledColorAttachment(i))
282 {
Geoff Lang005df412013-10-16 14:12:50 -0400283 GLenum drawInternalFormat = drawFramebuffer->getColorbuffer(i)->getActualFormat();
Geoff Langb2f3d052013-08-13 12:49:27 -0400284 GLenum drawComponentType = gl::GetComponentType(drawInternalFormat, clientVersion);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400285
Geoff Langb2f3d052013-08-13 12:49:27 -0400286 // The GL ES 3.0.2 spec (pg 193) states that:
287 // 1) If the read buffer is fixed point format, the draw buffer must be as well
288 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
289 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
290 if ( (readComponentType == GL_UNSIGNED_NORMALIZED || readComponentType == GL_SIGNED_NORMALIZED) &&
291 !(drawComponentType == GL_UNSIGNED_NORMALIZED || drawComponentType == GL_SIGNED_NORMALIZED))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400292 {
293 return gl::error(GL_INVALID_OPERATION, false);
294 }
295
Geoff Langb2f3d052013-08-13 12:49:27 -0400296 if (readComponentType == GL_UNSIGNED_INT && drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400297 {
298 return gl::error(GL_INVALID_OPERATION, false);
299 }
300
Geoff Langb2f3d052013-08-13 12:49:27 -0400301 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400302 {
303 return gl::error(GL_INVALID_OPERATION, false);
304 }
305
Geoff Langb2f3d052013-08-13 12:49:27 -0400306 if (readColorBuffer->getSamples() > 0 && (readInternalFormat != drawInternalFormat || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400307 {
308 return gl::error(GL_INVALID_OPERATION, false);
309 }
310 }
311 }
312
Geoff Langb2f3d052013-08-13 12:49:27 -0400313 if ((readComponentType == GL_INT || readComponentType == GL_UNSIGNED_INT) && filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400314 {
315 return gl::error(GL_INVALID_OPERATION, false);
316 }
317
318 if (fromAngleExtension)
319 {
320 const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType();
321 if (readColorbufferType != GL_TEXTURE_2D && readColorbufferType != GL_RENDERBUFFER)
322 {
323 return gl::error(GL_INVALID_OPERATION, false);
324 }
325
326 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
327 {
328 if (drawFramebuffer->isEnabledColorAttachment(colorAttachment))
329 {
330 if (drawFramebuffer->getColorbufferType(colorAttachment) != GL_TEXTURE_2D &&
331 drawFramebuffer->getColorbufferType(colorAttachment) != GL_RENDERBUFFER)
332 {
333 return gl::error(GL_INVALID_OPERATION, false);
334 }
335
336 if (drawFramebuffer->getColorbuffer(colorAttachment)->getActualFormat() != readColorBuffer->getActualFormat())
337 {
338 return gl::error(GL_INVALID_OPERATION, false);
339 }
340 }
341 }
Geoff Lang125deab2013-08-09 13:34:16 -0400342 if (readFramebuffer->getSamples() != 0 && IsPartialBlit(context, readColorBuffer, drawColorBuffer,
343 srcX0, srcY0, srcX1, srcY1,
344 dstX0, dstY0, dstX1, dstY1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400345 {
346 return gl::error(GL_INVALID_OPERATION, false);
347 }
348 }
349 }
350 }
351
352 if (mask & GL_DEPTH_BUFFER_BIT)
353 {
354 gl::Renderbuffer *readDepthBuffer = readFramebuffer->getDepthbuffer();
355 gl::Renderbuffer *drawDepthBuffer = drawFramebuffer->getDepthbuffer();
356
357 if (readDepthBuffer && drawDepthBuffer)
358 {
359 if (readDepthBuffer->getActualFormat() != drawDepthBuffer->getActualFormat())
360 {
361 return gl::error(GL_INVALID_OPERATION, false);
362 }
363
364 if (readDepthBuffer->getSamples() > 0 && !sameBounds)
365 {
366 return gl::error(GL_INVALID_OPERATION, false);
367 }
368
369 if (fromAngleExtension)
370 {
Geoff Lang125deab2013-08-09 13:34:16 -0400371 if (IsPartialBlit(context, readDepthBuffer, drawDepthBuffer,
372 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400373 {
374 ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
375 return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted
376 }
377
378 if (readDepthBuffer->getSamples() != 0 || drawDepthBuffer->getSamples() != 0)
379 {
380 return gl::error(GL_INVALID_OPERATION, false);
381 }
382 }
383 }
384 }
385
386 if (mask & GL_STENCIL_BUFFER_BIT)
387 {
388 gl::Renderbuffer *readStencilBuffer = readFramebuffer->getStencilbuffer();
389 gl::Renderbuffer *drawStencilBuffer = drawFramebuffer->getStencilbuffer();
390
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400391 if (readStencilBuffer && drawStencilBuffer)
392 {
393 if (readStencilBuffer->getActualFormat() != drawStencilBuffer->getActualFormat())
394 {
395 return gl::error(GL_INVALID_OPERATION, false);
396 }
397
398 if (readStencilBuffer->getSamples() > 0 && !sameBounds)
399 {
400 return gl::error(GL_INVALID_OPERATION, false);
401 }
402
403 if (fromAngleExtension)
404 {
Geoff Lang125deab2013-08-09 13:34:16 -0400405 if (IsPartialBlit(context, readStencilBuffer, drawStencilBuffer,
406 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400407 {
408 ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
409 return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted
410 }
411
412 if (readStencilBuffer->getSamples() != 0 || drawStencilBuffer->getSamples() != 0)
413 {
414 return gl::error(GL_INVALID_OPERATION, false);
415 }
416 }
417 }
418 }
419
420 return true;
421}
422
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400423bool ValidateGetVertexAttribParameters(GLenum pname, int clientVersion)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400424{
425 switch (pname)
426 {
427 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
428 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
429 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
430 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
431 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
432 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
433 case GL_CURRENT_VERTEX_ATTRIB:
434 return true;
435
436 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
437 // Don't verify ES3 context because GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE uses
438 // the same constant.
439 META_ASSERT(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE);
440 return true;
441
442 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
443 return ((clientVersion >= 3) ? true : gl::error(GL_INVALID_ENUM, false));
444
445 default:
446 return gl::error(GL_INVALID_ENUM, false);
447 }
448}
449
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400450bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400451{
452 switch (pname)
453 {
454 case GL_TEXTURE_WRAP_R:
455 case GL_TEXTURE_SWIZZLE_R:
456 case GL_TEXTURE_SWIZZLE_G:
457 case GL_TEXTURE_SWIZZLE_B:
458 case GL_TEXTURE_SWIZZLE_A:
459 case GL_TEXTURE_BASE_LEVEL:
460 case GL_TEXTURE_MAX_LEVEL:
461 case GL_TEXTURE_COMPARE_MODE:
462 case GL_TEXTURE_COMPARE_FUNC:
463 case GL_TEXTURE_MIN_LOD:
464 case GL_TEXTURE_MAX_LOD:
465 if (context->getClientVersion() < 3)
466 {
467 return gl::error(GL_INVALID_ENUM, false);
468 }
469 break;
470
471 default: break;
472 }
473
474 switch (pname)
475 {
476 case GL_TEXTURE_WRAP_S:
477 case GL_TEXTURE_WRAP_T:
478 case GL_TEXTURE_WRAP_R:
479 switch (param)
480 {
481 case GL_REPEAT:
482 case GL_CLAMP_TO_EDGE:
483 case GL_MIRRORED_REPEAT:
484 return true;
485 default:
486 return gl::error(GL_INVALID_ENUM, false);
487 }
488
489 case GL_TEXTURE_MIN_FILTER:
490 switch (param)
491 {
492 case GL_NEAREST:
493 case GL_LINEAR:
494 case GL_NEAREST_MIPMAP_NEAREST:
495 case GL_LINEAR_MIPMAP_NEAREST:
496 case GL_NEAREST_MIPMAP_LINEAR:
497 case GL_LINEAR_MIPMAP_LINEAR:
498 return true;
499 default:
500 return gl::error(GL_INVALID_ENUM, false);
501 }
502 break;
503
504 case GL_TEXTURE_MAG_FILTER:
505 switch (param)
506 {
507 case GL_NEAREST:
508 case GL_LINEAR:
509 return true;
510 default:
511 return gl::error(GL_INVALID_ENUM, false);
512 }
513 break;
514
515 case GL_TEXTURE_USAGE_ANGLE:
516 switch (param)
517 {
518 case GL_NONE:
519 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
520 return true;
521 default:
522 return gl::error(GL_INVALID_ENUM, false);
523 }
524 break;
525
526 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
527 if (!context->supportsTextureFilterAnisotropy())
528 {
529 return gl::error(GL_INVALID_ENUM, false);
530 }
531
532 // we assume the parameter passed to this validation method is truncated, not rounded
533 if (param < 1)
534 {
535 return gl::error(GL_INVALID_VALUE, false);
536 }
537 return true;
538
539 case GL_TEXTURE_MIN_LOD:
540 case GL_TEXTURE_MAX_LOD:
541 // any value is permissible
542 return true;
543
544 case GL_TEXTURE_COMPARE_MODE:
Geoff Lang63b5f1f2013-09-23 14:52:14 -0400545 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400546 switch (param)
547 {
548 case GL_NONE:
549 case GL_COMPARE_REF_TO_TEXTURE:
550 return true;
551 default:
552 return gl::error(GL_INVALID_ENUM, false);
553 }
554 break;
555
556 case GL_TEXTURE_COMPARE_FUNC:
Geoff Lang63b5f1f2013-09-23 14:52:14 -0400557 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400558 switch (param)
559 {
560 case GL_LEQUAL:
561 case GL_GEQUAL:
562 case GL_LESS:
563 case GL_GREATER:
564 case GL_EQUAL:
565 case GL_NOTEQUAL:
566 case GL_ALWAYS:
567 case GL_NEVER:
568 return true;
569 default:
570 return gl::error(GL_INVALID_ENUM, false);
571 }
572 break;
573
574 case GL_TEXTURE_SWIZZLE_R:
575 case GL_TEXTURE_SWIZZLE_G:
576 case GL_TEXTURE_SWIZZLE_B:
577 case GL_TEXTURE_SWIZZLE_A:
578 case GL_TEXTURE_BASE_LEVEL:
579 case GL_TEXTURE_MAX_LEVEL:
580 UNIMPLEMENTED();
581 return true;
582
583 default:
584 return gl::error(GL_INVALID_ENUM, false);
585 }
586}
587
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400588bool ValidateSamplerObjectParameter(GLenum pname)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400589{
590 switch (pname)
591 {
592 case GL_TEXTURE_MIN_FILTER:
593 case GL_TEXTURE_MAG_FILTER:
594 case GL_TEXTURE_WRAP_S:
595 case GL_TEXTURE_WRAP_T:
596 case GL_TEXTURE_WRAP_R:
597 case GL_TEXTURE_MIN_LOD:
598 case GL_TEXTURE_MAX_LOD:
599 case GL_TEXTURE_COMPARE_MODE:
600 case GL_TEXTURE_COMPARE_FUNC:
601 return true;
602
603 default:
604 return gl::error(GL_INVALID_ENUM, false);
605 }
606}
607
608}