Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / libGLESv2 / validationES.cpp
1 //
2 // Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
9 #include "libGLESv2/validationES.h"
10 #include "libGLESv2/validationES2.h"
11 #include "libGLESv2/validationES3.h"
12 #include "libGLESv2/Context.h"
13 #include "libGLESv2/Texture.h"
14 #include "libGLESv2/Framebuffer.h"
15 #include "libGLESv2/FramebufferAttachment.h"
16 #include "libGLESv2/formatutils.h"
17 #include "libGLESv2/main.h"
18 #include "libGLESv2/Query.h"
19 #include "libGLESv2/ProgramBinary.h"
20 #include "libGLESv2/TransformFeedback.h"
21 #include "libGLESv2/VertexArray.h"
22 #include "libGLESv2/renderer/BufferImpl.h"
23
24 #include "common/mathutil.h"
25 #include "common/utilities.h"
26
27 namespace gl
28 {
29
30 bool ValidCap(const Context *context, GLenum cap)
31 {
32     switch (cap)
33     {
34       case GL_CULL_FACE:
35       case GL_POLYGON_OFFSET_FILL:
36       case GL_SAMPLE_ALPHA_TO_COVERAGE:
37       case GL_SAMPLE_COVERAGE:
38       case GL_SCISSOR_TEST:
39       case GL_STENCIL_TEST:
40       case GL_DEPTH_TEST:
41       case GL_BLEND:
42       case GL_DITHER:
43         return true;
44       case GL_PRIMITIVE_RESTART_FIXED_INDEX:
45       case GL_RASTERIZER_DISCARD:
46         return (context->getClientVersion() >= 3);
47       default:
48         return false;
49     }
50 }
51
52 bool ValidTextureTarget(const Context *context, GLenum target)
53 {
54     switch (target)
55     {
56       case GL_TEXTURE_2D:
57       case GL_TEXTURE_CUBE_MAP:
58         return true;
59
60       case GL_TEXTURE_3D:
61       case GL_TEXTURE_2D_ARRAY:
62         return (context->getClientVersion() >= 3);
63
64       default:
65         return false;
66     }
67 }
68
69 // This function differs from ValidTextureTarget in that the target must be
70 // usable as the destination of a 2D operation-- so a cube face is valid, but
71 // GL_TEXTURE_CUBE_MAP is not.
72 // Note: duplicate of IsInternalTextureTarget
73 bool ValidTexture2DDestinationTarget(const Context *context, GLenum target)
74 {
75     switch (target)
76     {
77       case GL_TEXTURE_2D:
78       case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
79       case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
80       case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
81       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
82       case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
83       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
84         return true;
85       case GL_TEXTURE_2D_ARRAY:
86       case GL_TEXTURE_3D:
87         return (context->getClientVersion() >= 3);
88       default:
89         return false;
90     }
91 }
92
93 bool ValidFramebufferTarget(GLenum target)
94 {
95     META_ASSERT(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER);
96
97     switch (target)
98     {
99       case GL_FRAMEBUFFER:      return true;
100       case GL_READ_FRAMEBUFFER: return true;
101       case GL_DRAW_FRAMEBUFFER: return true;
102       default:                  return false;
103     }
104 }
105
106 bool ValidBufferTarget(const Context *context, GLenum target)
107 {
108     switch (target)
109     {
110       case GL_ARRAY_BUFFER:
111       case GL_ELEMENT_ARRAY_BUFFER:
112         return true;
113
114       case GL_PIXEL_PACK_BUFFER:
115       case GL_PIXEL_UNPACK_BUFFER:
116         return context->getExtensions().pixelBufferObject;
117
118       case GL_COPY_READ_BUFFER:
119       case GL_COPY_WRITE_BUFFER:
120       case GL_TRANSFORM_FEEDBACK_BUFFER:
121       case GL_UNIFORM_BUFFER:
122         return (context->getClientVersion() >= 3);
123
124       default:
125         return false;
126     }
127 }
128
129 bool ValidBufferParameter(const Context *context, GLenum pname)
130 {
131     switch (pname)
132     {
133       case GL_BUFFER_USAGE:
134       case GL_BUFFER_SIZE:
135         return true;
136
137       // GL_BUFFER_MAP_POINTER is a special case, and may only be
138       // queried with GetBufferPointerv
139       case GL_BUFFER_ACCESS_FLAGS:
140       case GL_BUFFER_MAPPED:
141       case GL_BUFFER_MAP_OFFSET:
142       case GL_BUFFER_MAP_LENGTH:
143         return (context->getClientVersion() >= 3);
144
145       default:
146         return false;
147     }
148 }
149
150 bool ValidMipLevel(const Context *context, GLenum target, GLint level)
151 {
152     size_t maxDimension = 0;
153     switch (target)
154     {
155       case GL_TEXTURE_2D:                  maxDimension = context->getCaps().max2DTextureSize;       break;
156       case GL_TEXTURE_CUBE_MAP:
157       case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
158       case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
159       case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
160       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
161       case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
162       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: maxDimension = context->getCaps().maxCubeMapTextureSize;  break;
163       case GL_TEXTURE_3D:                  maxDimension = context->getCaps().max3DTextureSize;       break;
164       case GL_TEXTURE_2D_ARRAY:            maxDimension = context->getCaps().max2DTextureSize;       break;
165       default: UNREACHABLE();
166     }
167
168     return level <= gl::log2(maxDimension);
169 }
170
171 bool ValidImageSize(const Context *context, GLenum target, GLint level,
172                     GLsizei width, GLsizei height, GLsizei depth)
173 {
174     if (level < 0 || width < 0 || height < 0 || depth < 0)
175     {
176         return false;
177     }
178
179     if (!context->getExtensions().textureNPOT &&
180         (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
181     {
182         return false;
183     }
184
185     if (!ValidMipLevel(context, target, level))
186     {
187         return false;
188     }
189
190     return true;
191 }
192
193 bool ValidCompressedImageSize(const Context *context, GLenum internalFormat, GLsizei width, GLsizei height)
194 {
195     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
196     if (!formatInfo.compressed)
197     {
198         return false;
199     }
200
201     if (width  < 0 || (static_cast<GLuint>(width)  > formatInfo.compressedBlockWidth  && width  % formatInfo.compressedBlockWidth != 0) ||
202         height < 0 || (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight && height % formatInfo.compressedBlockHeight != 0))
203     {
204         return false;
205     }
206
207     return true;
208 }
209
210 bool ValidQueryType(const Context *context, GLenum queryType)
211 {
212     META_ASSERT(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT);
213     META_ASSERT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT);
214
215     switch (queryType)
216     {
217       case GL_ANY_SAMPLES_PASSED:
218       case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
219         return true;
220       case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
221         return (context->getClientVersion() >= 3);
222       default:
223         return false;
224     }
225 }
226
227 bool ValidProgram(Context *context, GLuint id)
228 {
229     // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the
230     // error INVALID_VALUE if the provided name is not the name of either a shader or program object and
231     // INVALID_OPERATION if the provided name identifies an object that is not the expected type."
232
233     if (context->getProgram(id) != NULL)
234     {
235         return true;
236     }
237     else if (context->getShader(id) != NULL)
238     {
239         // ID is the wrong type
240         context->recordError(Error(GL_INVALID_OPERATION));
241         return false;
242     }
243     else
244     {
245         // No shader/program object has this ID
246         context->recordError(Error(GL_INVALID_VALUE));
247         return false;
248     }
249 }
250
251 bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
252 {
253     if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
254     {
255         const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
256
257         if (colorAttachment >= context->getCaps().maxColorAttachments)
258         {
259             context->recordError(Error(GL_INVALID_VALUE));
260             return false;
261         }
262     }
263     else
264     {
265         switch (attachment)
266         {
267           case GL_DEPTH_ATTACHMENT:
268           case GL_STENCIL_ATTACHMENT:
269             break;
270
271           case GL_DEPTH_STENCIL_ATTACHMENT:
272             if (context->getClientVersion() < 3)
273             {
274                 context->recordError(Error(GL_INVALID_ENUM));
275                 return false;
276             }
277             break;
278
279           default:
280             context->recordError(Error(GL_INVALID_ENUM));
281             return false;
282         }
283     }
284
285     return true;
286 }
287
288 bool ValidateRenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
289                                            GLenum internalformat, GLsizei width, GLsizei height,
290                                            bool angleExtension)
291 {
292     switch (target)
293     {
294       case GL_RENDERBUFFER:
295         break;
296       default:
297         context->recordError(Error(GL_INVALID_ENUM));
298         return false;
299     }
300
301     if (width < 0 || height < 0 || samples < 0)
302     {
303         context->recordError(Error(GL_INVALID_VALUE));
304         return false;
305     }
306
307     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
308     if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
309     {
310         context->recordError(Error(GL_INVALID_ENUM));
311         return false;
312     }
313
314     // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
315     // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
316     // only sized internal formats. The ES3 spec (section 4.4.2) does, however, state that the
317     // internal format must be sized and not an integer format if samples is greater than zero.
318     if (formatInfo.pixelBytes == 0)
319     {
320         context->recordError(Error(GL_INVALID_ENUM));
321         return false;
322     }
323
324     if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
325     {
326         context->recordError(Error(GL_INVALID_OPERATION));
327         return false;
328     }
329
330     const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
331     if (!formatCaps.renderable)
332     {
333         context->recordError(Error(GL_INVALID_ENUM));
334         return false;
335     }
336
337     if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
338     {
339         context->recordError(Error(GL_INVALID_VALUE));
340         return false;
341     }
342
343     // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
344     // to MAX_SAMPLES_ANGLE (Context::getMaxSupportedSamples) while the ES3.0 spec (section 4.4.2)
345     // states that samples must be less than or equal to the maximum samples for the specified
346     // internal format.
347     if (angleExtension)
348     {
349         ASSERT(context->getExtensions().framebufferMultisample);
350         if (static_cast<GLuint>(samples) > context->getExtensions().maxSamples)
351         {
352             context->recordError(Error(GL_INVALID_VALUE));
353             return false;
354         }
355
356         // Check if this specific format supports enough samples
357         if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
358         {
359             context->recordError(Error(GL_OUT_OF_MEMORY));
360             return false;
361         }
362     }
363     else
364     {
365         if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
366         {
367             context->recordError(Error(GL_INVALID_VALUE));
368             return false;
369         }
370     }
371
372     GLuint handle = context->getState().getRenderbufferId();
373     if (handle == 0)
374     {
375         context->recordError(Error(GL_INVALID_OPERATION));
376         return false;
377     }
378
379     return true;
380 }
381
382 bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
383                                                GLenum renderbuffertarget, GLuint renderbuffer)
384 {
385     if (!ValidFramebufferTarget(target))
386     {
387         context->recordError(Error(GL_INVALID_ENUM));
388         return false;
389     }
390
391     gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
392     GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id();
393
394     if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0))
395     {
396         context->recordError(Error(GL_INVALID_OPERATION));
397         return false;
398     }
399
400     if (!ValidateAttachmentTarget(context, attachment))
401     {
402         return false;
403     }
404
405     // [OpenGL ES 2.0.25] Section 4.4.3 page 112
406     // [OpenGL ES 3.0.2] Section 4.4.2 page 201
407     // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
408     // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
409     if (renderbuffer != 0)
410     {
411         if (!context->getRenderbuffer(renderbuffer))
412         {
413             context->recordError(Error(GL_INVALID_OPERATION));
414             return false;
415         }
416     }
417
418     return true;
419 }
420
421 static bool IsPartialBlit(gl::Context *context, gl::FramebufferAttachment *readBuffer, gl::FramebufferAttachment *writeBuffer,
422                           GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
423                           GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1)
424 {
425     if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 ||
426         dstX1 != writeBuffer->getWidth() || dstY1 != writeBuffer->getHeight() ||
427         srcX1 != readBuffer->getWidth() || srcY1 != readBuffer->getHeight())
428     {
429         return true;
430     }
431     else if (context->getState().isScissorTestEnabled())
432     {
433         const Rectangle &scissor = context->getState().getScissor();
434
435         return scissor.x > 0 || scissor.y > 0 ||
436                scissor.width < writeBuffer->getWidth() ||
437                scissor.height < writeBuffer->getHeight();
438     }
439     else
440     {
441         return false;
442     }
443 }
444
445 bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
446                                        GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask,
447                                        GLenum filter, bool fromAngleExtension)
448 {
449     switch (filter)
450     {
451       case GL_NEAREST:
452         break;
453       case GL_LINEAR:
454         if (fromAngleExtension)
455         {
456             context->recordError(Error(GL_INVALID_ENUM));
457             return false;
458         }
459         break;
460       default:
461         context->recordError(Error(GL_INVALID_ENUM));
462         return false;
463     }
464
465     if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
466     {
467         context->recordError(Error(GL_INVALID_VALUE));
468         return false;
469     }
470
471     if (mask == 0)
472     {
473         // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
474         // buffers are copied.
475         return false;
476     }
477
478     if (fromAngleExtension && (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0))
479     {
480         ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation.");
481         context->recordError(Error(GL_INVALID_OPERATION));
482         return false;
483     }
484
485     // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
486     // color buffer, leaving only nearest being unfiltered from above
487     if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
488     {
489         context->recordError(Error(GL_INVALID_OPERATION));
490         return false;
491     }
492
493     if (context->getState().getReadFramebuffer()->id() == context->getState().getDrawFramebuffer()->id())
494     {
495         if (fromAngleExtension)
496         {
497             ERR("Blits with the same source and destination framebuffer are not supported by this "
498                 "implementation.");
499         }
500         context->recordError(Error(GL_INVALID_OPERATION));
501         return false;
502     }
503
504     gl::Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
505     gl::Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
506     if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE ||
507         !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
508     {
509         context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
510         return false;
511     }
512
513     if (drawFramebuffer->getSamples() != 0)
514     {
515         context->recordError(Error(GL_INVALID_OPERATION));
516         return false;
517     }
518
519     bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
520
521     if (mask & GL_COLOR_BUFFER_BIT)
522     {
523         gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
524         gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
525
526         if (readColorBuffer && drawColorBuffer)
527         {
528             GLenum readInternalFormat = readColorBuffer->getActualFormat();
529             const InternalFormat &readFormatInfo = GetInternalFormatInfo(readInternalFormat);
530
531             for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; i++)
532             {
533                 if (drawFramebuffer->isEnabledColorAttachment(i))
534                 {
535                     GLenum drawInternalFormat = drawFramebuffer->getColorbuffer(i)->getActualFormat();
536                     const InternalFormat &drawFormatInfo = GetInternalFormatInfo(drawInternalFormat);
537
538                     // The GL ES 3.0.2 spec (pg 193) states that:
539                     // 1) If the read buffer is fixed point format, the draw buffer must be as well
540                     // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
541                     // 3) If the read buffer is a signed integer format, the draw buffer must be as well
542                     if ( (readFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || readFormatInfo.componentType == GL_SIGNED_NORMALIZED) &&
543                         !(drawFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || drawFormatInfo.componentType == GL_SIGNED_NORMALIZED))
544                     {
545                         context->recordError(Error(GL_INVALID_OPERATION));
546                         return false;
547                     }
548
549                     if (readFormatInfo.componentType == GL_UNSIGNED_INT && drawFormatInfo.componentType != GL_UNSIGNED_INT)
550                     {
551                         context->recordError(Error(GL_INVALID_OPERATION));
552                         return false;
553                     }
554
555                     if (readFormatInfo.componentType == GL_INT && drawFormatInfo.componentType != GL_INT)
556                     {
557                         context->recordError(Error(GL_INVALID_OPERATION));
558                         return false;
559                     }
560
561                     if (readColorBuffer->getSamples() > 0 && (readInternalFormat != drawInternalFormat || !sameBounds))
562                     {
563                         context->recordError(Error(GL_INVALID_OPERATION));
564                         return false;
565                     }
566                 }
567             }
568
569             if ((readFormatInfo.componentType == GL_INT || readFormatInfo.componentType == GL_UNSIGNED_INT) && filter == GL_LINEAR)
570             {
571                 context->recordError(Error(GL_INVALID_OPERATION));
572                 return false;
573             }
574
575             if (fromAngleExtension)
576             {
577                 const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType();
578                 if (readColorbufferType != GL_TEXTURE_2D && readColorbufferType != GL_RENDERBUFFER)
579                 {
580                     context->recordError(Error(GL_INVALID_OPERATION));
581                     return false;
582                 }
583
584                 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
585                 {
586                     if (drawFramebuffer->isEnabledColorAttachment(colorAttachment))
587                     {
588                         FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(colorAttachment);
589                         ASSERT(attachment);
590
591                         if (attachment->type() != GL_TEXTURE_2D && attachment->type() != GL_RENDERBUFFER)
592                         {
593                             context->recordError(Error(GL_INVALID_OPERATION));
594                             return false;
595                         }
596
597                         if (attachment->getActualFormat() != readColorBuffer->getActualFormat())
598                         {
599                             context->recordError(Error(GL_INVALID_OPERATION));
600                             return false;
601                         }
602                     }
603                 }
604                 if (readFramebuffer->getSamples() != 0 && IsPartialBlit(context, readColorBuffer, drawColorBuffer,
605                                                                         srcX0, srcY0, srcX1, srcY1,
606                                                                         dstX0, dstY0, dstX1, dstY1))
607                 {
608                     context->recordError(Error(GL_INVALID_OPERATION));
609                     return false;
610                 }
611             }
612         }
613     }
614
615     if (mask & GL_DEPTH_BUFFER_BIT)
616     {
617         gl::FramebufferAttachment *readDepthBuffer = readFramebuffer->getDepthbuffer();
618         gl::FramebufferAttachment *drawDepthBuffer = drawFramebuffer->getDepthbuffer();
619
620         if (readDepthBuffer && drawDepthBuffer)
621         {
622             if (readDepthBuffer->getActualFormat() != drawDepthBuffer->getActualFormat())
623             {
624                 context->recordError(Error(GL_INVALID_OPERATION));
625                 return false;
626             }
627
628             if (readDepthBuffer->getSamples() > 0 && !sameBounds)
629             {
630                 context->recordError(Error(GL_INVALID_OPERATION));
631                 return false;
632             }
633
634             if (fromAngleExtension)
635             {
636                 if (IsPartialBlit(context, readDepthBuffer, drawDepthBuffer,
637                                   srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
638                 {
639                     ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
640                     context->recordError(Error(GL_INVALID_OPERATION)); // only whole-buffer copies are permitted
641                     return false;
642                 }
643
644                 if (readDepthBuffer->getSamples() != 0 || drawDepthBuffer->getSamples() != 0)
645                 {
646                     context->recordError(Error(GL_INVALID_OPERATION));
647                     return false;
648                 }
649             }
650         }
651     }
652
653     if (mask & GL_STENCIL_BUFFER_BIT)
654     {
655         gl::FramebufferAttachment *readStencilBuffer = readFramebuffer->getStencilbuffer();
656         gl::FramebufferAttachment *drawStencilBuffer = drawFramebuffer->getStencilbuffer();
657
658         if (readStencilBuffer && drawStencilBuffer)
659         {
660             if (readStencilBuffer->getActualFormat() != drawStencilBuffer->getActualFormat())
661             {
662                 context->recordError(Error(GL_INVALID_OPERATION));
663                 return false;
664             }
665
666             if (readStencilBuffer->getSamples() > 0 && !sameBounds)
667             {
668                 context->recordError(Error(GL_INVALID_OPERATION));
669                 return false;
670             }
671
672             if (fromAngleExtension)
673             {
674                 if (IsPartialBlit(context, readStencilBuffer, drawStencilBuffer,
675                                   srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
676                 {
677                     ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
678                     context->recordError(Error(GL_INVALID_OPERATION)); // only whole-buffer copies are permitted
679                     return false;
680                 }
681
682                 if (readStencilBuffer->getSamples() != 0 || drawStencilBuffer->getSamples() != 0)
683                 {
684                     context->recordError(Error(GL_INVALID_OPERATION));
685                     return false;
686                 }
687             }
688         }
689     }
690
691     return true;
692 }
693
694 bool ValidateGetVertexAttribParameters(Context *context, GLenum pname)
695 {
696     switch (pname)
697     {
698       case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
699       case GL_VERTEX_ATTRIB_ARRAY_SIZE:
700       case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
701       case GL_VERTEX_ATTRIB_ARRAY_TYPE:
702       case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
703       case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
704       case GL_CURRENT_VERTEX_ATTRIB:
705         return true;
706
707       case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
708         // Don't verify ES3 context because GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE uses
709         // the same constant.
710         META_ASSERT(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE);
711         return true;
712
713       case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
714         if (context->getClientVersion() < 3)
715         {
716             context->recordError(Error(GL_INVALID_ENUM));
717             return false;
718         }
719         return true;
720
721       default:
722         context->recordError(Error(GL_INVALID_ENUM));
723         return false;
724     }
725 }
726
727 bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param)
728 {
729     switch (pname)
730     {
731       case GL_TEXTURE_WRAP_R:
732       case GL_TEXTURE_SWIZZLE_R:
733       case GL_TEXTURE_SWIZZLE_G:
734       case GL_TEXTURE_SWIZZLE_B:
735       case GL_TEXTURE_SWIZZLE_A:
736       case GL_TEXTURE_BASE_LEVEL:
737       case GL_TEXTURE_MAX_LEVEL:
738       case GL_TEXTURE_COMPARE_MODE:
739       case GL_TEXTURE_COMPARE_FUNC:
740       case GL_TEXTURE_MIN_LOD:
741       case GL_TEXTURE_MAX_LOD:
742         if (context->getClientVersion() < 3)
743         {
744             context->recordError(Error(GL_INVALID_ENUM));
745             return false;
746         }
747         break;
748
749       default: break;
750     }
751
752     switch (pname)
753     {
754       case GL_TEXTURE_WRAP_S:
755       case GL_TEXTURE_WRAP_T:
756       case GL_TEXTURE_WRAP_R:
757         switch (param)
758         {
759           case GL_REPEAT:
760           case GL_CLAMP_TO_EDGE:
761           case GL_MIRRORED_REPEAT:
762             return true;
763           default:
764             context->recordError(Error(GL_INVALID_ENUM));
765             return false;
766         }
767
768       case GL_TEXTURE_MIN_FILTER:
769         switch (param)
770         {
771           case GL_NEAREST:
772           case GL_LINEAR:
773           case GL_NEAREST_MIPMAP_NEAREST:
774           case GL_LINEAR_MIPMAP_NEAREST:
775           case GL_NEAREST_MIPMAP_LINEAR:
776           case GL_LINEAR_MIPMAP_LINEAR:
777             return true;
778           default:
779             context->recordError(Error(GL_INVALID_ENUM));
780             return false;
781         }
782         break;
783
784       case GL_TEXTURE_MAG_FILTER:
785         switch (param)
786         {
787           case GL_NEAREST:
788           case GL_LINEAR:
789             return true;
790           default:
791             context->recordError(Error(GL_INVALID_ENUM));
792             return false;
793         }
794         break;
795
796       case GL_TEXTURE_USAGE_ANGLE:
797         switch (param)
798         {
799           case GL_NONE:
800           case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
801             return true;
802           default:
803             context->recordError(Error(GL_INVALID_ENUM));
804             return false;
805         }
806         break;
807
808       case GL_TEXTURE_MAX_ANISOTROPY_EXT:
809         if (!context->getExtensions().textureFilterAnisotropic)
810         {
811             context->recordError(Error(GL_INVALID_ENUM));
812             return false;
813         }
814
815         // we assume the parameter passed to this validation method is truncated, not rounded
816         if (param < 1)
817         {
818             context->recordError(Error(GL_INVALID_VALUE));
819             return false;
820         }
821         return true;
822
823       case GL_TEXTURE_MIN_LOD:
824       case GL_TEXTURE_MAX_LOD:
825         // any value is permissible
826         return true;
827
828       case GL_TEXTURE_COMPARE_MODE:
829         // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
830         switch (param)
831         {
832           case GL_NONE:
833           case GL_COMPARE_REF_TO_TEXTURE:
834             return true;
835           default:
836             context->recordError(Error(GL_INVALID_ENUM));
837             return false;
838         }
839         break;
840
841       case GL_TEXTURE_COMPARE_FUNC:
842         // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
843         switch (param)
844         {
845           case GL_LEQUAL:
846           case GL_GEQUAL:
847           case GL_LESS:
848           case GL_GREATER:
849           case GL_EQUAL:
850           case GL_NOTEQUAL:
851           case GL_ALWAYS:
852           case GL_NEVER:
853             return true;
854           default:
855             context->recordError(Error(GL_INVALID_ENUM));
856             return false;
857         }
858         break;
859
860       case GL_TEXTURE_SWIZZLE_R:
861       case GL_TEXTURE_SWIZZLE_G:
862       case GL_TEXTURE_SWIZZLE_B:
863       case GL_TEXTURE_SWIZZLE_A:
864         switch (param)
865         {
866           case GL_RED:
867           case GL_GREEN:
868           case GL_BLUE:
869           case GL_ALPHA:
870           case GL_ZERO:
871           case GL_ONE:
872             return true;
873           default:
874             context->recordError(Error(GL_INVALID_ENUM));
875             return false;
876         }
877         break;
878
879       case GL_TEXTURE_BASE_LEVEL:
880       case GL_TEXTURE_MAX_LEVEL:
881         if (param < 0)
882         {
883             context->recordError(Error(GL_INVALID_VALUE));
884             return false;
885         }
886         return true;
887
888       default:
889         context->recordError(Error(GL_INVALID_ENUM));
890         return false;
891     }
892 }
893
894 bool ValidateSamplerObjectParameter(gl::Context *context, GLenum pname)
895 {
896     switch (pname)
897     {
898       case GL_TEXTURE_MIN_FILTER:
899       case GL_TEXTURE_MAG_FILTER:
900       case GL_TEXTURE_WRAP_S:
901       case GL_TEXTURE_WRAP_T:
902       case GL_TEXTURE_WRAP_R:
903       case GL_TEXTURE_MIN_LOD:
904       case GL_TEXTURE_MAX_LOD:
905       case GL_TEXTURE_COMPARE_MODE:
906       case GL_TEXTURE_COMPARE_FUNC:
907         return true;
908
909       default:
910         context->recordError(Error(GL_INVALID_ENUM));
911         return false;
912     }
913 }
914
915 bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsizei width, GLsizei height,
916                                   GLenum format, GLenum type, GLsizei *bufSize, GLvoid *pixels)
917 {
918     gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
919     ASSERT(framebuffer);
920
921     if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
922     {
923         context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
924         return false;
925     }
926
927     if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0)
928     {
929         context->recordError(Error(GL_INVALID_OPERATION));
930         return false;
931     }
932
933     if (!framebuffer->getReadColorbuffer())
934     {
935         context->recordError(Error(GL_INVALID_OPERATION));
936         return false;
937     }
938
939     GLenum currentInternalFormat, currentFormat, currentType;
940     GLuint clientVersion = context->getClientVersion();
941
942     context->getCurrentReadFormatType(&currentInternalFormat, &currentFormat, &currentType);
943
944     bool validReadFormat = (clientVersion < 3) ? ValidES2ReadFormatType(context, format, type) :
945                                                  ValidES3ReadFormatType(context, currentInternalFormat, format, type);
946
947     if (!(currentFormat == format && currentType == type) && !validReadFormat)
948     {
949         context->recordError(Error(GL_INVALID_OPERATION));
950         return false;
951     }
952
953     GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
954     const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat);
955
956     GLsizei outputPitch = sizedFormatInfo.computeRowPitch(type, width, context->getState().getPackAlignment());
957     // sized query sanity check
958     if (bufSize)
959     {
960         int requiredSize = outputPitch * height;
961         if (requiredSize > *bufSize)
962         {
963             context->recordError(Error(GL_INVALID_OPERATION));
964             return false;
965         }
966     }
967
968     return true;
969 }
970
971 bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id)
972 {
973     if (!ValidQueryType(context, target))
974     {
975         context->recordError(Error(GL_INVALID_ENUM));
976         return false;
977     }
978
979     if (id == 0)
980     {
981         context->recordError(Error(GL_INVALID_OPERATION));
982         return false;
983     }
984
985     // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
986     // of zero, if the active query object name for <target> is non-zero (for the
987     // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
988     // the active query for either target is non-zero), if <id> is the name of an
989     // existing query object whose type does not match <target>, or if <id> is the
990     // active query object name for any query type, the error INVALID_OPERATION is
991     // generated.
992
993     // Ensure no other queries are active
994     // NOTE: If other queries than occlusion are supported, we will need to check
995     // separately that:
996     //    a) The query ID passed is not the current active query for any target/type
997     //    b) There are no active queries for the requested target (and in the case
998     //       of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
999     //       no query may be active for either if glBeginQuery targets either.
1000     if (context->getState().isQueryActive())
1001     {
1002         context->recordError(Error(GL_INVALID_OPERATION));
1003         return false;
1004     }
1005
1006     Query *queryObject = context->getQuery(id, true, target);
1007
1008     // check that name was obtained with glGenQueries
1009     if (!queryObject)
1010     {
1011         context->recordError(Error(GL_INVALID_OPERATION));
1012         return false;
1013     }
1014
1015     // check for type mismatch
1016     if (queryObject->getType() != target)
1017     {
1018         context->recordError(Error(GL_INVALID_OPERATION));
1019         return false;
1020     }
1021
1022     return true;
1023 }
1024
1025 bool ValidateEndQuery(gl::Context *context, GLenum target)
1026 {
1027     if (!ValidQueryType(context, target))
1028     {
1029         context->recordError(Error(GL_INVALID_ENUM));
1030         return false;
1031     }
1032
1033     const Query *queryObject = context->getState().getActiveQuery(target);
1034
1035     if (queryObject == NULL)
1036     {
1037         context->recordError(Error(GL_INVALID_OPERATION));
1038         return false;
1039     }
1040
1041     return true;
1042 }
1043
1044 static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniformType,
1045                                       GLint location, GLsizei count, LinkedUniform **uniformOut)
1046 {
1047     if (count < 0)
1048     {
1049         context->recordError(Error(GL_INVALID_VALUE));
1050         return false;
1051     }
1052
1053     gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
1054     if (!programBinary)
1055     {
1056         context->recordError(Error(GL_INVALID_OPERATION));
1057         return false;
1058     }
1059
1060     if (location == -1)
1061     {
1062         // Silently ignore the uniform command
1063         return false;
1064     }
1065
1066     if (!programBinary->isValidUniformLocation(location))
1067     {
1068         context->recordError(Error(GL_INVALID_OPERATION));
1069         return false;
1070     }
1071
1072     LinkedUniform *uniform = programBinary->getUniformByLocation(location);
1073
1074     // attempting to write an array to a non-array uniform is an INVALID_OPERATION
1075     if (uniform->elementCount() == 1 && count > 1)
1076     {
1077         context->recordError(Error(GL_INVALID_OPERATION));
1078         return false;
1079     }
1080
1081     *uniformOut = uniform;
1082     return true;
1083 }
1084
1085 bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
1086 {
1087     // Check for ES3 uniform entry points
1088     if (VariableComponentType(uniformType) == GL_UNSIGNED_INT && context->getClientVersion() < 3)
1089     {
1090         context->recordError(Error(GL_INVALID_OPERATION));
1091         return false;
1092     }
1093
1094     LinkedUniform *uniform = NULL;
1095     if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
1096     {
1097         return false;
1098     }
1099
1100     GLenum targetBoolType = VariableBoolVectorType(uniformType);
1101     bool samplerUniformCheck = (IsSampler(uniform->type) && uniformType == GL_INT);
1102     if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
1103     {
1104         context->recordError(Error(GL_INVALID_OPERATION));
1105         return false;
1106     }
1107
1108     return true;
1109 }
1110
1111 bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count,
1112                            GLboolean transpose)
1113 {
1114     // Check for ES3 uniform entry points
1115     int rows = VariableRowCount(matrixType);
1116     int cols = VariableColumnCount(matrixType);
1117     if (rows != cols && context->getClientVersion() < 3)
1118     {
1119         context->recordError(Error(GL_INVALID_OPERATION));
1120         return false;
1121     }
1122
1123     if (transpose != GL_FALSE && context->getClientVersion() < 3)
1124     {
1125         context->recordError(Error(GL_INVALID_VALUE));
1126         return false;
1127     }
1128
1129     LinkedUniform *uniform = NULL;
1130     if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
1131     {
1132         return false;
1133     }
1134
1135     if (uniform->type != matrixType)
1136     {
1137         context->recordError(Error(GL_INVALID_OPERATION));
1138         return false;
1139     }
1140
1141     return true;
1142 }
1143
1144 bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
1145 {
1146     if (!context->getQueryParameterInfo(pname, nativeType, numParams))
1147     {
1148         context->recordError(Error(GL_INVALID_ENUM));
1149         return false;
1150     }
1151
1152     if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
1153     {
1154         unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
1155
1156         if (colorAttachment >= context->getCaps().maxDrawBuffers)
1157         {
1158             context->recordError(Error(GL_INVALID_OPERATION));
1159             return false;
1160         }
1161     }
1162
1163     switch (pname)
1164     {
1165       case GL_TEXTURE_BINDING_2D:
1166       case GL_TEXTURE_BINDING_CUBE_MAP:
1167       case GL_TEXTURE_BINDING_3D:
1168       case GL_TEXTURE_BINDING_2D_ARRAY:
1169         if (context->getState().getActiveSampler() >= context->getCaps().maxCombinedTextureImageUnits)
1170         {
1171             context->recordError(Error(GL_INVALID_OPERATION));
1172             return false;
1173         }
1174         break;
1175
1176       case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1177       case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1178         {
1179             Framebuffer *framebuffer = context->getState().getReadFramebuffer();
1180             ASSERT(framebuffer);
1181             if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
1182             {
1183                 context->recordError(Error(GL_INVALID_OPERATION));
1184                 return false;
1185             }
1186
1187             FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
1188             if (!attachment)
1189             {
1190                 context->recordError(Error(GL_INVALID_OPERATION));
1191                 return false;
1192             }
1193         }
1194         break;
1195
1196       default:
1197         break;
1198     }
1199
1200     // pname is valid, but there are no parameters to return
1201     if (numParams == 0)
1202     {
1203         return false;
1204     }
1205
1206     return true;
1207 }
1208
1209 bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage,
1210                                         GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height,
1211                                         GLint border, GLenum *textureFormatOut)
1212 {
1213
1214     if (!ValidTexture2DDestinationTarget(context, target))
1215     {
1216         context->recordError(Error(GL_INVALID_ENUM));
1217         return false;
1218     }
1219
1220     if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
1221     {
1222         context->recordError(Error(GL_INVALID_VALUE));
1223         return false;
1224     }
1225
1226     if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
1227     {
1228         context->recordError(Error(GL_INVALID_VALUE));
1229         return false;
1230     }
1231
1232     if (border != 0)
1233     {
1234         context->recordError(Error(GL_INVALID_VALUE));
1235         return false;
1236     }
1237
1238     if (!ValidMipLevel(context, target, level))
1239     {
1240         context->recordError(Error(GL_INVALID_VALUE));
1241         return false;
1242     }
1243
1244     gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
1245     if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
1246     {
1247         context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
1248         return false;
1249     }
1250
1251     if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0)
1252     {
1253         context->recordError(Error(GL_INVALID_OPERATION));
1254         return false;
1255     }
1256
1257     const gl::Caps &caps = context->getCaps();
1258
1259     gl::Texture *texture = NULL;
1260     GLenum textureInternalFormat = GL_NONE;
1261     GLint textureLevelWidth = 0;
1262     GLint textureLevelHeight = 0;
1263     GLint textureLevelDepth = 0;
1264     GLuint maxDimension = 0;
1265
1266     switch (target)
1267     {
1268       case GL_TEXTURE_2D:
1269         {
1270             gl::Texture2D *texture2d = context->getTexture2D();
1271             if (texture2d)
1272             {
1273                 textureInternalFormat = texture2d->getInternalFormat(level);
1274                 textureLevelWidth = texture2d->getWidth(level);
1275                 textureLevelHeight = texture2d->getHeight(level);
1276                 textureLevelDepth = 1;
1277                 texture = texture2d;
1278                 maxDimension = caps.max2DTextureSize;
1279             }
1280         }
1281         break;
1282
1283       case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1284       case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1285       case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1286       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1287       case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1288       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1289         {
1290             gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
1291             if (textureCube)
1292             {
1293                 textureInternalFormat = textureCube->getInternalFormat(target, level);
1294                 textureLevelWidth = textureCube->getWidth(target, level);
1295                 textureLevelHeight = textureCube->getHeight(target, level);
1296                 textureLevelDepth = 1;
1297                 texture = textureCube;
1298                 maxDimension = caps.maxCubeMapTextureSize;
1299             }
1300         }
1301         break;
1302
1303       case GL_TEXTURE_2D_ARRAY:
1304         {
1305             gl::Texture2DArray *texture2dArray = context->getTexture2DArray();
1306             if (texture2dArray)
1307             {
1308                 textureInternalFormat = texture2dArray->getInternalFormat(level);
1309                 textureLevelWidth = texture2dArray->getWidth(level);
1310                 textureLevelHeight = texture2dArray->getHeight(level);
1311                 textureLevelDepth = texture2dArray->getLayers(level);
1312                 texture = texture2dArray;
1313                 maxDimension = caps.max2DTextureSize;
1314             }
1315         }
1316         break;
1317
1318       case GL_TEXTURE_3D:
1319         {
1320             gl::Texture3D *texture3d = context->getTexture3D();
1321             if (texture3d)
1322             {
1323                 textureInternalFormat = texture3d->getInternalFormat(level);
1324                 textureLevelWidth = texture3d->getWidth(level);
1325                 textureLevelHeight = texture3d->getHeight(level);
1326                 textureLevelDepth = texture3d->getDepth(level);
1327                 texture = texture3d;
1328                 maxDimension = caps.max3DTextureSize;
1329             }
1330         }
1331         break;
1332
1333       default:
1334         context->recordError(Error(GL_INVALID_ENUM));
1335         return false;
1336     }
1337
1338     if (!texture)
1339     {
1340         context->recordError(Error(GL_INVALID_OPERATION));
1341         return false;
1342     }
1343
1344     if (texture->isImmutable() && !isSubImage)
1345     {
1346         context->recordError(Error(GL_INVALID_OPERATION));
1347         return false;
1348     }
1349
1350     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
1351
1352     if (formatInfo.depthBits > 0)
1353     {
1354         context->recordError(Error(GL_INVALID_OPERATION));
1355         return false;
1356     }
1357
1358     if (formatInfo.compressed)
1359     {
1360         if (((width % formatInfo.compressedBlockWidth) != 0 && width != textureLevelWidth) ||
1361             ((height % formatInfo.compressedBlockHeight) != 0 && height != textureLevelHeight))
1362         {
1363             context->recordError(Error(GL_INVALID_OPERATION));
1364             return false;
1365         }
1366     }
1367
1368     if (isSubImage)
1369     {
1370         if (xoffset + width > textureLevelWidth ||
1371             yoffset + height > textureLevelHeight ||
1372             zoffset >= textureLevelDepth)
1373         {
1374             context->recordError(Error(GL_INVALID_VALUE));
1375             return false;
1376         }
1377     }
1378     else
1379     {
1380         if (IsCubemapTextureTarget(target) && width != height)
1381         {
1382             context->recordError(Error(GL_INVALID_VALUE));
1383             return false;
1384         }
1385
1386         if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
1387         {
1388             context->recordError(Error(GL_INVALID_ENUM));
1389             return false;
1390         }
1391
1392         int maxLevelDimension = (maxDimension >> level);
1393         if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension)
1394         {
1395             context->recordError(Error(GL_INVALID_VALUE));
1396             return false;
1397         }
1398     }
1399
1400     *textureFormatOut = textureInternalFormat;
1401     return true;
1402 }
1403
1404 static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsizei maxVertex, GLsizei primcount)
1405 {
1406     switch (mode)
1407     {
1408       case GL_POINTS:
1409       case GL_LINES:
1410       case GL_LINE_LOOP:
1411       case GL_LINE_STRIP:
1412       case GL_TRIANGLES:
1413       case GL_TRIANGLE_STRIP:
1414       case GL_TRIANGLE_FAN:
1415         break;
1416       default:
1417         context->recordError(Error(GL_INVALID_ENUM));
1418         return false;
1419     }
1420
1421     if (count < 0)
1422     {
1423         context->recordError(Error(GL_INVALID_VALUE));
1424         return false;
1425     }
1426
1427     const State &state = context->getState();
1428
1429     // Check for mapped buffers
1430     if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
1431     {
1432         context->recordError(Error(GL_INVALID_OPERATION));
1433         return false;
1434     }
1435
1436     const gl::DepthStencilState &depthStencilState = state.getDepthStencilState();
1437     if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask ||
1438         state.getStencilRef() != state.getStencilBackRef() ||
1439         depthStencilState.stencilMask != depthStencilState.stencilBackMask)
1440     {
1441         // Note: these separate values are not supported in WebGL, due to D3D's limitations.
1442         // See Section 6.10 of the WebGL 1.0 spec
1443         ERR("This ANGLE implementation does not support separate front/back stencil "
1444             "writemasks, reference values, or stencil mask values.");
1445         context->recordError(Error(GL_INVALID_OPERATION));
1446         return false;
1447     }
1448
1449     const gl::Framebuffer *fbo = state.getDrawFramebuffer();
1450     if (!fbo || fbo->completeness() != GL_FRAMEBUFFER_COMPLETE)
1451     {
1452         context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
1453         return false;
1454     }
1455
1456     if (state.getCurrentProgramId() == 0)
1457     {
1458         context->recordError(Error(GL_INVALID_OPERATION));
1459         return false;
1460     }
1461
1462     gl::ProgramBinary *programBinary = state.getCurrentProgramBinary();
1463     if (!programBinary->validateSamplers(NULL, context->getCaps()))
1464     {
1465         context->recordError(Error(GL_INVALID_OPERATION));
1466         return false;
1467     }
1468
1469     // Buffer validations
1470     const VertexArray *vao = state.getVertexArray();
1471     for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
1472     {
1473         const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
1474         bool attribActive = (programBinary->getSemanticIndex(attributeIndex) != -1);
1475         if (attribActive && attrib.enabled)
1476         {
1477             gl::Buffer *buffer = attrib.buffer.get();
1478
1479             if (buffer)
1480             {
1481                 GLint64 attribStride = static_cast<GLint64>(ComputeVertexAttributeStride(attrib));
1482                 GLint64 maxVertexElement = 0;
1483
1484                 if (attrib.divisor > 0)
1485                 {
1486                     maxVertexElement = static_cast<GLint64>(primcount) / static_cast<GLint64>(attrib.divisor);
1487                 }
1488                 else
1489                 {
1490                     maxVertexElement = static_cast<GLint64>(maxVertex);
1491                 }
1492
1493                 GLint64 attribDataSize = maxVertexElement * attribStride;
1494
1495                 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
1496                 // We can return INVALID_OPERATION if our vertex attribute does not have
1497                 // enough backing data.
1498                 if (attribDataSize > buffer->getSize())
1499                 {
1500                     context->recordError(Error(GL_INVALID_OPERATION));
1501                     return false;
1502                 }
1503             }
1504             else if (attrib.pointer == NULL)
1505             {
1506                 // This is an application error that would normally result in a crash,
1507                 // but we catch it and return an error
1508                 context->recordError(Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer."));
1509                 return false;
1510             }
1511         }
1512     }
1513
1514     // No-op if zero count
1515     return (count > 0);
1516 }
1517
1518 bool ValidateDrawArrays(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
1519 {
1520     if (first < 0)
1521     {
1522         context->recordError(Error(GL_INVALID_VALUE));
1523         return false;
1524     }
1525
1526     const State &state = context->getState();
1527     gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
1528     if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused() &&
1529         curTransformFeedback->getDrawMode() != mode)
1530     {
1531         // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
1532         // that does not match the current transform feedback object's draw mode (if transform feedback
1533         // is active), (3.0.2, section 2.14, pg 86)
1534         context->recordError(Error(GL_INVALID_OPERATION));
1535         return false;
1536     }
1537
1538     if (!ValidateDrawBase(context, mode, count, count, primcount))
1539     {
1540         return false;
1541     }
1542
1543     return true;
1544 }
1545
1546 bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
1547 {
1548     if (primcount < 0)
1549     {
1550         context->recordError(Error(GL_INVALID_VALUE));
1551         return false;
1552     }
1553
1554     if (!ValidateDrawArrays(context, mode, first, count, primcount))
1555     {
1556         return false;
1557     }
1558
1559     // No-op if zero primitive count
1560     return (primcount > 0);
1561 }
1562
1563 static bool ValidateDrawInstancedANGLE(Context *context)
1564 {
1565     // Verify there is at least one active attribute with a divisor of zero
1566     const gl::State& state = context->getState();
1567
1568     gl::ProgramBinary *programBinary = state.getCurrentProgramBinary();
1569
1570     const VertexArray *vao = state.getVertexArray();
1571     for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
1572     {
1573         const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
1574         bool active = (programBinary->getSemanticIndex(attributeIndex) != -1);
1575         if (active && attrib.divisor == 0)
1576         {
1577             return true;
1578         }
1579     }
1580
1581     context->recordError(Error(GL_INVALID_OPERATION, "ANGLE_instanced_arrays requires that at least one active attribute"
1582                                                      "has a divisor of zero."));
1583     return false;
1584 }
1585
1586 bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
1587 {
1588     if (!ValidateDrawInstancedANGLE(context))
1589     {
1590         return false;
1591     }
1592
1593     return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
1594 }
1595
1596 bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum type,
1597                           const GLvoid* indices, GLsizei primcount, rx::RangeUI *indexRangeOut)
1598 {
1599     switch (type)
1600     {
1601       case GL_UNSIGNED_BYTE:
1602       case GL_UNSIGNED_SHORT:
1603         break;
1604       case GL_UNSIGNED_INT:
1605         if (!context->getExtensions().elementIndexUint)
1606         {
1607             context->recordError(Error(GL_INVALID_ENUM));
1608             return false;
1609         }
1610         break;
1611       default:
1612         context->recordError(Error(GL_INVALID_ENUM));
1613         return false;
1614     }
1615
1616     const State &state = context->getState();
1617
1618     gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
1619     if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused())
1620     {
1621         // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
1622         // while transform feedback is active, (3.0.2, section 2.14, pg 86)
1623         context->recordError(Error(GL_INVALID_OPERATION));
1624         return false;
1625     }
1626
1627     // Check for mapped buffers
1628     if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
1629     {
1630         context->recordError(Error(GL_INVALID_OPERATION));
1631         return false;
1632     }
1633
1634     const gl::VertexArray *vao = state.getVertexArray();
1635     const gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
1636     if (!indices && !elementArrayBuffer)
1637     {
1638         context->recordError(Error(GL_INVALID_OPERATION));
1639         return false;
1640     }
1641
1642     if (elementArrayBuffer)
1643     {
1644         const gl::Type &typeInfo = gl::GetTypeInfo(type);
1645
1646         GLint64 offset = reinterpret_cast<GLint64>(indices);
1647         GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset;
1648
1649         // check for integer overflows
1650         if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
1651             byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
1652         {
1653             context->recordError(Error(GL_OUT_OF_MEMORY));
1654             return false;
1655         }
1656
1657         // Check for reading past the end of the bound buffer object
1658         if (byteCount > elementArrayBuffer->getSize())
1659         {
1660             context->recordError(Error(GL_INVALID_OPERATION));
1661             return false;
1662         }
1663     }
1664     else if (!indices)
1665     {
1666         // Catch this programming error here
1667         context->recordError(Error(GL_INVALID_OPERATION));
1668         return false;
1669     }
1670
1671     // Use max index to validate if our vertex buffers are large enough for the pull.
1672     // TODO: offer fast path, with disabled index validation.
1673     // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
1674     if (elementArrayBuffer)
1675     {
1676         unsigned int offset = reinterpret_cast<unsigned int>(indices);
1677         if (!elementArrayBuffer->getIndexRangeCache()->findRange(type, offset, count, indexRangeOut, NULL))
1678         {
1679             const void *dataPointer = elementArrayBuffer->getImplementation()->getData();
1680             const uint8_t *offsetPointer = static_cast<const uint8_t *>(dataPointer) + offset;
1681             *indexRangeOut = rx::IndexRangeCache::ComputeRange(type, offsetPointer, count);
1682         }
1683     }
1684     else
1685     {
1686         *indexRangeOut = rx::IndexRangeCache::ComputeRange(type, indices, count);
1687     }
1688
1689     if (!ValidateDrawBase(context, mode, count, static_cast<GLsizei>(indexRangeOut->end), primcount))
1690     {
1691         return false;
1692     }
1693
1694     return true;
1695 }
1696
1697 bool ValidateDrawElementsInstanced(Context *context,
1698                                    GLenum mode, GLsizei count, GLenum type,
1699                                    const GLvoid *indices, GLsizei primcount,
1700                                    rx::RangeUI *indexRangeOut)
1701 {
1702     if (primcount < 0)
1703     {
1704         context->recordError(Error(GL_INVALID_VALUE));
1705         return false;
1706     }
1707
1708     if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
1709     {
1710         return false;
1711     }
1712
1713     // No-op zero primitive count
1714     return (primcount > 0);
1715 }
1716
1717 bool ValidateDrawElementsInstancedANGLE(Context *context, GLenum mode, GLsizei count, GLenum type,
1718                                         const GLvoid *indices, GLsizei primcount, rx::RangeUI *indexRangeOut)
1719 {
1720     if (!ValidateDrawInstancedANGLE(context))
1721     {
1722         return false;
1723     }
1724
1725     return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut);
1726 }
1727
1728 bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
1729                                     GLuint texture, GLint level)
1730 {
1731     if (!ValidFramebufferTarget(target))
1732     {
1733         context->recordError(Error(GL_INVALID_ENUM));
1734         return false;
1735     }
1736
1737     if (!ValidateAttachmentTarget(context, attachment))
1738     {
1739         return false;
1740     }
1741
1742     if (texture != 0)
1743     {
1744         gl::Texture *tex = context->getTexture(texture);
1745
1746         if (tex == NULL)
1747         {
1748             context->recordError(Error(GL_INVALID_OPERATION));
1749             return false;
1750         }
1751
1752         if (level < 0)
1753         {
1754             context->recordError(Error(GL_INVALID_VALUE));
1755             return false;
1756         }
1757     }
1758
1759     const gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
1760     GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id();
1761
1762     if (framebufferHandle == 0 || !framebuffer)
1763     {
1764         context->recordError(Error(GL_INVALID_OPERATION));
1765         return false;
1766     }
1767
1768     return true;
1769 }
1770
1771 bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
1772                                   GLenum textarget, GLuint texture, GLint level)
1773 {
1774     // Attachments are required to be bound to level 0 in ES2
1775     if (context->getClientVersion() < 3 && level != 0)
1776     {
1777         context->recordError(Error(GL_INVALID_VALUE));
1778         return false;
1779     }
1780
1781     if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1782     {
1783         return false;
1784     }
1785
1786     if (texture != 0)
1787     {
1788         gl::Texture *tex = context->getTexture(texture);
1789         ASSERT(tex);
1790
1791         const gl::Caps &caps = context->getCaps();
1792
1793         switch (textarget)
1794         {
1795           case GL_TEXTURE_2D:
1796             {
1797                 if (level > gl::log2(caps.max2DTextureSize))
1798                 {
1799                     context->recordError(Error(GL_INVALID_VALUE));
1800                     return false;
1801                 }
1802                 if (tex->getTarget() != GL_TEXTURE_2D)
1803                 {
1804                     context->recordError(Error(GL_INVALID_OPERATION));
1805                     return false;
1806                 }
1807                 gl::Texture2D *tex2d = static_cast<gl::Texture2D *>(tex);
1808                 if (tex2d->isCompressed(level))
1809                 {
1810                     context->recordError(Error(GL_INVALID_OPERATION));
1811                     return false;
1812                 }
1813             }
1814             break;
1815
1816           case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1817           case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1818           case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1819           case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1820           case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1821           case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1822             {
1823                 if (level > gl::log2(caps.maxCubeMapTextureSize))
1824                 {
1825                     context->recordError(Error(GL_INVALID_VALUE));
1826                     return false;
1827                 }
1828                 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
1829                 {
1830                     context->recordError(Error(GL_INVALID_OPERATION));
1831                     return false;
1832                 }
1833                 gl::TextureCubeMap *texcube = static_cast<gl::TextureCubeMap *>(tex);
1834                 if (texcube->isCompressed(textarget, level))
1835                 {
1836                     context->recordError(Error(GL_INVALID_OPERATION));
1837                     return false;
1838                 }
1839             }
1840             break;
1841
1842           default:
1843             context->recordError(Error(GL_INVALID_ENUM));
1844             return false;
1845         }
1846     }
1847
1848     return true;
1849 }
1850
1851 bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
1852 {
1853     if (program == 0)
1854     {
1855         context->recordError(Error(GL_INVALID_VALUE));
1856         return false;
1857     }
1858
1859     gl::Program *programObject = context->getProgram(program);
1860
1861     if (!programObject || !programObject->isLinked())
1862     {
1863         context->recordError(Error(GL_INVALID_OPERATION));
1864         return false;
1865     }
1866
1867     gl::ProgramBinary *programBinary = programObject->getProgramBinary();
1868     if (!programBinary)
1869     {
1870         context->recordError(Error(GL_INVALID_OPERATION));
1871         return false;
1872     }
1873
1874     if (!programBinary->isValidUniformLocation(location))
1875     {
1876         context->recordError(Error(GL_INVALID_OPERATION));
1877         return false;
1878     }
1879
1880     return true;
1881 }
1882
1883 bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params)
1884 {
1885     return ValidateGetUniformBase(context, program, location);
1886 }
1887
1888 bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params)
1889 {
1890     return ValidateGetUniformBase(context, program, location);
1891 }
1892
1893 static bool ValidateSizedGetUniform(Context *context, GLuint program, GLint location, GLsizei bufSize)
1894 {
1895     if (!ValidateGetUniformBase(context, program, location))
1896     {
1897         return false;
1898     }
1899
1900     gl::Program *programObject = context->getProgram(program);
1901     ASSERT(programObject);
1902     gl::ProgramBinary *programBinary = programObject->getProgramBinary();
1903
1904     // sized queries -- ensure the provided buffer is large enough
1905     LinkedUniform *uniform = programBinary->getUniformByLocation(location);
1906     size_t requiredBytes = VariableExternalSize(uniform->type);
1907     if (static_cast<size_t>(bufSize) < requiredBytes)
1908     {
1909         context->recordError(Error(GL_INVALID_OPERATION));
1910         return false;
1911     }
1912
1913     return true;
1914 }
1915
1916 bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
1917 {
1918     return ValidateSizedGetUniform(context, program, location, bufSize);
1919 }
1920
1921 bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params)
1922 {
1923     return ValidateSizedGetUniform(context, program, location, bufSize);
1924 }
1925
1926 }