Move HTML canvas and tracks from ExceptionCode to Exception
[WebKit-https.git] / Source / WebCore / html / canvas / WebGLRenderingContext.cpp
1 /*
2  * Copyright (C) 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27
28 #if ENABLE(WEBGL)
29 #include "WebGLRenderingContext.h"
30
31 #include "ANGLEInstancedArrays.h"
32 #include "CachedImage.h"
33 #include "EXTBlendMinMax.h"
34 #include "EXTFragDepth.h"
35 #include "EXTShaderTextureLOD.h"
36 #include "EXTTextureFilterAnisotropic.h"
37 #include "EXTsRGB.h"
38 #include "Extensions3D.h"
39 #include "HTMLCanvasElement.h"
40 #include "HTMLImageElement.h"
41 #include "HTMLVideoElement.h"
42 #include "ImageData.h"
43 #include "OESElementIndexUint.h"
44 #include "OESStandardDerivatives.h"
45 #include "OESTextureFloat.h"
46 #include "OESTextureFloatLinear.h"
47 #include "OESTextureHalfFloat.h"
48 #include "OESTextureHalfFloatLinear.h"
49 #include "OESVertexArrayObject.h"
50 #include "RenderBox.h"
51 #include "WebGLCompressedTextureATC.h"
52 #include "WebGLCompressedTexturePVRTC.h"
53 #include "WebGLCompressedTextureS3TC.h"
54 #include "WebGLDebugRendererInfo.h"
55 #include "WebGLDebugShaders.h"
56 #include "WebGLDepthTexture.h"
57 #include "WebGLDrawBuffers.h"
58 #include "WebGLLoseContext.h"
59 #include "WebGLVertexArrayObjectOES.h"
60 #include <JavaScriptCore/GenericTypedArrayViewInlines.h>
61 #include <JavaScriptCore/JSCJSValueInlines.h>
62 #include <JavaScriptCore/JSCellInlines.h>
63 #include <JavaScriptCore/JSGenericTypedArrayViewInlines.h>
64
65 namespace WebCore {
66
67 WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, GraphicsContext3D::Attributes attributes)
68     : WebGLRenderingContextBase(passedCanvas, attributes)
69 {
70 }
71
72 WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassRefPtr<GraphicsContext3D> context,
73     GraphicsContext3D::Attributes attributes) : WebGLRenderingContextBase(passedCanvas, context, attributes)
74 {
75     initializeVertexArrayObjects();
76 }
77
78 void WebGLRenderingContext::initializeVertexArrayObjects()
79 {
80     m_defaultVertexArrayObject = WebGLVertexArrayObjectOES::create(this, WebGLVertexArrayObjectOES::VAOTypeDefault);
81     addContextObject(m_defaultVertexArrayObject.get());
82     m_boundVertexArrayObject = m_defaultVertexArrayObject;
83     if (!isGLES2Compliant())
84         initVertexAttrib0();
85 }
86
87 WebGLExtension* WebGLRenderingContext::getExtension(const String& name)
88 {
89     if (isContextLostOrPending())
90         return nullptr;
91     
92     if (equalIgnoringASCIICase(name, "EXT_blend_minmax")
93         && m_context->getExtensions()->supports("GL_EXT_blend_minmax")) {
94         if (!m_extBlendMinMax) {
95             m_context->getExtensions()->ensureEnabled("GL_EXT_blend_minmax");
96             m_extBlendMinMax = std::make_unique<EXTBlendMinMax>(this);
97         }
98         return m_extBlendMinMax.get();
99     }
100     if (equalIgnoringASCIICase(name, "EXT_sRGB")
101         && m_context->getExtensions()->supports("GL_EXT_sRGB")) {
102         if (!m_extsRGB) {
103             m_context->getExtensions()->ensureEnabled("GL_EXT_sRGB");
104             m_extsRGB = std::make_unique<EXTsRGB>(this);
105         }
106         return m_extsRGB.get();
107     }
108     if (equalIgnoringASCIICase(name, "EXT_frag_depth")
109         && m_context->getExtensions()->supports("GL_EXT_frag_depth")) {
110         if (!m_extFragDepth) {
111             m_context->getExtensions()->ensureEnabled("GL_EXT_frag_depth");
112             m_extFragDepth = std::make_unique<EXTFragDepth>(this);
113         }
114         return m_extFragDepth.get();
115     }
116     if (equalIgnoringASCIICase(name, "EXT_shader_texture_lod")
117         && (m_context->getExtensions()->supports("GL_EXT_shader_texture_lod") || m_context->getExtensions()->supports("GL_ARB_shader_texture_lod"))) {
118         if (!m_extShaderTextureLOD) {
119             m_context->getExtensions()->ensureEnabled("GL_EXT_shader_texture_lod");
120             m_extShaderTextureLOD = std::make_unique<EXTShaderTextureLOD>(this);
121         }
122         return m_extShaderTextureLOD.get();
123     }
124     if ((equalIgnoringASCIICase(name, "EXT_texture_filter_anisotropic") || equalIgnoringASCIICase(name, "WEBKIT_EXT_texture_filter_anisotropic"))
125         && m_context->getExtensions()->supports("GL_EXT_texture_filter_anisotropic")) {
126         if (!m_extTextureFilterAnisotropic) {
127             m_context->getExtensions()->ensureEnabled("GL_EXT_texture_filter_anisotropic");
128             m_extTextureFilterAnisotropic = std::make_unique<EXTTextureFilterAnisotropic>(this);
129         }
130         return m_extTextureFilterAnisotropic.get();
131     }
132     if (equalIgnoringASCIICase(name, "OES_standard_derivatives")
133         && m_context->getExtensions()->supports("GL_OES_standard_derivatives")) {
134         if (!m_oesStandardDerivatives) {
135             m_context->getExtensions()->ensureEnabled("GL_OES_standard_derivatives");
136             m_oesStandardDerivatives = std::make_unique<OESStandardDerivatives>(this);
137         }
138         return m_oesStandardDerivatives.get();
139     }
140     if (equalIgnoringASCIICase(name, "OES_texture_float")
141         && m_context->getExtensions()->supports("GL_OES_texture_float")) {
142         if (!m_oesTextureFloat) {
143             m_context->getExtensions()->ensureEnabled("GL_OES_texture_float");
144             m_oesTextureFloat = std::make_unique<OESTextureFloat>(this);
145         }
146         return m_oesTextureFloat.get();
147     }
148     if (equalIgnoringASCIICase(name, "OES_texture_float_linear")
149         && m_context->getExtensions()->supports("GL_OES_texture_float_linear")) {
150         if (!m_oesTextureFloatLinear) {
151             m_context->getExtensions()->ensureEnabled("GL_OES_texture_float_linear");
152             m_oesTextureFloatLinear = std::make_unique<OESTextureFloatLinear>(this);
153         }
154         return m_oesTextureFloatLinear.get();
155     }
156     if (equalIgnoringASCIICase(name, "OES_texture_half_float")
157         && m_context->getExtensions()->supports("GL_OES_texture_half_float")) {
158         if (!m_oesTextureHalfFloat) {
159             m_context->getExtensions()->ensureEnabled("GL_OES_texture_half_float");
160             m_oesTextureHalfFloat = std::make_unique<OESTextureHalfFloat>(this);
161         }
162         return m_oesTextureHalfFloat.get();
163     }
164     if (equalIgnoringASCIICase(name, "OES_texture_half_float_linear")
165         && m_context->getExtensions()->supports("GL_OES_texture_half_float_linear")) {
166         if (!m_oesTextureHalfFloatLinear) {
167             m_context->getExtensions()->ensureEnabled("GL_OES_texture_half_float_linear");
168             m_oesTextureHalfFloatLinear = std::make_unique<OESTextureHalfFloatLinear>(this);
169         }
170         return m_oesTextureHalfFloatLinear.get();
171     }
172     if (equalIgnoringASCIICase(name, "OES_vertex_array_object")
173         && m_context->getExtensions()->supports("GL_OES_vertex_array_object")) {
174         if (!m_oesVertexArrayObject) {
175             m_context->getExtensions()->ensureEnabled("GL_OES_vertex_array_object");
176             m_oesVertexArrayObject = std::make_unique<OESVertexArrayObject>(*this);
177         }
178         return m_oesVertexArrayObject.get();
179     }
180     if (equalIgnoringASCIICase(name, "OES_element_index_uint")
181         && m_context->getExtensions()->supports("GL_OES_element_index_uint")) {
182         if (!m_oesElementIndexUint) {
183             m_context->getExtensions()->ensureEnabled("GL_OES_element_index_uint");
184             m_oesElementIndexUint = std::make_unique<OESElementIndexUint>(this);
185         }
186         return m_oesElementIndexUint.get();
187     }
188     if (equalIgnoringASCIICase(name, "WEBGL_lose_context")) {
189         if (!m_webglLoseContext)
190             m_webglLoseContext = std::make_unique<WebGLLoseContext>(this);
191         return m_webglLoseContext.get();
192     }
193     if ((equalIgnoringASCIICase(name, "WEBKIT_WEBGL_compressed_texture_atc"))
194         && WebGLCompressedTextureATC::supported(this)) {
195         if (!m_webglCompressedTextureATC)
196             m_webglCompressedTextureATC = std::make_unique<WebGLCompressedTextureATC>(this);
197         return m_webglCompressedTextureATC.get();
198     }
199     if ((equalIgnoringASCIICase(name, "WEBKIT_WEBGL_compressed_texture_pvrtc"))
200         && WebGLCompressedTexturePVRTC::supported(this)) {
201         if (!m_webglCompressedTexturePVRTC)
202             m_webglCompressedTexturePVRTC = std::make_unique<WebGLCompressedTexturePVRTC>(this);
203         return m_webglCompressedTexturePVRTC.get();
204     }
205     if (equalIgnoringASCIICase(name, "WEBGL_compressed_texture_s3tc")
206         && WebGLCompressedTextureS3TC::supported(this)) {
207         if (!m_webglCompressedTextureS3TC)
208             m_webglCompressedTextureS3TC = std::make_unique<WebGLCompressedTextureS3TC>(this);
209         return m_webglCompressedTextureS3TC.get();
210     }
211     if (equalIgnoringASCIICase(name, "WEBGL_depth_texture")
212         && WebGLDepthTexture::supported(graphicsContext3D())) {
213         if (!m_webglDepthTexture) {
214             m_context->getExtensions()->ensureEnabled("GL_CHROMIUM_depth_texture");
215             m_webglDepthTexture = std::make_unique<WebGLDepthTexture>(this);
216         }
217         return m_webglDepthTexture.get();
218     }
219     if (equalIgnoringASCIICase(name, "WEBGL_draw_buffers") && supportsDrawBuffers()) {
220         if (!m_webglDrawBuffers) {
221             m_context->getExtensions()->ensureEnabled("GL_EXT_draw_buffers");
222             m_webglDrawBuffers = std::make_unique<WebGLDrawBuffers>(this);
223         }
224         return m_webglDrawBuffers.get();
225     }
226     if (equalIgnoringASCIICase(name, "ANGLE_instanced_arrays") && ANGLEInstancedArrays::supported(this)) {
227         if (!m_angleInstancedArrays) {
228             m_context->getExtensions()->ensureEnabled("GL_ANGLE_instanced_arrays");
229             m_angleInstancedArrays = std::make_unique<ANGLEInstancedArrays>(this);
230         }
231         return m_angleInstancedArrays.get();
232     }
233     if (equalIgnoringASCIICase(name, "WEBGL_debug_renderer_info")) {
234         if (!m_webglDebugRendererInfo)
235             m_webglDebugRendererInfo = std::make_unique<WebGLDebugRendererInfo>(this);
236         return m_webglDebugRendererInfo.get();
237     }
238     if (equalIgnoringASCIICase(name, "WEBGL_debug_shaders")
239         && m_context->getExtensions()->supports("GL_ANGLE_translated_shader_source")) {
240         if (!m_webglDebugShaders)
241             m_webglDebugShaders = std::make_unique<WebGLDebugShaders>(this);
242         return m_webglDebugShaders.get();
243     }
244
245     return nullptr;
246 }
247
248 Vector<String> WebGLRenderingContext::getSupportedExtensions()
249 {
250     Vector<String> result;
251     
252     if (m_isPendingPolicyResolution)
253         return result;
254     
255     if (m_context->getExtensions()->supports("GL_EXT_blend_minmax"))
256         result.append("EXT_blend_minmax");
257     if (m_context->getExtensions()->supports("GL_EXT_sRGB"))
258         result.append("EXT_sRGB");
259     if (m_context->getExtensions()->supports("GL_EXT_frag_depth"))
260         result.append("EXT_frag_depth");
261     if (m_context->getExtensions()->supports("GL_OES_texture_float"))
262         result.append("OES_texture_float");
263     if (m_context->getExtensions()->supports("GL_OES_texture_float_linear"))
264         result.append("OES_texture_float_linear");
265     if (m_context->getExtensions()->supports("GL_OES_texture_half_float"))
266         result.append("OES_texture_half_float");
267     if (m_context->getExtensions()->supports("GL_OES_texture_half_float_linear"))
268         result.append("OES_texture_half_float_linear");
269     if (m_context->getExtensions()->supports("GL_OES_standard_derivatives"))
270         result.append("OES_standard_derivatives");
271     if (m_context->getExtensions()->supports("GL_EXT_shader_texture_lod") || m_context->getExtensions()->supports("GL_ARB_shader_texture_lod"))
272         result.append("EXT_shader_texture_lod");
273     if (m_context->getExtensions()->supports("GL_EXT_texture_filter_anisotropic"))
274         result.append("EXT_texture_filter_anisotropic");
275     if (m_context->getExtensions()->supports("GL_OES_vertex_array_object"))
276         result.append("OES_vertex_array_object");
277     if (m_context->getExtensions()->supports("GL_OES_element_index_uint"))
278         result.append("OES_element_index_uint");
279     result.append("WEBGL_lose_context");
280     if (WebGLCompressedTextureATC::supported(this))
281         result.append("WEBKIT_WEBGL_compressed_texture_atc");
282     if (WebGLCompressedTexturePVRTC::supported(this))
283         result.append("WEBKIT_WEBGL_compressed_texture_pvrtc");
284     if (WebGLCompressedTextureS3TC::supported(this))
285         result.append("WEBGL_compressed_texture_s3tc");
286     if (WebGLDepthTexture::supported(graphicsContext3D()))
287         result.append("WEBGL_depth_texture");
288     if (supportsDrawBuffers())
289         result.append("WEBGL_draw_buffers");
290     if (ANGLEInstancedArrays::supported(this))
291         result.append("ANGLE_instanced_arrays");
292     if (m_context->getExtensions()->supports("GL_ANGLE_translated_shader_source"))
293         result.append("WEBGL_debug_shaders");
294     result.append("WEBGL_debug_renderer_info");
295
296     return result;
297 }
298
299 WebGLGetInfo WebGLRenderingContext::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname)
300 {
301     if (isContextLostOrPending() || !validateFramebufferFuncParameters("getFramebufferAttachmentParameter", target, attachment))
302         return WebGLGetInfo();
303     
304     if (!m_framebufferBinding || !m_framebufferBinding->object()) {
305         synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getFramebufferAttachmentParameter", "no framebuffer bound");
306         return WebGLGetInfo();
307     }
308     
309     WebGLSharedObject* object = m_framebufferBinding->getAttachmentObject(attachment);
310     if (!object) {
311         if (pname == GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)
312             return WebGLGetInfo(GraphicsContext3D::NONE);
313         // OpenGL ES 2.0 specifies INVALID_ENUM in this case, while desktop GL
314         // specifies INVALID_OPERATION.
315         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name");
316         return WebGLGetInfo();
317     }
318     
319     ASSERT(object->isTexture() || object->isRenderbuffer());
320     if (object->isTexture()) {
321         switch (pname) {
322         case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
323             return WebGLGetInfo(GraphicsContext3D::TEXTURE);
324         case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
325             return WebGLGetInfo(PassRefPtr<WebGLTexture>(reinterpret_cast<WebGLTexture*>(object)));
326         case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
327         case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
328         case Extensions3D::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT: {
329             GC3Dint value = 0;
330             m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value);
331             return WebGLGetInfo(value);
332         }
333         default:
334             synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for texture attachment");
335             return WebGLGetInfo();
336         }
337     } else {
338         switch (pname) {
339         case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
340             return WebGLGetInfo(GraphicsContext3D::RENDERBUFFER);
341         case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
342             return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(reinterpret_cast<WebGLRenderbuffer*>(object)));
343         case Extensions3D::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT: {
344             if (!m_extsRGB) {
345                 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for renderbuffer attachment");
346                 return WebGLGetInfo();
347             }
348             WebGLRenderbuffer* renderBuffer = reinterpret_cast<WebGLRenderbuffer*>(object);
349             GC3Denum renderBufferFormat = renderBuffer->getInternalFormat();
350             ASSERT(renderBufferFormat != Extensions3D::SRGB_EXT && renderBufferFormat != Extensions3D::SRGB_ALPHA_EXT);
351             if (renderBufferFormat == Extensions3D::SRGB8_ALPHA8_EXT)
352                 return WebGLGetInfo(Extensions3D::SRGB_EXT);
353             return WebGLGetInfo(GraphicsContext3D::LINEAR);
354         }
355         default:
356             synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for renderbuffer attachment");
357             return WebGLGetInfo();
358         }
359     }
360 }
361
362 bool WebGLRenderingContext::validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment)
363 {
364     if (target != GraphicsContext3D::FRAMEBUFFER) {
365         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
366         return false;
367     }
368     switch (attachment) {
369     case GraphicsContext3D::COLOR_ATTACHMENT0:
370     case GraphicsContext3D::DEPTH_ATTACHMENT:
371     case GraphicsContext3D::STENCIL_ATTACHMENT:
372     case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
373         break;
374     default:
375         if (m_webglDrawBuffers
376             && attachment > GraphicsContext3D::COLOR_ATTACHMENT0
377             && attachment < static_cast<GC3Denum>(GraphicsContext3D::COLOR_ATTACHMENT0 + getMaxColorAttachments()))
378             break;
379         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid attachment");
380         return false;
381     }
382     return true;
383 }
384     
385 void WebGLRenderingContext::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height)
386 {
387     if (isContextLostOrPending())
388         return;
389     if (target != GraphicsContext3D::RENDERBUFFER) {
390         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid target");
391         return;
392     }
393     if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
394         synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "renderbufferStorage", "no bound renderbuffer");
395         return;
396     }
397     if (!validateSize("renderbufferStorage", width, height))
398         return;
399     switch (internalformat) {
400     case GraphicsContext3D::DEPTH_COMPONENT16:
401     case GraphicsContext3D::RGBA4:
402     case GraphicsContext3D::RGB5_A1:
403     case GraphicsContext3D::RGB565:
404     case GraphicsContext3D::STENCIL_INDEX8:
405     case Extensions3D::SRGB8_ALPHA8_EXT:
406         if (internalformat == Extensions3D::SRGB8_ALPHA8_EXT && !m_extsRGB) {
407             synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid internalformat");
408             return;
409         }
410         m_context->renderbufferStorage(target, internalformat, width, height);
411         m_renderbufferBinding->setInternalFormat(internalformat);
412         m_renderbufferBinding->setIsValid(true);
413         m_renderbufferBinding->setSize(width, height);
414         break;
415     case GraphicsContext3D::DEPTH_STENCIL:
416         if (isDepthStencilSupported())
417             m_context->renderbufferStorage(target, Extensions3D::DEPTH24_STENCIL8, width, height);
418         m_renderbufferBinding->setSize(width, height);
419         m_renderbufferBinding->setIsValid(isDepthStencilSupported());
420         m_renderbufferBinding->setInternalFormat(internalformat);
421         break;
422     default:
423         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid internalformat");
424         return;
425     }
426     applyStencilTest();
427 }
428
429 void WebGLRenderingContext::hint(GC3Denum target, GC3Denum mode)
430 {
431     if (isContextLostOrPending())
432         return;
433     bool isValid = false;
434     switch (target) {
435     case GraphicsContext3D::GENERATE_MIPMAP_HINT:
436         isValid = true;
437         break;
438     case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
439         if (m_oesStandardDerivatives)
440             isValid = true;
441         break;
442     }
443     if (!isValid) {
444         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "hint", "invalid target");
445         return;
446     }
447     m_context->hint(target, mode);
448 }
449     
450 void WebGLRenderingContext::clear(GC3Dbitfield mask)
451 {
452     if (isContextLostOrPending())
453         return;
454     if (mask & ~(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) {
455         synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clear", "invalid mask");
456         return;
457     }
458     const char* reason = "framebuffer incomplete";
459     if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
460         synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "clear", reason);
461         return;
462     }
463     if (!clearIfComposited(mask))
464         m_context->clear(mask);
465     markContextChanged();
466 }
467
468 void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
469 {
470     if (isContextLostOrPending())
471         return;
472     if (!validateTexFuncParameters("copyTexImage2D", CopyTexImage, target, level, internalformat, width, height, border, internalformat, GraphicsContext3D::UNSIGNED_BYTE))
473         return;
474     if (!validateSettableTexFormat("copyTexImage2D", internalformat))
475         return;
476     WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true);
477     if (!tex)
478         return;
479     if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
480         synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexImage2D", "framebuffer is incompatible format");
481         return;
482     }
483     if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) {
484         synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexImage2D", "level > 0 not power of 2");
485         return;
486     }
487     const char* reason = "framebuffer incomplete";
488     if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
489         synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason);
490         return;
491     }
492     clearIfComposited();
493     if (isResourceSafe())
494         m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
495     else {
496         GC3Dint clippedX, clippedY;
497         GC3Dsizei clippedWidth, clippedHeight;
498         if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
499             m_context->texImage2DResourceSafe(target, level, internalformat, width, height, border,
500                 internalformat, GraphicsContext3D::UNSIGNED_BYTE, m_unpackAlignment);
501             if (clippedWidth > 0 && clippedHeight > 0) {
502                 m_context->copyTexSubImage2D(target, level, clippedX - x, clippedY - y,
503                     clippedX, clippedY, clippedWidth, clippedHeight);
504             }
505         } else
506             m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
507     }
508     // FIXME: if the framebuffer is not complete, none of the below should be executed.
509     tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
510 }
511
512 void WebGLRenderingContext::texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum internalformat, GC3Denum format, GC3Denum type, const void* pixels)
513 {
514     UNUSED_PARAM(internalformat);
515     ASSERT(!isContextLost());
516     ASSERT(validateTexFuncParameters("texSubImage2D", TexSubImage, target, level, format, width, height, 0, format, type));
517     ASSERT(validateSize("texSubImage2D", xoffset, yoffset));
518     ASSERT(validateSettableTexFormat("texSubImage2D", format));
519     WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true);
520     if (!tex) {
521         ASSERT_NOT_REACHED();
522         return;
523     }
524     ASSERT((xoffset + width) >= 0);
525     ASSERT((yoffset + height) >= 0);
526     ASSERT(tex->getWidth(target, level) >= (xoffset + width));
527     ASSERT(tex->getHeight(target, level) >= (yoffset + height));
528     ASSERT(tex->getInternalFormat(target, level) == format);
529     ASSERT(tex->getType(target, level) == type);
530     m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
531 }
532
533 void WebGLRenderingContext::texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha)
534 {
535     Vector<uint8_t> data;
536     GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE);
537     if (!imageExtractor.extractSucceeded()) {
538         synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image");
539         return;
540     }
541     GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
542     GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
543     const void* imagePixelData = imageExtractor.imagePixelData();
544     
545     bool needConversion = true;
546     if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY)
547         needConversion = false;
548     else {
549         if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
550             synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
551             return;
552         }
553     }
554     
555     if (m_unpackAlignment != 1)
556         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
557
558     texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(), format, format, type, needConversion ? data.data() : imagePixelData);
559     if (m_unpackAlignment != 1)
560         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
561 }
562
563 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&& pixels)
564 {
565     if (isContextLostOrPending() || !validateTexFuncData("texSubImage2D", level, width, height, format, format, type, pixels.get(), NullNotAllowed) || !validateTexFunc("texSubImage2D", TexSubImage, SourceArrayBufferView, target, level, format, width, height, 0, format, type, xoffset, yoffset))
566         return;
567     
568     void* data = pixels->baseAddress();
569     Vector<uint8_t> tempData;
570     bool changeUnpackAlignment = false;
571     if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
572         if (!m_context->extractTextureData(width, height, format, type,
573             m_unpackAlignment,
574             m_unpackFlipY, m_unpackPremultiplyAlpha,
575             data,
576             tempData))
577             return;
578         data = tempData.data();
579         changeUnpackAlignment = true;
580     }
581     if (changeUnpackAlignment)
582         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
583
584     texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, format, type, data);
585     if (changeUnpackAlignment)
586         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
587 }
588
589 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, ImageData* pixels)
590 {
591     if (isContextLostOrPending() || !pixels || !validateTexFunc("texSubImage2D", TexSubImage, SourceImageData, target, level, format,  pixels->width(), pixels->height(), 0, format, type, xoffset, yoffset))
592         return;
593     
594     Vector<uint8_t> data;
595     bool needConversion = true;
596     // The data from ImageData is always of format RGBA8.
597     // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required.
598     if (format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha)
599         needConversion = false;
600     else {
601         if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
602             synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image data");
603             return;
604         }
605     }
606     if (m_unpackAlignment != 1)
607         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
608     
609     texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(), format, format, type, needConversion ? data.data() : pixels->data()->data());
610     if (m_unpackAlignment != 1)
611         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
612 }
613
614 ExceptionOr<void> WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, HTMLImageElement* image)
615 {
616     if (wouldTaintOrigin(image))
617         return Exception { SECURITY_ERR };
618     if (isContextLostOrPending() || !validateHTMLImageElement("texSubImage2D", image))
619         return { };
620
621     RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer());
622     if (!imageForRender)
623         return { };
624
625     if (imageForRender->isSVGImage())
626         imageForRender = drawImageIntoBuffer(*imageForRender, image->width(), image->height(), 1);
627     
628     if (!imageForRender || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLImageElement, target, level, format, imageForRender->width(), imageForRender->height(), 0, format, type, xoffset, yoffset))
629         return { };
630
631     texSubImage2DImpl(target, level, xoffset, yoffset, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha);
632     return { };
633 }
634
635 ExceptionOr<void> WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas)
636 {
637     if (wouldTaintOrigin(canvas))
638         return Exception { SECURITY_ERR };
639     if (isContextLostOrPending() || !validateHTMLCanvasElement("texSubImage2D", canvas)
640         || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLCanvasElement, target, level, format, canvas->width(), canvas->height(), 0, format, type, xoffset, yoffset))
641         return { };
642
643     RefPtr<ImageData> imageData = canvas->getImageData();
644     if (imageData)
645         texSubImage2D(target, level, xoffset, yoffset, format, type, imageData.get());
646     else
647         texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha);
648     return { };
649 }
650
651 #if ENABLE(VIDEO)
652
653 ExceptionOr<void> WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, HTMLVideoElement* video)
654 {
655     if (wouldTaintOrigin(video))
656         return Exception { SECURITY_ERR };
657     if (isContextLostOrPending() || !validateHTMLVideoElement("texSubImage2D", video)
658         || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLVideoElement, target, level, format, video->videoWidth(), video->videoHeight(), 0, format, type, xoffset, yoffset))
659         return { };
660
661     RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode());
662     if (!image)
663         return { };
664     texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha);
665     return { };
666 }
667
668 #endif
669
670 bool WebGLRenderingContext::validateTexFuncParameters(const char* functionName,
671     TexFuncValidationFunctionType functionType,
672     GC3Denum target, GC3Dint level,
673     GC3Denum internalformat,
674     GC3Dsizei width, GC3Dsizei height, GC3Dint border,
675     GC3Denum format, GC3Denum type)
676 {
677     // We absolutely have to validate the format and type combination.
678     // The texImage2D entry points taking HTMLImage, etc. will produce
679     // temporary data based on this combination, so it must be legal.
680     if (!validateTexFuncFormatAndType(functionName, internalformat, format, type, level) || !validateTexFuncLevel(functionName, target, level))
681         return false;
682     
683     if (width < 0 || height < 0) {
684         synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
685         return false;
686     }
687     
688     GC3Dint maxTextureSizeForLevel = pow(2.0, m_maxTextureLevel - 1 - level);
689     switch (target) {
690     case GraphicsContext3D::TEXTURE_2D:
691         if (width > maxTextureSizeForLevel || height > maxTextureSizeForLevel) {
692             synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range");
693             return false;
694         }
695         break;
696     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
697     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
698     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
699     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
700     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
701     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
702         if (functionType != TexSubImage && width != height) {
703             synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width != height for cube map");
704             return false;
705         }
706         // No need to check height here. For texImage width == height.
707         // For texSubImage that will be checked when checking yoffset + height is in range.
708         if (width > maxTextureSizeForLevel) {
709             synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range for cube map");
710             return false;
711         }
712         break;
713     default:
714         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
715         return false;
716     }
717
718     if (format != internalformat) {
719         synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format != internalformat");
720         return false;
721     }
722     
723     if (border) {
724         synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "border != 0");
725         return false;
726     }
727     
728     return true;
729 }
730
731 bool WebGLRenderingContext::validateTexFuncFormatAndType(const char* functionName, GC3Denum internalformat, GC3Denum format, GC3Denum type, GC3Dint level)
732 {
733     UNUSED_PARAM(internalformat);
734     switch (format) {
735     case GraphicsContext3D::ALPHA:
736     case GraphicsContext3D::LUMINANCE:
737     case GraphicsContext3D::LUMINANCE_ALPHA:
738     case GraphicsContext3D::RGB:
739     case GraphicsContext3D::RGBA:
740         break;
741     case GraphicsContext3D::DEPTH_STENCIL:
742     case GraphicsContext3D::DEPTH_COMPONENT:
743         if (m_webglDepthTexture)
744             break;
745         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "depth texture formats not enabled");
746         return false;
747     case Extensions3D::SRGB_EXT:
748     case Extensions3D::SRGB_ALPHA_EXT:
749     default:
750         if ((format == Extensions3D::SRGB_EXT || format == Extensions3D::SRGB_ALPHA_EXT)
751             && m_extsRGB)
752             break;
753         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture format");
754         return false;
755     }
756     
757     switch (type) {
758     case GraphicsContext3D::UNSIGNED_BYTE:
759     case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
760     case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
761     case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
762         break;
763     case GraphicsContext3D::FLOAT:
764         if (m_oesTextureFloat)
765             break;
766         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
767         return false;
768     case GraphicsContext3D::HALF_FLOAT_OES:
769         if (m_oesTextureHalfFloat)
770             break;
771         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
772         return false;
773     case GraphicsContext3D::UNSIGNED_INT:
774     case GraphicsContext3D::UNSIGNED_INT_24_8:
775     case GraphicsContext3D::UNSIGNED_SHORT:
776         if (m_webglDepthTexture)
777             break;
778         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
779         return false;
780     default:
781         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
782         return false;
783     }
784     
785     // Verify that the combination of format and type is supported.
786     switch (format) {
787     case GraphicsContext3D::ALPHA:
788     case GraphicsContext3D::LUMINANCE:
789     case GraphicsContext3D::LUMINANCE_ALPHA:
790         if (type != GraphicsContext3D::UNSIGNED_BYTE
791             && type != GraphicsContext3D::FLOAT
792             && type != GraphicsContext3D::HALF_FLOAT_OES) {
793             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for format");
794             return false;
795         }
796         break;
797     case GraphicsContext3D::RGB:
798     case Extensions3D::SRGB_EXT:
799         if (type != GraphicsContext3D::UNSIGNED_BYTE
800             && type != GraphicsContext3D::UNSIGNED_SHORT_5_6_5
801             && type != GraphicsContext3D::FLOAT
802             && type != GraphicsContext3D::HALF_FLOAT_OES) {
803             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGB format");
804             return false;
805         }
806         break;
807     case GraphicsContext3D::RGBA:
808     case Extensions3D::SRGB_ALPHA_EXT:
809         if (type != GraphicsContext3D::UNSIGNED_BYTE
810             && type != GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4
811             && type != GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1
812             && type != GraphicsContext3D::FLOAT
813             && type != GraphicsContext3D::HALF_FLOAT_OES) {
814             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGBA format");
815             return false;
816         }
817         break;
818     case GraphicsContext3D::DEPTH_COMPONENT:
819         if (!m_webglDepthTexture) {
820             synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_COMPONENT not enabled");
821             return false;
822         }
823         if (type != GraphicsContext3D::UNSIGNED_SHORT
824             && type != GraphicsContext3D::UNSIGNED_INT) {
825             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_COMPONENT format");
826             return false;
827         }
828         if (level > 0) {
829             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_COMPONENT format");
830             return false;
831         }
832         break;
833     case GraphicsContext3D::DEPTH_STENCIL:
834         if (!m_webglDepthTexture) {
835             synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_STENCIL not enabled");
836             return false;
837         }
838         if (type != GraphicsContext3D::UNSIGNED_INT_24_8) {
839             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_STENCIL format");
840             return false;
841         }
842         if (level > 0) {
843             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_STENCIL format");
844             return false;
845         }
846         break;
847     default:
848         ASSERT_NOT_REACHED();
849     }
850     
851     return true;
852 }
853
854 bool WebGLRenderingContext::validateTexFuncData(const char* functionName, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum internalformat, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, NullDisposition disposition)
855 {
856     if (!pixels) {
857         if (disposition == NullAllowed)
858             return true;
859         synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels");
860         return false;
861     }
862
863     if (!validateTexFuncFormatAndType(functionName, internalformat, format, type, level))
864         return false;
865     if (!validateSettableTexFormat(functionName, format))
866         return false;
867     
868     switch (type) {
869     case GraphicsContext3D::UNSIGNED_BYTE:
870         if (pixels->getType() != JSC::TypeUint8) {
871             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_BYTE but ArrayBufferView not Uint8Array");
872             return false;
873         }
874         break;
875     case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
876     case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
877     case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
878         if (pixels->getType() != JSC::TypeUint16) {
879             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_SHORT but ArrayBufferView not Uint16Array");
880             return false;
881         }
882         break;
883     case GraphicsContext3D::FLOAT: // OES_texture_float
884         if (pixels->getType() != JSC::TypeFloat32) {
885             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type FLOAT but ArrayBufferView not Float32Array");
886             return false;
887         }
888         break;
889     case GraphicsContext3D::HALF_FLOAT_OES: // OES_texture_half_float
890         // As per the specification, ArrayBufferView should be null when
891         // OES_texture_half_float is enabled.
892         if (pixels) {
893             synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type HALF_FLOAT_OES but ArrayBufferView is not NULL");
894             return false;
895         }
896         break;
897     default:
898         ASSERT_NOT_REACHED();
899     }
900     
901     unsigned totalBytesRequired;
902     GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0);
903     if (error != GraphicsContext3D::NO_ERROR) {
904         synthesizeGLError(error, functionName, "invalid texture dimensions");
905         return false;
906     }
907     if (pixels->byteLength() < totalBytesRequired) {
908         if (m_unpackAlignment != 1) {
909             m_context->computeImageSizeInBytes(format, type, width, height, 1, &totalBytesRequired, 0);
910             if (pixels->byteLength() == totalBytesRequired) {
911                 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request with UNPACK_ALIGNMENT > 1");
912                 return false;
913             }
914         }
915         synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request");
916         return false;
917     }
918     return true;
919 }
920
921 WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname)
922 {
923     if (isContextLostOrPending())
924         return WebGLGetInfo();
925     const int intZero = 0;
926     switch (pname) {
927     case GraphicsContext3D::ACTIVE_TEXTURE:
928         return getUnsignedIntParameter(pname);
929     case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
930         return getWebGLFloatArrayParameter(pname);
931     case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
932         return getWebGLFloatArrayParameter(pname);
933     case GraphicsContext3D::ALPHA_BITS:
934         return getIntParameter(pname);
935     case GraphicsContext3D::ARRAY_BUFFER_BINDING:
936         return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundArrayBuffer));
937     case GraphicsContext3D::BLEND:
938         return getBooleanParameter(pname);
939     case GraphicsContext3D::BLEND_COLOR:
940         return getWebGLFloatArrayParameter(pname);
941     case GraphicsContext3D::BLEND_DST_ALPHA:
942         return getUnsignedIntParameter(pname);
943     case GraphicsContext3D::BLEND_DST_RGB:
944         return getUnsignedIntParameter(pname);
945     case GraphicsContext3D::BLEND_EQUATION_ALPHA:
946         return getUnsignedIntParameter(pname);
947     case GraphicsContext3D::BLEND_EQUATION_RGB:
948         return getUnsignedIntParameter(pname);
949     case GraphicsContext3D::BLEND_SRC_ALPHA:
950         return getUnsignedIntParameter(pname);
951     case GraphicsContext3D::BLEND_SRC_RGB:
952         return getUnsignedIntParameter(pname);
953     case GraphicsContext3D::BLUE_BITS:
954         return getIntParameter(pname);
955     case GraphicsContext3D::COLOR_CLEAR_VALUE:
956         return getWebGLFloatArrayParameter(pname);
957     case GraphicsContext3D::COLOR_WRITEMASK:
958         return getBooleanArrayParameter(pname);
959     case GraphicsContext3D::COMPRESSED_TEXTURE_FORMATS:
960         return WebGLGetInfo(PassRefPtr<Uint32Array>(Uint32Array::create(m_compressedTextureFormats.data(), m_compressedTextureFormats.size())));
961     case GraphicsContext3D::CULL_FACE:
962         return getBooleanParameter(pname);
963     case GraphicsContext3D::CULL_FACE_MODE:
964         return getUnsignedIntParameter(pname);
965     case GraphicsContext3D::CURRENT_PROGRAM:
966         return WebGLGetInfo(PassRefPtr<WebGLProgram>(m_currentProgram));
967     case GraphicsContext3D::DEPTH_BITS:
968         if (!m_framebufferBinding && !m_attributes.depth)
969             return WebGLGetInfo(intZero);
970         return getIntParameter(pname);
971     case GraphicsContext3D::DEPTH_CLEAR_VALUE:
972         return getFloatParameter(pname);
973     case GraphicsContext3D::DEPTH_FUNC:
974         return getUnsignedIntParameter(pname);
975     case GraphicsContext3D::DEPTH_RANGE:
976         return getWebGLFloatArrayParameter(pname);
977     case GraphicsContext3D::DEPTH_TEST:
978         return getBooleanParameter(pname);
979     case GraphicsContext3D::DEPTH_WRITEMASK:
980         return getBooleanParameter(pname);
981     case GraphicsContext3D::DITHER:
982         return getBooleanParameter(pname);
983     case GraphicsContext3D::ELEMENT_ARRAY_BUFFER_BINDING:
984         return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundVertexArrayObject->getElementArrayBuffer()));
985     case GraphicsContext3D::FRAMEBUFFER_BINDING:
986         return WebGLGetInfo(PassRefPtr<WebGLFramebuffer>(m_framebufferBinding));
987     case GraphicsContext3D::FRONT_FACE:
988         return getUnsignedIntParameter(pname);
989     case GraphicsContext3D::GENERATE_MIPMAP_HINT:
990         return getUnsignedIntParameter(pname);
991     case GraphicsContext3D::GREEN_BITS:
992         return getIntParameter(pname);
993     case GraphicsContext3D::IMPLEMENTATION_COLOR_READ_FORMAT:
994         return getIntParameter(pname);
995     case GraphicsContext3D::IMPLEMENTATION_COLOR_READ_TYPE:
996         return getIntParameter(pname);
997     case GraphicsContext3D::LINE_WIDTH:
998         return getFloatParameter(pname);
999     case GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS:
1000         return getIntParameter(pname);
1001     case GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE:
1002         return getIntParameter(pname);
1003     case GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS:
1004         return getIntParameter(pname);
1005     case GraphicsContext3D::MAX_RENDERBUFFER_SIZE:
1006         return getIntParameter(pname);
1007     case GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS:
1008         return getIntParameter(pname);
1009     case GraphicsContext3D::MAX_TEXTURE_SIZE:
1010         return getIntParameter(pname);
1011     case GraphicsContext3D::MAX_VARYING_VECTORS:
1012         return getIntParameter(pname);
1013     case GraphicsContext3D::MAX_VERTEX_ATTRIBS:
1014         return getIntParameter(pname);
1015     case GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS:
1016         return getIntParameter(pname);
1017     case GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS:
1018         return getIntParameter(pname);
1019     case GraphicsContext3D::MAX_VIEWPORT_DIMS:
1020         return getWebGLIntArrayParameter(pname);
1021     case GraphicsContext3D::NUM_SHADER_BINARY_FORMATS:
1022         return getIntParameter(pname);
1023     case GraphicsContext3D::PACK_ALIGNMENT:
1024         return getIntParameter(pname);
1025     case GraphicsContext3D::POLYGON_OFFSET_FACTOR:
1026         return getFloatParameter(pname);
1027     case GraphicsContext3D::POLYGON_OFFSET_FILL:
1028         return getBooleanParameter(pname);
1029     case GraphicsContext3D::POLYGON_OFFSET_UNITS:
1030         return getFloatParameter(pname);
1031     case GraphicsContext3D::RED_BITS:
1032         return getIntParameter(pname);
1033     case GraphicsContext3D::RENDERBUFFER_BINDING:
1034         return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(m_renderbufferBinding));
1035     case GraphicsContext3D::RENDERER:
1036         return WebGLGetInfo(String("WebKit WebGL"));
1037     case GraphicsContext3D::SAMPLE_BUFFERS:
1038         return getIntParameter(pname);
1039     case GraphicsContext3D::SAMPLE_COVERAGE_INVERT:
1040         return getBooleanParameter(pname);
1041     case GraphicsContext3D::SAMPLE_COVERAGE_VALUE:
1042         return getFloatParameter(pname);
1043     case GraphicsContext3D::SAMPLES:
1044         return getIntParameter(pname);
1045     case GraphicsContext3D::SCISSOR_BOX:
1046         return getWebGLIntArrayParameter(pname);
1047     case GraphicsContext3D::SCISSOR_TEST:
1048         return getBooleanParameter(pname);
1049     case GraphicsContext3D::SHADING_LANGUAGE_VERSION:
1050         return WebGLGetInfo("WebGL GLSL ES 1.0 (" + m_context->getString(GraphicsContext3D::SHADING_LANGUAGE_VERSION) + ")");
1051     case GraphicsContext3D::STENCIL_BACK_FAIL:
1052         return getUnsignedIntParameter(pname);
1053     case GraphicsContext3D::STENCIL_BACK_FUNC:
1054         return getUnsignedIntParameter(pname);
1055     case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_FAIL:
1056         return getUnsignedIntParameter(pname);
1057     case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_PASS:
1058         return getUnsignedIntParameter(pname);
1059     case GraphicsContext3D::STENCIL_BACK_REF:
1060         return getIntParameter(pname);
1061     case GraphicsContext3D::STENCIL_BACK_VALUE_MASK:
1062         return getUnsignedIntParameter(pname);
1063     case GraphicsContext3D::STENCIL_BACK_WRITEMASK:
1064         return getUnsignedIntParameter(pname);
1065     case GraphicsContext3D::STENCIL_BITS:
1066         if (!m_framebufferBinding && !m_attributes.stencil)
1067             return WebGLGetInfo(intZero);
1068         return getIntParameter(pname);
1069     case GraphicsContext3D::STENCIL_CLEAR_VALUE:
1070         return getIntParameter(pname);
1071     case GraphicsContext3D::STENCIL_FAIL:
1072         return getUnsignedIntParameter(pname);
1073     case GraphicsContext3D::STENCIL_FUNC:
1074         return getUnsignedIntParameter(pname);
1075     case GraphicsContext3D::STENCIL_PASS_DEPTH_FAIL:
1076         return getUnsignedIntParameter(pname);
1077     case GraphicsContext3D::STENCIL_PASS_DEPTH_PASS:
1078         return getUnsignedIntParameter(pname);
1079     case GraphicsContext3D::STENCIL_REF:
1080         return getIntParameter(pname);
1081     case GraphicsContext3D::STENCIL_TEST:
1082         return getBooleanParameter(pname);
1083     case GraphicsContext3D::STENCIL_VALUE_MASK:
1084         return getUnsignedIntParameter(pname);
1085     case GraphicsContext3D::STENCIL_WRITEMASK:
1086         return getUnsignedIntParameter(pname);
1087     case GraphicsContext3D::SUBPIXEL_BITS:
1088         return getIntParameter(pname);
1089     case GraphicsContext3D::TEXTURE_BINDING_2D:
1090         return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].texture2DBinding));
1091     case GraphicsContext3D::TEXTURE_BINDING_CUBE_MAP:
1092         return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].textureCubeMapBinding));
1093     case GraphicsContext3D::UNPACK_ALIGNMENT:
1094         return getIntParameter(pname);
1095     case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
1096         return WebGLGetInfo(m_unpackFlipY);
1097     case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
1098         return WebGLGetInfo(m_unpackPremultiplyAlpha);
1099     case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
1100         return WebGLGetInfo(m_unpackColorspaceConversion);
1101     case GraphicsContext3D::VENDOR:
1102         return WebGLGetInfo(String("WebKit"));
1103     case GraphicsContext3D::VERSION:
1104         return WebGLGetInfo("WebGL 1.0 (" + m_context->getString(GraphicsContext3D::VERSION) + ")");
1105     case GraphicsContext3D::VIEWPORT:
1106         return getWebGLIntArrayParameter(pname);
1107     case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
1108         if (m_oesStandardDerivatives)
1109             return getUnsignedIntParameter(Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES);
1110         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, OES_standard_derivatives not enabled");
1111         return WebGLGetInfo();
1112     case WebGLDebugRendererInfo::UNMASKED_RENDERER_WEBGL:
1113         if (m_webglDebugRendererInfo)
1114             return WebGLGetInfo(m_context->getString(GraphicsContext3D::RENDERER));
1115         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled");
1116         return WebGLGetInfo();
1117     case WebGLDebugRendererInfo::UNMASKED_VENDOR_WEBGL:
1118         if (m_webglDebugRendererInfo)
1119             return WebGLGetInfo(m_context->getString(GraphicsContext3D::VENDOR));
1120         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled");
1121         return WebGLGetInfo();
1122     case Extensions3D::VERTEX_ARRAY_BINDING_OES: // OES_vertex_array_object
1123         if (m_oesVertexArrayObject) {
1124             if (!m_boundVertexArrayObject->isDefaultObject())
1125                 return WebGLGetInfo(PassRefPtr<WebGLVertexArrayObjectOES>(static_cast<WebGLVertexArrayObjectOES*>(m_boundVertexArrayObject.get())));
1126             return WebGLGetInfo();
1127         }
1128         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, OES_vertex_array_object not enabled");
1129         return WebGLGetInfo();
1130     case Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
1131         if (m_extTextureFilterAnisotropic)
1132             return getUnsignedIntParameter(Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT);
1133         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled");
1134         return WebGLGetInfo();
1135     case Extensions3D::MAX_COLOR_ATTACHMENTS_EXT: // EXT_draw_buffers BEGIN
1136         if (m_webglDrawBuffers)
1137             return WebGLGetInfo(getMaxColorAttachments());
1138         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled");
1139         return WebGLGetInfo();
1140     case Extensions3D::MAX_DRAW_BUFFERS_EXT:
1141         if (m_webglDrawBuffers)
1142             return WebGLGetInfo(getMaxDrawBuffers());
1143         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled");
1144         return WebGLGetInfo();
1145     default:
1146         if (m_webglDrawBuffers
1147             && pname >= Extensions3D::DRAW_BUFFER0_EXT
1148             && pname < static_cast<GC3Denum>(Extensions3D::DRAW_BUFFER0_EXT + getMaxDrawBuffers())) {
1149             GC3Dint value = GraphicsContext3D::NONE;
1150             if (m_framebufferBinding)
1151                 value = m_framebufferBinding->getDrawBuffer(pname);
1152             else // emulated backbuffer
1153                 value = m_backDrawBuffer;
1154             return WebGLGetInfo(value);
1155         }
1156         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name");
1157         return WebGLGetInfo();
1158     }
1159 }
1160
1161 GC3Dint WebGLRenderingContext::getMaxDrawBuffers()
1162 {
1163     if (!supportsDrawBuffers())
1164         return 0;
1165     if (!m_maxDrawBuffers)
1166         m_context->getIntegerv(Extensions3D::MAX_DRAW_BUFFERS_EXT, &m_maxDrawBuffers);
1167     if (!m_maxColorAttachments)
1168         m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments);
1169     // WEBGL_draw_buffers requires MAX_COLOR_ATTACHMENTS >= MAX_DRAW_BUFFERS.
1170     return std::min(m_maxDrawBuffers, m_maxColorAttachments);
1171 }
1172
1173 GC3Dint WebGLRenderingContext::getMaxColorAttachments()
1174 {
1175     if (!supportsDrawBuffers())
1176         return 0;
1177     if (!m_maxColorAttachments)
1178         m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments);
1179     return m_maxColorAttachments;
1180 }
1181     
1182 bool WebGLRenderingContext::validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired)
1183 {
1184     // Performs conservative validation by caching a maximum index of
1185     // the given type per element array buffer. If all of the bound
1186     // array buffers have enough elements to satisfy that maximum
1187     // index, skips the expensive per-draw-call iteration in
1188     // validateIndexArrayPrecise.
1189     
1190     RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1191     
1192     if (!elementArrayBuffer)
1193         return false;
1194     
1195     GC3Dsizeiptr numElements = elementArrayBuffer->byteLength();
1196     // The case count==0 is already dealt with in drawElements before validateIndexArrayConservative.
1197     if (!numElements)
1198         return false;
1199     const ArrayBuffer* buffer = elementArrayBuffer->elementArrayBuffer();
1200     ASSERT(buffer);
1201     
1202     int maxIndex = elementArrayBuffer->getCachedMaxIndex(type);
1203     if (maxIndex < 0) {
1204         // Compute the maximum index in the entire buffer for the given type of index.
1205         switch (type) {
1206         case GraphicsContext3D::UNSIGNED_BYTE: {
1207             const GC3Dubyte* p = static_cast<const GC3Dubyte*>(buffer->data());
1208             for (GC3Dsizeiptr i = 0; i < numElements; i++)
1209                 maxIndex = std::max(maxIndex, static_cast<int>(p[i]));
1210             break;
1211         }
1212         case GraphicsContext3D::UNSIGNED_SHORT: {
1213             numElements /= sizeof(GC3Dushort);
1214             const GC3Dushort* p = static_cast<const GC3Dushort*>(buffer->data());
1215             for (GC3Dsizeiptr i = 0; i < numElements; i++)
1216                 maxIndex = std::max(maxIndex, static_cast<int>(p[i]));
1217             break;
1218         }
1219         case GraphicsContext3D::UNSIGNED_INT: {
1220             if (!m_oesElementIndexUint)
1221                 return false;
1222             numElements /= sizeof(GC3Duint);
1223             const GC3Duint* p = static_cast<const GC3Duint*>(buffer->data());
1224             for (GC3Dsizeiptr i = 0; i < numElements; i++)
1225                 maxIndex = std::max(maxIndex, static_cast<int>(p[i]));
1226             break;
1227         }
1228         default:
1229             return false;
1230     }
1231     elementArrayBuffer->setCachedMaxIndex(type, maxIndex);
1232     }
1233     
1234     if (maxIndex >= 0) {
1235         // The number of required elements is one more than the maximum
1236         // index that will be accessed.
1237         numElementsRequired = maxIndex + 1;
1238         return true;
1239     }
1240     
1241     return false;
1242 }
1243
1244 bool WebGLRenderingContext::validateBlendEquation(const char* functionName, GC3Denum mode)
1245 {
1246     switch (mode) {
1247     case GraphicsContext3D::FUNC_ADD:
1248     case GraphicsContext3D::FUNC_SUBTRACT:
1249     case GraphicsContext3D::FUNC_REVERSE_SUBTRACT:
1250     case Extensions3D::MIN_EXT:
1251     case Extensions3D::MAX_EXT:
1252         if ((mode == Extensions3D::MIN_EXT || mode == Extensions3D::MAX_EXT) && !m_extBlendMinMax) {
1253             synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid mode");
1254             return false;
1255         }
1256         return true;
1257         break;
1258     default:
1259         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid mode");
1260         return false;
1261     }
1262 }
1263
1264 bool WebGLRenderingContext::validateCapability(const char* functionName, GC3Denum cap)
1265 {
1266     switch (cap) {
1267     case GraphicsContext3D::BLEND:
1268     case GraphicsContext3D::CULL_FACE:
1269     case GraphicsContext3D::DEPTH_TEST:
1270     case GraphicsContext3D::DITHER:
1271     case GraphicsContext3D::POLYGON_OFFSET_FILL:
1272     case GraphicsContext3D::SAMPLE_ALPHA_TO_COVERAGE:
1273     case GraphicsContext3D::SAMPLE_COVERAGE:
1274     case GraphicsContext3D::SCISSOR_TEST:
1275     case GraphicsContext3D::STENCIL_TEST:
1276         return true;
1277     default:
1278         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid capability");
1279         return false;
1280     }
1281 }
1282
1283 } // namespace WebCore
1284
1285 #endif // ENABLE(WEBGL)