Assertion failed in JSC::createError
[WebKit-https.git] / Source / WebCore / html / canvas / WebGLRenderingContext.cpp
1 /*
2  * Copyright (C) 2015-2017 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 #include "WebGLRenderingContext.h"
28
29 #if ENABLE(WEBGL)
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 "InspectorInstrumentation.h"
44 #include "OESElementIndexUint.h"
45 #include "OESStandardDerivatives.h"
46 #include "OESTextureFloat.h"
47 #include "OESTextureFloatLinear.h"
48 #include "OESTextureHalfFloat.h"
49 #include "OESTextureHalfFloatLinear.h"
50 #include "OESVertexArrayObject.h"
51 #include "RenderBox.h"
52 #include "WebGLCompressedTextureASTC.h"
53 #include "WebGLCompressedTextureATC.h"
54 #include "WebGLCompressedTexturePVRTC.h"
55 #include "WebGLCompressedTextureS3TC.h"
56 #include "WebGLDebugRendererInfo.h"
57 #include "WebGLDebugShaders.h"
58 #include "WebGLDepthTexture.h"
59 #include "WebGLDrawBuffers.h"
60 #include "WebGLLoseContext.h"
61 #include "WebGLVertexArrayObjectOES.h"
62 #include <JavaScriptCore/GenericTypedArrayViewInlines.h>
63 #include <JavaScriptCore/HeapInlines.h>
64 #include <JavaScriptCore/JSCJSValueInlines.h>
65 #include <JavaScriptCore/JSCellInlines.h>
66 #include <JavaScriptCore/JSGenericTypedArrayViewInlines.h>
67
68 namespace WebCore {
69
70 std::unique_ptr<WebGLRenderingContext> WebGLRenderingContext::create(CanvasBase& canvas, GraphicsContext3DAttributes attributes)
71 {
72     auto renderingContext = std::unique_ptr<WebGLRenderingContext>(new WebGLRenderingContext(canvas, attributes));
73
74     InspectorInstrumentation::didCreateCanvasRenderingContext(*renderingContext);
75
76     return renderingContext;
77 }
78
79 std::unique_ptr<WebGLRenderingContext> WebGLRenderingContext::create(CanvasBase& canvas, Ref<GraphicsContext3D>&& context, GraphicsContext3DAttributes attributes)
80 {
81     auto renderingContext = std::unique_ptr<WebGLRenderingContext>(new WebGLRenderingContext(canvas, WTFMove(context), attributes));
82
83     InspectorInstrumentation::didCreateCanvasRenderingContext(*renderingContext);
84
85     return renderingContext;
86 }
87
88 WebGLRenderingContext::WebGLRenderingContext(CanvasBase& canvas, GraphicsContext3DAttributes attributes)
89     : WebGLRenderingContextBase(canvas, attributes)
90 {
91 }
92
93 WebGLRenderingContext::WebGLRenderingContext(CanvasBase& canvas, Ref<GraphicsContext3D>&& context, GraphicsContext3DAttributes attributes)
94     : WebGLRenderingContextBase(canvas, WTFMove(context), attributes)
95 {
96     initializeVertexArrayObjects();
97 }
98
99 void WebGLRenderingContext::initializeVertexArrayObjects()
100 {
101     m_defaultVertexArrayObject = WebGLVertexArrayObjectOES::create(*this, WebGLVertexArrayObjectOES::Type::Default);
102     addContextObject(*m_defaultVertexArrayObject);
103     m_boundVertexArrayObject = m_defaultVertexArrayObject;
104     if (!isGLES2Compliant())
105         initVertexAttrib0();
106 }
107
108 WebGLExtension* WebGLRenderingContext::getExtension(const String& name)
109 {
110     if (isContextLostOrPending())
111         return nullptr;
112
113 #define ENABLE_IF_REQUESTED(type, variable, nameLiteral, canEnable) \
114     if (equalIgnoringASCIICase(name, nameLiteral)) { \
115         if (!variable) { \
116             variable = (canEnable) ? std::make_unique<type>(*this) : nullptr; \
117             if (variable != nullptr) \
118                 InspectorInstrumentation::didEnableExtension(*this, name); \
119         } \
120         return variable.get(); \
121     }
122
123     ENABLE_IF_REQUESTED(EXTBlendMinMax, m_extBlendMinMax, "EXT_blend_minmax", enableSupportedExtension("GL_EXT_blend_minmax"_s));
124     ENABLE_IF_REQUESTED(EXTsRGB, m_extsRGB, "EXT_sRGB", enableSupportedExtension("GL_EXT_sRGB"_s));
125     ENABLE_IF_REQUESTED(EXTFragDepth, m_extFragDepth, "EXT_frag_depth", enableSupportedExtension("GL_EXT_frag_depth"_s));
126     if (equalIgnoringASCIICase(name, "EXT_shader_texture_lod")) {
127         if (!m_extShaderTextureLOD) {
128             if (!(m_context->getExtensions().supports("GL_EXT_shader_texture_lod"_s) || m_context->getExtensions().supports("GL_ARB_shader_texture_lod"_s)))
129                 m_extShaderTextureLOD = nullptr;
130             else {
131                 m_context->getExtensions().ensureEnabled("GL_EXT_shader_texture_lod"_s);
132                 m_extShaderTextureLOD = std::make_unique<EXTShaderTextureLOD>(*this);
133                 InspectorInstrumentation::didEnableExtension(*this, name);
134             }
135         }
136         return m_extShaderTextureLOD.get();
137     }
138     ENABLE_IF_REQUESTED(EXTTextureFilterAnisotropic, m_extTextureFilterAnisotropic, "EXT_texture_filter_anisotropic", enableSupportedExtension("GL_EXT_texture_filter_anisotropic"_s));
139     ENABLE_IF_REQUESTED(EXTTextureFilterAnisotropic, m_extTextureFilterAnisotropic, "WEBKIT_EXT_texture_filter_anisotropic", enableSupportedExtension("GL_EXT_texture_filter_anisotropic"_s));
140     ENABLE_IF_REQUESTED(OESStandardDerivatives, m_oesStandardDerivatives, "OES_standard_derivatives", enableSupportedExtension("GL_OES_standard_derivatives"_s));
141     ENABLE_IF_REQUESTED(OESTextureFloat, m_oesTextureFloat, "OES_texture_float", enableSupportedExtension("GL_OES_texture_float"_s));
142     ENABLE_IF_REQUESTED(OESTextureFloatLinear, m_oesTextureFloatLinear, "OES_texture_float_linear", enableSupportedExtension("GL_OES_texture_float_linear"_s));
143     ENABLE_IF_REQUESTED(OESTextureHalfFloat, m_oesTextureHalfFloat, "OES_texture_half_float", enableSupportedExtension("GL_OES_texture_half_float"_s));
144     ENABLE_IF_REQUESTED(OESTextureHalfFloatLinear, m_oesTextureHalfFloatLinear, "OES_texture_half_float_linear", enableSupportedExtension("GL_OES_texture_half_float_linear"_s));
145     ENABLE_IF_REQUESTED(OESVertexArrayObject, m_oesVertexArrayObject, "OES_vertex_array_object", enableSupportedExtension("GL_OES_vertex_array_object"_s));
146     ENABLE_IF_REQUESTED(OESElementIndexUint, m_oesElementIndexUint, "OES_element_index_uint", enableSupportedExtension("GL_OES_element_index_uint"_s));
147     ENABLE_IF_REQUESTED(WebGLLoseContext, m_webglLoseContext, "WEBGL_lose_context", true);
148     ENABLE_IF_REQUESTED(WebGLCompressedTextureATC, m_webglCompressedTextureATC, "WEBKIT_WEBGL_compressed_texture_atc", WebGLCompressedTextureATC::supported(*this));
149     ENABLE_IF_REQUESTED(WebGLCompressedTexturePVRTC, m_webglCompressedTexturePVRTC, "WEBKIT_WEBGL_compressed_texture_pvrtc", WebGLCompressedTexturePVRTC::supported(*this));
150     ENABLE_IF_REQUESTED(WebGLCompressedTextureS3TC, m_webglCompressedTextureS3TC, "WEBGL_compressed_texture_s3tc", WebGLCompressedTextureS3TC::supported(*this));
151     ENABLE_IF_REQUESTED(WebGLCompressedTextureASTC, m_webglCompressedTextureASTC, "WEBGL_compressed_texture_astc", WebGLCompressedTextureASTC::supported(*this));
152     ENABLE_IF_REQUESTED(WebGLDepthTexture, m_webglDepthTexture, "WEBGL_depth_texture", WebGLDepthTexture::supported(*m_context));
153     if (equalIgnoringASCIICase(name, "WEBGL_draw_buffers")) {
154         if (!m_webglDrawBuffers) {
155             if (!supportsDrawBuffers())
156                 m_webglDrawBuffers = nullptr;
157             else {
158                 m_context->getExtensions().ensureEnabled("GL_EXT_draw_buffers"_s);
159                 m_webglDrawBuffers = std::make_unique<WebGLDrawBuffers>(*this);
160                 InspectorInstrumentation::didEnableExtension(*this, name);
161             }
162         }
163         return m_webglDrawBuffers.get();
164     }
165     if (equalIgnoringASCIICase(name, "ANGLE_instanced_arrays")) {
166         if (!m_angleInstancedArrays) {
167             if (!ANGLEInstancedArrays::supported(*this))
168                 m_angleInstancedArrays = nullptr;
169             else {
170                 m_context->getExtensions().ensureEnabled("GL_ANGLE_instanced_arrays"_s);
171                 m_angleInstancedArrays = std::make_unique<ANGLEInstancedArrays>(*this);
172                 InspectorInstrumentation::didEnableExtension(*this, name);
173             }
174         }
175         return m_angleInstancedArrays.get();
176     }
177     ENABLE_IF_REQUESTED(WebGLDebugRendererInfo, m_webglDebugRendererInfo, "WEBGL_debug_renderer_info", true);
178     ENABLE_IF_REQUESTED(WebGLDebugShaders, m_webglDebugShaders, "WEBGL_debug_shaders", m_context->getExtensions().supports("GL_ANGLE_translated_shader_source"_s));
179     return nullptr;
180 }
181
182 Optional<Vector<String>> WebGLRenderingContext::getSupportedExtensions()
183 {
184     if (isContextLost())
185         return WTF::nullopt;
186
187     Vector<String> result;
188     
189     if (m_isPendingPolicyResolution)
190         return result;
191     
192     if (m_context->getExtensions().supports("GL_EXT_blend_minmax"_s))
193         result.append("EXT_blend_minmax"_s);
194     if (m_context->getExtensions().supports("GL_EXT_sRGB"_s))
195         result.append("EXT_sRGB"_s);
196     if (m_context->getExtensions().supports("GL_EXT_frag_depth"_s))
197         result.append("EXT_frag_depth"_s);
198     if (m_context->getExtensions().supports("GL_OES_texture_float"_s))
199         result.append("OES_texture_float"_s);
200     if (m_context->getExtensions().supports("GL_OES_texture_float_linear"_s))
201         result.append("OES_texture_float_linear"_s);
202     if (m_context->getExtensions().supports("GL_OES_texture_half_float"_s))
203         result.append("OES_texture_half_float"_s);
204     if (m_context->getExtensions().supports("GL_OES_texture_half_float_linear"_s))
205         result.append("OES_texture_half_float_linear"_s);
206     if (m_context->getExtensions().supports("GL_OES_standard_derivatives"_s))
207         result.append("OES_standard_derivatives"_s);
208     if (m_context->getExtensions().supports("GL_EXT_shader_texture_lod"_s) || m_context->getExtensions().supports("GL_ARB_shader_texture_lod"_s))
209         result.append("EXT_shader_texture_lod"_s);
210     if (m_context->getExtensions().supports("GL_EXT_texture_filter_anisotropic"_s))
211         result.append("EXT_texture_filter_anisotropic"_s);
212     if (m_context->getExtensions().supports("GL_OES_vertex_array_object"_s))
213         result.append("OES_vertex_array_object"_s);
214     if (m_context->getExtensions().supports("GL_OES_element_index_uint"_s))
215         result.append("OES_element_index_uint"_s);
216     result.append("WEBGL_lose_context"_s);
217     if (WebGLCompressedTextureATC::supported(*this))
218         result.append("WEBKIT_WEBGL_compressed_texture_atc"_s);
219     if (WebGLCompressedTexturePVRTC::supported(*this))
220         result.append("WEBKIT_WEBGL_compressed_texture_pvrtc"_s);
221     if (WebGLCompressedTextureS3TC::supported(*this))
222         result.append("WEBGL_compressed_texture_s3tc"_s);
223     if (WebGLCompressedTextureASTC::supported(*this))
224         result.append("WEBGL_compressed_texture_astc"_s);
225     if (WebGLDepthTexture::supported(*m_context))
226         result.append("WEBGL_depth_texture"_s);
227     if (supportsDrawBuffers())
228         result.append("WEBGL_draw_buffers"_s);
229     if (ANGLEInstancedArrays::supported(*this))
230         result.append("ANGLE_instanced_arrays"_s);
231     if (m_context->getExtensions().supports("GL_ANGLE_translated_shader_source"_s))
232         result.append("WEBGL_debug_shaders"_s);
233     result.append("WEBGL_debug_renderer_info"_s);
234
235     return result;
236 }
237
238 WebGLAny WebGLRenderingContext::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname)
239 {
240     if (isContextLostOrPending() || !validateFramebufferFuncParameters("getFramebufferAttachmentParameter", target, attachment))
241         return nullptr;
242     
243     if (!m_framebufferBinding || !m_framebufferBinding->object()) {
244         synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getFramebufferAttachmentParameter", "no framebuffer bound");
245         return nullptr;
246     }
247     
248     auto object = makeRefPtr(m_framebufferBinding->getAttachmentObject(attachment));
249     if (!object) {
250         if (pname == GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)
251             return static_cast<unsigned>(GraphicsContext3D::NONE);
252         // OpenGL ES 2.0 specifies INVALID_ENUM in this case, while desktop GL
253         // specifies INVALID_OPERATION.
254         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name");
255         return nullptr;
256     }
257     
258     if (object->isTexture()) {
259         switch (pname) {
260         case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
261             return static_cast<unsigned>(GraphicsContext3D::TEXTURE);
262         case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
263             return makeRefPtr(reinterpret_cast<WebGLTexture&>(*object));
264         case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
265         case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
266         case Extensions3D::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT: {
267             GC3Dint value = 0;
268             m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value);
269             return value;
270         }
271         default:
272             synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for texture attachment");
273             return nullptr;
274         }
275     } else {
276         ASSERT(object->isRenderbuffer());
277         switch (pname) {
278         case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
279             return static_cast<unsigned>(GraphicsContext3D::RENDERBUFFER);
280         case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
281             return makeRefPtr(reinterpret_cast<WebGLRenderbuffer&>(*object));
282         case Extensions3D::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT: {
283             if (!m_extsRGB) {
284                 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for renderbuffer attachment");
285                 return nullptr;
286             }
287             RefPtr<WebGLRenderbuffer> renderBuffer = reinterpret_cast<WebGLRenderbuffer*>(object.get());
288             GC3Denum renderBufferFormat = renderBuffer->getInternalFormat();
289             ASSERT(renderBufferFormat != Extensions3D::SRGB_EXT && renderBufferFormat != Extensions3D::SRGB_ALPHA_EXT);
290             if (renderBufferFormat == Extensions3D::SRGB8_ALPHA8_EXT)
291                 return static_cast<unsigned>(Extensions3D::SRGB_EXT);
292             return static_cast<unsigned>(GraphicsContext3D::LINEAR);
293         }
294         default:
295             synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for renderbuffer attachment");
296             return nullptr;
297         }
298     }
299 }
300
301 bool WebGLRenderingContext::validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment)
302 {
303     if (target != GraphicsContext3D::FRAMEBUFFER) {
304         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
305         return false;
306     }
307     // FIXME: Why does this return true unconditionally for COLOR_ATTACHMENT0,
308     // but false for other COLOR_ATTACHMENT values if m_webglDrawBuffers is false?
309     switch (attachment) {
310     case GraphicsContext3D::COLOR_ATTACHMENT0:
311     case GraphicsContext3D::DEPTH_ATTACHMENT:
312     case GraphicsContext3D::STENCIL_ATTACHMENT:
313     case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
314         return true;
315     default:
316         if (m_webglDrawBuffers
317             && attachment >= GraphicsContext3D::COLOR_ATTACHMENT0
318             && attachment < static_cast<GC3Denum>(GraphicsContext3D::COLOR_ATTACHMENT0 + getMaxColorAttachments()))
319             return true;
320         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid attachment");
321         return false;
322     }
323 }
324     
325 void WebGLRenderingContext::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height)
326 {
327     if (isContextLostOrPending())
328         return;
329     if (target != GraphicsContext3D::RENDERBUFFER) {
330         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid target");
331         return;
332     }
333     if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
334         synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "renderbufferStorage", "no bound renderbuffer");
335         return;
336     }
337     if (!validateSize("renderbufferStorage", width, height))
338         return;
339     switch (internalformat) {
340     case GraphicsContext3D::DEPTH_COMPONENT16:
341     case GraphicsContext3D::RGBA4:
342     case GraphicsContext3D::RGB5_A1:
343     case GraphicsContext3D::RGB565:
344     case GraphicsContext3D::STENCIL_INDEX8:
345     case Extensions3D::SRGB8_ALPHA8_EXT:
346         if (internalformat == Extensions3D::SRGB8_ALPHA8_EXT && !m_extsRGB) {
347             synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid internalformat");
348             return;
349         }
350         m_context->renderbufferStorage(target, internalformat, width, height);
351         m_renderbufferBinding->setInternalFormat(internalformat);
352         m_renderbufferBinding->setIsValid(true);
353         m_renderbufferBinding->setSize(width, height);
354         break;
355     case GraphicsContext3D::DEPTH_STENCIL:
356         if (isDepthStencilSupported())
357             m_context->renderbufferStorage(target, Extensions3D::DEPTH24_STENCIL8, width, height);
358         m_renderbufferBinding->setSize(width, height);
359         m_renderbufferBinding->setIsValid(isDepthStencilSupported());
360         m_renderbufferBinding->setInternalFormat(internalformat);
361         break;
362     default:
363         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid internalformat");
364         return;
365     }
366     applyStencilTest();
367 }
368
369 void WebGLRenderingContext::hint(GC3Denum target, GC3Denum mode)
370 {
371     if (isContextLostOrPending())
372         return;
373     bool isValid = false;
374     switch (target) {
375     case GraphicsContext3D::GENERATE_MIPMAP_HINT:
376         isValid = true;
377         break;
378     case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
379         if (m_oesStandardDerivatives)
380             isValid = true;
381         break;
382     }
383     if (!isValid) {
384         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "hint", "invalid target");
385         return;
386     }
387     m_context->hint(target, mode);
388 }
389     
390 void WebGLRenderingContext::clear(GC3Dbitfield mask)
391 {
392     if (isContextLostOrPending())
393         return;
394     if (mask & ~(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) {
395         synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clear", "invalid mask");
396         return;
397     }
398     const char* reason = "framebuffer incomplete";
399     if (m_framebufferBinding && !m_framebufferBinding->onAccess(m_context.get(), &reason)) {
400         synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "clear", reason);
401         return;
402     }
403     if (!clearIfComposited(mask))
404         m_context->clear(mask);
405     markContextChangedAndNotifyCanvasObserver();
406 }
407
408 WebGLAny WebGLRenderingContext::getParameter(GC3Denum pname)
409 {
410     if (isContextLostOrPending())
411         return nullptr;
412
413     switch (pname) {
414     case GraphicsContext3D::ACTIVE_TEXTURE:
415         return getUnsignedIntParameter(pname);
416     case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
417         return getWebGLFloatArrayParameter(pname);
418     case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
419         return getWebGLFloatArrayParameter(pname);
420     case GraphicsContext3D::ALPHA_BITS:
421         return getIntParameter(pname);
422     case GraphicsContext3D::ARRAY_BUFFER_BINDING:
423         return m_boundArrayBuffer;
424     case GraphicsContext3D::BLEND:
425         return getBooleanParameter(pname);
426     case GraphicsContext3D::BLEND_COLOR:
427         return getWebGLFloatArrayParameter(pname);
428     case GraphicsContext3D::BLEND_DST_ALPHA:
429         return getUnsignedIntParameter(pname);
430     case GraphicsContext3D::BLEND_DST_RGB:
431         return getUnsignedIntParameter(pname);
432     case GraphicsContext3D::BLEND_EQUATION_ALPHA:
433         return getUnsignedIntParameter(pname);
434     case GraphicsContext3D::BLEND_EQUATION_RGB:
435         return getUnsignedIntParameter(pname);
436     case GraphicsContext3D::BLEND_SRC_ALPHA:
437         return getUnsignedIntParameter(pname);
438     case GraphicsContext3D::BLEND_SRC_RGB:
439         return getUnsignedIntParameter(pname);
440     case GraphicsContext3D::BLUE_BITS:
441         return getIntParameter(pname);
442     case GraphicsContext3D::COLOR_CLEAR_VALUE:
443         return getWebGLFloatArrayParameter(pname);
444     case GraphicsContext3D::COLOR_WRITEMASK:
445         return getBooleanArrayParameter(pname);
446     case GraphicsContext3D::COMPRESSED_TEXTURE_FORMATS:
447         return Uint32Array::tryCreate(m_compressedTextureFormats.data(), m_compressedTextureFormats.size());
448     case GraphicsContext3D::CULL_FACE:
449         return getBooleanParameter(pname);
450     case GraphicsContext3D::CULL_FACE_MODE:
451         return getUnsignedIntParameter(pname);
452     case GraphicsContext3D::CURRENT_PROGRAM:
453         return m_currentProgram;
454     case GraphicsContext3D::DEPTH_BITS:
455         if (!m_framebufferBinding && !m_attributes.depth)
456             return 0;
457         return getIntParameter(pname);
458     case GraphicsContext3D::DEPTH_CLEAR_VALUE:
459         return getFloatParameter(pname);
460     case GraphicsContext3D::DEPTH_FUNC:
461         return getUnsignedIntParameter(pname);
462     case GraphicsContext3D::DEPTH_RANGE:
463         return getWebGLFloatArrayParameter(pname);
464     case GraphicsContext3D::DEPTH_TEST:
465         return getBooleanParameter(pname);
466     case GraphicsContext3D::DEPTH_WRITEMASK:
467         return getBooleanParameter(pname);
468     case GraphicsContext3D::DITHER:
469         return getBooleanParameter(pname);
470     case GraphicsContext3D::ELEMENT_ARRAY_BUFFER_BINDING:
471         return makeRefPtr(m_boundVertexArrayObject->getElementArrayBuffer());
472     case GraphicsContext3D::FRAMEBUFFER_BINDING:
473         return m_framebufferBinding;
474     case GraphicsContext3D::FRONT_FACE:
475         return getUnsignedIntParameter(pname);
476     case GraphicsContext3D::GENERATE_MIPMAP_HINT:
477         return getUnsignedIntParameter(pname);
478     case GraphicsContext3D::GREEN_BITS:
479         return getIntParameter(pname);
480     case GraphicsContext3D::IMPLEMENTATION_COLOR_READ_FORMAT:
481         return getIntParameter(pname);
482     case GraphicsContext3D::IMPLEMENTATION_COLOR_READ_TYPE:
483         return getIntParameter(pname);
484     case GraphicsContext3D::LINE_WIDTH:
485         return getFloatParameter(pname);
486     case GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS:
487         return getIntParameter(pname);
488     case GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE:
489         return getIntParameter(pname);
490     case GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS:
491         return getIntParameter(pname);
492     case GraphicsContext3D::MAX_RENDERBUFFER_SIZE:
493         return getIntParameter(pname);
494     case GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS:
495         return getIntParameter(pname);
496     case GraphicsContext3D::MAX_TEXTURE_SIZE:
497         return getIntParameter(pname);
498     case GraphicsContext3D::MAX_VARYING_VECTORS:
499         return getIntParameter(pname);
500     case GraphicsContext3D::MAX_VERTEX_ATTRIBS:
501         return getIntParameter(pname);
502     case GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS:
503         return getIntParameter(pname);
504     case GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS:
505         return getIntParameter(pname);
506     case GraphicsContext3D::MAX_VIEWPORT_DIMS:
507         return getWebGLIntArrayParameter(pname);
508     case GraphicsContext3D::NUM_SHADER_BINARY_FORMATS:
509         return getIntParameter(pname);
510     case GraphicsContext3D::PACK_ALIGNMENT:
511         return getIntParameter(pname);
512     case GraphicsContext3D::POLYGON_OFFSET_FACTOR:
513         return getFloatParameter(pname);
514     case GraphicsContext3D::POLYGON_OFFSET_FILL:
515         return getBooleanParameter(pname);
516     case GraphicsContext3D::POLYGON_OFFSET_UNITS:
517         return getFloatParameter(pname);
518     case GraphicsContext3D::RED_BITS:
519         return getIntParameter(pname);
520     case GraphicsContext3D::RENDERBUFFER_BINDING:
521         return m_renderbufferBinding;
522     case GraphicsContext3D::RENDERER:
523         return "WebKit WebGL"_str;
524     case GraphicsContext3D::SAMPLE_BUFFERS:
525         return getIntParameter(pname);
526     case GraphicsContext3D::SAMPLE_COVERAGE_INVERT:
527         return getBooleanParameter(pname);
528     case GraphicsContext3D::SAMPLE_COVERAGE_VALUE:
529         return getFloatParameter(pname);
530     case GraphicsContext3D::SAMPLES:
531         return getIntParameter(pname);
532     case GraphicsContext3D::SCISSOR_BOX:
533         return getWebGLIntArrayParameter(pname);
534     case GraphicsContext3D::SCISSOR_TEST:
535         return getBooleanParameter(pname);
536     case GraphicsContext3D::SHADING_LANGUAGE_VERSION:
537         return "WebGL GLSL ES 1.0 (" + m_context->getString(GraphicsContext3D::SHADING_LANGUAGE_VERSION) + ")";
538     case GraphicsContext3D::STENCIL_BACK_FAIL:
539         return getUnsignedIntParameter(pname);
540     case GraphicsContext3D::STENCIL_BACK_FUNC:
541         return getUnsignedIntParameter(pname);
542     case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_FAIL:
543         return getUnsignedIntParameter(pname);
544     case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_PASS:
545         return getUnsignedIntParameter(pname);
546     case GraphicsContext3D::STENCIL_BACK_REF:
547         return getIntParameter(pname);
548     case GraphicsContext3D::STENCIL_BACK_VALUE_MASK:
549         return getUnsignedIntParameter(pname);
550     case GraphicsContext3D::STENCIL_BACK_WRITEMASK:
551         return getUnsignedIntParameter(pname);
552     case GraphicsContext3D::STENCIL_BITS:
553         if (!m_framebufferBinding && !m_attributes.stencil)
554             return 0;
555         return getIntParameter(pname);
556     case GraphicsContext3D::STENCIL_CLEAR_VALUE:
557         return getIntParameter(pname);
558     case GraphicsContext3D::STENCIL_FAIL:
559         return getUnsignedIntParameter(pname);
560     case GraphicsContext3D::STENCIL_FUNC:
561         return getUnsignedIntParameter(pname);
562     case GraphicsContext3D::STENCIL_PASS_DEPTH_FAIL:
563         return getUnsignedIntParameter(pname);
564     case GraphicsContext3D::STENCIL_PASS_DEPTH_PASS:
565         return getUnsignedIntParameter(pname);
566     case GraphicsContext3D::STENCIL_REF:
567         return getIntParameter(pname);
568     case GraphicsContext3D::STENCIL_TEST:
569         return getBooleanParameter(pname);
570     case GraphicsContext3D::STENCIL_VALUE_MASK:
571         return getUnsignedIntParameter(pname);
572     case GraphicsContext3D::STENCIL_WRITEMASK:
573         return getUnsignedIntParameter(pname);
574     case GraphicsContext3D::SUBPIXEL_BITS:
575         return getIntParameter(pname);
576     case GraphicsContext3D::TEXTURE_BINDING_2D:
577         return m_textureUnits[m_activeTextureUnit].texture2DBinding;
578     case GraphicsContext3D::TEXTURE_BINDING_CUBE_MAP:
579         return m_textureUnits[m_activeTextureUnit].textureCubeMapBinding;
580     case GraphicsContext3D::UNPACK_ALIGNMENT:
581         return getIntParameter(pname);
582     case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
583         return m_unpackFlipY;
584     case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
585         return m_unpackPremultiplyAlpha;
586     case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
587         return m_unpackColorspaceConversion;
588     case GraphicsContext3D::VENDOR:
589         return "WebKit"_str;
590     case GraphicsContext3D::VERSION:
591         return "WebGL 1.0"_str;
592     case GraphicsContext3D::VIEWPORT:
593         return getWebGLIntArrayParameter(pname);
594     case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
595         if (m_oesStandardDerivatives)
596             return getUnsignedIntParameter(Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES);
597         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, OES_standard_derivatives not enabled");
598         return nullptr;
599     case WebGLDebugRendererInfo::UNMASKED_RENDERER_WEBGL:
600         if (m_webglDebugRendererInfo) {
601 #if PLATFORM(IOS_FAMILY)
602             return "Apple GPU"_str;
603 #else
604             return m_context->getString(GraphicsContext3D::RENDERER);
605 #endif
606         }
607         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled");
608         return nullptr;
609     case WebGLDebugRendererInfo::UNMASKED_VENDOR_WEBGL:
610         if (m_webglDebugRendererInfo)
611             return m_context->getString(GraphicsContext3D::VENDOR);
612         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled");
613         return nullptr;
614     case Extensions3D::VERTEX_ARRAY_BINDING_OES: // OES_vertex_array_object
615         if (m_oesVertexArrayObject) {
616             if (m_boundVertexArrayObject->isDefaultObject())
617                 return nullptr;
618             return makeRefPtr(static_cast<WebGLVertexArrayObjectOES&>(*m_boundVertexArrayObject));
619         }
620         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, OES_vertex_array_object not enabled");
621         return nullptr;
622     case Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
623         if (m_extTextureFilterAnisotropic)
624             return getUnsignedIntParameter(Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT);
625         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled");
626         return nullptr;
627     case Extensions3D::MAX_COLOR_ATTACHMENTS_EXT: // EXT_draw_buffers BEGIN
628         if (m_webglDrawBuffers)
629             return getMaxColorAttachments();
630         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled");
631         return nullptr;
632     case Extensions3D::MAX_DRAW_BUFFERS_EXT:
633         if (m_webglDrawBuffers)
634             return getMaxDrawBuffers();
635         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled");
636         return nullptr;
637     default:
638         if (m_webglDrawBuffers
639             && pname >= Extensions3D::DRAW_BUFFER0_EXT
640             && pname < static_cast<GC3Denum>(Extensions3D::DRAW_BUFFER0_EXT + getMaxDrawBuffers())) {
641             GC3Dint value = GraphicsContext3D::NONE;
642             if (m_framebufferBinding)
643                 value = m_framebufferBinding->getDrawBuffer(pname);
644             else // emulated backbuffer
645                 value = m_backDrawBuffer;
646             return value;
647         }
648         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name");
649         return nullptr;
650     }
651 }
652
653 GC3Dint WebGLRenderingContext::getMaxDrawBuffers()
654 {
655     if (!supportsDrawBuffers())
656         return 0;
657     if (!m_maxDrawBuffers)
658         m_context->getIntegerv(Extensions3D::MAX_DRAW_BUFFERS_EXT, &m_maxDrawBuffers);
659     if (!m_maxColorAttachments)
660         m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments);
661     // WEBGL_draw_buffers requires MAX_COLOR_ATTACHMENTS >= MAX_DRAW_BUFFERS.
662     return std::min(m_maxDrawBuffers, m_maxColorAttachments);
663 }
664
665 GC3Dint WebGLRenderingContext::getMaxColorAttachments()
666 {
667     if (!supportsDrawBuffers())
668         return 0;
669     if (!m_maxColorAttachments)
670         m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments);
671     return m_maxColorAttachments;
672 }
673     
674 bool WebGLRenderingContext::validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired)
675 {
676     // Performs conservative validation by caching a maximum index of
677     // the given type per element array buffer. If all of the bound
678     // array buffers have enough elements to satisfy that maximum
679     // index, skips the expensive per-draw-call iteration in
680     // validateIndexArrayPrecise.
681     
682     RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
683     
684     if (!elementArrayBuffer)
685         return false;
686     
687     GC3Dsizeiptr numElements = elementArrayBuffer->byteLength();
688     // The case count==0 is already dealt with in drawElements before validateIndexArrayConservative.
689     if (!numElements)
690         return false;
691     auto buffer = elementArrayBuffer->elementArrayBuffer();
692     ASSERT(buffer);
693     
694     Optional<unsigned> maxIndex = elementArrayBuffer->getCachedMaxIndex(type);
695     if (!maxIndex) {
696         // Compute the maximum index in the entire buffer for the given type of index.
697         switch (type) {
698         case GraphicsContext3D::UNSIGNED_BYTE: {
699             const GC3Dubyte* p = static_cast<const GC3Dubyte*>(buffer->data());
700             for (GC3Dsizeiptr i = 0; i < numElements; i++)
701                 maxIndex = maxIndex ? std::max(maxIndex.value(), static_cast<unsigned>(p[i])) : static_cast<unsigned>(p[i]);
702             break;
703         }
704         case GraphicsContext3D::UNSIGNED_SHORT: {
705             numElements /= sizeof(GC3Dushort);
706             const GC3Dushort* p = static_cast<const GC3Dushort*>(buffer->data());
707             for (GC3Dsizeiptr i = 0; i < numElements; i++)
708                 maxIndex = maxIndex ? std::max(maxIndex.value(), static_cast<unsigned>(p[i])) : static_cast<unsigned>(p[i]);
709             break;
710         }
711         case GraphicsContext3D::UNSIGNED_INT: {
712             if (!m_oesElementIndexUint)
713                 return false;
714             numElements /= sizeof(GC3Duint);
715             const GC3Duint* p = static_cast<const GC3Duint*>(buffer->data());
716             for (GC3Dsizeiptr i = 0; i < numElements; i++)
717                 maxIndex = maxIndex ? std::max(maxIndex.value(), static_cast<unsigned>(p[i])) : static_cast<unsigned>(p[i]);
718             break;
719         }
720         default:
721             return false;
722         }
723         if (maxIndex)
724             elementArrayBuffer->setCachedMaxIndex(type, maxIndex.value());
725     }
726     
727     if (!maxIndex)
728         return false;
729
730     // The number of required elements is one more than the maximum index that will be accessed.
731     auto checkedNumElementsRequired = checkedAddAndMultiply<unsigned>(maxIndex.value(), 1, 1);
732     if (!checkedNumElementsRequired)
733         return false;
734     numElementsRequired = checkedNumElementsRequired.value();
735
736     return true;
737 }
738
739 bool WebGLRenderingContext::validateBlendEquation(const char* functionName, GC3Denum mode)
740 {
741     switch (mode) {
742     case GraphicsContext3D::FUNC_ADD:
743     case GraphicsContext3D::FUNC_SUBTRACT:
744     case GraphicsContext3D::FUNC_REVERSE_SUBTRACT:
745     case Extensions3D::MIN_EXT:
746     case Extensions3D::MAX_EXT:
747         if ((mode == Extensions3D::MIN_EXT || mode == Extensions3D::MAX_EXT) && !m_extBlendMinMax) {
748             synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid mode");
749             return false;
750         }
751         return true;
752         break;
753     default:
754         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid mode");
755         return false;
756     }
757 }
758
759 bool WebGLRenderingContext::validateCapability(const char* functionName, GC3Denum cap)
760 {
761     switch (cap) {
762     case GraphicsContext3D::BLEND:
763     case GraphicsContext3D::CULL_FACE:
764     case GraphicsContext3D::DEPTH_TEST:
765     case GraphicsContext3D::DITHER:
766     case GraphicsContext3D::POLYGON_OFFSET_FILL:
767     case GraphicsContext3D::SAMPLE_ALPHA_TO_COVERAGE:
768     case GraphicsContext3D::SAMPLE_COVERAGE:
769     case GraphicsContext3D::SCISSOR_TEST:
770     case GraphicsContext3D::STENCIL_TEST:
771         return true;
772     default:
773         synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid capability");
774         return false;
775     }
776 }
777
778 } // namespace WebCore
779
780 #endif // ENABLE(WEBGL)