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