blob: 3bc63f6af408034a94cd3fa2ffe7a5d031014b41 [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 Lang0550d032014-01-30 11:29:07 -050024bool ValidCap(const Context *context, GLenum cap)
25{
26 switch (cap)
27 {
28 case GL_CULL_FACE:
29 case GL_POLYGON_OFFSET_FILL:
30 case GL_SAMPLE_ALPHA_TO_COVERAGE:
31 case GL_SAMPLE_COVERAGE:
32 case GL_SCISSOR_TEST:
33 case GL_STENCIL_TEST:
34 case GL_DEPTH_TEST:
35 case GL_BLEND:
36 case GL_DITHER:
37 return true;
38 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
39 case GL_RASTERIZER_DISCARD:
40 return (context->getClientVersion() >= 3);
41 default:
42 return false;
43 }
44}
45
Jamie Madill1fc7e2c2014-01-21 16:47:10 -050046bool ValidTextureTarget(const Context *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -040047{
Jamie Madilld7460c72014-01-21 16:38:14 -050048 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -040049 {
Jamie Madilld7460c72014-01-21 16:38:14 -050050 case GL_TEXTURE_2D:
51 case GL_TEXTURE_CUBE_MAP:
52 return true;
Jamie Madill35d15012013-10-07 10:46:37 -040053
Jamie Madilld7460c72014-01-21 16:38:14 -050054 case GL_TEXTURE_3D:
55 case GL_TEXTURE_2D_ARRAY:
56 return (context->getClientVersion() >= 3);
57
58 default:
59 return false;
60 }
Jamie Madill35d15012013-10-07 10:46:37 -040061}
62
Jamie Madill1fc7e2c2014-01-21 16:47:10 -050063bool ValidFramebufferTarget(GLenum target)
64{
65 META_ASSERT(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER);
66
67 switch (target)
68 {
69 case GL_FRAMEBUFFER: return true;
70 case GL_READ_FRAMEBUFFER: return true;
71 case GL_DRAW_FRAMEBUFFER: return true;
72 default: return false;
73 }
74}
75
Geoff Langce635692013-09-24 13:56:32 -040076bool ValidMipLevel(const gl::Context *context, GLenum target, GLint level)
77{
78 int maxLevel = 0;
79 switch (target)
80 {
81 case GL_TEXTURE_2D: maxLevel = context->getMaximum2DTextureLevel(); break;
82 case GL_TEXTURE_CUBE_MAP:
83 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
84 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
85 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
86 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
87 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
88 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: maxLevel = context->getMaximumCubeTextureLevel(); break;
89 case GL_TEXTURE_3D: maxLevel = context->getMaximum3DTextureLevel(); break;
90 case GL_TEXTURE_2D_ARRAY: maxLevel = context->getMaximum2DArrayTextureLevel(); break;
91 default: UNREACHABLE();
92 }
93
94 return level < maxLevel;
95}
96
97bool ValidImageSize(const gl::Context *context, GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth)
98{
99 if (level < 0 || width < 0 || height < 0 || depth < 0)
100 {
101 return false;
102 }
103
104 if (!context->supportsNonPower2Texture() && (level != 0 || !gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth)))
105 {
106 return false;
107 }
108
109 if (!ValidMipLevel(context, target, level))
110 {
111 return false;
112 }
113
114 return true;
115}
116
Geoff Lang005df412013-10-16 14:12:50 -0400117bool ValidCompressedImageSize(const gl::Context *context, GLenum internalFormat, GLsizei width, GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400118{
119 GLuint clientVersion = context->getClientVersion();
120 if (!IsFormatCompressed(internalFormat, clientVersion))
121 {
122 return false;
123 }
124
125 GLint blockWidth = GetCompressedBlockWidth(internalFormat, clientVersion);
126 GLint blockHeight = GetCompressedBlockHeight(internalFormat, clientVersion);
127 if (width < 0 || (width > blockWidth && width % blockWidth != 0) ||
128 height < 0 || (height > blockHeight && height % blockHeight != 0))
129 {
130 return false;
131 }
132
133 return true;
134}
135
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400136bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum target, GLsizei samples,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400137 GLenum internalformat, GLsizei width, GLsizei height,
138 bool angleExtension)
139{
140 switch (target)
141 {
142 case GL_RENDERBUFFER:
143 break;
144 default:
145 return gl::error(GL_INVALID_ENUM, false);
146 }
147
148 if (width < 0 || height < 0 || samples < 0)
149 {
150 return gl::error(GL_INVALID_VALUE, false);
151 }
152
153 if (!gl::IsValidInternalFormat(internalformat, context))
154 {
155 return gl::error(GL_INVALID_ENUM, false);
156 }
157
158 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
159 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
160 // only sized internal formats. The ES3 spec (section 4.4.2) does, however, state that the
161 // internal format must be sized and not an integer format if samples is greater than zero.
162 if (!gl::IsSizedInternalFormat(internalformat, context->getClientVersion()))
163 {
164 return gl::error(GL_INVALID_ENUM, false);
165 }
166
Geoff Langb2f3d052013-08-13 12:49:27 -0400167 GLenum componentType = gl::GetComponentType(internalformat, context->getClientVersion());
168 if ((componentType == GL_UNSIGNED_INT || componentType == GL_INT) && samples > 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400169 {
170 return gl::error(GL_INVALID_OPERATION, false);
171 }
172
173 if (!gl::IsColorRenderingSupported(internalformat, context) &&
174 !gl::IsDepthRenderingSupported(internalformat, context) &&
175 !gl::IsStencilRenderingSupported(internalformat, context))
176 {
177 return gl::error(GL_INVALID_ENUM, false);
178 }
179
180 if (std::max(width, height) > context->getMaximumRenderbufferDimension())
181 {
182 return gl::error(GL_INVALID_VALUE, false);
183 }
184
185 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
186 // to MAX_SAMPLES_ANGLE (Context::getMaxSupportedSamples) while the ES3.0 spec (section 4.4.2)
187 // states that samples must be less than or equal to the maximum samples for the specified
188 // internal format.
189 if (angleExtension)
190 {
191 if (samples > context->getMaxSupportedSamples())
192 {
193 return gl::error(GL_INVALID_VALUE, false);
194 }
195 }
196 else
197 {
198 if (samples > context->getMaxSupportedFormatSamples(internalformat))
199 {
200 return gl::error(GL_INVALID_VALUE, false);
201 }
202 }
203
204 GLuint handle = context->getRenderbufferHandle();
205 if (handle == 0)
206 {
207 return gl::error(GL_INVALID_OPERATION, false);
208 }
209
210 return true;
211}
212
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500213bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
214 GLenum renderbuffertarget, GLuint renderbuffer)
215{
216 gl::Framebuffer *framebuffer = context->getTargetFramebuffer(target);
217 GLuint framebufferHandle = context->getTargetFramebufferHandle(target);
218
219 if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0))
220 {
221 return gl::error(GL_INVALID_OPERATION, false);
222 }
223
224 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
225 {
226 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
227
228 if (colorAttachment >= context->getMaximumRenderTargets())
229 {
230 return gl::error(GL_INVALID_VALUE, false);
231 }
232 }
233 else
234 {
235 switch (attachment)
236 {
237 case GL_DEPTH_ATTACHMENT:
238 break;
239 case GL_STENCIL_ATTACHMENT:
240 break;
241 case GL_DEPTH_STENCIL_ATTACHMENT:
242 if (context->getClientVersion() < 3)
243 {
244 return gl::error(GL_INVALID_ENUM, false);
245 }
246 break;
247 default:
248 return gl::error(GL_INVALID_ENUM, false);
249 }
250 }
251
Jamie Madillab9d82c2014-01-21 16:38:14 -0500252 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
253 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
254 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
255 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
256 if (renderbuffer != 0)
257 {
258 if (!context->getRenderbuffer(renderbuffer))
259 {
260 return gl::error(GL_INVALID_OPERATION, false);
261 }
262 }
263
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500264 return true;
265}
266
Geoff Lang125deab2013-08-09 13:34:16 -0400267static bool IsPartialBlit(gl::Context *context, gl::Renderbuffer *readBuffer, gl::Renderbuffer *writeBuffer,
268 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
269 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
270{
271 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 ||
272 dstX1 != writeBuffer->getWidth() || dstY1 != writeBuffer->getHeight() ||
273 srcX1 != readBuffer->getWidth() || srcY1 != readBuffer->getHeight())
274 {
275 return true;
276 }
277 else if (context->isScissorTestEnabled())
278 {
279 int scissorX, scissorY, scissorWidth, scissorHeight;
280 context->getScissorParams(&scissorX, &scissorY, &scissorWidth, &scissorHeight);
281
282 return scissorX > 0 || scissorY > 0 ||
283 scissorWidth < writeBuffer->getWidth() ||
284 scissorHeight < writeBuffer->getHeight();
285 }
286 else
287 {
288 return false;
289 }
290}
291
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400292bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400293 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask,
294 GLenum filter, bool fromAngleExtension)
295{
296 switch (filter)
297 {
298 case GL_NEAREST:
299 break;
300 case GL_LINEAR:
301 if (fromAngleExtension)
302 {
303 return gl::error(GL_INVALID_ENUM, false);
304 }
305 break;
306 default:
307 return gl::error(GL_INVALID_ENUM, false);
308 }
309
310 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
311 {
312 return gl::error(GL_INVALID_VALUE, false);
313 }
314
315 if (mask == 0)
316 {
317 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
318 // buffers are copied.
319 return false;
320 }
321
322 if (fromAngleExtension && (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0))
323 {
324 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation.");
325 return gl::error(GL_INVALID_OPERATION, false);
326 }
327
328 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
329 // color buffer, leaving only nearest being unfiltered from above
330 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
331 {
332 return gl::error(GL_INVALID_OPERATION, false);
333 }
334
335 if (context->getReadFramebufferHandle() == context->getDrawFramebufferHandle())
336 {
337 if (fromAngleExtension)
338 {
339 ERR("Blits with the same source and destination framebuffer are not supported by this "
340 "implementation.");
341 }
342 return gl::error(GL_INVALID_OPERATION, false);
343 }
344
345 gl::Framebuffer *readFramebuffer = context->getReadFramebuffer();
346 gl::Framebuffer *drawFramebuffer = context->getDrawFramebuffer();
347 if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE ||
348 !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
349 {
350 return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
351 }
352
353 if (drawFramebuffer->getSamples() != 0)
354 {
355 return gl::error(GL_INVALID_OPERATION, false);
356 }
357
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400358 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
359
360 GLuint clientVersion = context->getClientVersion();
361
362 if (mask & GL_COLOR_BUFFER_BIT)
363 {
364 gl::Renderbuffer *readColorBuffer = readFramebuffer->getReadColorbuffer();
365 gl::Renderbuffer *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
366
367 if (readColorBuffer && drawColorBuffer)
368 {
Geoff Lang005df412013-10-16 14:12:50 -0400369 GLenum readInternalFormat = readColorBuffer->getActualFormat();
Geoff Langb2f3d052013-08-13 12:49:27 -0400370 GLenum readComponentType = gl::GetComponentType(readInternalFormat, clientVersion);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400371
372 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; i++)
373 {
374 if (drawFramebuffer->isEnabledColorAttachment(i))
375 {
Geoff Lang005df412013-10-16 14:12:50 -0400376 GLenum drawInternalFormat = drawFramebuffer->getColorbuffer(i)->getActualFormat();
Geoff Langb2f3d052013-08-13 12:49:27 -0400377 GLenum drawComponentType = gl::GetComponentType(drawInternalFormat, clientVersion);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400378
Geoff Langb2f3d052013-08-13 12:49:27 -0400379 // The GL ES 3.0.2 spec (pg 193) states that:
380 // 1) If the read buffer is fixed point format, the draw buffer must be as well
381 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
382 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
383 if ( (readComponentType == GL_UNSIGNED_NORMALIZED || readComponentType == GL_SIGNED_NORMALIZED) &&
384 !(drawComponentType == GL_UNSIGNED_NORMALIZED || drawComponentType == GL_SIGNED_NORMALIZED))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400385 {
386 return gl::error(GL_INVALID_OPERATION, false);
387 }
388
Geoff Langb2f3d052013-08-13 12:49:27 -0400389 if (readComponentType == GL_UNSIGNED_INT && drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400390 {
391 return gl::error(GL_INVALID_OPERATION, false);
392 }
393
Geoff Langb2f3d052013-08-13 12:49:27 -0400394 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400395 {
396 return gl::error(GL_INVALID_OPERATION, false);
397 }
398
Geoff Langb2f3d052013-08-13 12:49:27 -0400399 if (readColorBuffer->getSamples() > 0 && (readInternalFormat != drawInternalFormat || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400400 {
401 return gl::error(GL_INVALID_OPERATION, false);
402 }
403 }
404 }
405
Geoff Langb2f3d052013-08-13 12:49:27 -0400406 if ((readComponentType == GL_INT || readComponentType == GL_UNSIGNED_INT) && filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400407 {
408 return gl::error(GL_INVALID_OPERATION, false);
409 }
410
411 if (fromAngleExtension)
412 {
413 const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType();
414 if (readColorbufferType != GL_TEXTURE_2D && readColorbufferType != GL_RENDERBUFFER)
415 {
416 return gl::error(GL_INVALID_OPERATION, false);
417 }
418
419 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
420 {
421 if (drawFramebuffer->isEnabledColorAttachment(colorAttachment))
422 {
423 if (drawFramebuffer->getColorbufferType(colorAttachment) != GL_TEXTURE_2D &&
424 drawFramebuffer->getColorbufferType(colorAttachment) != GL_RENDERBUFFER)
425 {
426 return gl::error(GL_INVALID_OPERATION, false);
427 }
428
429 if (drawFramebuffer->getColorbuffer(colorAttachment)->getActualFormat() != readColorBuffer->getActualFormat())
430 {
431 return gl::error(GL_INVALID_OPERATION, false);
432 }
433 }
434 }
Geoff Lang125deab2013-08-09 13:34:16 -0400435 if (readFramebuffer->getSamples() != 0 && IsPartialBlit(context, readColorBuffer, drawColorBuffer,
436 srcX0, srcY0, srcX1, srcY1,
437 dstX0, dstY0, dstX1, dstY1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400438 {
439 return gl::error(GL_INVALID_OPERATION, false);
440 }
441 }
442 }
443 }
444
445 if (mask & GL_DEPTH_BUFFER_BIT)
446 {
447 gl::Renderbuffer *readDepthBuffer = readFramebuffer->getDepthbuffer();
448 gl::Renderbuffer *drawDepthBuffer = drawFramebuffer->getDepthbuffer();
449
450 if (readDepthBuffer && drawDepthBuffer)
451 {
452 if (readDepthBuffer->getActualFormat() != drawDepthBuffer->getActualFormat())
453 {
454 return gl::error(GL_INVALID_OPERATION, false);
455 }
456
457 if (readDepthBuffer->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, readDepthBuffer, drawDepthBuffer,
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 (readDepthBuffer->getSamples() != 0 || drawDepthBuffer->getSamples() != 0)
472 {
473 return gl::error(GL_INVALID_OPERATION, false);
474 }
475 }
476 }
477 }
478
479 if (mask & GL_STENCIL_BUFFER_BIT)
480 {
481 gl::Renderbuffer *readStencilBuffer = readFramebuffer->getStencilbuffer();
482 gl::Renderbuffer *drawStencilBuffer = drawFramebuffer->getStencilbuffer();
483
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400484 if (readStencilBuffer && drawStencilBuffer)
485 {
486 if (readStencilBuffer->getActualFormat() != drawStencilBuffer->getActualFormat())
487 {
488 return gl::error(GL_INVALID_OPERATION, false);
489 }
490
491 if (readStencilBuffer->getSamples() > 0 && !sameBounds)
492 {
493 return gl::error(GL_INVALID_OPERATION, false);
494 }
495
496 if (fromAngleExtension)
497 {
Geoff Lang125deab2013-08-09 13:34:16 -0400498 if (IsPartialBlit(context, readStencilBuffer, drawStencilBuffer,
499 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400500 {
501 ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
502 return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted
503 }
504
505 if (readStencilBuffer->getSamples() != 0 || drawStencilBuffer->getSamples() != 0)
506 {
507 return gl::error(GL_INVALID_OPERATION, false);
508 }
509 }
510 }
511 }
512
513 return true;
514}
515
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400516bool ValidateGetVertexAttribParameters(GLenum pname, int clientVersion)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400517{
518 switch (pname)
519 {
520 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
521 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
522 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
523 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
524 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
525 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
526 case GL_CURRENT_VERTEX_ATTRIB:
527 return true;
528
529 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
530 // Don't verify ES3 context because GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE uses
531 // the same constant.
532 META_ASSERT(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE);
533 return true;
534
535 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
536 return ((clientVersion >= 3) ? true : gl::error(GL_INVALID_ENUM, false));
537
538 default:
539 return gl::error(GL_INVALID_ENUM, false);
540 }
541}
542
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400543bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400544{
545 switch (pname)
546 {
547 case GL_TEXTURE_WRAP_R:
548 case GL_TEXTURE_SWIZZLE_R:
549 case GL_TEXTURE_SWIZZLE_G:
550 case GL_TEXTURE_SWIZZLE_B:
551 case GL_TEXTURE_SWIZZLE_A:
552 case GL_TEXTURE_BASE_LEVEL:
553 case GL_TEXTURE_MAX_LEVEL:
554 case GL_TEXTURE_COMPARE_MODE:
555 case GL_TEXTURE_COMPARE_FUNC:
556 case GL_TEXTURE_MIN_LOD:
557 case GL_TEXTURE_MAX_LOD:
558 if (context->getClientVersion() < 3)
559 {
560 return gl::error(GL_INVALID_ENUM, false);
561 }
562 break;
563
564 default: break;
565 }
566
567 switch (pname)
568 {
569 case GL_TEXTURE_WRAP_S:
570 case GL_TEXTURE_WRAP_T:
571 case GL_TEXTURE_WRAP_R:
572 switch (param)
573 {
574 case GL_REPEAT:
575 case GL_CLAMP_TO_EDGE:
576 case GL_MIRRORED_REPEAT:
577 return true;
578 default:
579 return gl::error(GL_INVALID_ENUM, false);
580 }
581
582 case GL_TEXTURE_MIN_FILTER:
583 switch (param)
584 {
585 case GL_NEAREST:
586 case GL_LINEAR:
587 case GL_NEAREST_MIPMAP_NEAREST:
588 case GL_LINEAR_MIPMAP_NEAREST:
589 case GL_NEAREST_MIPMAP_LINEAR:
590 case GL_LINEAR_MIPMAP_LINEAR:
591 return true;
592 default:
593 return gl::error(GL_INVALID_ENUM, false);
594 }
595 break;
596
597 case GL_TEXTURE_MAG_FILTER:
598 switch (param)
599 {
600 case GL_NEAREST:
601 case GL_LINEAR:
602 return true;
603 default:
604 return gl::error(GL_INVALID_ENUM, false);
605 }
606 break;
607
608 case GL_TEXTURE_USAGE_ANGLE:
609 switch (param)
610 {
611 case GL_NONE:
612 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
613 return true;
614 default:
615 return gl::error(GL_INVALID_ENUM, false);
616 }
617 break;
618
619 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
620 if (!context->supportsTextureFilterAnisotropy())
621 {
622 return gl::error(GL_INVALID_ENUM, false);
623 }
624
625 // we assume the parameter passed to this validation method is truncated, not rounded
626 if (param < 1)
627 {
628 return gl::error(GL_INVALID_VALUE, false);
629 }
630 return true;
631
632 case GL_TEXTURE_MIN_LOD:
633 case GL_TEXTURE_MAX_LOD:
634 // any value is permissible
635 return true;
636
637 case GL_TEXTURE_COMPARE_MODE:
Geoff Lang63b5f1f2013-09-23 14:52:14 -0400638 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400639 switch (param)
640 {
641 case GL_NONE:
642 case GL_COMPARE_REF_TO_TEXTURE:
643 return true;
644 default:
645 return gl::error(GL_INVALID_ENUM, false);
646 }
647 break;
648
649 case GL_TEXTURE_COMPARE_FUNC:
Geoff Lang63b5f1f2013-09-23 14:52:14 -0400650 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400651 switch (param)
652 {
653 case GL_LEQUAL:
654 case GL_GEQUAL:
655 case GL_LESS:
656 case GL_GREATER:
657 case GL_EQUAL:
658 case GL_NOTEQUAL:
659 case GL_ALWAYS:
660 case GL_NEVER:
661 return true;
662 default:
663 return gl::error(GL_INVALID_ENUM, false);
664 }
665 break;
666
667 case GL_TEXTURE_SWIZZLE_R:
668 case GL_TEXTURE_SWIZZLE_G:
669 case GL_TEXTURE_SWIZZLE_B:
670 case GL_TEXTURE_SWIZZLE_A:
Geoff Langbc90a482013-09-17 16:51:27 -0400671 switch (param)
672 {
673 case GL_RED:
674 case GL_GREEN:
675 case GL_BLUE:
676 case GL_ALPHA:
677 case GL_ZERO:
678 case GL_ONE:
679 return true;
680 default:
681 return gl::error(GL_INVALID_ENUM, false);
682 }
683 break;
684
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400685 case GL_TEXTURE_BASE_LEVEL:
686 case GL_TEXTURE_MAX_LEVEL:
687 UNIMPLEMENTED();
688 return true;
689
690 default:
691 return gl::error(GL_INVALID_ENUM, false);
692 }
693}
694
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400695bool ValidateSamplerObjectParameter(GLenum pname)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400696{
697 switch (pname)
698 {
699 case GL_TEXTURE_MIN_FILTER:
700 case GL_TEXTURE_MAG_FILTER:
701 case GL_TEXTURE_WRAP_S:
702 case GL_TEXTURE_WRAP_T:
703 case GL_TEXTURE_WRAP_R:
704 case GL_TEXTURE_MIN_LOD:
705 case GL_TEXTURE_MAX_LOD:
706 case GL_TEXTURE_COMPARE_MODE:
707 case GL_TEXTURE_COMPARE_FUNC:
708 return true;
709
710 default:
711 return gl::error(GL_INVALID_ENUM, false);
712 }
713}
714
715}