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