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