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