2 * Copyright (C) 2015 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
29 #include "WebGLRenderingContext.h"
31 #include "ANGLEInstancedArrays.h"
32 #include "CachedImage.h"
33 #include "EXTBlendMinMax.h"
34 #include "EXTFragDepth.h"
35 #include "EXTShaderTextureLOD.h"
36 #include "EXTTextureFilterAnisotropic.h"
38 #include "Extensions3D.h"
39 #include "HTMLCanvasElement.h"
40 #include "HTMLImageElement.h"
41 #include "HTMLVideoElement.h"
42 #include "ImageData.h"
43 #include "OESElementIndexUint.h"
44 #include "OESStandardDerivatives.h"
45 #include "OESTextureFloat.h"
46 #include "OESTextureFloatLinear.h"
47 #include "OESTextureHalfFloat.h"
48 #include "OESTextureHalfFloatLinear.h"
49 #include "OESVertexArrayObject.h"
50 #include "RenderBox.h"
51 #include "WebGLCompressedTextureATC.h"
52 #include "WebGLCompressedTexturePVRTC.h"
53 #include "WebGLCompressedTextureS3TC.h"
54 #include "WebGLDebugRendererInfo.h"
55 #include "WebGLDebugShaders.h"
56 #include "WebGLDepthTexture.h"
57 #include "WebGLDrawBuffers.h"
58 #include "WebGLLoseContext.h"
59 #include "WebGLVertexArrayObjectOES.h"
60 #include <JavaScriptCore/GenericTypedArrayViewInlines.h>
61 #include <JavaScriptCore/JSCJSValueInlines.h>
62 #include <JavaScriptCore/JSCellInlines.h>
63 #include <JavaScriptCore/JSGenericTypedArrayViewInlines.h>
67 WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, GraphicsContext3D::Attributes attributes)
68 : WebGLRenderingContextBase(passedCanvas, attributes)
72 WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassRefPtr<GraphicsContext3D> context,
73 GraphicsContext3D::Attributes attributes) : WebGLRenderingContextBase(passedCanvas, context, attributes)
75 initializeVertexArrayObjects();
78 void WebGLRenderingContext::initializeVertexArrayObjects()
80 m_defaultVertexArrayObject = WebGLVertexArrayObjectOES::create(this, WebGLVertexArrayObjectOES::VAOTypeDefault);
81 addContextObject(m_defaultVertexArrayObject.get());
82 m_boundVertexArrayObject = m_defaultVertexArrayObject;
83 if (!isGLES2Compliant())
87 WebGLExtension* WebGLRenderingContext::getExtension(const String& name)
89 if (isContextLostOrPending())
92 if (equalIgnoringASCIICase(name, "EXT_blend_minmax")
93 && m_context->getExtensions()->supports("GL_EXT_blend_minmax")) {
94 if (!m_extBlendMinMax) {
95 m_context->getExtensions()->ensureEnabled("GL_EXT_blend_minmax");
96 m_extBlendMinMax = std::make_unique<EXTBlendMinMax>(this);
98 return m_extBlendMinMax.get();
100 if (equalIgnoringASCIICase(name, "EXT_sRGB")
101 && m_context->getExtensions()->supports("GL_EXT_sRGB")) {
103 m_context->getExtensions()->ensureEnabled("GL_EXT_sRGB");
104 m_extsRGB = std::make_unique<EXTsRGB>(this);
106 return m_extsRGB.get();
108 if (equalIgnoringASCIICase(name, "EXT_frag_depth")
109 && m_context->getExtensions()->supports("GL_EXT_frag_depth")) {
110 if (!m_extFragDepth) {
111 m_context->getExtensions()->ensureEnabled("GL_EXT_frag_depth");
112 m_extFragDepth = std::make_unique<EXTFragDepth>(this);
114 return m_extFragDepth.get();
116 if (equalIgnoringASCIICase(name, "EXT_shader_texture_lod")
117 && (m_context->getExtensions()->supports("GL_EXT_shader_texture_lod") || m_context->getExtensions()->supports("GL_ARB_shader_texture_lod"))) {
118 if (!m_extShaderTextureLOD) {
119 m_context->getExtensions()->ensureEnabled("GL_EXT_shader_texture_lod");
120 m_extShaderTextureLOD = std::make_unique<EXTShaderTextureLOD>(this);
122 return m_extShaderTextureLOD.get();
124 if ((equalIgnoringASCIICase(name, "EXT_texture_filter_anisotropic") || equalIgnoringASCIICase(name, "WEBKIT_EXT_texture_filter_anisotropic"))
125 && m_context->getExtensions()->supports("GL_EXT_texture_filter_anisotropic")) {
126 if (!m_extTextureFilterAnisotropic) {
127 m_context->getExtensions()->ensureEnabled("GL_EXT_texture_filter_anisotropic");
128 m_extTextureFilterAnisotropic = std::make_unique<EXTTextureFilterAnisotropic>(this);
130 return m_extTextureFilterAnisotropic.get();
132 if (equalIgnoringASCIICase(name, "OES_standard_derivatives")
133 && m_context->getExtensions()->supports("GL_OES_standard_derivatives")) {
134 if (!m_oesStandardDerivatives) {
135 m_context->getExtensions()->ensureEnabled("GL_OES_standard_derivatives");
136 m_oesStandardDerivatives = std::make_unique<OESStandardDerivatives>(this);
138 return m_oesStandardDerivatives.get();
140 if (equalIgnoringASCIICase(name, "OES_texture_float")
141 && m_context->getExtensions()->supports("GL_OES_texture_float")) {
142 if (!m_oesTextureFloat) {
143 m_context->getExtensions()->ensureEnabled("GL_OES_texture_float");
144 m_oesTextureFloat = std::make_unique<OESTextureFloat>(this);
146 return m_oesTextureFloat.get();
148 if (equalIgnoringASCIICase(name, "OES_texture_float_linear")
149 && m_context->getExtensions()->supports("GL_OES_texture_float_linear")) {
150 if (!m_oesTextureFloatLinear) {
151 m_context->getExtensions()->ensureEnabled("GL_OES_texture_float_linear");
152 m_oesTextureFloatLinear = std::make_unique<OESTextureFloatLinear>(this);
154 return m_oesTextureFloatLinear.get();
156 if (equalIgnoringASCIICase(name, "OES_texture_half_float")
157 && m_context->getExtensions()->supports("GL_OES_texture_half_float")) {
158 if (!m_oesTextureHalfFloat) {
159 m_context->getExtensions()->ensureEnabled("GL_OES_texture_half_float");
160 m_oesTextureHalfFloat = std::make_unique<OESTextureHalfFloat>(this);
162 return m_oesTextureHalfFloat.get();
164 if (equalIgnoringASCIICase(name, "OES_texture_half_float_linear")
165 && m_context->getExtensions()->supports("GL_OES_texture_half_float_linear")) {
166 if (!m_oesTextureHalfFloatLinear) {
167 m_context->getExtensions()->ensureEnabled("GL_OES_texture_half_float_linear");
168 m_oesTextureHalfFloatLinear = std::make_unique<OESTextureHalfFloatLinear>(this);
170 return m_oesTextureHalfFloatLinear.get();
172 if (equalIgnoringASCIICase(name, "OES_vertex_array_object")
173 && m_context->getExtensions()->supports("GL_OES_vertex_array_object")) {
174 if (!m_oesVertexArrayObject) {
175 m_context->getExtensions()->ensureEnabled("GL_OES_vertex_array_object");
176 m_oesVertexArrayObject = std::make_unique<OESVertexArrayObject>(*this);
178 return m_oesVertexArrayObject.get();
180 if (equalIgnoringASCIICase(name, "OES_element_index_uint")
181 && m_context->getExtensions()->supports("GL_OES_element_index_uint")) {
182 if (!m_oesElementIndexUint) {
183 m_context->getExtensions()->ensureEnabled("GL_OES_element_index_uint");
184 m_oesElementIndexUint = std::make_unique<OESElementIndexUint>(this);
186 return m_oesElementIndexUint.get();
188 if (equalIgnoringASCIICase(name, "WEBGL_lose_context")) {
189 if (!m_webglLoseContext)
190 m_webglLoseContext = std::make_unique<WebGLLoseContext>(this);
191 return m_webglLoseContext.get();
193 if ((equalIgnoringASCIICase(name, "WEBKIT_WEBGL_compressed_texture_atc"))
194 && WebGLCompressedTextureATC::supported(this)) {
195 if (!m_webglCompressedTextureATC)
196 m_webglCompressedTextureATC = std::make_unique<WebGLCompressedTextureATC>(this);
197 return m_webglCompressedTextureATC.get();
199 if ((equalIgnoringASCIICase(name, "WEBKIT_WEBGL_compressed_texture_pvrtc"))
200 && WebGLCompressedTexturePVRTC::supported(this)) {
201 if (!m_webglCompressedTexturePVRTC)
202 m_webglCompressedTexturePVRTC = std::make_unique<WebGLCompressedTexturePVRTC>(this);
203 return m_webglCompressedTexturePVRTC.get();
205 if (equalIgnoringASCIICase(name, "WEBGL_compressed_texture_s3tc")
206 && WebGLCompressedTextureS3TC::supported(this)) {
207 if (!m_webglCompressedTextureS3TC)
208 m_webglCompressedTextureS3TC = std::make_unique<WebGLCompressedTextureS3TC>(this);
209 return m_webglCompressedTextureS3TC.get();
211 if (equalIgnoringASCIICase(name, "WEBGL_depth_texture")
212 && WebGLDepthTexture::supported(graphicsContext3D())) {
213 if (!m_webglDepthTexture) {
214 m_context->getExtensions()->ensureEnabled("GL_CHROMIUM_depth_texture");
215 m_webglDepthTexture = std::make_unique<WebGLDepthTexture>(this);
217 return m_webglDepthTexture.get();
219 if (equalIgnoringASCIICase(name, "WEBGL_draw_buffers") && supportsDrawBuffers()) {
220 if (!m_webglDrawBuffers) {
221 m_context->getExtensions()->ensureEnabled("GL_EXT_draw_buffers");
222 m_webglDrawBuffers = std::make_unique<WebGLDrawBuffers>(this);
224 return m_webglDrawBuffers.get();
226 if (equalIgnoringASCIICase(name, "ANGLE_instanced_arrays") && ANGLEInstancedArrays::supported(this)) {
227 if (!m_angleInstancedArrays) {
228 m_context->getExtensions()->ensureEnabled("GL_ANGLE_instanced_arrays");
229 m_angleInstancedArrays = std::make_unique<ANGLEInstancedArrays>(this);
231 return m_angleInstancedArrays.get();
233 if (equalIgnoringASCIICase(name, "WEBGL_debug_renderer_info")) {
234 if (!m_webglDebugRendererInfo)
235 m_webglDebugRendererInfo = std::make_unique<WebGLDebugRendererInfo>(this);
236 return m_webglDebugRendererInfo.get();
238 if (equalIgnoringASCIICase(name, "WEBGL_debug_shaders")
239 && m_context->getExtensions()->supports("GL_ANGLE_translated_shader_source")) {
240 if (!m_webglDebugShaders)
241 m_webglDebugShaders = std::make_unique<WebGLDebugShaders>(this);
242 return m_webglDebugShaders.get();
248 Vector<String> WebGLRenderingContext::getSupportedExtensions()
250 Vector<String> result;
252 if (m_isPendingPolicyResolution)
255 if (m_context->getExtensions()->supports("GL_EXT_blend_minmax"))
256 result.append("EXT_blend_minmax");
257 if (m_context->getExtensions()->supports("GL_EXT_sRGB"))
258 result.append("EXT_sRGB");
259 if (m_context->getExtensions()->supports("GL_EXT_frag_depth"))
260 result.append("EXT_frag_depth");
261 if (m_context->getExtensions()->supports("GL_OES_texture_float"))
262 result.append("OES_texture_float");
263 if (m_context->getExtensions()->supports("GL_OES_texture_float_linear"))
264 result.append("OES_texture_float_linear");
265 if (m_context->getExtensions()->supports("GL_OES_texture_half_float"))
266 result.append("OES_texture_half_float");
267 if (m_context->getExtensions()->supports("GL_OES_texture_half_float_linear"))
268 result.append("OES_texture_half_float_linear");
269 if (m_context->getExtensions()->supports("GL_OES_standard_derivatives"))
270 result.append("OES_standard_derivatives");
271 if (m_context->getExtensions()->supports("GL_EXT_shader_texture_lod") || m_context->getExtensions()->supports("GL_ARB_shader_texture_lod"))
272 result.append("EXT_shader_texture_lod");
273 if (m_context->getExtensions()->supports("GL_EXT_texture_filter_anisotropic"))
274 result.append("EXT_texture_filter_anisotropic");
275 if (m_context->getExtensions()->supports("GL_OES_vertex_array_object"))
276 result.append("OES_vertex_array_object");
277 if (m_context->getExtensions()->supports("GL_OES_element_index_uint"))
278 result.append("OES_element_index_uint");
279 result.append("WEBGL_lose_context");
280 if (WebGLCompressedTextureATC::supported(this))
281 result.append("WEBKIT_WEBGL_compressed_texture_atc");
282 if (WebGLCompressedTexturePVRTC::supported(this))
283 result.append("WEBKIT_WEBGL_compressed_texture_pvrtc");
284 if (WebGLCompressedTextureS3TC::supported(this))
285 result.append("WEBGL_compressed_texture_s3tc");
286 if (WebGLDepthTexture::supported(graphicsContext3D()))
287 result.append("WEBGL_depth_texture");
288 if (supportsDrawBuffers())
289 result.append("WEBGL_draw_buffers");
290 if (ANGLEInstancedArrays::supported(this))
291 result.append("ANGLE_instanced_arrays");
292 if (m_context->getExtensions()->supports("GL_ANGLE_translated_shader_source"))
293 result.append("WEBGL_debug_shaders");
294 result.append("WEBGL_debug_renderer_info");
299 WebGLGetInfo WebGLRenderingContext::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname)
301 if (isContextLostOrPending() || !validateFramebufferFuncParameters("getFramebufferAttachmentParameter", target, attachment))
302 return WebGLGetInfo();
304 if (!m_framebufferBinding || !m_framebufferBinding->object()) {
305 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getFramebufferAttachmentParameter", "no framebuffer bound");
306 return WebGLGetInfo();
309 WebGLSharedObject* object = m_framebufferBinding->getAttachmentObject(attachment);
311 if (pname == GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)
312 return WebGLGetInfo(GraphicsContext3D::NONE);
313 // OpenGL ES 2.0 specifies INVALID_ENUM in this case, while desktop GL
314 // specifies INVALID_OPERATION.
315 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name");
316 return WebGLGetInfo();
319 ASSERT(object->isTexture() || object->isRenderbuffer());
320 if (object->isTexture()) {
322 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
323 return WebGLGetInfo(GraphicsContext3D::TEXTURE);
324 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
325 return WebGLGetInfo(PassRefPtr<WebGLTexture>(reinterpret_cast<WebGLTexture*>(object)));
326 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
327 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
328 case Extensions3D::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT: {
330 m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value);
331 return WebGLGetInfo(value);
334 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for texture attachment");
335 return WebGLGetInfo();
339 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
340 return WebGLGetInfo(GraphicsContext3D::RENDERBUFFER);
341 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
342 return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(reinterpret_cast<WebGLRenderbuffer*>(object)));
343 case Extensions3D::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT: {
345 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for renderbuffer attachment");
346 return WebGLGetInfo();
348 WebGLRenderbuffer* renderBuffer = reinterpret_cast<WebGLRenderbuffer*>(object);
349 GC3Denum renderBufferFormat = renderBuffer->getInternalFormat();
350 ASSERT(renderBufferFormat != Extensions3D::SRGB_EXT && renderBufferFormat != Extensions3D::SRGB_ALPHA_EXT);
351 if (renderBufferFormat == Extensions3D::SRGB8_ALPHA8_EXT)
352 return WebGLGetInfo(Extensions3D::SRGB_EXT);
353 return WebGLGetInfo(GraphicsContext3D::LINEAR);
356 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for renderbuffer attachment");
357 return WebGLGetInfo();
362 bool WebGLRenderingContext::validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment)
364 if (target != GraphicsContext3D::FRAMEBUFFER) {
365 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
368 switch (attachment) {
369 case GraphicsContext3D::COLOR_ATTACHMENT0:
370 case GraphicsContext3D::DEPTH_ATTACHMENT:
371 case GraphicsContext3D::STENCIL_ATTACHMENT:
372 case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
375 if (m_webglDrawBuffers
376 && attachment > GraphicsContext3D::COLOR_ATTACHMENT0
377 && attachment < static_cast<GC3Denum>(GraphicsContext3D::COLOR_ATTACHMENT0 + getMaxColorAttachments()))
379 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid attachment");
385 void WebGLRenderingContext::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height)
387 if (isContextLostOrPending())
389 if (target != GraphicsContext3D::RENDERBUFFER) {
390 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid target");
393 if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
394 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "renderbufferStorage", "no bound renderbuffer");
397 if (!validateSize("renderbufferStorage", width, height))
399 switch (internalformat) {
400 case GraphicsContext3D::DEPTH_COMPONENT16:
401 case GraphicsContext3D::RGBA4:
402 case GraphicsContext3D::RGB5_A1:
403 case GraphicsContext3D::RGB565:
404 case GraphicsContext3D::STENCIL_INDEX8:
405 case Extensions3D::SRGB8_ALPHA8_EXT:
406 if (internalformat == Extensions3D::SRGB8_ALPHA8_EXT && !m_extsRGB) {
407 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid internalformat");
410 m_context->renderbufferStorage(target, internalformat, width, height);
411 m_renderbufferBinding->setInternalFormat(internalformat);
412 m_renderbufferBinding->setIsValid(true);
413 m_renderbufferBinding->setSize(width, height);
415 case GraphicsContext3D::DEPTH_STENCIL:
416 if (isDepthStencilSupported())
417 m_context->renderbufferStorage(target, Extensions3D::DEPTH24_STENCIL8, width, height);
418 m_renderbufferBinding->setSize(width, height);
419 m_renderbufferBinding->setIsValid(isDepthStencilSupported());
420 m_renderbufferBinding->setInternalFormat(internalformat);
423 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid internalformat");
429 void WebGLRenderingContext::hint(GC3Denum target, GC3Denum mode)
431 if (isContextLostOrPending())
433 bool isValid = false;
435 case GraphicsContext3D::GENERATE_MIPMAP_HINT:
438 case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
439 if (m_oesStandardDerivatives)
444 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "hint", "invalid target");
447 m_context->hint(target, mode);
450 void WebGLRenderingContext::clear(GC3Dbitfield mask)
452 if (isContextLostOrPending())
454 if (mask & ~(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) {
455 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clear", "invalid mask");
458 const char* reason = "framebuffer incomplete";
459 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
460 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "clear", reason);
463 if (!clearIfComposited(mask))
464 m_context->clear(mask);
465 markContextChanged();
468 void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
470 if (isContextLostOrPending())
472 if (!validateTexFuncParameters("copyTexImage2D", CopyTexImage, target, level, internalformat, width, height, border, internalformat, GraphicsContext3D::UNSIGNED_BYTE))
474 if (!validateSettableTexFormat("copyTexImage2D", internalformat))
476 WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true);
479 if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) {
480 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexImage2D", "framebuffer is incompatible format");
483 if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) {
484 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexImage2D", "level > 0 not power of 2");
487 const char* reason = "framebuffer incomplete";
488 if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) {
489 synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason);
493 if (isResourceSafe())
494 m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
496 GC3Dint clippedX, clippedY;
497 GC3Dsizei clippedWidth, clippedHeight;
498 if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) {
499 m_context->texImage2DResourceSafe(target, level, internalformat, width, height, border,
500 internalformat, GraphicsContext3D::UNSIGNED_BYTE, m_unpackAlignment);
501 if (clippedWidth > 0 && clippedHeight > 0) {
502 m_context->copyTexSubImage2D(target, level, clippedX - x, clippedY - y,
503 clippedX, clippedY, clippedWidth, clippedHeight);
506 m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border);
508 // FIXME: if the framebuffer is not complete, none of the below should be executed.
509 tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
512 void WebGLRenderingContext::texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum internalformat, GC3Denum format, GC3Denum type, const void* pixels)
514 UNUSED_PARAM(internalformat);
515 ASSERT(!isContextLost());
516 ASSERT(validateTexFuncParameters("texSubImage2D", TexSubImage, target, level, format, width, height, 0, format, type));
517 ASSERT(validateSize("texSubImage2D", xoffset, yoffset));
518 ASSERT(validateSettableTexFormat("texSubImage2D", format));
519 WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true);
521 ASSERT_NOT_REACHED();
524 ASSERT((xoffset + width) >= 0);
525 ASSERT((yoffset + height) >= 0);
526 ASSERT(tex->getWidth(target, level) >= (xoffset + width));
527 ASSERT(tex->getHeight(target, level) >= (yoffset + height));
528 ASSERT(tex->getInternalFormat(target, level) == format);
529 ASSERT(tex->getType(target, level) == type);
530 m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
533 void WebGLRenderingContext::texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha)
535 Vector<uint8_t> data;
536 GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE);
537 if (!imageExtractor.extractSucceeded()) {
538 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image");
541 GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat();
542 GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp();
543 const void* imagePixelData = imageExtractor.imagePixelData();
545 bool needConversion = true;
546 if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY)
547 needConversion = false;
549 if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) {
550 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data");
555 if (m_unpackAlignment != 1)
556 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
558 texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(), format, format, type, needConversion ? data.data() : imagePixelData);
559 if (m_unpackAlignment != 1)
560 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
563 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&& pixels)
565 if (isContextLostOrPending() || !validateTexFuncData("texSubImage2D", level, width, height, format, format, type, pixels.get(), NullNotAllowed) || !validateTexFunc("texSubImage2D", TexSubImage, SourceArrayBufferView, target, level, format, width, height, 0, format, type, xoffset, yoffset))
568 void* data = pixels->baseAddress();
569 Vector<uint8_t> tempData;
570 bool changeUnpackAlignment = false;
571 if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
572 if (!m_context->extractTextureData(width, height, format, type,
574 m_unpackFlipY, m_unpackPremultiplyAlpha,
578 data = tempData.data();
579 changeUnpackAlignment = true;
581 if (changeUnpackAlignment)
582 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
584 texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, format, type, data);
585 if (changeUnpackAlignment)
586 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
589 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, ImageData* pixels)
591 if (isContextLostOrPending() || !pixels || !validateTexFunc("texSubImage2D", TexSubImage, SourceImageData, target, level, format, pixels->width(), pixels->height(), 0, format, type, xoffset, yoffset))
594 Vector<uint8_t> data;
595 bool needConversion = true;
596 // The data from ImageData is always of format RGBA8.
597 // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required.
598 if (format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha)
599 needConversion = false;
601 if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
602 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image data");
606 if (m_unpackAlignment != 1)
607 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
609 texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(), format, format, type, needConversion ? data.data() : pixels->data()->data());
610 if (m_unpackAlignment != 1)
611 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
614 ExceptionOr<void> WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, HTMLImageElement* image)
616 if (wouldTaintOrigin(image))
617 return Exception { SECURITY_ERR };
618 if (isContextLostOrPending() || !validateHTMLImageElement("texSubImage2D", image))
621 RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer());
625 if (imageForRender->isSVGImage())
626 imageForRender = drawImageIntoBuffer(*imageForRender, image->width(), image->height(), 1);
628 if (!imageForRender || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLImageElement, target, level, format, imageForRender->width(), imageForRender->height(), 0, format, type, xoffset, yoffset))
631 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha);
635 ExceptionOr<void> WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas)
637 if (wouldTaintOrigin(canvas))
638 return Exception { SECURITY_ERR };
639 if (isContextLostOrPending() || !validateHTMLCanvasElement("texSubImage2D", canvas)
640 || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLCanvasElement, target, level, format, canvas->width(), canvas->height(), 0, format, type, xoffset, yoffset))
643 RefPtr<ImageData> imageData = canvas->getImageData();
645 texSubImage2D(target, level, xoffset, yoffset, format, type, imageData.get());
647 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha);
653 ExceptionOr<void> WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, HTMLVideoElement* video)
655 if (wouldTaintOrigin(video))
656 return Exception { SECURITY_ERR };
657 if (isContextLostOrPending() || !validateHTMLVideoElement("texSubImage2D", video)
658 || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLVideoElement, target, level, format, video->videoWidth(), video->videoHeight(), 0, format, type, xoffset, yoffset))
661 RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode());
664 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha);
670 bool WebGLRenderingContext::validateTexFuncParameters(const char* functionName,
671 TexFuncValidationFunctionType functionType,
672 GC3Denum target, GC3Dint level,
673 GC3Denum internalformat,
674 GC3Dsizei width, GC3Dsizei height, GC3Dint border,
675 GC3Denum format, GC3Denum type)
677 // We absolutely have to validate the format and type combination.
678 // The texImage2D entry points taking HTMLImage, etc. will produce
679 // temporary data based on this combination, so it must be legal.
680 if (!validateTexFuncFormatAndType(functionName, internalformat, format, type, level) || !validateTexFuncLevel(functionName, target, level))
683 if (width < 0 || height < 0) {
684 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
688 GC3Dint maxTextureSizeForLevel = pow(2.0, m_maxTextureLevel - 1 - level);
690 case GraphicsContext3D::TEXTURE_2D:
691 if (width > maxTextureSizeForLevel || height > maxTextureSizeForLevel) {
692 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range");
696 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
697 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
698 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
699 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
700 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
701 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
702 if (functionType != TexSubImage && width != height) {
703 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width != height for cube map");
706 // No need to check height here. For texImage width == height.
707 // For texSubImage that will be checked when checking yoffset + height is in range.
708 if (width > maxTextureSizeForLevel) {
709 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range for cube map");
714 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
718 if (format != internalformat) {
719 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format != internalformat");
724 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "border != 0");
731 bool WebGLRenderingContext::validateTexFuncFormatAndType(const char* functionName, GC3Denum internalformat, GC3Denum format, GC3Denum type, GC3Dint level)
733 UNUSED_PARAM(internalformat);
735 case GraphicsContext3D::ALPHA:
736 case GraphicsContext3D::LUMINANCE:
737 case GraphicsContext3D::LUMINANCE_ALPHA:
738 case GraphicsContext3D::RGB:
739 case GraphicsContext3D::RGBA:
741 case GraphicsContext3D::DEPTH_STENCIL:
742 case GraphicsContext3D::DEPTH_COMPONENT:
743 if (m_webglDepthTexture)
745 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "depth texture formats not enabled");
747 case Extensions3D::SRGB_EXT:
748 case Extensions3D::SRGB_ALPHA_EXT:
750 if ((format == Extensions3D::SRGB_EXT || format == Extensions3D::SRGB_ALPHA_EXT)
753 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture format");
758 case GraphicsContext3D::UNSIGNED_BYTE:
759 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
760 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
761 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
763 case GraphicsContext3D::FLOAT:
764 if (m_oesTextureFloat)
766 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
768 case GraphicsContext3D::HALF_FLOAT_OES:
769 if (m_oesTextureHalfFloat)
771 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
773 case GraphicsContext3D::UNSIGNED_INT:
774 case GraphicsContext3D::UNSIGNED_INT_24_8:
775 case GraphicsContext3D::UNSIGNED_SHORT:
776 if (m_webglDepthTexture)
778 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
781 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type");
785 // Verify that the combination of format and type is supported.
787 case GraphicsContext3D::ALPHA:
788 case GraphicsContext3D::LUMINANCE:
789 case GraphicsContext3D::LUMINANCE_ALPHA:
790 if (type != GraphicsContext3D::UNSIGNED_BYTE
791 && type != GraphicsContext3D::FLOAT
792 && type != GraphicsContext3D::HALF_FLOAT_OES) {
793 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for format");
797 case GraphicsContext3D::RGB:
798 case Extensions3D::SRGB_EXT:
799 if (type != GraphicsContext3D::UNSIGNED_BYTE
800 && type != GraphicsContext3D::UNSIGNED_SHORT_5_6_5
801 && type != GraphicsContext3D::FLOAT
802 && type != GraphicsContext3D::HALF_FLOAT_OES) {
803 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGB format");
807 case GraphicsContext3D::RGBA:
808 case Extensions3D::SRGB_ALPHA_EXT:
809 if (type != GraphicsContext3D::UNSIGNED_BYTE
810 && type != GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4
811 && type != GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1
812 && type != GraphicsContext3D::FLOAT
813 && type != GraphicsContext3D::HALF_FLOAT_OES) {
814 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGBA format");
818 case GraphicsContext3D::DEPTH_COMPONENT:
819 if (!m_webglDepthTexture) {
820 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_COMPONENT not enabled");
823 if (type != GraphicsContext3D::UNSIGNED_SHORT
824 && type != GraphicsContext3D::UNSIGNED_INT) {
825 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_COMPONENT format");
829 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_COMPONENT format");
833 case GraphicsContext3D::DEPTH_STENCIL:
834 if (!m_webglDepthTexture) {
835 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_STENCIL not enabled");
838 if (type != GraphicsContext3D::UNSIGNED_INT_24_8) {
839 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_STENCIL format");
843 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_STENCIL format");
848 ASSERT_NOT_REACHED();
854 bool WebGLRenderingContext::validateTexFuncData(const char* functionName, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum internalformat, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, NullDisposition disposition)
857 if (disposition == NullAllowed)
859 synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels");
863 if (!validateTexFuncFormatAndType(functionName, internalformat, format, type, level))
865 if (!validateSettableTexFormat(functionName, format))
869 case GraphicsContext3D::UNSIGNED_BYTE:
870 if (pixels->getType() != JSC::TypeUint8) {
871 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_BYTE but ArrayBufferView not Uint8Array");
875 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
876 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
877 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
878 if (pixels->getType() != JSC::TypeUint16) {
879 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_SHORT but ArrayBufferView not Uint16Array");
883 case GraphicsContext3D::FLOAT: // OES_texture_float
884 if (pixels->getType() != JSC::TypeFloat32) {
885 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type FLOAT but ArrayBufferView not Float32Array");
889 case GraphicsContext3D::HALF_FLOAT_OES: // OES_texture_half_float
890 // As per the specification, ArrayBufferView should be null when
891 // OES_texture_half_float is enabled.
893 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type HALF_FLOAT_OES but ArrayBufferView is not NULL");
898 ASSERT_NOT_REACHED();
901 unsigned totalBytesRequired;
902 GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0);
903 if (error != GraphicsContext3D::NO_ERROR) {
904 synthesizeGLError(error, functionName, "invalid texture dimensions");
907 if (pixels->byteLength() < totalBytesRequired) {
908 if (m_unpackAlignment != 1) {
909 m_context->computeImageSizeInBytes(format, type, width, height, 1, &totalBytesRequired, 0);
910 if (pixels->byteLength() == totalBytesRequired) {
911 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request with UNPACK_ALIGNMENT > 1");
915 synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request");
921 WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname)
923 if (isContextLostOrPending())
924 return WebGLGetInfo();
925 const int intZero = 0;
927 case GraphicsContext3D::ACTIVE_TEXTURE:
928 return getUnsignedIntParameter(pname);
929 case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
930 return getWebGLFloatArrayParameter(pname);
931 case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
932 return getWebGLFloatArrayParameter(pname);
933 case GraphicsContext3D::ALPHA_BITS:
934 return getIntParameter(pname);
935 case GraphicsContext3D::ARRAY_BUFFER_BINDING:
936 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundArrayBuffer));
937 case GraphicsContext3D::BLEND:
938 return getBooleanParameter(pname);
939 case GraphicsContext3D::BLEND_COLOR:
940 return getWebGLFloatArrayParameter(pname);
941 case GraphicsContext3D::BLEND_DST_ALPHA:
942 return getUnsignedIntParameter(pname);
943 case GraphicsContext3D::BLEND_DST_RGB:
944 return getUnsignedIntParameter(pname);
945 case GraphicsContext3D::BLEND_EQUATION_ALPHA:
946 return getUnsignedIntParameter(pname);
947 case GraphicsContext3D::BLEND_EQUATION_RGB:
948 return getUnsignedIntParameter(pname);
949 case GraphicsContext3D::BLEND_SRC_ALPHA:
950 return getUnsignedIntParameter(pname);
951 case GraphicsContext3D::BLEND_SRC_RGB:
952 return getUnsignedIntParameter(pname);
953 case GraphicsContext3D::BLUE_BITS:
954 return getIntParameter(pname);
955 case GraphicsContext3D::COLOR_CLEAR_VALUE:
956 return getWebGLFloatArrayParameter(pname);
957 case GraphicsContext3D::COLOR_WRITEMASK:
958 return getBooleanArrayParameter(pname);
959 case GraphicsContext3D::COMPRESSED_TEXTURE_FORMATS:
960 return WebGLGetInfo(PassRefPtr<Uint32Array>(Uint32Array::create(m_compressedTextureFormats.data(), m_compressedTextureFormats.size())));
961 case GraphicsContext3D::CULL_FACE:
962 return getBooleanParameter(pname);
963 case GraphicsContext3D::CULL_FACE_MODE:
964 return getUnsignedIntParameter(pname);
965 case GraphicsContext3D::CURRENT_PROGRAM:
966 return WebGLGetInfo(PassRefPtr<WebGLProgram>(m_currentProgram));
967 case GraphicsContext3D::DEPTH_BITS:
968 if (!m_framebufferBinding && !m_attributes.depth)
969 return WebGLGetInfo(intZero);
970 return getIntParameter(pname);
971 case GraphicsContext3D::DEPTH_CLEAR_VALUE:
972 return getFloatParameter(pname);
973 case GraphicsContext3D::DEPTH_FUNC:
974 return getUnsignedIntParameter(pname);
975 case GraphicsContext3D::DEPTH_RANGE:
976 return getWebGLFloatArrayParameter(pname);
977 case GraphicsContext3D::DEPTH_TEST:
978 return getBooleanParameter(pname);
979 case GraphicsContext3D::DEPTH_WRITEMASK:
980 return getBooleanParameter(pname);
981 case GraphicsContext3D::DITHER:
982 return getBooleanParameter(pname);
983 case GraphicsContext3D::ELEMENT_ARRAY_BUFFER_BINDING:
984 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundVertexArrayObject->getElementArrayBuffer()));
985 case GraphicsContext3D::FRAMEBUFFER_BINDING:
986 return WebGLGetInfo(PassRefPtr<WebGLFramebuffer>(m_framebufferBinding));
987 case GraphicsContext3D::FRONT_FACE:
988 return getUnsignedIntParameter(pname);
989 case GraphicsContext3D::GENERATE_MIPMAP_HINT:
990 return getUnsignedIntParameter(pname);
991 case GraphicsContext3D::GREEN_BITS:
992 return getIntParameter(pname);
993 case GraphicsContext3D::IMPLEMENTATION_COLOR_READ_FORMAT:
994 return getIntParameter(pname);
995 case GraphicsContext3D::IMPLEMENTATION_COLOR_READ_TYPE:
996 return getIntParameter(pname);
997 case GraphicsContext3D::LINE_WIDTH:
998 return getFloatParameter(pname);
999 case GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS:
1000 return getIntParameter(pname);
1001 case GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE:
1002 return getIntParameter(pname);
1003 case GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS:
1004 return getIntParameter(pname);
1005 case GraphicsContext3D::MAX_RENDERBUFFER_SIZE:
1006 return getIntParameter(pname);
1007 case GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS:
1008 return getIntParameter(pname);
1009 case GraphicsContext3D::MAX_TEXTURE_SIZE:
1010 return getIntParameter(pname);
1011 case GraphicsContext3D::MAX_VARYING_VECTORS:
1012 return getIntParameter(pname);
1013 case GraphicsContext3D::MAX_VERTEX_ATTRIBS:
1014 return getIntParameter(pname);
1015 case GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS:
1016 return getIntParameter(pname);
1017 case GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS:
1018 return getIntParameter(pname);
1019 case GraphicsContext3D::MAX_VIEWPORT_DIMS:
1020 return getWebGLIntArrayParameter(pname);
1021 case GraphicsContext3D::NUM_SHADER_BINARY_FORMATS:
1022 return getIntParameter(pname);
1023 case GraphicsContext3D::PACK_ALIGNMENT:
1024 return getIntParameter(pname);
1025 case GraphicsContext3D::POLYGON_OFFSET_FACTOR:
1026 return getFloatParameter(pname);
1027 case GraphicsContext3D::POLYGON_OFFSET_FILL:
1028 return getBooleanParameter(pname);
1029 case GraphicsContext3D::POLYGON_OFFSET_UNITS:
1030 return getFloatParameter(pname);
1031 case GraphicsContext3D::RED_BITS:
1032 return getIntParameter(pname);
1033 case GraphicsContext3D::RENDERBUFFER_BINDING:
1034 return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(m_renderbufferBinding));
1035 case GraphicsContext3D::RENDERER:
1036 return WebGLGetInfo(String("WebKit WebGL"));
1037 case GraphicsContext3D::SAMPLE_BUFFERS:
1038 return getIntParameter(pname);
1039 case GraphicsContext3D::SAMPLE_COVERAGE_INVERT:
1040 return getBooleanParameter(pname);
1041 case GraphicsContext3D::SAMPLE_COVERAGE_VALUE:
1042 return getFloatParameter(pname);
1043 case GraphicsContext3D::SAMPLES:
1044 return getIntParameter(pname);
1045 case GraphicsContext3D::SCISSOR_BOX:
1046 return getWebGLIntArrayParameter(pname);
1047 case GraphicsContext3D::SCISSOR_TEST:
1048 return getBooleanParameter(pname);
1049 case GraphicsContext3D::SHADING_LANGUAGE_VERSION:
1050 return WebGLGetInfo("WebGL GLSL ES 1.0 (" + m_context->getString(GraphicsContext3D::SHADING_LANGUAGE_VERSION) + ")");
1051 case GraphicsContext3D::STENCIL_BACK_FAIL:
1052 return getUnsignedIntParameter(pname);
1053 case GraphicsContext3D::STENCIL_BACK_FUNC:
1054 return getUnsignedIntParameter(pname);
1055 case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_FAIL:
1056 return getUnsignedIntParameter(pname);
1057 case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_PASS:
1058 return getUnsignedIntParameter(pname);
1059 case GraphicsContext3D::STENCIL_BACK_REF:
1060 return getIntParameter(pname);
1061 case GraphicsContext3D::STENCIL_BACK_VALUE_MASK:
1062 return getUnsignedIntParameter(pname);
1063 case GraphicsContext3D::STENCIL_BACK_WRITEMASK:
1064 return getUnsignedIntParameter(pname);
1065 case GraphicsContext3D::STENCIL_BITS:
1066 if (!m_framebufferBinding && !m_attributes.stencil)
1067 return WebGLGetInfo(intZero);
1068 return getIntParameter(pname);
1069 case GraphicsContext3D::STENCIL_CLEAR_VALUE:
1070 return getIntParameter(pname);
1071 case GraphicsContext3D::STENCIL_FAIL:
1072 return getUnsignedIntParameter(pname);
1073 case GraphicsContext3D::STENCIL_FUNC:
1074 return getUnsignedIntParameter(pname);
1075 case GraphicsContext3D::STENCIL_PASS_DEPTH_FAIL:
1076 return getUnsignedIntParameter(pname);
1077 case GraphicsContext3D::STENCIL_PASS_DEPTH_PASS:
1078 return getUnsignedIntParameter(pname);
1079 case GraphicsContext3D::STENCIL_REF:
1080 return getIntParameter(pname);
1081 case GraphicsContext3D::STENCIL_TEST:
1082 return getBooleanParameter(pname);
1083 case GraphicsContext3D::STENCIL_VALUE_MASK:
1084 return getUnsignedIntParameter(pname);
1085 case GraphicsContext3D::STENCIL_WRITEMASK:
1086 return getUnsignedIntParameter(pname);
1087 case GraphicsContext3D::SUBPIXEL_BITS:
1088 return getIntParameter(pname);
1089 case GraphicsContext3D::TEXTURE_BINDING_2D:
1090 return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].texture2DBinding));
1091 case GraphicsContext3D::TEXTURE_BINDING_CUBE_MAP:
1092 return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].textureCubeMapBinding));
1093 case GraphicsContext3D::UNPACK_ALIGNMENT:
1094 return getIntParameter(pname);
1095 case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
1096 return WebGLGetInfo(m_unpackFlipY);
1097 case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
1098 return WebGLGetInfo(m_unpackPremultiplyAlpha);
1099 case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
1100 return WebGLGetInfo(m_unpackColorspaceConversion);
1101 case GraphicsContext3D::VENDOR:
1102 return WebGLGetInfo(String("WebKit"));
1103 case GraphicsContext3D::VERSION:
1104 return WebGLGetInfo("WebGL 1.0 (" + m_context->getString(GraphicsContext3D::VERSION) + ")");
1105 case GraphicsContext3D::VIEWPORT:
1106 return getWebGLIntArrayParameter(pname);
1107 case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives
1108 if (m_oesStandardDerivatives)
1109 return getUnsignedIntParameter(Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES);
1110 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, OES_standard_derivatives not enabled");
1111 return WebGLGetInfo();
1112 case WebGLDebugRendererInfo::UNMASKED_RENDERER_WEBGL:
1113 if (m_webglDebugRendererInfo)
1114 return WebGLGetInfo(m_context->getString(GraphicsContext3D::RENDERER));
1115 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled");
1116 return WebGLGetInfo();
1117 case WebGLDebugRendererInfo::UNMASKED_VENDOR_WEBGL:
1118 if (m_webglDebugRendererInfo)
1119 return WebGLGetInfo(m_context->getString(GraphicsContext3D::VENDOR));
1120 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled");
1121 return WebGLGetInfo();
1122 case Extensions3D::VERTEX_ARRAY_BINDING_OES: // OES_vertex_array_object
1123 if (m_oesVertexArrayObject) {
1124 if (!m_boundVertexArrayObject->isDefaultObject())
1125 return WebGLGetInfo(PassRefPtr<WebGLVertexArrayObjectOES>(static_cast<WebGLVertexArrayObjectOES*>(m_boundVertexArrayObject.get())));
1126 return WebGLGetInfo();
1128 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, OES_vertex_array_object not enabled");
1129 return WebGLGetInfo();
1130 case Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
1131 if (m_extTextureFilterAnisotropic)
1132 return getUnsignedIntParameter(Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT);
1133 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled");
1134 return WebGLGetInfo();
1135 case Extensions3D::MAX_COLOR_ATTACHMENTS_EXT: // EXT_draw_buffers BEGIN
1136 if (m_webglDrawBuffers)
1137 return WebGLGetInfo(getMaxColorAttachments());
1138 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled");
1139 return WebGLGetInfo();
1140 case Extensions3D::MAX_DRAW_BUFFERS_EXT:
1141 if (m_webglDrawBuffers)
1142 return WebGLGetInfo(getMaxDrawBuffers());
1143 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled");
1144 return WebGLGetInfo();
1146 if (m_webglDrawBuffers
1147 && pname >= Extensions3D::DRAW_BUFFER0_EXT
1148 && pname < static_cast<GC3Denum>(Extensions3D::DRAW_BUFFER0_EXT + getMaxDrawBuffers())) {
1149 GC3Dint value = GraphicsContext3D::NONE;
1150 if (m_framebufferBinding)
1151 value = m_framebufferBinding->getDrawBuffer(pname);
1152 else // emulated backbuffer
1153 value = m_backDrawBuffer;
1154 return WebGLGetInfo(value);
1156 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name");
1157 return WebGLGetInfo();
1161 GC3Dint WebGLRenderingContext::getMaxDrawBuffers()
1163 if (!supportsDrawBuffers())
1165 if (!m_maxDrawBuffers)
1166 m_context->getIntegerv(Extensions3D::MAX_DRAW_BUFFERS_EXT, &m_maxDrawBuffers);
1167 if (!m_maxColorAttachments)
1168 m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments);
1169 // WEBGL_draw_buffers requires MAX_COLOR_ATTACHMENTS >= MAX_DRAW_BUFFERS.
1170 return std::min(m_maxDrawBuffers, m_maxColorAttachments);
1173 GC3Dint WebGLRenderingContext::getMaxColorAttachments()
1175 if (!supportsDrawBuffers())
1177 if (!m_maxColorAttachments)
1178 m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments);
1179 return m_maxColorAttachments;
1182 bool WebGLRenderingContext::validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired)
1184 // Performs conservative validation by caching a maximum index of
1185 // the given type per element array buffer. If all of the bound
1186 // array buffers have enough elements to satisfy that maximum
1187 // index, skips the expensive per-draw-call iteration in
1188 // validateIndexArrayPrecise.
1190 RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
1192 if (!elementArrayBuffer)
1195 GC3Dsizeiptr numElements = elementArrayBuffer->byteLength();
1196 // The case count==0 is already dealt with in drawElements before validateIndexArrayConservative.
1199 const ArrayBuffer* buffer = elementArrayBuffer->elementArrayBuffer();
1202 int maxIndex = elementArrayBuffer->getCachedMaxIndex(type);
1204 // Compute the maximum index in the entire buffer for the given type of index.
1206 case GraphicsContext3D::UNSIGNED_BYTE: {
1207 const GC3Dubyte* p = static_cast<const GC3Dubyte*>(buffer->data());
1208 for (GC3Dsizeiptr i = 0; i < numElements; i++)
1209 maxIndex = std::max(maxIndex, static_cast<int>(p[i]));
1212 case GraphicsContext3D::UNSIGNED_SHORT: {
1213 numElements /= sizeof(GC3Dushort);
1214 const GC3Dushort* p = static_cast<const GC3Dushort*>(buffer->data());
1215 for (GC3Dsizeiptr i = 0; i < numElements; i++)
1216 maxIndex = std::max(maxIndex, static_cast<int>(p[i]));
1219 case GraphicsContext3D::UNSIGNED_INT: {
1220 if (!m_oesElementIndexUint)
1222 numElements /= sizeof(GC3Duint);
1223 const GC3Duint* p = static_cast<const GC3Duint*>(buffer->data());
1224 for (GC3Dsizeiptr i = 0; i < numElements; i++)
1225 maxIndex = std::max(maxIndex, static_cast<int>(p[i]));
1231 elementArrayBuffer->setCachedMaxIndex(type, maxIndex);
1234 if (maxIndex >= 0) {
1235 // The number of required elements is one more than the maximum
1236 // index that will be accessed.
1237 numElementsRequired = maxIndex + 1;
1244 bool WebGLRenderingContext::validateBlendEquation(const char* functionName, GC3Denum mode)
1247 case GraphicsContext3D::FUNC_ADD:
1248 case GraphicsContext3D::FUNC_SUBTRACT:
1249 case GraphicsContext3D::FUNC_REVERSE_SUBTRACT:
1250 case Extensions3D::MIN_EXT:
1251 case Extensions3D::MAX_EXT:
1252 if ((mode == Extensions3D::MIN_EXT || mode == Extensions3D::MAX_EXT) && !m_extBlendMinMax) {
1253 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid mode");
1259 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid mode");
1264 bool WebGLRenderingContext::validateCapability(const char* functionName, GC3Denum cap)
1267 case GraphicsContext3D::BLEND:
1268 case GraphicsContext3D::CULL_FACE:
1269 case GraphicsContext3D::DEPTH_TEST:
1270 case GraphicsContext3D::DITHER:
1271 case GraphicsContext3D::POLYGON_OFFSET_FILL:
1272 case GraphicsContext3D::SAMPLE_ALPHA_TO_COVERAGE:
1273 case GraphicsContext3D::SAMPLE_COVERAGE:
1274 case GraphicsContext3D::SCISSOR_TEST:
1275 case GraphicsContext3D::STENCIL_TEST:
1278 synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid capability");
1283 } // namespace WebCore
1285 #endif // ENABLE(WEBGL)