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