blob: 5ed852cb75133e097f4f34e0e6ba26175865fa7c [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
Jamie Madill8c96d582014-03-05 15:01:23 -050076bool ValidBufferTarget(const Context *context, GLenum target)
77{
78 switch (target)
79 {
80 case GL_ARRAY_BUFFER:
81 case GL_ELEMENT_ARRAY_BUFFER:
82 return true;
83
84 case GL_COPY_READ_BUFFER:
85 case GL_COPY_WRITE_BUFFER:
86 case GL_PIXEL_PACK_BUFFER:
87 case GL_PIXEL_UNPACK_BUFFER:
88 case GL_TRANSFORM_FEEDBACK_BUFFER:
89 case GL_UNIFORM_BUFFER:
90 return (context->getClientVersion() >= 3);
91
92 default:
93 return false;
94 }
95}
96
Jamie Madill70656a62014-03-05 15:01:26 -050097bool ValidBufferParameter(const Context *context, GLenum pname)
98{
99 switch (pname)
100 {
101 case GL_BUFFER_USAGE:
102 case GL_BUFFER_SIZE:
103 return true;
104
105 // GL_BUFFER_MAP_POINTER is a special case, and may only be
106 // queried with GetBufferPointerv
107 case GL_BUFFER_ACCESS_FLAGS:
108 case GL_BUFFER_MAPPED:
109 case GL_BUFFER_MAP_OFFSET:
110 case GL_BUFFER_MAP_LENGTH:
111 return (context->getClientVersion() >= 3);
112
113 default:
114 return false;
115 }
116}
117
Jamie Madill8c96d582014-03-05 15:01:23 -0500118bool ValidMipLevel(const Context *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400119{
120 int maxLevel = 0;
121 switch (target)
122 {
123 case GL_TEXTURE_2D: maxLevel = context->getMaximum2DTextureLevel(); break;
124 case GL_TEXTURE_CUBE_MAP:
125 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
126 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
127 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
128 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
129 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
130 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: maxLevel = context->getMaximumCubeTextureLevel(); break;
131 case GL_TEXTURE_3D: maxLevel = context->getMaximum3DTextureLevel(); break;
132 case GL_TEXTURE_2D_ARRAY: maxLevel = context->getMaximum2DArrayTextureLevel(); break;
133 default: UNREACHABLE();
134 }
135
136 return level < maxLevel;
137}
138
139bool ValidImageSize(const gl::Context *context, GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth)
140{
141 if (level < 0 || width < 0 || height < 0 || depth < 0)
142 {
143 return false;
144 }
145
146 if (!context->supportsNonPower2Texture() && (level != 0 || !gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth)))
147 {
148 return false;
149 }
150
151 if (!ValidMipLevel(context, target, level))
152 {
153 return false;
154 }
155
156 return true;
157}
158
Geoff Lang005df412013-10-16 14:12:50 -0400159bool ValidCompressedImageSize(const gl::Context *context, GLenum internalFormat, GLsizei width, GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400160{
161 GLuint clientVersion = context->getClientVersion();
162 if (!IsFormatCompressed(internalFormat, clientVersion))
163 {
164 return false;
165 }
166
167 GLint blockWidth = GetCompressedBlockWidth(internalFormat, clientVersion);
168 GLint blockHeight = GetCompressedBlockHeight(internalFormat, clientVersion);
169 if (width < 0 || (width > blockWidth && width % blockWidth != 0) ||
170 height < 0 || (height > blockHeight && height % blockHeight != 0))
171 {
172 return false;
173 }
174
175 return true;
176}
177
Geoff Lang37dde692014-01-31 16:34:54 -0500178bool ValidQueryType(const Context *context, GLenum queryType)
179{
180 META_ASSERT(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT);
181 META_ASSERT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT);
182
183 switch (queryType)
184 {
185 case GL_ANY_SAMPLES_PASSED:
186 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
187 return true;
188 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
189 return (context->getClientVersion() >= 3);
190 default:
191 return false;
192 }
193}
194
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400195bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum target, GLsizei samples,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400196 GLenum internalformat, GLsizei width, GLsizei height,
197 bool angleExtension)
198{
199 switch (target)
200 {
201 case GL_RENDERBUFFER:
202 break;
203 default:
204 return gl::error(GL_INVALID_ENUM, false);
205 }
206
207 if (width < 0 || height < 0 || samples < 0)
208 {
209 return gl::error(GL_INVALID_VALUE, false);
210 }
211
212 if (!gl::IsValidInternalFormat(internalformat, context))
213 {
214 return gl::error(GL_INVALID_ENUM, false);
215 }
216
217 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
218 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
219 // only sized internal formats. The ES3 spec (section 4.4.2) does, however, state that the
220 // internal format must be sized and not an integer format if samples is greater than zero.
221 if (!gl::IsSizedInternalFormat(internalformat, context->getClientVersion()))
222 {
223 return gl::error(GL_INVALID_ENUM, false);
224 }
225
Geoff Langb2f3d052013-08-13 12:49:27 -0400226 GLenum componentType = gl::GetComponentType(internalformat, context->getClientVersion());
227 if ((componentType == GL_UNSIGNED_INT || componentType == GL_INT) && samples > 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400228 {
229 return gl::error(GL_INVALID_OPERATION, false);
230 }
231
232 if (!gl::IsColorRenderingSupported(internalformat, context) &&
233 !gl::IsDepthRenderingSupported(internalformat, context) &&
234 !gl::IsStencilRenderingSupported(internalformat, context))
235 {
236 return gl::error(GL_INVALID_ENUM, false);
237 }
238
239 if (std::max(width, height) > context->getMaximumRenderbufferDimension())
240 {
241 return gl::error(GL_INVALID_VALUE, false);
242 }
243
244 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
245 // to MAX_SAMPLES_ANGLE (Context::getMaxSupportedSamples) while the ES3.0 spec (section 4.4.2)
246 // states that samples must be less than or equal to the maximum samples for the specified
247 // internal format.
248 if (angleExtension)
249 {
250 if (samples > context->getMaxSupportedSamples())
251 {
252 return gl::error(GL_INVALID_VALUE, false);
253 }
254 }
255 else
256 {
257 if (samples > context->getMaxSupportedFormatSamples(internalformat))
258 {
259 return gl::error(GL_INVALID_VALUE, false);
260 }
261 }
262
263 GLuint handle = context->getRenderbufferHandle();
264 if (handle == 0)
265 {
266 return gl::error(GL_INVALID_OPERATION, false);
267 }
268
269 return true;
270}
271
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500272bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
273 GLenum renderbuffertarget, GLuint renderbuffer)
274{
275 gl::Framebuffer *framebuffer = context->getTargetFramebuffer(target);
276 GLuint framebufferHandle = context->getTargetFramebufferHandle(target);
277
278 if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0))
279 {
280 return gl::error(GL_INVALID_OPERATION, false);
281 }
282
283 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
284 {
285 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
286
287 if (colorAttachment >= context->getMaximumRenderTargets())
288 {
289 return gl::error(GL_INVALID_VALUE, false);
290 }
291 }
292 else
293 {
294 switch (attachment)
295 {
296 case GL_DEPTH_ATTACHMENT:
297 break;
298 case GL_STENCIL_ATTACHMENT:
299 break;
300 case GL_DEPTH_STENCIL_ATTACHMENT:
301 if (context->getClientVersion() < 3)
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
Jamie Madillab9d82c2014-01-21 16:38:14 -0500311 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
312 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
313 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
314 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
315 if (renderbuffer != 0)
316 {
317 if (!context->getRenderbuffer(renderbuffer))
318 {
319 return gl::error(GL_INVALID_OPERATION, false);
320 }
321 }
322
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500323 return true;
324}
325
Geoff Lang125deab2013-08-09 13:34:16 -0400326static bool IsPartialBlit(gl::Context *context, gl::Renderbuffer *readBuffer, gl::Renderbuffer *writeBuffer,
327 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
328 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
329{
330 if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 ||
331 dstX1 != writeBuffer->getWidth() || dstY1 != writeBuffer->getHeight() ||
332 srcX1 != readBuffer->getWidth() || srcY1 != readBuffer->getHeight())
333 {
334 return true;
335 }
336 else if (context->isScissorTestEnabled())
337 {
338 int scissorX, scissorY, scissorWidth, scissorHeight;
339 context->getScissorParams(&scissorX, &scissorY, &scissorWidth, &scissorHeight);
340
341 return scissorX > 0 || scissorY > 0 ||
342 scissorWidth < writeBuffer->getWidth() ||
343 scissorHeight < writeBuffer->getHeight();
344 }
345 else
346 {
347 return false;
348 }
349}
350
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400351bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400352 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask,
353 GLenum filter, bool fromAngleExtension)
354{
355 switch (filter)
356 {
357 case GL_NEAREST:
358 break;
359 case GL_LINEAR:
360 if (fromAngleExtension)
361 {
362 return gl::error(GL_INVALID_ENUM, false);
363 }
364 break;
365 default:
366 return gl::error(GL_INVALID_ENUM, false);
367 }
368
369 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
370 {
371 return gl::error(GL_INVALID_VALUE, false);
372 }
373
374 if (mask == 0)
375 {
376 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
377 // buffers are copied.
378 return false;
379 }
380
381 if (fromAngleExtension && (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0))
382 {
383 ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation.");
384 return gl::error(GL_INVALID_OPERATION, false);
385 }
386
387 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
388 // color buffer, leaving only nearest being unfiltered from above
389 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
390 {
391 return gl::error(GL_INVALID_OPERATION, false);
392 }
393
394 if (context->getReadFramebufferHandle() == context->getDrawFramebufferHandle())
395 {
396 if (fromAngleExtension)
397 {
398 ERR("Blits with the same source and destination framebuffer are not supported by this "
399 "implementation.");
400 }
401 return gl::error(GL_INVALID_OPERATION, false);
402 }
403
404 gl::Framebuffer *readFramebuffer = context->getReadFramebuffer();
405 gl::Framebuffer *drawFramebuffer = context->getDrawFramebuffer();
406 if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE ||
407 !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
408 {
409 return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
410 }
411
412 if (drawFramebuffer->getSamples() != 0)
413 {
414 return gl::error(GL_INVALID_OPERATION, false);
415 }
416
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400417 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
418
419 GLuint clientVersion = context->getClientVersion();
420
421 if (mask & GL_COLOR_BUFFER_BIT)
422 {
423 gl::Renderbuffer *readColorBuffer = readFramebuffer->getReadColorbuffer();
424 gl::Renderbuffer *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
425
426 if (readColorBuffer && drawColorBuffer)
427 {
Geoff Lang005df412013-10-16 14:12:50 -0400428 GLenum readInternalFormat = readColorBuffer->getActualFormat();
Geoff Langb2f3d052013-08-13 12:49:27 -0400429 GLenum readComponentType = gl::GetComponentType(readInternalFormat, clientVersion);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400430
431 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; i++)
432 {
433 if (drawFramebuffer->isEnabledColorAttachment(i))
434 {
Geoff Lang005df412013-10-16 14:12:50 -0400435 GLenum drawInternalFormat = drawFramebuffer->getColorbuffer(i)->getActualFormat();
Geoff Langb2f3d052013-08-13 12:49:27 -0400436 GLenum drawComponentType = gl::GetComponentType(drawInternalFormat, clientVersion);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400437
Geoff Langb2f3d052013-08-13 12:49:27 -0400438 // The GL ES 3.0.2 spec (pg 193) states that:
439 // 1) If the read buffer is fixed point format, the draw buffer must be as well
440 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
441 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
442 if ( (readComponentType == GL_UNSIGNED_NORMALIZED || readComponentType == GL_SIGNED_NORMALIZED) &&
443 !(drawComponentType == GL_UNSIGNED_NORMALIZED || drawComponentType == GL_SIGNED_NORMALIZED))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400444 {
445 return gl::error(GL_INVALID_OPERATION, false);
446 }
447
Geoff Langb2f3d052013-08-13 12:49:27 -0400448 if (readComponentType == GL_UNSIGNED_INT && drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400449 {
450 return gl::error(GL_INVALID_OPERATION, false);
451 }
452
Geoff Langb2f3d052013-08-13 12:49:27 -0400453 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400454 {
455 return gl::error(GL_INVALID_OPERATION, false);
456 }
457
Geoff Langb2f3d052013-08-13 12:49:27 -0400458 if (readColorBuffer->getSamples() > 0 && (readInternalFormat != drawInternalFormat || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400459 {
460 return gl::error(GL_INVALID_OPERATION, false);
461 }
462 }
463 }
464
Geoff Langb2f3d052013-08-13 12:49:27 -0400465 if ((readComponentType == GL_INT || readComponentType == GL_UNSIGNED_INT) && filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400466 {
467 return gl::error(GL_INVALID_OPERATION, false);
468 }
469
470 if (fromAngleExtension)
471 {
472 const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType();
473 if (readColorbufferType != GL_TEXTURE_2D && readColorbufferType != GL_RENDERBUFFER)
474 {
475 return gl::error(GL_INVALID_OPERATION, false);
476 }
477
478 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
479 {
480 if (drawFramebuffer->isEnabledColorAttachment(colorAttachment))
481 {
482 if (drawFramebuffer->getColorbufferType(colorAttachment) != GL_TEXTURE_2D &&
483 drawFramebuffer->getColorbufferType(colorAttachment) != GL_RENDERBUFFER)
484 {
485 return gl::error(GL_INVALID_OPERATION, false);
486 }
487
488 if (drawFramebuffer->getColorbuffer(colorAttachment)->getActualFormat() != readColorBuffer->getActualFormat())
489 {
490 return gl::error(GL_INVALID_OPERATION, false);
491 }
492 }
493 }
Geoff Lang125deab2013-08-09 13:34:16 -0400494 if (readFramebuffer->getSamples() != 0 && IsPartialBlit(context, readColorBuffer, drawColorBuffer,
495 srcX0, srcY0, srcX1, srcY1,
496 dstX0, dstY0, dstX1, dstY1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400497 {
498 return gl::error(GL_INVALID_OPERATION, false);
499 }
500 }
501 }
502 }
503
504 if (mask & GL_DEPTH_BUFFER_BIT)
505 {
506 gl::Renderbuffer *readDepthBuffer = readFramebuffer->getDepthbuffer();
507 gl::Renderbuffer *drawDepthBuffer = drawFramebuffer->getDepthbuffer();
508
509 if (readDepthBuffer && drawDepthBuffer)
510 {
511 if (readDepthBuffer->getActualFormat() != drawDepthBuffer->getActualFormat())
512 {
513 return gl::error(GL_INVALID_OPERATION, false);
514 }
515
516 if (readDepthBuffer->getSamples() > 0 && !sameBounds)
517 {
518 return gl::error(GL_INVALID_OPERATION, false);
519 }
520
521 if (fromAngleExtension)
522 {
Geoff Lang125deab2013-08-09 13:34:16 -0400523 if (IsPartialBlit(context, readDepthBuffer, drawDepthBuffer,
524 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400525 {
526 ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
527 return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted
528 }
529
530 if (readDepthBuffer->getSamples() != 0 || drawDepthBuffer->getSamples() != 0)
531 {
532 return gl::error(GL_INVALID_OPERATION, false);
533 }
534 }
535 }
536 }
537
538 if (mask & GL_STENCIL_BUFFER_BIT)
539 {
540 gl::Renderbuffer *readStencilBuffer = readFramebuffer->getStencilbuffer();
541 gl::Renderbuffer *drawStencilBuffer = drawFramebuffer->getStencilbuffer();
542
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400543 if (readStencilBuffer && drawStencilBuffer)
544 {
545 if (readStencilBuffer->getActualFormat() != drawStencilBuffer->getActualFormat())
546 {
547 return gl::error(GL_INVALID_OPERATION, false);
548 }
549
550 if (readStencilBuffer->getSamples() > 0 && !sameBounds)
551 {
552 return gl::error(GL_INVALID_OPERATION, false);
553 }
554
555 if (fromAngleExtension)
556 {
Geoff Lang125deab2013-08-09 13:34:16 -0400557 if (IsPartialBlit(context, readStencilBuffer, drawStencilBuffer,
558 srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400559 {
560 ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
561 return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted
562 }
563
564 if (readStencilBuffer->getSamples() != 0 || drawStencilBuffer->getSamples() != 0)
565 {
566 return gl::error(GL_INVALID_OPERATION, false);
567 }
568 }
569 }
570 }
571
572 return true;
573}
574
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400575bool ValidateGetVertexAttribParameters(GLenum pname, int clientVersion)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400576{
577 switch (pname)
578 {
579 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
580 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
581 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
582 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
583 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
584 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
585 case GL_CURRENT_VERTEX_ATTRIB:
586 return true;
587
588 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
589 // Don't verify ES3 context because GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE uses
590 // the same constant.
591 META_ASSERT(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE);
592 return true;
593
594 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
595 return ((clientVersion >= 3) ? true : gl::error(GL_INVALID_ENUM, false));
596
597 default:
598 return gl::error(GL_INVALID_ENUM, false);
599 }
600}
601
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400602bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400603{
604 switch (pname)
605 {
606 case GL_TEXTURE_WRAP_R:
607 case GL_TEXTURE_SWIZZLE_R:
608 case GL_TEXTURE_SWIZZLE_G:
609 case GL_TEXTURE_SWIZZLE_B:
610 case GL_TEXTURE_SWIZZLE_A:
611 case GL_TEXTURE_BASE_LEVEL:
612 case GL_TEXTURE_MAX_LEVEL:
613 case GL_TEXTURE_COMPARE_MODE:
614 case GL_TEXTURE_COMPARE_FUNC:
615 case GL_TEXTURE_MIN_LOD:
616 case GL_TEXTURE_MAX_LOD:
617 if (context->getClientVersion() < 3)
618 {
619 return gl::error(GL_INVALID_ENUM, false);
620 }
621 break;
622
623 default: break;
624 }
625
626 switch (pname)
627 {
628 case GL_TEXTURE_WRAP_S:
629 case GL_TEXTURE_WRAP_T:
630 case GL_TEXTURE_WRAP_R:
631 switch (param)
632 {
633 case GL_REPEAT:
634 case GL_CLAMP_TO_EDGE:
635 case GL_MIRRORED_REPEAT:
636 return true;
637 default:
638 return gl::error(GL_INVALID_ENUM, false);
639 }
640
641 case GL_TEXTURE_MIN_FILTER:
642 switch (param)
643 {
644 case GL_NEAREST:
645 case GL_LINEAR:
646 case GL_NEAREST_MIPMAP_NEAREST:
647 case GL_LINEAR_MIPMAP_NEAREST:
648 case GL_NEAREST_MIPMAP_LINEAR:
649 case GL_LINEAR_MIPMAP_LINEAR:
650 return true;
651 default:
652 return gl::error(GL_INVALID_ENUM, false);
653 }
654 break;
655
656 case GL_TEXTURE_MAG_FILTER:
657 switch (param)
658 {
659 case GL_NEAREST:
660 case GL_LINEAR:
661 return true;
662 default:
663 return gl::error(GL_INVALID_ENUM, false);
664 }
665 break;
666
667 case GL_TEXTURE_USAGE_ANGLE:
668 switch (param)
669 {
670 case GL_NONE:
671 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
672 return true;
673 default:
674 return gl::error(GL_INVALID_ENUM, false);
675 }
676 break;
677
678 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
679 if (!context->supportsTextureFilterAnisotropy())
680 {
681 return gl::error(GL_INVALID_ENUM, false);
682 }
683
684 // we assume the parameter passed to this validation method is truncated, not rounded
685 if (param < 1)
686 {
687 return gl::error(GL_INVALID_VALUE, false);
688 }
689 return true;
690
691 case GL_TEXTURE_MIN_LOD:
692 case GL_TEXTURE_MAX_LOD:
693 // any value is permissible
694 return true;
695
696 case GL_TEXTURE_COMPARE_MODE:
Geoff Lang63b5f1f2013-09-23 14:52:14 -0400697 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400698 switch (param)
699 {
700 case GL_NONE:
701 case GL_COMPARE_REF_TO_TEXTURE:
702 return true;
703 default:
704 return gl::error(GL_INVALID_ENUM, false);
705 }
706 break;
707
708 case GL_TEXTURE_COMPARE_FUNC:
Geoff Lang63b5f1f2013-09-23 14:52:14 -0400709 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400710 switch (param)
711 {
712 case GL_LEQUAL:
713 case GL_GEQUAL:
714 case GL_LESS:
715 case GL_GREATER:
716 case GL_EQUAL:
717 case GL_NOTEQUAL:
718 case GL_ALWAYS:
719 case GL_NEVER:
720 return true;
721 default:
722 return gl::error(GL_INVALID_ENUM, false);
723 }
724 break;
725
726 case GL_TEXTURE_SWIZZLE_R:
727 case GL_TEXTURE_SWIZZLE_G:
728 case GL_TEXTURE_SWIZZLE_B:
729 case GL_TEXTURE_SWIZZLE_A:
Geoff Langbc90a482013-09-17 16:51:27 -0400730 switch (param)
731 {
732 case GL_RED:
733 case GL_GREEN:
734 case GL_BLUE:
735 case GL_ALPHA:
736 case GL_ZERO:
737 case GL_ONE:
738 return true;
739 default:
740 return gl::error(GL_INVALID_ENUM, false);
741 }
742 break;
743
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400744 case GL_TEXTURE_BASE_LEVEL:
745 case GL_TEXTURE_MAX_LEVEL:
746 UNIMPLEMENTED();
747 return true;
748
749 default:
750 return gl::error(GL_INVALID_ENUM, false);
751 }
752}
753
Geoff Lang34dbb6f2013-08-05 15:05:47 -0400754bool ValidateSamplerObjectParameter(GLenum pname)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400755{
756 switch (pname)
757 {
758 case GL_TEXTURE_MIN_FILTER:
759 case GL_TEXTURE_MAG_FILTER:
760 case GL_TEXTURE_WRAP_S:
761 case GL_TEXTURE_WRAP_T:
762 case GL_TEXTURE_WRAP_R:
763 case GL_TEXTURE_MIN_LOD:
764 case GL_TEXTURE_MAX_LOD:
765 case GL_TEXTURE_COMPARE_MODE:
766 case GL_TEXTURE_COMPARE_FUNC:
767 return true;
768
769 default:
770 return gl::error(GL_INVALID_ENUM, false);
771 }
772}
773
774}