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