diff options
Diffstat (limited to 'Source/WebCore/html/canvas')
155 files changed, 14801 insertions, 10956 deletions
diff --git a/Source/WebCore/html/canvas/ANGLEInstancedArrays.cpp b/Source/WebCore/html/canvas/ANGLEInstancedArrays.cpp index a0e573a5f..aed7da6a9 100644 --- a/Source/WebCore/html/canvas/ANGLEInstancedArrays.cpp +++ b/Source/WebCore/html/canvas/ANGLEInstancedArrays.cpp @@ -28,9 +28,13 @@ #if ENABLE(WEBGL) #include "ANGLEInstancedArrays.h" +#if PLATFORM(GTK) +#include "Extensions3D.h" +#endif + namespace WebCore { -ANGLEInstancedArrays::ANGLEInstancedArrays(WebGLRenderingContext* context) +ANGLEInstancedArrays::ANGLEInstancedArrays(WebGLRenderingContextBase& context) : WebGLExtension(context) { } @@ -44,39 +48,38 @@ WebGLExtension::ExtensionName ANGLEInstancedArrays::getName() const return ANGLEInstancedArraysName; } -OwnPtr<ANGLEInstancedArrays> ANGLEInstancedArrays::create(WebGLRenderingContext* context) -{ - return adoptPtr(new ANGLEInstancedArrays(context)); -} - -bool ANGLEInstancedArrays::supported(WebGLRenderingContext*) +bool ANGLEInstancedArrays::supported(WebGLRenderingContextBase& context) { -#if PLATFORM(IOS) || PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 +#if PLATFORM(COCOA) + UNUSED_PARAM(context); return true; +#elif PLATFORM(GTK) + return context.graphicsContext3D()->getExtensions().supports("GL_ANGLE_instanced_arrays"); #else + UNUSED_PARAM(context); return false; #endif } void ANGLEInstancedArrays::drawArraysInstancedANGLE(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount) { - if (m_context->isContextLost()) + if (m_context.isContextLost()) return; - m_context->drawArraysInstanced(mode, first, count, primcount); + m_context.drawArraysInstanced(mode, first, count, primcount); } void ANGLEInstancedArrays::drawElementsInstancedANGLE(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount) { - if (m_context->isContextLost()) + if (m_context.isContextLost()) return; - m_context->drawElementsInstanced(mode, count, type, offset, primcount); + m_context.drawElementsInstanced(mode, count, type, offset, primcount); } void ANGLEInstancedArrays::vertexAttribDivisorANGLE(GC3Duint index, GC3Duint divisor) { - if (m_context->isContextLost()) + if (m_context.isContextLost()) return; - m_context->vertexAttribDivisor(index, divisor); + m_context.vertexAttribDivisor(index, divisor); } } // namespace WebCore diff --git a/Source/WebCore/html/canvas/ANGLEInstancedArrays.h b/Source/WebCore/html/canvas/ANGLEInstancedArrays.h index f87126fbb..d4138277f 100644 --- a/Source/WebCore/html/canvas/ANGLEInstancedArrays.h +++ b/Source/WebCore/html/canvas/ANGLEInstancedArrays.h @@ -23,32 +23,26 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ANGLEInstancedArrays_h -#define ANGLEInstancedArrays_h +#pragma once #include "WebGLExtension.h" -#include <wtf/PassOwnPtr.h> namespace WebCore { -class WebGLRenderingContext; +class WebGLRenderingContextBase; -class ANGLEInstancedArrays : public WebGLExtension { +class ANGLEInstancedArrays final : public WebGLExtension { public: - static OwnPtr<ANGLEInstancedArrays> create(WebGLRenderingContext*); + explicit ANGLEInstancedArrays(WebGLRenderingContextBase&); virtual ~ANGLEInstancedArrays(); - virtual ExtensionName getName() const; - static bool supported(WebGLRenderingContext*); + ExtensionName getName() const final; + + static bool supported(WebGLRenderingContextBase&); void drawArraysInstancedANGLE(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount); void drawElementsInstancedANGLE(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount); void vertexAttribDivisorANGLE(GC3Duint index, GC3Duint divisor); - -private: - ANGLEInstancedArrays(WebGLRenderingContext*); }; } // namespace WebCore - -#endif // ANGLEInstancedArrays_h diff --git a/Source/WebCore/html/canvas/ANGLEInstancedArrays.idl b/Source/WebCore/html/canvas/ANGLEInstancedArrays.idl index 95d7ebd3a..bf15db187 100644 --- a/Source/WebCore/html/canvas/ANGLEInstancedArrays.idl +++ b/Source/WebCore/html/canvas/ANGLEInstancedArrays.idl @@ -30,7 +30,7 @@ ] interface ANGLEInstancedArrays { const GLenum VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE = 0x88FE; - [StrictTypeChecking] void drawArraysInstancedANGLE(unsigned long mode, long first, long count, long primcount); - [StrictTypeChecking] void drawElementsInstancedANGLE(unsigned long mode, long count, unsigned long type, long long offset, long primcount); - [StrictTypeChecking] void vertexAttribDivisorANGLE(unsigned long index, unsigned long divisor); + void drawArraysInstancedANGLE(unsigned long mode, long first, long count, long primcount); + void drawElementsInstancedANGLE(unsigned long mode, long count, unsigned long type, long long offset, long primcount); + void vertexAttribDivisorANGLE(unsigned long index, unsigned long divisor); }; diff --git a/Source/WebCore/html/canvas/CanvasContextAttributes.cpp b/Source/WebCore/html/canvas/CanvasContextAttributes.cpp deleted file mode 100644 index d3d0398af..000000000 --- a/Source/WebCore/html/canvas/CanvasContextAttributes.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2010, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#include "CanvasContextAttributes.h" - -namespace WebCore { - -CanvasContextAttributes::CanvasContextAttributes() -{ -} - -CanvasContextAttributes::~CanvasContextAttributes() -{ -} - -} // namespace WebCore diff --git a/Source/WebCore/html/canvas/CanvasContextAttributes.h b/Source/WebCore/html/canvas/CanvasContextAttributes.h deleted file mode 100644 index 97483b366..000000000 --- a/Source/WebCore/html/canvas/CanvasContextAttributes.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2010, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef CanvasContextAttributes_h -#define CanvasContextAttributes_h - -#include <wtf/RefCounted.h> - -namespace WebCore { - -// A base class for any attributes that are needed which would affect -// the creation of the Canvas's rendering context. Currently only the -// WebGLRenderingContext uses this mechanism. - -class CanvasContextAttributes : public RefCounted<CanvasContextAttributes> { - public: - virtual ~CanvasContextAttributes(); - - protected: - CanvasContextAttributes(); -}; - -} // namespace WebCore - -#endif // CanvasContextAttributes_h diff --git a/Source/WebCore/html/canvas/CanvasGradient.cpp b/Source/WebCore/html/canvas/CanvasGradient.cpp index 8a7ace0cf..a5efa3296 100644 --- a/Source/WebCore/html/canvas/CanvasGradient.cpp +++ b/Source/WebCore/html/canvas/CanvasGradient.cpp @@ -11,10 +11,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -27,48 +27,38 @@ #include "config.h" #include "CanvasGradient.h" -#include "CanvasPattern.h" #include "CanvasStyle.h" -#include "CSSParser.h" #include "ExceptionCode.h" namespace WebCore { CanvasGradient::CanvasGradient(const FloatPoint& p0, const FloatPoint& p1) : m_gradient(Gradient::create(p0, p1)) -#if ENABLE(DASHBOARD_SUPPORT) - , m_dashbardCompatibilityMode(false) -#endif { } CanvasGradient::CanvasGradient(const FloatPoint& p0, float r0, const FloatPoint& p1, float r1) : m_gradient(Gradient::create(p0, r0, p1, r1)) -#if ENABLE(DASHBOARD_SUPPORT) - , m_dashbardCompatibilityMode(false) -#endif { } -void CanvasGradient::addColorStop(float value, const String& color, ExceptionCode& ec) +ExceptionOr<void> CanvasGradient::addColorStop(float value, const String& colorString) { - if (!(value >= 0 && value <= 1.0f)) { - ec = INDEX_SIZE_ERR; - return; - } + if (!(value >= 0 && value <= 1)) + return Exception { INDEX_SIZE_ERR }; - RGBA32 rgba = 0; - if (!parseColorOrCurrentColor(rgba, color, 0 /*canvas*/)) { + // FIXME: Passing null for canvas means this won't work for current color. Is that OK? + Color color = parseColorOrCurrentColor(colorString, nullptr /*canvas*/); + if (!color.isValid()) { #if ENABLE(DASHBOARD_SUPPORT) - if (!m_dashbardCompatibilityMode) - ec = SYNTAX_ERR; -#else - ec = SYNTAX_ERR; + if (m_dashboardCompatibilityMode) + return { }; #endif - return; + return Exception { SYNTAX_ERR }; } - m_gradient->addColorStop(value, Color(rgba)); + m_gradient->addColorStop(value, color); + return { }; } -} // namespace +} diff --git a/Source/WebCore/html/canvas/CanvasGradient.h b/Source/WebCore/html/canvas/CanvasGradient.h index 8529d584d..bf7501338 100644 --- a/Source/WebCore/html/canvas/CanvasGradient.h +++ b/Source/WebCore/html/canvas/CanvasGradient.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. * Copyright (C) 2007 Alp Toker <alp@atoker.com> * * Redistribution and use in source and binary forms, with or without @@ -11,10 +11,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,47 +24,41 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CanvasGradient_h -#define CanvasGradient_h +#pragma once +#include "ExceptionOr.h" #include "Gradient.h" -#include <wtf/Forward.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> namespace WebCore { - typedef int ExceptionCode; +class CanvasGradient : public RefCounted<CanvasGradient> { +public: + static Ref<CanvasGradient> create(const FloatPoint& p0, const FloatPoint& p1) + { + return adoptRef(*new CanvasGradient(p0, p1)); + } + static Ref<CanvasGradient> create(const FloatPoint& p0, float r0, const FloatPoint& p1, float r1) + { + return adoptRef(*new CanvasGradient(p0, r0, p1, r1)); + } - class CanvasGradient : public RefCounted<CanvasGradient> { - public: - static PassRefPtr<CanvasGradient> create(const FloatPoint& p0, const FloatPoint& p1) - { - return adoptRef(new CanvasGradient(p0, p1)); - } - static PassRefPtr<CanvasGradient> create(const FloatPoint& p0, float r0, const FloatPoint& p1, float r1) - { - return adoptRef(new CanvasGradient(p0, r0, p1, r1)); - } - - Gradient* gradient() const { return m_gradient.get(); } + Gradient& gradient() { return m_gradient; } + const Gradient& gradient() const { return m_gradient; } - void addColorStop(float value, const String& color, ExceptionCode&); + ExceptionOr<void> addColorStop(float value, const String& color); #if ENABLE(DASHBOARD_SUPPORT) - void setDashboardCompatibilityMode() { m_dashbardCompatibilityMode = true; } + void setDashboardCompatibilityMode() { m_dashboardCompatibilityMode = true; } #endif - private: - CanvasGradient(const FloatPoint& p0, const FloatPoint& p1); - CanvasGradient(const FloatPoint& p0, float r0, const FloatPoint& p1, float r1); - - RefPtr<Gradient> m_gradient; +private: + CanvasGradient(const FloatPoint& p0, const FloatPoint& p1); + CanvasGradient(const FloatPoint& p0, float r0, const FloatPoint& p1, float r1); + + Ref<Gradient> m_gradient; #if ENABLE(DASHBOARD_SUPPORT) - bool m_dashbardCompatibilityMode; + bool m_dashboardCompatibilityMode { false }; #endif - }; - -} //namespace +}; -#endif +} diff --git a/Source/WebCore/html/canvas/CanvasGradient.idl b/Source/WebCore/html/canvas/CanvasGradient.idl index 793be9275..d9c9d0931 100644 --- a/Source/WebCore/html/canvas/CanvasGradient.idl +++ b/Source/WebCore/html/canvas/CanvasGradient.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -22,12 +22,9 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + [ ImplementationLacksVTable, ] interface CanvasGradient { - - [RaisesException] void addColorStop([Default=Undefined] optional float offset, - [Default=Undefined] optional DOMString color); - + [MayThrowException] void addColorStop(float offset, DOMString color); }; - diff --git a/Source/WebCore/html/canvas/CanvasPathMethods.cpp b/Source/WebCore/html/canvas/CanvasPath.cpp index 9332700e7..a7ff3c947 100644 --- a/Source/WebCore/html/canvas/CanvasPathMethods.cpp +++ b/Source/WebCore/html/canvas/CanvasPath.cpp @@ -33,15 +33,16 @@ */ #include "config.h" -#include "CanvasPathMethods.h" +#include "CanvasPath.h" +#include "AffineTransform.h" #include "ExceptionCode.h" #include "FloatRect.h" #include <wtf/MathExtras.h> namespace WebCore { -void CanvasPathMethods::closePath() +void CanvasPath::closePath() { if (m_path.isEmpty()) return; @@ -51,7 +52,7 @@ void CanvasPathMethods::closePath() m_path.closeSubpath(); } -void CanvasPathMethods::moveTo(float x, float y) +void CanvasPath::moveTo(float x, float y) { if (!std::isfinite(x) || !std::isfinite(y)) return; @@ -60,7 +61,12 @@ void CanvasPathMethods::moveTo(float x, float y) m_path.moveTo(FloatPoint(x, y)); } -void CanvasPathMethods::lineTo(float x, float y) +void CanvasPath::lineTo(FloatPoint point) +{ + lineTo(point.x(), point.y()); +} + +void CanvasPath::lineTo(float x, float y) { if (!std::isfinite(x) || !std::isfinite(y)) return; @@ -74,7 +80,7 @@ void CanvasPathMethods::lineTo(float x, float y) m_path.addLineTo(p1); } -void CanvasPathMethods::quadraticCurveTo(float cpx, float cpy, float x, float y) +void CanvasPath::quadraticCurveTo(float cpx, float cpy, float x, float y) { if (!std::isfinite(cpx) || !std::isfinite(cpy) || !std::isfinite(x) || !std::isfinite(y)) return; @@ -89,7 +95,7 @@ void CanvasPathMethods::quadraticCurveTo(float cpx, float cpy, float x, float y) m_path.addQuadCurveTo(cp, p1); } -void CanvasPathMethods::bezierCurveTo(float cp1x, float cp1y, float cp2x, float cp2y, float x, float y) +void CanvasPath::bezierCurveTo(float cp1x, float cp1y, float cp2x, float cp2y, float x, float y) { if (!std::isfinite(cp1x) || !std::isfinite(cp1y) || !std::isfinite(cp2x) || !std::isfinite(cp2y) || !std::isfinite(x) || !std::isfinite(y)) return; @@ -105,19 +111,16 @@ void CanvasPathMethods::bezierCurveTo(float cp1x, float cp1y, float cp2x, float m_path.addBezierCurveTo(cp1, cp2, p1); } -void CanvasPathMethods::arcTo(float x1, float y1, float x2, float y2, float r, ExceptionCode& ec) +ExceptionOr<void> CanvasPath::arcTo(float x1, float y1, float x2, float y2, float r) { - ec = 0; if (!std::isfinite(x1) || !std::isfinite(y1) || !std::isfinite(x2) || !std::isfinite(y2) || !std::isfinite(r)) - return; + return { }; - if (r < 0) { - ec = INDEX_SIZE_ERR; - return; - } + if (r < 0) + return Exception { INDEX_SIZE_ERR }; if (!hasInvertibleTransform()) - return; + return { }; FloatPoint p1 = FloatPoint(x1, y1); FloatPoint p2 = FloatPoint(x2, y2); @@ -128,42 +131,96 @@ void CanvasPathMethods::arcTo(float x1, float y1, float x2, float y2, float r, E lineTo(x1, y1); else m_path.addArcTo(p1, p2, r); + + return { }; } -void CanvasPathMethods::arc(float x, float y, float r, float sa, float ea, bool anticlockwise, ExceptionCode& ec) +static void normalizeAngles(float& startAngle, float& endAngle, bool anticlockwise) { - ec = 0; - if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(r) || !std::isfinite(sa) || !std::isfinite(ea)) - return; + float newStartAngle = startAngle; + if (newStartAngle < 0) + newStartAngle = (2 * piFloat) + fmodf(newStartAngle, -(2 * piFloat)); + else + newStartAngle = fmodf(newStartAngle, 2 * piFloat); - if (r < 0) { - ec = INDEX_SIZE_ERR; - return; - } + float delta = newStartAngle - startAngle; + startAngle = newStartAngle; + endAngle = endAngle + delta; + ASSERT(newStartAngle >= 0 && newStartAngle < 2 * piFloat); + + if (anticlockwise && startAngle - endAngle >= 2 * piFloat) + endAngle = startAngle - 2 * piFloat; + else if (!anticlockwise && endAngle - startAngle >= 2 * piFloat) + endAngle = startAngle + 2 * piFloat; +} + +ExceptionOr<void> CanvasPath::arc(float x, float y, float radius, float startAngle, float endAngle, bool anticlockwise) +{ + if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(radius) || !std::isfinite(startAngle) || !std::isfinite(endAngle)) + return { }; + + if (radius < 0) + return Exception { INDEX_SIZE_ERR }; - if (!r || sa == ea) { + if (!hasInvertibleTransform()) + return { }; + + normalizeAngles(startAngle, endAngle, anticlockwise); + + if (!radius || startAngle == endAngle) { // The arc is empty but we still need to draw the connecting line. - lineTo(x + r * cosf(sa), y + r * sinf(sa)); - return; + lineTo(x + radius * cosf(startAngle), y + radius * sinf(startAngle)); + return { }; } + m_path.addArc(FloatPoint(x, y), radius, startAngle, endAngle, anticlockwise); + return { }; +} + +ExceptionOr<void> CanvasPath::ellipse(float x, float y, float radiusX, float radiusY, float rotation, float startAngle, float endAngle, bool anticlockwise) +{ + if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(radiusX) || !std::isfinite(radiusY) || !std::isfinite(rotation) || !std::isfinite(startAngle) || !std::isfinite(endAngle)) + return { }; + + if (radiusX < 0 || radiusY < 0) + return Exception { INDEX_SIZE_ERR }; + if (!hasInvertibleTransform()) - return; + return { }; - // If 'sa' and 'ea' differ by more than 2Pi, just add a circle starting/ending at 'sa'. - if (anticlockwise && sa - ea >= 2 * piFloat) { - m_path.addArc(FloatPoint(x, y), r, sa, sa - 2 * piFloat, anticlockwise); - return; + normalizeAngles(startAngle, endAngle, anticlockwise); + + if ((!radiusX && !radiusY) || startAngle == endAngle) { + AffineTransform transform; + transform.translate(x, y).rotate(rad2deg(rotation)); + + lineTo(transform.mapPoint(FloatPoint(radiusX * cosf(startAngle), radiusY * sinf(startAngle)))); + return { }; } - if (!anticlockwise && ea - sa >= 2 * piFloat) { - m_path.addArc(FloatPoint(x, y), r, sa, sa + 2 * piFloat, anticlockwise); - return; + + if (!radiusX || !radiusY) { + AffineTransform transform; + transform.translate(x, y).rotate(rad2deg(rotation)); + + lineTo(transform.mapPoint(FloatPoint(radiusX * cosf(startAngle), radiusY * sinf(startAngle)))); + + if (!anticlockwise) { + for (float angle = startAngle - fmodf(startAngle, piOverTwoFloat) + piOverTwoFloat; angle < endAngle; angle += piOverTwoFloat) + lineTo(transform.mapPoint(FloatPoint(radiusX * cosf(angle), radiusY * sinf(angle)))); + } else { + for (float angle = startAngle - fmodf(startAngle, piOverTwoFloat); angle > endAngle; angle -= piOverTwoFloat) + lineTo(transform.mapPoint(FloatPoint(radiusX * cosf(angle), radiusY * sinf(angle)))); + } + + lineTo(transform.mapPoint(FloatPoint(radiusX * cosf(endAngle), radiusY * sinf(endAngle)))); + return { }; } - m_path.addArc(FloatPoint(x, y), r, sa, ea, anticlockwise); + m_path.addEllipse(FloatPoint(x, y), radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise); + return { }; } -void CanvasPathMethods::rect(float x, float y, float width, float height) +void CanvasPath::rect(float x, float y, float width, float height) { if (!hasInvertibleTransform()) return; diff --git a/Source/WebCore/html/canvas/CanvasPathMethods.h b/Source/WebCore/html/canvas/CanvasPath.h index 041808df1..e752560b8 100644 --- a/Source/WebCore/html/canvas/CanvasPathMethods.h +++ b/Source/WebCore/html/canvas/CanvasPath.h @@ -26,39 +26,38 @@ * SUCH DAMAGE. */ -#ifndef CanvasPathMethods_h -#define CanvasPathMethods_h +#pragma once +#include "ExceptionOr.h" #include "Path.h" namespace WebCore { -class FloatRect; - -typedef int ExceptionCode; - -class CanvasPathMethods { +class CanvasPath { public: - virtual ~CanvasPathMethods() { } + virtual ~CanvasPath() { } void closePath(); void moveTo(float x, float y); void lineTo(float x, float y); void quadraticCurveTo(float cpx, float cpy, float x, float y); void bezierCurveTo(float cp1x, float cp1y, float cp2x, float cp2y, float x, float y); - void arcTo(float x0, float y0, float x1, float y1, float radius, ExceptionCode&); - void arc(float x, float y, float r, float sa, float ea, bool anticlockwise, ExceptionCode&); + ExceptionOr<void> arcTo(float x0, float y0, float x1, float y1, float radius); + ExceptionOr<void> arc(float x, float y, float r, float sa, float ea, bool anticlockwise); + ExceptionOr<void> ellipse(float x, float y, float radiusX, float radiusY, float rotation, float startAngle, float endAngled, bool anticlockwise); void rect(float x, float y, float width, float height); protected: - CanvasPathMethods() { } - CanvasPathMethods(const Path& path) : m_path(path) { } + CanvasPath() { } + CanvasPath(const Path& path) + : m_path(path) + { } virtual bool hasInvertibleTransform() const { return true; } + void lineTo(FloatPoint); + Path m_path; }; } - -#endif diff --git a/Source/WebCore/html/canvas/CanvasPath.idl b/Source/WebCore/html/canvas/CanvasPath.idl new file mode 100644 index 000000000..da0cc878b --- /dev/null +++ b/Source/WebCore/html/canvas/CanvasPath.idl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2016 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +[ + NoInterfaceObject +] interface CanvasPath { + void closePath(); + void moveTo(unrestricted double x, unrestricted double y); + void lineTo(unrestricted double x, unrestricted double y); + void quadraticCurveTo(unrestricted double cpx, unrestricted double cpy, unrestricted double x, unrestricted double y); + void bezierCurveTo(unrestricted double cp1x, unrestricted double cp1y, unrestricted double cp2x, unrestricted double cp2y, unrestricted double x, unrestricted double y); + [MayThrowException] void arcTo(unrestricted double x1, unrestricted double y1, unrestricted double x2, unrestricted double y2, unrestricted double radius); + // [MayThrowException] void arcTo(unrestricted double x1, unrestricted double y1, unrestricted double x2, unrestricted double y2, unrestricted double radiusX, unrestricted double radiusY, unrestricted double rotation); + void rect(unrestricted double x, unrestricted double y, unrestricted double w, unrestricted double h); + [MayThrowException] void arc(unrestricted double x, unrestricted double y, unrestricted double radius, unrestricted double startAngle, unrestricted double endAngle, optional boolean anticlockwise = false); + [MayThrowException] void ellipse(unrestricted double x, unrestricted double y, unrestricted double radiusX, unrestricted double radiusY, unrestricted double rotation, unrestricted double startAngle, unrestricted double endAngle, optional boolean anticlockwise = false); +}; diff --git a/Source/WebCore/html/canvas/CanvasPattern.cpp b/Source/WebCore/html/canvas/CanvasPattern.cpp index a4557418e..e95eb6330 100644 --- a/Source/WebCore/html/canvas/CanvasPattern.cpp +++ b/Source/WebCore/html/canvas/CanvasPattern.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -26,20 +26,19 @@ #include "config.h" #include "CanvasPattern.h" -#include "ExceptionCode.h" #include "Image.h" #include "Pattern.h" #include <wtf/text/WTFString.h> namespace WebCore { -PassRefPtr<CanvasPattern> CanvasPattern::create(PassRefPtr<Image> image, bool repeatX, bool repeatY, bool originClean) +Ref<CanvasPattern> CanvasPattern::create(Ref<Image>&& image, bool repeatX, bool repeatY, bool originClean) { - return adoptRef(new CanvasPattern(image, repeatX, repeatY, originClean)); + return adoptRef(*new CanvasPattern(WTFMove(image), repeatX, repeatY, originClean)); } -CanvasPattern::CanvasPattern(PassRefPtr<Image> image, bool repeatX, bool repeatY, bool originClean) - : m_pattern(Pattern::create(image, repeatX, repeatY)) +CanvasPattern::CanvasPattern(Ref<Image>&& image, bool repeatX, bool repeatY, bool originClean) + : m_pattern(Pattern::create(WTFMove(image), repeatX, repeatY)) , m_originClean(originClean) { } @@ -48,30 +47,29 @@ CanvasPattern::~CanvasPattern() { } -void CanvasPattern::parseRepetitionType(const String& type, bool& repeatX, bool& repeatY, ExceptionCode& ec) +bool CanvasPattern::parseRepetitionType(const String& type, bool& repeatX, bool& repeatY) { - ec = 0; if (type.isEmpty() || type == "repeat") { repeatX = true; repeatY = true; - return; + return true; } if (type == "no-repeat") { repeatX = false; repeatY = false; - return; + return true; } if (type == "repeat-x") { repeatX = true; repeatY = false; - return; + return true; } if (type == "repeat-y") { repeatX = false; repeatY = true; - return; + return true; } - ec = SYNTAX_ERR; + return false; } } // namespace WebCore diff --git a/Source/WebCore/html/canvas/CanvasPattern.h b/Source/WebCore/html/canvas/CanvasPattern.h index 9fed5759a..b8faaab1a 100644 --- a/Source/WebCore/html/canvas/CanvasPattern.h +++ b/Source/WebCore/html/canvas/CanvasPattern.h @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,39 +23,34 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CanvasPattern_h -#define CanvasPattern_h +#pragma once #include <wtf/Forward.h> -#include <wtf/PassRefPtr.h> +#include <wtf/Ref.h> #include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> namespace WebCore { class Image; class Pattern; -typedef int ExceptionCode; - class CanvasPattern : public RefCounted<CanvasPattern> { public: - static PassRefPtr<CanvasPattern> create(PassRefPtr<Image>, bool repeatX, bool repeatY, bool originClean); + static Ref<CanvasPattern> create(Ref<Image>&&, bool repeatX, bool repeatY, bool originClean); ~CanvasPattern(); - static void parseRepetitionType(const String&, bool& repeatX, bool& repeatY, ExceptionCode&); + static bool parseRepetitionType(const String&, bool& repeatX, bool& repeatY); - Pattern* pattern() const { return m_pattern.get(); } + Pattern& pattern() { return m_pattern; } + const Pattern& pattern() const { return m_pattern; } bool originClean() const { return m_originClean; } private: - CanvasPattern(PassRefPtr<Image>, bool repeatX, bool repeatY, bool originClean); + CanvasPattern(Ref<Image>&&, bool repeatX, bool repeatY, bool originClean); - RefPtr<Pattern> m_pattern; + Ref<Pattern> m_pattern; bool m_originClean; }; } // namespace WebCore - -#endif diff --git a/Source/WebCore/html/canvas/CanvasPattern.idl b/Source/WebCore/html/canvas/CanvasPattern.idl index 4ded936d7..733d5511f 100644 --- a/Source/WebCore/html/canvas/CanvasPattern.idl +++ b/Source/WebCore/html/canvas/CanvasPattern.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR diff --git a/Source/WebCore/html/canvas/CanvasProxy.cpp b/Source/WebCore/html/canvas/CanvasProxy.cpp index 3006ed65e..baf0a0846 100644 --- a/Source/WebCore/html/canvas/CanvasProxy.cpp +++ b/Source/WebCore/html/canvas/CanvasProxy.cpp @@ -32,9 +32,9 @@ namespace WebCore { -PassRefPtr<CanvasProxy> CanvasProxy::create() +Ref<CanvasProxy> CanvasProxy::create() { - return adoptRef(new CanvasProxy()); + return adoptRef(*new CanvasProxy()); } CanvasProxy::CanvasProxy() diff --git a/Source/WebCore/html/canvas/CanvasProxy.h b/Source/WebCore/html/canvas/CanvasProxy.h index 2591f0eb0..0dcfb1fb9 100644 --- a/Source/WebCore/html/canvas/CanvasProxy.h +++ b/Source/WebCore/html/canvas/CanvasProxy.h @@ -24,17 +24,15 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CanvasProxy_h -#define CanvasProxy_h +#pragma once -#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> namespace WebCore { class CanvasProxy : public RefCounted<CanvasProxy> { public: - static PassRefPtr<CanvasProxy> create(); + static Ref<CanvasProxy> create(); virtual ~CanvasProxy(); @@ -43,5 +41,3 @@ private: }; } // namespace WebCore - -#endif // CanvasProxy_h diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext.cpp b/Source/WebCore/html/canvas/CanvasRenderingContext.cpp index e8bf03a90..2b718e6ba 100644 --- a/Source/WebCore/html/canvas/CanvasRenderingContext.cpp +++ b/Source/WebCore/html/canvas/CanvasRenderingContext.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -36,35 +36,48 @@ namespace WebCore { -CanvasRenderingContext::CanvasRenderingContext(HTMLCanvasElement* canvas) +CanvasRenderingContext::CanvasRenderingContext(HTMLCanvasElement& canvas) : m_canvas(canvas) { } bool CanvasRenderingContext::wouldTaintOrigin(const CanvasPattern* pattern) { - if (canvas()->originClean() && pattern && !pattern->originClean()) + if (canvas().originClean() && pattern && !pattern->originClean()) return true; return false; } bool CanvasRenderingContext::wouldTaintOrigin(const HTMLCanvasElement* sourceCanvas) { - if (canvas()->originClean() && sourceCanvas && !sourceCanvas->originClean()) + if (canvas().originClean() && sourceCanvas && !sourceCanvas->originClean()) return true; return false; } -bool CanvasRenderingContext::wouldTaintOrigin(const HTMLImageElement* image) +bool CanvasRenderingContext::wouldTaintOrigin(const HTMLImageElement* element) { - if (!image || !canvas()->originClean()) + if (!element || !canvas().originClean()) return false; - CachedImage* cachedImage = image->cachedImage(); - if (!cachedImage->image()->hasSingleSecurityOrigin()) + auto* cachedImage = element->cachedImage(); + if (!cachedImage) + return false; + + auto* image = cachedImage->image(); + if (!image) + return false; + + if (!image->hasSingleSecurityOrigin()) + return true; + + if (!cachedImage->isCORSSameOrigin()) return true; - return wouldTaintOrigin(cachedImage->response().url()) && !cachedImage->passesAccessControlCheck(canvas()->securityOrigin()); + ASSERT(canvas().securityOrigin()); + ASSERT(cachedImage->origin()); + ASSERT(canvas().securityOrigin()->toString() == cachedImage->origin()->toString()); + return false; } bool CanvasRenderingContext::wouldTaintOrigin(const HTMLVideoElement* video) @@ -74,7 +87,7 @@ bool CanvasRenderingContext::wouldTaintOrigin(const HTMLVideoElement* video) // to test the finalURL. Please be careful when fixing this issue not to // make currentSrc be the final URL because then the // HTMLMediaElement.currentSrc DOM API would leak redirect destinations! - if (!video || !canvas()->originClean()) + if (!video || !canvas().originClean()) return false; if (!video->hasSingleSecurityOrigin()) @@ -92,23 +105,19 @@ bool CanvasRenderingContext::wouldTaintOrigin(const HTMLVideoElement* video) bool CanvasRenderingContext::wouldTaintOrigin(const URL& url) { - if (!canvas()->originClean() || m_cleanURLs.contains(url.string())) + if (!canvas().originClean()) return false; - if (canvas()->securityOrigin()->taintsCanvas(url)) - return true; - if (url.protocolIsData()) return false; - m_cleanURLs.add(url.string()); - return false; + return !canvas().securityOrigin()->canRequest(url); } void CanvasRenderingContext::checkOrigin(const URL& url) { if (wouldTaintOrigin(url)) - canvas()->setOriginTainted(); + canvas().setOriginTainted(); } } // namespace WebCore diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext.h b/Source/WebCore/html/canvas/CanvasRenderingContext.h index b5b2781f7..759080f53 100644 --- a/Source/WebCore/html/canvas/CanvasRenderingContext.h +++ b/Source/WebCore/html/canvas/CanvasRenderingContext.h @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CanvasRenderingContext_h -#define CanvasRenderingContext_h +#pragma once #include "GraphicsLayer.h" #include "HTMLCanvasElement.h" @@ -47,22 +46,21 @@ class CanvasRenderingContext : public ScriptWrappable { public: virtual ~CanvasRenderingContext() { } - void ref() { m_canvas->ref(); } - void deref() { m_canvas->deref(); } - HTMLCanvasElement* canvas() const { return m_canvas; } + void ref() { m_canvas.ref(); } + void deref() { m_canvas.deref(); } + HTMLCanvasElement& canvas() const { return m_canvas; } virtual bool is2d() const { return false; } - virtual bool is3d() const { return false; } + virtual bool isWebGL1() const { return false; } + virtual bool isWebGL2() const { return false; } + bool is3d() const { return isWebGL1() || isWebGL2(); } virtual bool isAccelerated() const { return false; } virtual void paintRenderingResultsToCanvas() {} - -#if USE(ACCELERATED_COMPOSITING) virtual PlatformLayer* platformLayer() const { return 0; } -#endif protected: - CanvasRenderingContext(HTMLCanvasElement*); + CanvasRenderingContext(HTMLCanvasElement&); bool wouldTaintOrigin(const CanvasPattern*); bool wouldTaintOrigin(const HTMLCanvasElement*); bool wouldTaintOrigin(const HTMLImageElement*); @@ -72,15 +70,17 @@ protected: template<class T> void checkOrigin(const T* arg) { if (wouldTaintOrigin(arg)) - canvas()->setOriginTainted(); + canvas().setOriginTainted(); } void checkOrigin(const URL&); private: - HTMLCanvasElement* m_canvas; - HashSet<String> m_cleanURLs; + HTMLCanvasElement& m_canvas; }; } // namespace WebCore -#endif +#define SPECIALIZE_TYPE_TRAITS_CANVASRENDERINGCONTEXT(ToValueTypeName, predicate) \ +SPECIALIZE_TYPE_TRAITS_BEGIN(ToValueTypeName) \ + static bool isType(const WebCore::CanvasRenderingContext& context) { return context.predicate; } \ +SPECIALIZE_TYPE_TRAITS_END() diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp b/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp index dc55df0e3..5bd1c76f2 100755..100644 --- a/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp +++ b/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp @@ -1,12 +1,12 @@ /* - * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2004-2017 Apple Inc. All rights reserved. * Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies) * Copyright (C) 2007 Alp Toker <alp@atoker.com> * Copyright (C) 2008 Eric Seidel <eric@webkit.org> * Copyright (C) 2008 Dirk Schulze <krit@webkit.org> * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. * Copyright (C) 2012 Intel Corporation. All rights reserved. - * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved. + * Copyright (C) 2013, 2014 Adobe Systems Incorporated. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -17,10 +17,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -33,6 +33,7 @@ #include "config.h" #include "CanvasRenderingContext2D.h" +#include "BitmapImage.h" #include "CSSFontSelector.h" #include "CSSParser.h" #include "CSSPropertyNames.h" @@ -40,47 +41,68 @@ #include "CanvasGradient.h" #include "CanvasPattern.h" #include "DOMPath.h" -#include "ExceptionCodePlaceholder.h" +#include "DisplayListRecorder.h" +#include "DisplayListReplayer.h" #include "FloatQuad.h" -#include "FontCache.h" -#include "GraphicsContext.h" #include "HTMLImageElement.h" #include "HTMLVideoElement.h" +#include "ImageBuffer.h" #include "ImageData.h" #include "RenderElement.h" +#include "RenderImage.h" +#include "RenderLayer.h" +#include "RenderTheme.h" #include "SecurityOrigin.h" #include "StrokeStyleApplier.h" #include "StyleProperties.h" #include "StyleResolver.h" #include "TextMetrics.h" #include "TextRun.h" - -#if USE(ACCELERATED_COMPOSITING) -#include "RenderLayer.h" -#endif - +#include "TextStream.h" #include <wtf/CheckedArithmetic.h> #include <wtf/MathExtras.h> +#include <wtf/NeverDestroyed.h> #include <wtf/text/StringBuilder.h> -#if USE(CG) -#if !PLATFORM(IOS) +#if USE(CG) && !PLATFORM(IOS) #include <ApplicationServices/ApplicationServices.h> -#endif // !PLATFORM(IOS) -#endif - -#if PLATFORM(IOS) -#include "Settings.h" #endif namespace WebCore { using namespace HTMLNames; +#if USE(CG) +const CanvasRenderingContext2D::ImageSmoothingQuality defaultSmoothingQuality = CanvasRenderingContext2D::ImageSmoothingQuality::Low; +#else +const CanvasRenderingContext2D::ImageSmoothingQuality defaultSmoothingQuality = CanvasRenderingContext2D::ImageSmoothingQuality::Medium; +#endif + static const int defaultFontSize = 10; static const char* const defaultFontFamily = "sans-serif"; static const char* const defaultFont = "10px sans-serif"; +struct DisplayListDrawingContext { + WTF_MAKE_FAST_ALLOCATED; +public: + GraphicsContext context; + DisplayList::Recorder recorder; + DisplayList::DisplayList displayList; + + DisplayListDrawingContext(const FloatRect& clip) + : recorder(context, displayList, clip, AffineTransform()) + { + } +}; + +typedef HashMap<const CanvasRenderingContext2D*, std::unique_ptr<DisplayList::DisplayList>> ContextDisplayListHashMap; + +static ContextDisplayListHashMap& contextDisplayListMap() +{ + static NeverDestroyed<ContextDisplayListHashMap> sharedHashMap; + return sharedHashMap; +} + class CanvasStrokeStyleApplier : public StrokeStyleApplier { public: CanvasStrokeStyleApplier(CanvasRenderingContext2D* canvasContext) @@ -88,7 +110,7 @@ public: { } - virtual void strokeStyle(GraphicsContext* c) override + void strokeStyle(GraphicsContext* c) override { c->setStrokeThickness(m_canvasContext->lineWidth()); c->setLineCap(m_canvasContext->getLineCap()); @@ -105,10 +127,9 @@ private: CanvasRenderingContext2D* m_canvasContext; }; -CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas, bool usesCSSCompatibilityParseMode, bool usesDashboardCompatibilityMode) +CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement& canvas, bool usesCSSCompatibilityParseMode, bool usesDashboardCompatibilityMode) : CanvasRenderingContext(canvas) , m_stateStack(1) - , m_unrealizedSaveCount(0) , m_usesCSSCompatibilityParseMode(usesCSSCompatibilityParseMode) #if ENABLE(DASHBOARD_SUPPORT) , m_usesDashboardCompatibilityMode(usesDashboardCompatibilityMode) @@ -125,7 +146,7 @@ void CanvasRenderingContext2D::unwindStateStack() // is cleared before destruction, to avoid assertions in the // GraphicsContext dtor. if (size_t stackSize = m_stateStack.size()) { - if (GraphicsContext* context = canvas()->existingDrawingContext()) { + if (GraphicsContext* context = canvas().existingDrawingContext()) { while (--stackSize) context->restore(); } @@ -137,14 +158,17 @@ CanvasRenderingContext2D::~CanvasRenderingContext2D() #if !ASSERT_DISABLED unwindStateStack(); #endif + + if (UNLIKELY(tracksDisplayListReplay())) + contextDisplayListMap().remove(this); } bool CanvasRenderingContext2D::isAccelerated() const { #if USE(IOSURFACE_CANVAS_BACKING_STORE) || ENABLE(ACCELERATED_2D_CANVAS) - if (!canvas()->hasCreatedImageBuffer()) + if (!canvas().hasCreatedImageBuffer()) return false; - GraphicsContext* context = drawingContext(); + auto* context = drawingContext(); return context && context->isAcceleratedContext(); #else return false; @@ -158,58 +182,59 @@ void CanvasRenderingContext2D::reset() m_stateStack.first() = State(); m_path.clear(); m_unrealizedSaveCount = 0; + + m_recordingContext = nullptr; } CanvasRenderingContext2D::State::State() - : m_strokeStyle(Color::black) - , m_fillStyle(Color::black) - , m_lineWidth(1) - , m_lineCap(ButtCap) - , m_lineJoin(MiterJoin) - , m_miterLimit(10) - , m_shadowBlur(0) - , m_shadowColor(Color::transparent) - , m_globalAlpha(1) - , m_globalComposite(CompositeSourceOver) - , m_globalBlend(BlendModeNormal) - , m_hasInvertibleTransform(true) - , m_lineDashOffset(0) - , m_imageSmoothingEnabled(true) - , m_textAlign(StartTextAlign) - , m_textBaseline(AlphabeticTextBaseline) - , m_unparsedFont(defaultFont) - , m_realizedFont(false) + : strokeStyle(Color::black) + , fillStyle(Color::black) + , lineWidth(1) + , lineCap(ButtCap) + , lineJoin(MiterJoin) + , miterLimit(10) + , shadowBlur(0) + , shadowColor(Color::transparent) + , globalAlpha(1) + , globalComposite(CompositeSourceOver) + , globalBlend(BlendModeNormal) + , hasInvertibleTransform(true) + , lineDashOffset(0) + , imageSmoothingEnabled(true) + , imageSmoothingQuality(defaultSmoothingQuality) + , textAlign(StartTextAlign) + , textBaseline(AlphabeticTextBaseline) + , direction(Direction::Inherit) + , unparsedFont(defaultFont) { } CanvasRenderingContext2D::State::State(const State& other) - : FontSelectorClient() - , m_unparsedStrokeColor(other.m_unparsedStrokeColor) - , m_unparsedFillColor(other.m_unparsedFillColor) - , m_strokeStyle(other.m_strokeStyle) - , m_fillStyle(other.m_fillStyle) - , m_lineWidth(other.m_lineWidth) - , m_lineCap(other.m_lineCap) - , m_lineJoin(other.m_lineJoin) - , m_miterLimit(other.m_miterLimit) - , m_shadowOffset(other.m_shadowOffset) - , m_shadowBlur(other.m_shadowBlur) - , m_shadowColor(other.m_shadowColor) - , m_globalAlpha(other.m_globalAlpha) - , m_globalComposite(other.m_globalComposite) - , m_globalBlend(other.m_globalBlend) - , m_transform(other.m_transform) - , m_hasInvertibleTransform(other.m_hasInvertibleTransform) - , m_lineDashOffset(other.m_lineDashOffset) - , m_imageSmoothingEnabled(other.m_imageSmoothingEnabled) - , m_textAlign(other.m_textAlign) - , m_textBaseline(other.m_textBaseline) - , m_unparsedFont(other.m_unparsedFont) - , m_font(other.m_font) - , m_realizedFont(other.m_realizedFont) -{ - if (m_realizedFont) - m_font.fontSelector()->registerForInvalidationCallbacks(this); + : unparsedStrokeColor(other.unparsedStrokeColor) + , unparsedFillColor(other.unparsedFillColor) + , strokeStyle(other.strokeStyle) + , fillStyle(other.fillStyle) + , lineWidth(other.lineWidth) + , lineCap(other.lineCap) + , lineJoin(other.lineJoin) + , miterLimit(other.miterLimit) + , shadowOffset(other.shadowOffset) + , shadowBlur(other.shadowBlur) + , shadowColor(other.shadowColor) + , globalAlpha(other.globalAlpha) + , globalComposite(other.globalComposite) + , globalBlend(other.globalBlend) + , transform(other.transform) + , hasInvertibleTransform(other.hasInvertibleTransform) + , lineDashOffset(other.lineDashOffset) + , imageSmoothingEnabled(other.imageSmoothingEnabled) + , imageSmoothingQuality(other.imageSmoothingQuality) + , textAlign(other.textAlign) + , textBaseline(other.textBaseline) + , direction(other.direction) + , unparsedFont(other.unparsedFont) + , font(other.font) +{ } CanvasRenderingContext2D::State& CanvasRenderingContext2D::State::operator=(const State& other) @@ -217,50 +242,119 @@ CanvasRenderingContext2D::State& CanvasRenderingContext2D::State::operator=(cons if (this == &other) return *this; - if (m_realizedFont) - m_font.fontSelector()->unregisterForInvalidationCallbacks(this); - - m_unparsedStrokeColor = other.m_unparsedStrokeColor; - m_unparsedFillColor = other.m_unparsedFillColor; - m_strokeStyle = other.m_strokeStyle; - m_fillStyle = other.m_fillStyle; - m_lineWidth = other.m_lineWidth; - m_lineCap = other.m_lineCap; - m_lineJoin = other.m_lineJoin; - m_miterLimit = other.m_miterLimit; - m_shadowOffset = other.m_shadowOffset; - m_shadowBlur = other.m_shadowBlur; - m_shadowColor = other.m_shadowColor; - m_globalAlpha = other.m_globalAlpha; - m_globalComposite = other.m_globalComposite; - m_globalBlend = other.m_globalBlend; - m_transform = other.m_transform; - m_hasInvertibleTransform = other.m_hasInvertibleTransform; - m_imageSmoothingEnabled = other.m_imageSmoothingEnabled; - m_textAlign = other.m_textAlign; - m_textBaseline = other.m_textBaseline; - m_unparsedFont = other.m_unparsedFont; + unparsedStrokeColor = other.unparsedStrokeColor; + unparsedFillColor = other.unparsedFillColor; + strokeStyle = other.strokeStyle; + fillStyle = other.fillStyle; + lineWidth = other.lineWidth; + lineCap = other.lineCap; + lineJoin = other.lineJoin; + miterLimit = other.miterLimit; + shadowOffset = other.shadowOffset; + shadowBlur = other.shadowBlur; + shadowColor = other.shadowColor; + globalAlpha = other.globalAlpha; + globalComposite = other.globalComposite; + globalBlend = other.globalBlend; + transform = other.transform; + hasInvertibleTransform = other.hasInvertibleTransform; + imageSmoothingEnabled = other.imageSmoothingEnabled; + imageSmoothingQuality = other.imageSmoothingQuality; + textAlign = other.textAlign; + textBaseline = other.textBaseline; + direction = other.direction; + unparsedFont = other.unparsedFont; + font = other.font; + + return *this; +} + +CanvasRenderingContext2D::FontProxy::~FontProxy() +{ + if (realized()) + m_font.fontSelector()->unregisterForInvalidationCallbacks(*this); +} + +CanvasRenderingContext2D::FontProxy::FontProxy(const FontProxy& other) + : m_font(other.m_font) +{ + if (realized()) + m_font.fontSelector()->registerForInvalidationCallbacks(*this); +} + +auto CanvasRenderingContext2D::FontProxy::operator=(const FontProxy& other) -> FontProxy& +{ + if (realized()) + m_font.fontSelector()->unregisterForInvalidationCallbacks(*this); + m_font = other.m_font; - m_realizedFont = other.m_realizedFont; - if (m_realizedFont) - m_font.fontSelector()->registerForInvalidationCallbacks(this); + if (realized()) + m_font.fontSelector()->registerForInvalidationCallbacks(*this); return *this; } -CanvasRenderingContext2D::State::~State() +inline void CanvasRenderingContext2D::FontProxy::update(FontSelector& selector) { - if (m_realizedFont) - m_font.fontSelector()->unregisterForInvalidationCallbacks(this); + ASSERT(&selector == m_font.fontSelector()); // This is an invariant. We should only ever be registered for callbacks on m_font.m_fonts.m_fontSelector. + if (realized()) + m_font.fontSelector()->unregisterForInvalidationCallbacks(*this); + m_font.update(&selector); + if (realized()) + m_font.fontSelector()->registerForInvalidationCallbacks(*this); + ASSERT(&selector == m_font.fontSelector()); } -void CanvasRenderingContext2D::State::fontsNeedUpdate(FontSelector* fontSelector) +void CanvasRenderingContext2D::FontProxy::fontsNeedUpdate(FontSelector& selector) { - ASSERT_ARG(fontSelector, fontSelector == m_font.fontSelector()); - ASSERT(m_realizedFont); + ASSERT_ARG(selector, &selector == m_font.fontSelector()); + ASSERT(realized()); + + update(selector); +} - m_font.update(fontSelector); +inline void CanvasRenderingContext2D::FontProxy::initialize(FontSelector& fontSelector, const RenderStyle& newStyle) +{ + // Beware! m_font.fontSelector() might not point to document.fontSelector()! + ASSERT(newStyle.fontCascade().fontSelector() == &fontSelector); + if (realized()) + m_font.fontSelector()->unregisterForInvalidationCallbacks(*this); + m_font = newStyle.fontCascade(); + m_font.update(&fontSelector); + ASSERT(&fontSelector == m_font.fontSelector()); + m_font.fontSelector()->registerForInvalidationCallbacks(*this); +} + +inline FontMetrics CanvasRenderingContext2D::FontProxy::fontMetrics() const +{ + return m_font.fontMetrics(); +} + +inline const FontCascadeDescription& CanvasRenderingContext2D::FontProxy::fontDescription() const +{ + return m_font.fontDescription(); +} + +inline float CanvasRenderingContext2D::FontProxy::width(const TextRun& textRun) const +{ + return m_font.width(textRun); +} + +inline void CanvasRenderingContext2D::FontProxy::drawBidiText(GraphicsContext& context, const TextRun& run, const FloatPoint& point, FontCascade::CustomFontNotReadyAction action) const +{ + context.drawBidiText(m_font, run, point, action); +} + +void CanvasRenderingContext2D::realizeSaves() +{ + if (m_unrealizedSaveCount) + realizeSavesLoop(); + + if (m_unrealizedSaveCount) { + static NeverDestroyed<String> consoleMessage(ASCIILiteral("CanvasRenderingContext2D.save() has been called without a matching restore() too many times. Ignoring save().")); + canvas().document().addConsoleMessage(MessageSource::Rendering, MessageLevel::Error, consoleMessage); + } } void CanvasRenderingContext2D::realizeSavesLoop() @@ -269,6 +363,8 @@ void CanvasRenderingContext2D::realizeSavesLoop() ASSERT(m_stateStack.size() >= 1); GraphicsContext* context = drawingContext(); do { + if (m_stateStack.size() > MaxSaveCount) + break; m_stateStack.append(state()); if (context) context->save(); @@ -284,9 +380,10 @@ void CanvasRenderingContext2D::restore() ASSERT(m_stateStack.size() >= 1); if (m_stateStack.size() <= 1) return; - m_path.transform(state().m_transform); + m_path.transform(state().transform); m_stateStack.removeLast(); - m_path.transform(state().m_transform.inverse()); + if (std::optional<AffineTransform> inverse = state().transform.inverse()) + m_path.transform(inverse.value()); GraphicsContext* c = drawingContext(); if (!c) return; @@ -298,25 +395,26 @@ void CanvasRenderingContext2D::setStrokeStyle(CanvasStyle style) if (!style.isValid()) return; - if (state().m_strokeStyle.isValid() && state().m_strokeStyle.isEquivalentColor(style)) + if (state().strokeStyle.isValid() && state().strokeStyle.isEquivalentColor(style)) return; if (style.isCurrentColor()) { - if (style.hasOverrideAlpha()) - style = CanvasStyle(colorWithOverrideAlpha(currentColor(canvas()), style.overrideAlpha())); - else - style = CanvasStyle(currentColor(canvas())); + if (style.hasOverrideAlpha()) { + // FIXME: Should not use RGBA32 here. + style = CanvasStyle(colorWithOverrideAlpha(currentColor(&canvas()).rgb(), style.overrideAlpha())); + } else + style = CanvasStyle(currentColor(&canvas())); } else checkOrigin(style.canvasPattern()); realizeSaves(); State& state = modifiableState(); - state.m_strokeStyle = style; + state.strokeStyle = style; GraphicsContext* c = drawingContext(); if (!c) return; - state.m_strokeStyle.applyStrokeColor(c); - state.m_unparsedStrokeColor = String(); + state.strokeStyle.applyStrokeColor(*c); + state.unparsedStrokeColor = String(); } void CanvasRenderingContext2D::setFillStyle(CanvasStyle style) @@ -324,40 +422,41 @@ void CanvasRenderingContext2D::setFillStyle(CanvasStyle style) if (!style.isValid()) return; - if (state().m_fillStyle.isValid() && state().m_fillStyle.isEquivalentColor(style)) + if (state().fillStyle.isValid() && state().fillStyle.isEquivalentColor(style)) return; if (style.isCurrentColor()) { - if (style.hasOverrideAlpha()) - style = CanvasStyle(colorWithOverrideAlpha(currentColor(canvas()), style.overrideAlpha())); - else - style = CanvasStyle(currentColor(canvas())); + if (style.hasOverrideAlpha()) { + // FIXME: Should not use RGBA32 here. + style = CanvasStyle(colorWithOverrideAlpha(currentColor(&canvas()).rgb(), style.overrideAlpha())); + } else + style = CanvasStyle(currentColor(&canvas())); } else checkOrigin(style.canvasPattern()); realizeSaves(); State& state = modifiableState(); - state.m_fillStyle = style; + state.fillStyle = style; GraphicsContext* c = drawingContext(); if (!c) return; - state.m_fillStyle.applyFillColor(c); - state.m_unparsedFillColor = String(); + state.fillStyle.applyFillColor(*c); + state.unparsedFillColor = String(); } float CanvasRenderingContext2D::lineWidth() const { - return state().m_lineWidth; + return state().lineWidth; } void CanvasRenderingContext2D::setLineWidth(float width) { if (!(std::isfinite(width) && width > 0)) return; - if (state().m_lineWidth == width) + if (state().lineWidth == width) return; realizeSaves(); - modifiableState().m_lineWidth = width; + modifiableState().lineWidth = width; GraphicsContext* c = drawingContext(); if (!c) return; @@ -366,7 +465,7 @@ void CanvasRenderingContext2D::setLineWidth(float width) String CanvasRenderingContext2D::lineCap() const { - return lineCapName(state().m_lineCap); + return lineCapName(state().lineCap); } void CanvasRenderingContext2D::setLineCap(const String& s) @@ -374,10 +473,10 @@ void CanvasRenderingContext2D::setLineCap(const String& s) LineCap cap; if (!parseLineCap(s, cap)) return; - if (state().m_lineCap == cap) + if (state().lineCap == cap) return; realizeSaves(); - modifiableState().m_lineCap = cap; + modifiableState().lineCap = cap; GraphicsContext* c = drawingContext(); if (!c) return; @@ -386,7 +485,7 @@ void CanvasRenderingContext2D::setLineCap(const String& s) String CanvasRenderingContext2D::lineJoin() const { - return lineJoinName(state().m_lineJoin); + return lineJoinName(state().lineJoin); } void CanvasRenderingContext2D::setLineJoin(const String& s) @@ -394,10 +493,10 @@ void CanvasRenderingContext2D::setLineJoin(const String& s) LineJoin join; if (!parseLineJoin(s, join)) return; - if (state().m_lineJoin == join) + if (state().lineJoin == join) return; realizeSaves(); - modifiableState().m_lineJoin = join; + modifiableState().lineJoin = join; GraphicsContext* c = drawingContext(); if (!c) return; @@ -406,17 +505,17 @@ void CanvasRenderingContext2D::setLineJoin(const String& s) float CanvasRenderingContext2D::miterLimit() const { - return state().m_miterLimit; + return state().miterLimit; } void CanvasRenderingContext2D::setMiterLimit(float limit) { if (!(std::isfinite(limit) && limit > 0)) return; - if (state().m_miterLimit == limit) + if (state().miterLimit == limit) return; realizeSaves(); - modifiableState().m_miterLimit = limit; + modifiableState().miterLimit = limit; GraphicsContext* c = drawingContext(); if (!c) return; @@ -425,72 +524,72 @@ void CanvasRenderingContext2D::setMiterLimit(float limit) float CanvasRenderingContext2D::shadowOffsetX() const { - return state().m_shadowOffset.width(); + return state().shadowOffset.width(); } void CanvasRenderingContext2D::setShadowOffsetX(float x) { if (!std::isfinite(x)) return; - if (state().m_shadowOffset.width() == x) + if (state().shadowOffset.width() == x) return; realizeSaves(); - modifiableState().m_shadowOffset.setWidth(x); + modifiableState().shadowOffset.setWidth(x); applyShadow(); } float CanvasRenderingContext2D::shadowOffsetY() const { - return state().m_shadowOffset.height(); + return state().shadowOffset.height(); } void CanvasRenderingContext2D::setShadowOffsetY(float y) { if (!std::isfinite(y)) return; - if (state().m_shadowOffset.height() == y) + if (state().shadowOffset.height() == y) return; realizeSaves(); - modifiableState().m_shadowOffset.setHeight(y); + modifiableState().shadowOffset.setHeight(y); applyShadow(); } float CanvasRenderingContext2D::shadowBlur() const { - return state().m_shadowBlur; + return state().shadowBlur; } void CanvasRenderingContext2D::setShadowBlur(float blur) { if (!(std::isfinite(blur) && blur >= 0)) return; - if (state().m_shadowBlur == blur) + if (state().shadowBlur == blur) return; realizeSaves(); - modifiableState().m_shadowBlur = blur; + modifiableState().shadowBlur = blur; applyShadow(); } String CanvasRenderingContext2D::shadowColor() const { - return Color(state().m_shadowColor).serialized(); + return Color(state().shadowColor).serialized(); } -void CanvasRenderingContext2D::setShadowColor(const String& color) +void CanvasRenderingContext2D::setShadowColor(const String& colorString) { - RGBA32 rgba; - if (!parseColorOrCurrentColor(rgba, color, canvas())) + Color color = parseColorOrCurrentColor(colorString, &canvas()); + if (!color.isValid()) return; - if (state().m_shadowColor == rgba) + if (state().shadowColor == color) return; realizeSaves(); - modifiableState().m_shadowColor = rgba; + modifiableState().shadowColor = color; applyShadow(); } const Vector<float>& CanvasRenderingContext2D::getLineDash() const { - return state().m_lineDash; + return state().lineDash; } static bool lineDashSequenceIsValid(const Vector<float>& dash) @@ -508,11 +607,11 @@ void CanvasRenderingContext2D::setLineDash(const Vector<float>& dash) return; realizeSaves(); - modifiableState().m_lineDash = dash; + modifiableState().lineDash = dash; // Spec requires the concatenation of two copies the dash list when the // number of elements is odd if (dash.size() % 2) - modifiableState().m_lineDash.appendVector(dash); + modifiableState().lineDash.appendVector(dash); applyLineDash(); } @@ -523,60 +622,50 @@ void CanvasRenderingContext2D::setWebkitLineDash(const Vector<float>& dash) return; realizeSaves(); - modifiableState().m_lineDash = dash; + modifiableState().lineDash = dash; applyLineDash(); } float CanvasRenderingContext2D::lineDashOffset() const { - return state().m_lineDashOffset; + return state().lineDashOffset; } void CanvasRenderingContext2D::setLineDashOffset(float offset) { - if (!std::isfinite(offset) || state().m_lineDashOffset == offset) + if (!std::isfinite(offset) || state().lineDashOffset == offset) return; realizeSaves(); - modifiableState().m_lineDashOffset = offset; + modifiableState().lineDashOffset = offset; applyLineDash(); } -float CanvasRenderingContext2D::webkitLineDashOffset() const -{ - return lineDashOffset(); -} - -void CanvasRenderingContext2D::setWebkitLineDashOffset(float offset) -{ - setLineDashOffset(offset); -} - void CanvasRenderingContext2D::applyLineDash() const { GraphicsContext* c = drawingContext(); if (!c) return; - DashArray convertedLineDash(state().m_lineDash.size()); - for (size_t i = 0; i < state().m_lineDash.size(); ++i) - convertedLineDash[i] = static_cast<DashArrayElement>(state().m_lineDash[i]); - c->setLineDash(convertedLineDash, state().m_lineDashOffset); + DashArray convertedLineDash(state().lineDash.size()); + for (size_t i = 0; i < state().lineDash.size(); ++i) + convertedLineDash[i] = static_cast<DashArrayElement>(state().lineDash[i]); + c->setLineDash(convertedLineDash, state().lineDashOffset); } float CanvasRenderingContext2D::globalAlpha() const { - return state().m_globalAlpha; + return state().globalAlpha; } void CanvasRenderingContext2D::setGlobalAlpha(float alpha) { if (!(alpha >= 0 && alpha <= 1)) return; - if (state().m_globalAlpha == alpha) + if (state().globalAlpha == alpha) return; realizeSaves(); - modifiableState().m_globalAlpha = alpha; + modifiableState().globalAlpha = alpha; GraphicsContext* c = drawingContext(); if (!c) return; @@ -585,7 +674,7 @@ void CanvasRenderingContext2D::setGlobalAlpha(float alpha) String CanvasRenderingContext2D::globalCompositeOperation() const { - return compositeOperatorName(state().m_globalComposite, state().m_globalBlend); + return compositeOperatorName(state().globalComposite, state().globalBlend); } void CanvasRenderingContext2D::setGlobalCompositeOperation(const String& operation) @@ -594,11 +683,11 @@ void CanvasRenderingContext2D::setGlobalCompositeOperation(const String& operati BlendMode blendMode = BlendModeNormal; if (!parseCompositeAndBlendOperator(operation, op, blendMode)) return; - if ((state().m_globalComposite == op) && (state().m_globalBlend == blendMode)) + if ((state().globalComposite == op) && (state().globalBlend == blendMode)) return; realizeSaves(); - modifiableState().m_globalComposite = op; - modifiableState().m_globalBlend = blendMode; + modifiableState().globalComposite = op; + modifiableState().globalBlend = blendMode; GraphicsContext* c = drawingContext(); if (!c) return; @@ -610,25 +699,25 @@ void CanvasRenderingContext2D::scale(float sx, float sy) GraphicsContext* c = drawingContext(); if (!c) return; - if (!state().m_hasInvertibleTransform) + if (!state().hasInvertibleTransform) return; - if (!std::isfinite(sx) | !std::isfinite(sy)) + if (!std::isfinite(sx) || !std::isfinite(sy)) return; - AffineTransform newTransform = state().m_transform; + AffineTransform newTransform = state().transform; newTransform.scaleNonUniform(sx, sy); - if (state().m_transform == newTransform) + if (state().transform == newTransform) return; realizeSaves(); - if (!newTransform.isInvertible()) { - modifiableState().m_hasInvertibleTransform = false; + if (!sx || !sy) { + modifiableState().hasInvertibleTransform = false; return; } - modifiableState().m_transform = newTransform; + modifiableState().transform = newTransform; c->scale(FloatSize(sx, sy)); m_path.transform(AffineTransform().scaleNonUniform(1.0 / sx, 1.0 / sy)); } @@ -638,25 +727,20 @@ void CanvasRenderingContext2D::rotate(float angleInRadians) GraphicsContext* c = drawingContext(); if (!c) return; - if (!state().m_hasInvertibleTransform) + if (!state().hasInvertibleTransform) return; if (!std::isfinite(angleInRadians)) return; - AffineTransform newTransform = state().m_transform; + AffineTransform newTransform = state().transform; newTransform.rotate(angleInRadians / piDouble * 180.0); - if (state().m_transform == newTransform) + if (state().transform == newTransform) return; realizeSaves(); - if (!newTransform.isInvertible()) { - modifiableState().m_hasInvertibleTransform = false; - return; - } - - modifiableState().m_transform = newTransform; + modifiableState().transform = newTransform; c->rotate(angleInRadians); m_path.transform(AffineTransform().rotate(-angleInRadians / piDouble * 180.0)); } @@ -666,25 +750,20 @@ void CanvasRenderingContext2D::translate(float tx, float ty) GraphicsContext* c = drawingContext(); if (!c) return; - if (!state().m_hasInvertibleTransform) + if (!state().hasInvertibleTransform) return; if (!std::isfinite(tx) | !std::isfinite(ty)) return; - AffineTransform newTransform = state().m_transform; + AffineTransform newTransform = state().transform; newTransform.translate(tx, ty); - if (state().m_transform == newTransform) + if (state().transform == newTransform) return; realizeSaves(); - if (!newTransform.isInvertible()) { - modifiableState().m_hasInvertibleTransform = false; - return; - } - - modifiableState().m_transform = newTransform; + modifiableState().transform = newTransform; c->translate(tx, ty); m_path.transform(AffineTransform().translate(-tx, -ty)); } @@ -694,27 +773,26 @@ void CanvasRenderingContext2D::transform(float m11, float m12, float m21, float GraphicsContext* c = drawingContext(); if (!c) return; - if (!state().m_hasInvertibleTransform) + if (!state().hasInvertibleTransform) return; if (!std::isfinite(m11) | !std::isfinite(m21) | !std::isfinite(dx) | !std::isfinite(m12) | !std::isfinite(m22) | !std::isfinite(dy)) return; AffineTransform transform(m11, m12, m21, m22, dx, dy); - AffineTransform newTransform = state().m_transform * transform; - if (state().m_transform == newTransform) + AffineTransform newTransform = state().transform * transform; + if (state().transform == newTransform) return; realizeSaves(); - if (!newTransform.isInvertible()) { - modifiableState().m_hasInvertibleTransform = false; + if (auto inverse = transform.inverse()) { + modifiableState().transform = newTransform; + c->concatCTM(transform); + m_path.transform(inverse.value()); return; } - - modifiableState().m_transform = newTransform; - c->concatCTM(transform); - m_path.transform(transform.inverse()); + modifiableState().hasInvertibleTransform = false; } void CanvasRenderingContext2D::setTransform(float m11, float m12, float m21, float m22, float dx, float dy) @@ -726,100 +804,98 @@ void CanvasRenderingContext2D::setTransform(float m11, float m12, float m21, flo if (!std::isfinite(m11) | !std::isfinite(m21) | !std::isfinite(dx) | !std::isfinite(m12) | !std::isfinite(m22) | !std::isfinite(dy)) return; - AffineTransform ctm = state().m_transform; - if (!ctm.isInvertible()) - return; - - realizeSaves(); - - c->setCTM(canvas()->baseTransform()); - modifiableState().m_transform = AffineTransform(); - m_path.transform(ctm); - - modifiableState().m_hasInvertibleTransform = true; + resetTransform(); transform(m11, m12, m21, m22, dx, dy); } -void CanvasRenderingContext2D::setStrokeColor(const String& color) +void CanvasRenderingContext2D::resetTransform() { - if (color == state().m_unparsedStrokeColor) + GraphicsContext* c = drawingContext(); + if (!c) return; + + AffineTransform ctm = state().transform; + bool hasInvertibleTransform = state().hasInvertibleTransform; + realizeSaves(); - setStrokeStyle(CanvasStyle::createFromString(color, &canvas()->document())); - modifiableState().m_unparsedStrokeColor = color; + + c->setCTM(canvas().baseTransform()); + modifiableState().transform = AffineTransform(); + + if (hasInvertibleTransform) + m_path.transform(ctm); + + modifiableState().hasInvertibleTransform = true; } -void CanvasRenderingContext2D::setStrokeColor(float grayLevel) +void CanvasRenderingContext2D::setStrokeColor(const String& color, std::optional<float> alpha) { - if (state().m_strokeStyle.isValid() && state().m_strokeStyle.isEquivalentRGBA(grayLevel, grayLevel, grayLevel, 1.0f)) + if (alpha) { + setStrokeStyle(CanvasStyle::createFromStringWithOverrideAlpha(color, alpha.value())); return; - setStrokeStyle(CanvasStyle(grayLevel, 1.0f)); -} + } -void CanvasRenderingContext2D::setStrokeColor(const String& color, float alpha) -{ - setStrokeStyle(CanvasStyle::createFromStringWithOverrideAlpha(color, alpha)); + if (color == state().unparsedStrokeColor) + return; + + realizeSaves(); + setStrokeStyle(CanvasStyle::createFromString(color, &canvas().document())); + modifiableState().unparsedStrokeColor = color; } void CanvasRenderingContext2D::setStrokeColor(float grayLevel, float alpha) { - if (state().m_strokeStyle.isValid() && state().m_strokeStyle.isEquivalentRGBA(grayLevel, grayLevel, grayLevel, alpha)) + if (state().strokeStyle.isValid() && state().strokeStyle.isEquivalentRGBA(grayLevel, grayLevel, grayLevel, alpha)) return; setStrokeStyle(CanvasStyle(grayLevel, alpha)); } void CanvasRenderingContext2D::setStrokeColor(float r, float g, float b, float a) { - if (state().m_strokeStyle.isValid() && state().m_strokeStyle.isEquivalentRGBA(r, g, b, a)) + if (state().strokeStyle.isValid() && state().strokeStyle.isEquivalentRGBA(r, g, b, a)) return; setStrokeStyle(CanvasStyle(r, g, b, a)); } void CanvasRenderingContext2D::setStrokeColor(float c, float m, float y, float k, float a) { - if (state().m_strokeStyle.isValid() && state().m_strokeStyle.isEquivalentCMYKA(c, m, y, k, a)) + if (state().strokeStyle.isValid() && state().strokeStyle.isEquivalentCMYKA(c, m, y, k, a)) return; setStrokeStyle(CanvasStyle(c, m, y, k, a)); } -void CanvasRenderingContext2D::setFillColor(const String& color) +void CanvasRenderingContext2D::setFillColor(const String& color, std::optional<float> alpha) { - if (color == state().m_unparsedFillColor) + if (alpha) { + setFillStyle(CanvasStyle::createFromStringWithOverrideAlpha(color, alpha.value())); return; - realizeSaves(); - setFillStyle(CanvasStyle::createFromString(color, &canvas()->document())); - modifiableState().m_unparsedFillColor = color; -} + } -void CanvasRenderingContext2D::setFillColor(float grayLevel) -{ - if (state().m_fillStyle.isValid() && state().m_fillStyle.isEquivalentRGBA(grayLevel, grayLevel, grayLevel, 1.0f)) + if (color == state().unparsedFillColor) return; - setFillStyle(CanvasStyle(grayLevel, 1.0f)); -} -void CanvasRenderingContext2D::setFillColor(const String& color, float alpha) -{ - setFillStyle(CanvasStyle::createFromStringWithOverrideAlpha(color, alpha)); + realizeSaves(); + setFillStyle(CanvasStyle::createFromString(color, &canvas().document())); + modifiableState().unparsedFillColor = color; } void CanvasRenderingContext2D::setFillColor(float grayLevel, float alpha) { - if (state().m_fillStyle.isValid() && state().m_fillStyle.isEquivalentRGBA(grayLevel, grayLevel, grayLevel, alpha)) + if (state().fillStyle.isValid() && state().fillStyle.isEquivalentRGBA(grayLevel, grayLevel, grayLevel, alpha)) return; setFillStyle(CanvasStyle(grayLevel, alpha)); } void CanvasRenderingContext2D::setFillColor(float r, float g, float b, float a) { - if (state().m_fillStyle.isValid() && state().m_fillStyle.isEquivalentRGBA(r, g, b, a)) + if (state().fillStyle.isValid() && state().fillStyle.isEquivalentRGBA(r, g, b, a)) return; setFillStyle(CanvasStyle(r, g, b, a)); } void CanvasRenderingContext2D::setFillColor(float c, float m, float y, float k, float a) { - if (state().m_fillStyle.isValid() && state().m_fillStyle.isEquivalentCMYKA(c, m, y, k, a)) + if (state().fillStyle.isValid() && state().fillStyle.isEquivalentCMYKA(c, m, y, k, a)) return; setFillStyle(CanvasStyle(c, m, y, k, a)); } @@ -829,22 +905,6 @@ void CanvasRenderingContext2D::beginPath() m_path.clear(); } -#if ENABLE(CANVAS_PATH) - -PassRefPtr<DOMPath> CanvasRenderingContext2D::currentPath() -{ - return DOMPath::create(m_path); -} - -void CanvasRenderingContext2D::setCurrentPath(DOMPath* path) -{ - if (!path) - return; - m_path = path->path(); -} - -#endif - static bool validateRectForCanvas(float& x, float& y, float& width, float& height) { if (!std::isfinite(x) | !std::isfinite(y) | !std::isfinite(width) | !std::isfinite(height)) @@ -866,13 +926,13 @@ static bool validateRectForCanvas(float& x, float& y, float& width, float& heigh return true; } -#if ENABLE(DASHBOARD_SUPPORT) -void CanvasRenderingContext2D::clearPathForDashboardBackwardCompatibilityMode() +inline void CanvasRenderingContext2D::clearPathForDashboardBackwardCompatibilityMode() { +#if ENABLE(DASHBOARD_SUPPORT) if (m_usesDashboardCompatibilityMode) m_path.clear(); -} #endif +} static bool isFullCanvasCompositeMode(CompositeOperator op) { @@ -882,152 +942,197 @@ static bool isFullCanvasCompositeMode(CompositeOperator op) return op == CompositeSourceIn || op == CompositeSourceOut || op == CompositeDestinationIn || op == CompositeDestinationAtop; } -static bool parseWinding(const String& windingRuleString, WindRule& windRule) +static WindRule toWindRule(CanvasRenderingContext2D::WindingRule rule) { - if (windingRuleString == "nonzero") - windRule = RULE_NONZERO; - else if (windingRuleString == "evenodd") - windRule = RULE_EVENODD; - else - return false; - - return true; + return rule == CanvasRenderingContext2D::WindingRule::Nonzero ? RULE_NONZERO : RULE_EVENODD; } -void CanvasRenderingContext2D::fill(const String& windingRuleString) +void CanvasRenderingContext2D::fill(WindingRule windingRule) { - GraphicsContext* c = drawingContext(); + fillInternal(m_path, windingRule); + clearPathForDashboardBackwardCompatibilityMode(); +} + +void CanvasRenderingContext2D::stroke() +{ + strokeInternal(m_path); + clearPathForDashboardBackwardCompatibilityMode(); +} + +void CanvasRenderingContext2D::clip(WindingRule windingRule) +{ + clipInternal(m_path, windingRule); + clearPathForDashboardBackwardCompatibilityMode(); +} + +void CanvasRenderingContext2D::fill(DOMPath& path, WindingRule windingRule) +{ + fillInternal(path.path(), windingRule); +} + +void CanvasRenderingContext2D::stroke(DOMPath& path) +{ + strokeInternal(path.path()); +} + +void CanvasRenderingContext2D::clip(DOMPath& path, WindingRule windingRule) +{ + clipInternal(path.path(), windingRule); +} + +void CanvasRenderingContext2D::fillInternal(const Path& path, WindingRule windingRule) +{ + auto* c = drawingContext(); if (!c) return; - if (!state().m_hasInvertibleTransform) + if (!state().hasInvertibleTransform) return; // If gradient size is zero, then paint nothing. - Gradient* gradient = c->fillGradient(); + auto* gradient = c->fillGradient(); if (gradient && gradient->isZeroSize()) return; - if (!m_path.isEmpty()) { - WindRule windRule = c->fillRule(); - WindRule newWindRule = RULE_NONZERO; - if (!parseWinding(windingRuleString, newWindRule)) - return; - c->setFillRule(newWindRule); + if (!path.isEmpty()) { + auto savedFillRule = c->fillRule(); + c->setFillRule(toWindRule(windingRule)); - if (isFullCanvasCompositeMode(state().m_globalComposite)) { - fullCanvasCompositedFill(m_path); + if (isFullCanvasCompositeMode(state().globalComposite)) { + beginCompositeLayer(); + c->fillPath(path); + endCompositeLayer(); didDrawEntireCanvas(); - } else if (state().m_globalComposite == CompositeCopy) { + } else if (state().globalComposite == CompositeCopy) { clearCanvas(); - c->fillPath(m_path); + c->fillPath(path); didDrawEntireCanvas(); } else { - c->fillPath(m_path); - didDraw(m_path.fastBoundingRect()); + c->fillPath(path); + didDraw(path.fastBoundingRect()); } - c->setFillRule(windRule); + c->setFillRule(savedFillRule); } - -#if ENABLE(DASHBOARD_SUPPORT) - clearPathForDashboardBackwardCompatibilityMode(); -#endif } -void CanvasRenderingContext2D::stroke() +void CanvasRenderingContext2D::strokeInternal(const Path& path) { - GraphicsContext* c = drawingContext(); + auto* c = drawingContext(); if (!c) return; - if (!state().m_hasInvertibleTransform) + if (!state().hasInvertibleTransform) return; // If gradient size is zero, then paint nothing. - Gradient* gradient = c->strokeGradient(); + auto* gradient = c->strokeGradient(); if (gradient && gradient->isZeroSize()) return; - if (!m_path.isEmpty()) { - FloatRect dirtyRect = m_path.fastBoundingRect(); - inflateStrokeRect(dirtyRect); - - c->strokePath(m_path); - didDraw(dirtyRect); + if (!path.isEmpty()) { + if (isFullCanvasCompositeMode(state().globalComposite)) { + beginCompositeLayer(); + c->strokePath(path); + endCompositeLayer(); + didDrawEntireCanvas(); + } else if (state().globalComposite == CompositeCopy) { + clearCanvas(); + c->strokePath(path); + didDrawEntireCanvas(); + } else { + FloatRect dirtyRect = path.fastBoundingRect(); + inflateStrokeRect(dirtyRect); + c->strokePath(path); + didDraw(dirtyRect); + } } - -#if ENABLE(DASHBOARD_SUPPORT) - clearPathForDashboardBackwardCompatibilityMode(); -#endif } -void CanvasRenderingContext2D::clip(const String& windingRuleString) +void CanvasRenderingContext2D::clipInternal(const Path& path, WindingRule windingRule) { - GraphicsContext* c = drawingContext(); + auto* c = drawingContext(); if (!c) return; - if (!state().m_hasInvertibleTransform) - return; - - WindRule newWindRule = RULE_NONZERO; - if (!parseWinding(windingRuleString, newWindRule)) + if (!state().hasInvertibleTransform) return; realizeSaves(); - c->canvasClip(m_path, newWindRule); - -#if ENABLE(DASHBOARD_SUPPORT) - clearPathForDashboardBackwardCompatibilityMode(); + c->canvasClip(path, toWindRule(windingRule)); +} + +inline void CanvasRenderingContext2D::beginCompositeLayer() +{ +#if !USE(CAIRO) + drawingContext()->beginTransparencyLayer(1); #endif } -bool CanvasRenderingContext2D::isPointInPath(const float x, const float y, const String& windingRuleString) +inline void CanvasRenderingContext2D::endCompositeLayer() { - GraphicsContext* c = drawingContext(); +#if !USE(CAIRO) + drawingContext()->endTransparencyLayer(); +#endif +} + +bool CanvasRenderingContext2D::isPointInPath(float x, float y, WindingRule windingRule) +{ + return isPointInPathInternal(m_path, x, y, windingRule); +} + +bool CanvasRenderingContext2D::isPointInStroke(float x, float y) +{ + return isPointInStrokeInternal(m_path, x, y); +} + +bool CanvasRenderingContext2D::isPointInPath(DOMPath& path, float x, float y, WindingRule windingRule) +{ + return isPointInPathInternal(path.path(), x, y, windingRule); +} + +bool CanvasRenderingContext2D::isPointInStroke(DOMPath& path, float x, float y) +{ + return isPointInStrokeInternal(path.path(), x, y); +} + +bool CanvasRenderingContext2D::isPointInPathInternal(const Path& path, float x, float y, WindingRule windingRule) +{ + auto* c = drawingContext(); if (!c) return false; - if (!state().m_hasInvertibleTransform) + if (!state().hasInvertibleTransform) return false; - FloatPoint point(x, y); - AffineTransform ctm = state().m_transform; - FloatPoint transformedPoint = ctm.inverse().mapPoint(point); + auto transformedPoint = state().transform.inverse().value_or(AffineTransform()).mapPoint(FloatPoint(x, y)); + if (!std::isfinite(transformedPoint.x()) || !std::isfinite(transformedPoint.y())) return false; - WindRule windRule = RULE_NONZERO; - if (!parseWinding(windingRuleString, windRule)) - return false; - - return m_path.contains(transformedPoint, windRule); + return path.contains(transformedPoint, toWindRule(windingRule)); } - -bool CanvasRenderingContext2D::isPointInStroke(const float x, const float y) +bool CanvasRenderingContext2D::isPointInStrokeInternal(const Path& path, float x, float y) { - GraphicsContext* c = drawingContext(); + auto* c = drawingContext(); if (!c) return false; - if (!state().m_hasInvertibleTransform) + if (!state().hasInvertibleTransform) return false; - FloatPoint point(x, y); - AffineTransform ctm = state().m_transform; - FloatPoint transformedPoint = ctm.inverse().mapPoint(point); + auto transformedPoint = state().transform.inverse().value_or(AffineTransform()).mapPoint(FloatPoint(x, y)); if (!std::isfinite(transformedPoint.x()) || !std::isfinite(transformedPoint.y())) return false; CanvasStrokeStyleApplier applier(this); - return m_path.strokeContains(&applier, transformedPoint); + return path.strokeContains(&applier, transformedPoint); } void CanvasRenderingContext2D::clearRect(float x, float y, float width, float height) { if (!validateRectForCanvas(x, y, width, height)) return; - GraphicsContext* context = drawingContext(); + auto* context = drawingContext(); if (!context) return; - if (!state().m_hasInvertibleTransform) + if (!state().hasInvertibleTransform) return; FloatRect rect(x, y, width, height); @@ -1035,16 +1140,16 @@ void CanvasRenderingContext2D::clearRect(float x, float y, float width, float he if (shouldDrawShadows()) { context->save(); saved = true; - context->setLegacyShadow(FloatSize(), 0, Color::transparent, ColorSpaceDeviceRGB); + context->setLegacyShadow(FloatSize(), 0, Color::transparent); } - if (state().m_globalAlpha != 1) { + if (state().globalAlpha != 1) { if (!saved) { context->save(); saved = true; } context->setAlpha(1); } - if (state().m_globalComposite != CompositeSourceOver) { + if (state().globalComposite != CompositeSourceOver) { if (!saved) { context->save(); saved = true; @@ -1062,16 +1167,16 @@ void CanvasRenderingContext2D::fillRect(float x, float y, float width, float hei if (!validateRectForCanvas(x, y, width, height)) return; - GraphicsContext* c = drawingContext(); + auto* c = drawingContext(); if (!c) return; - if (!state().m_hasInvertibleTransform) + if (!state().hasInvertibleTransform) return; // from the HTML5 Canvas spec: // If x0 = x1 and y0 = y1, then the linear gradient must paint nothing // If x0 = x1 and y0 = y1 and r0 = r1, then the radial gradient must paint nothing - Gradient* gradient = c->fillGradient(); + auto* gradient = c->fillGradient(); if (gradient && gradient->isZeroSize()) return; @@ -1080,10 +1185,12 @@ void CanvasRenderingContext2D::fillRect(float x, float y, float width, float hei if (rectContainsCanvas(rect)) { c->fillRect(rect); didDrawEntireCanvas(); - } else if (isFullCanvasCompositeMode(state().m_globalComposite)) { - fullCanvasCompositedFill(rect); + } else if (isFullCanvasCompositeMode(state().globalComposite)) { + beginCompositeLayer(); + c->fillRect(rect); + endCompositeLayer(); didDrawEntireCanvas(); - } else if (state().m_globalComposite == CompositeCopy) { + } else if (state().globalComposite == CompositeCopy) { clearCanvas(); c->fillRect(rect); didDrawEntireCanvas(); @@ -1098,67 +1205,62 @@ void CanvasRenderingContext2D::strokeRect(float x, float y, float width, float h if (!validateRectForCanvas(x, y, width, height)) return; - GraphicsContext* c = drawingContext(); + auto* c = drawingContext(); if (!c) return; - if (!state().m_hasInvertibleTransform) + if (!state().hasInvertibleTransform) return; - if (!(state().m_lineWidth >= 0)) + if (!(state().lineWidth >= 0)) return; // If gradient size is zero, then paint nothing. - Gradient* gradient = c->strokeGradient(); + auto* gradient = c->strokeGradient(); if (gradient && gradient->isZeroSize()) return; FloatRect rect(x, y, width, height); - - FloatRect boundingRect = rect; - boundingRect.inflate(state().m_lineWidth / 2); - - c->strokeRect(rect, state().m_lineWidth); - didDraw(boundingRect); -} - -void CanvasRenderingContext2D::setShadow(float width, float height, float blur) -{ - setShadow(FloatSize(width, height), blur, Color::transparent); -} - -void CanvasRenderingContext2D::setShadow(float width, float height, float blur, const String& color) -{ - RGBA32 rgba; - if (!parseColorOrCurrentColor(rgba, color, canvas())) - return; - setShadow(FloatSize(width, height), blur, rgba); -} - -void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float grayLevel) -{ - setShadow(FloatSize(width, height), blur, makeRGBA32FromFloats(grayLevel, grayLevel, grayLevel, 1)); + if (isFullCanvasCompositeMode(state().globalComposite)) { + beginCompositeLayer(); + c->strokeRect(rect, state().lineWidth); + endCompositeLayer(); + didDrawEntireCanvas(); + } else if (state().globalComposite == CompositeCopy) { + clearCanvas(); + c->strokeRect(rect, state().lineWidth); + didDrawEntireCanvas(); + } else { + FloatRect boundingRect = rect; + boundingRect.inflate(state().lineWidth / 2); + c->strokeRect(rect, state().lineWidth); + didDraw(boundingRect); + } } -void CanvasRenderingContext2D::setShadow(float width, float height, float blur, const String& color, float alpha) +void CanvasRenderingContext2D::setShadow(float width, float height, float blur, const String& colorString, std::optional<float> alpha) { - RGBA32 rgba; - if (!parseColorOrCurrentColor(rgba, color, canvas())) - return; - setShadow(FloatSize(width, height), blur, colorWithOverrideAlpha(rgba, alpha)); + Color color = Color::transparent; + if (!colorString.isNull()) { + color = parseColorOrCurrentColor(colorString, &canvas()); + if (!color.isValid()) + return; + } + // FIXME: Should not use RGBA32 here. + setShadow(FloatSize(width, height), blur, colorWithOverrideAlpha(color.rgb(), alpha)); } void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float grayLevel, float alpha) { - setShadow(FloatSize(width, height), blur, makeRGBA32FromFloats(grayLevel, grayLevel, grayLevel, alpha)); + setShadow(FloatSize(width, height), blur, Color(grayLevel, grayLevel, grayLevel, alpha)); } void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float r, float g, float b, float a) { - setShadow(FloatSize(width, height), blur, makeRGBA32FromFloats(r, g, b, a)); + setShadow(FloatSize(width, height), blur, Color(r, g, b, a)); } void CanvasRenderingContext2D::setShadow(float width, float height, float blur, float c, float m, float y, float k, float a) { - setShadow(FloatSize(width, height), blur, makeRGBAFromCMYKA(c, m, y, k, a)); + setShadow(FloatSize(width, height), blur, Color(c, m, y, k, a)); } void CanvasRenderingContext2D::clearShadow() @@ -1166,15 +1268,15 @@ void CanvasRenderingContext2D::clearShadow() setShadow(FloatSize(), 0, Color::transparent); } -void CanvasRenderingContext2D::setShadow(const FloatSize& offset, float blur, RGBA32 color) +void CanvasRenderingContext2D::setShadow(const FloatSize& offset, float blur, const Color& color) { - if (state().m_shadowOffset == offset && state().m_shadowBlur == blur && state().m_shadowColor == color) + if (state().shadowOffset == offset && state().shadowBlur == blur && state().shadowColor == color) return; bool wasDrawingShadows = shouldDrawShadows(); realizeSaves(); - modifiableState().m_shadowOffset = offset; - modifiableState().m_shadowBlur = blur; - modifiableState().m_shadowColor = color; + modifiableState().shadowOffset = offset; + modifiableState().shadowBlur = blur; + modifiableState().shadowColor = color; if (!wasDrawingShadows && !shouldDrawShadows()) return; applyShadow(); @@ -1182,37 +1284,50 @@ void CanvasRenderingContext2D::setShadow(const FloatSize& offset, float blur, RG void CanvasRenderingContext2D::applyShadow() { - GraphicsContext* c = drawingContext(); + auto* c = drawingContext(); if (!c) return; if (shouldDrawShadows()) { - float width = state().m_shadowOffset.width(); - float height = state().m_shadowOffset.height(); - c->setLegacyShadow(FloatSize(width, -height), state().m_shadowBlur, state().m_shadowColor, ColorSpaceDeviceRGB); + float width = state().shadowOffset.width(); + float height = state().shadowOffset.height(); + c->setLegacyShadow(FloatSize(width, -height), state().shadowBlur, state().shadowColor); } else - c->setLegacyShadow(FloatSize(), 0, Color::transparent, ColorSpaceDeviceRGB); + c->setLegacyShadow(FloatSize(), 0, Color::transparent); } bool CanvasRenderingContext2D::shouldDrawShadows() const { - return alphaChannel(state().m_shadowColor) && (state().m_shadowBlur || !state().m_shadowOffset.isZero()); + return state().shadowColor.isVisible() && (state().shadowBlur || !state().shadowOffset.isZero()); +} + +enum class ImageSizeType { AfterDevicePixelRatio, BeforeDevicePixelRatio }; +static LayoutSize size(HTMLImageElement& element, ImageSizeType sizeType = ImageSizeType::BeforeDevicePixelRatio) +{ + LayoutSize size; + if (auto* cachedImage = element.cachedImage()) { + size = cachedImage->imageSizeForRenderer(element.renderer(), 1.0f); // FIXME: Not sure about this. + if (sizeType == ImageSizeType::AfterDevicePixelRatio && is<RenderImage>(element.renderer()) && cachedImage->image() && !cachedImage->image()->hasRelativeWidth()) + size.scale(downcast<RenderImage>(*element.renderer()).imageDevicePixelRatio()); + } + return size; } -static LayoutSize size(HTMLImageElement* image) +static inline FloatSize size(HTMLCanvasElement& canvasElement) { - if (CachedImage* cachedImage = image->cachedImage()) - return cachedImage->imageSizeForRenderer(image->renderer(), 1.0f); // FIXME: Not sure about this. - return IntSize(); + return canvasElement.size(); } #if ENABLE(VIDEO) -static IntSize size(HTMLVideoElement* video) + +static inline FloatSize size(HTMLVideoElement& video) { - if (MediaPlayer* player = video->player()) - return player->naturalSize(); - return IntSize(); + auto* player = video.player(); + if (!player) + return { }; + return player->naturalSize(); } + #endif static inline FloatRect normalizeRect(const FloatRect& rect) @@ -1223,248 +1338,208 @@ static inline FloatRect normalizeRect(const FloatRect& rect) std::max(rect.height(), -rect.height())); } -void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, float x, float y, ExceptionCode& ec) +ExceptionOr<void> CanvasRenderingContext2D::drawImage(CanvasImageSource&& image, float dx, float dy) { - if (!image) { - ec = TYPE_MISMATCH_ERR; - return; - } - LayoutSize s = size(image); - drawImage(image, x, y, s.width(), s.height(), ec); + return WTF::switchOn(image, + [&] (RefPtr<HTMLImageElement>& imageElement) -> ExceptionOr<void> { + LayoutSize destRectSize = size(*imageElement, ImageSizeType::AfterDevicePixelRatio); + LayoutSize sourceRectSize = size(*imageElement, ImageSizeType::BeforeDevicePixelRatio); + return this->drawImage(*imageElement, FloatRect { 0, 0, sourceRectSize.width(), sourceRectSize.height() }, FloatRect { dx, dy, destRectSize.width(), destRectSize.height() }); + }, + [&] (auto& element) -> ExceptionOr<void> { + FloatSize elementSize = size(*element); + return this->drawImage(*element, FloatRect { 0, 0, elementSize.width(), elementSize.height() }, FloatRect { dx, dy, elementSize.width(), elementSize.height() }); + } + ); } -void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, - float x, float y, float width, float height, ExceptionCode& ec) +ExceptionOr<void> CanvasRenderingContext2D::drawImage(CanvasImageSource&& image, float dx, float dy, float dw, float dh) { - if (!image) { - ec = TYPE_MISMATCH_ERR; - return; - } - LayoutSize s = size(image); - drawImage(image, FloatRect(0, 0, s.width(), s.height()), FloatRect(x, y, width, height), ec); + return WTF::switchOn(image, + [&] (auto& element) -> ExceptionOr<void> { + FloatSize elementSize = size(*element); + return this->drawImage(*element, FloatRect { 0, 0, elementSize.width(), elementSize.height() }, FloatRect { dx, dy, dw, dh }); + } + ); } -void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, - float sx, float sy, float sw, float sh, - float dx, float dy, float dw, float dh, ExceptionCode& ec) +ExceptionOr<void> CanvasRenderingContext2D::drawImage(CanvasImageSource&& image, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh) { - drawImage(image, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), ec); + return WTF::switchOn(image, + [&] (auto& element) -> ExceptionOr<void> { + return this->drawImage(*element, FloatRect { sx, sy, sw, sh }, FloatRect { dx, dy, dw, dh }); + } + ); } -void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionCode& ec) +ExceptionOr<void> CanvasRenderingContext2D::drawImage(HTMLImageElement& imageElement, const FloatRect& srcRect, const FloatRect& dstRect) { - drawImage(image, srcRect, dstRect, state().m_globalComposite, state().m_globalBlend, ec); + return drawImage(imageElement, srcRect, dstRect, state().globalComposite, state().globalBlend); } -void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator& op, const BlendMode& blendMode, ExceptionCode& ec) +ExceptionOr<void> CanvasRenderingContext2D::drawImage(HTMLImageElement& imageElement, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator& op, const BlendMode& blendMode) { - if (!image) { - ec = TYPE_MISMATCH_ERR; - return; - } - - ec = 0; - if (!std::isfinite(dstRect.x()) || !std::isfinite(dstRect.y()) || !std::isfinite(dstRect.width()) || !std::isfinite(dstRect.height()) || !std::isfinite(srcRect.x()) || !std::isfinite(srcRect.y()) || !std::isfinite(srcRect.width()) || !std::isfinite(srcRect.height())) - return; + return { }; if (!dstRect.width() || !dstRect.height()) - return; + return { }; - if (!image->complete()) - return; + if (!imageElement.complete()) + return { }; FloatRect normalizedSrcRect = normalizeRect(srcRect); FloatRect normalizedDstRect = normalizeRect(dstRect); - FloatRect imageRect = FloatRect(FloatPoint(), size(image)); - if (!srcRect.width() || !srcRect.height()) { - ec = INDEX_SIZE_ERR; - return; + FloatRect imageRect = FloatRect(FloatPoint(), size(imageElement, ImageSizeType::BeforeDevicePixelRatio)); + if (!srcRect.width() || !srcRect.height()) + return Exception { INDEX_SIZE_ERR }; + + // When the source rectangle is outside the source image, the source rectangle must be clipped + // to the source image and the destination rectangle must be clipped in the same proportion. + FloatRect originalNormalizedSrcRect = normalizedSrcRect; + normalizedSrcRect.intersect(imageRect); + if (normalizedSrcRect.isEmpty()) + return { }; + + if (normalizedSrcRect != originalNormalizedSrcRect) { + normalizedDstRect.setWidth(normalizedDstRect.width() * normalizedSrcRect.width() / originalNormalizedSrcRect.width()); + normalizedDstRect.setHeight(normalizedDstRect.height() * normalizedSrcRect.height() / originalNormalizedSrcRect.height()); + if (normalizedDstRect.isEmpty()) + return { }; } - if (!imageRect.contains(normalizedSrcRect)) - return; GraphicsContext* c = drawingContext(); if (!c) - return; - if (!state().m_hasInvertibleTransform) - return; + return { }; + if (!state().hasInvertibleTransform) + return { }; - CachedImage* cachedImage = image->cachedImage(); + CachedImage* cachedImage = imageElement.cachedImage(); if (!cachedImage) - return; + return { }; + + Image* image = cachedImage->imageForRenderer(imageElement.renderer()); + if (!image) + return { }; + + ImageObserver* observer = image->imageObserver(); + + if (image->isSVGImage()) { + image->setImageObserver(nullptr); + image->setContainerSize(imageRect.size()); + } if (rectContainsCanvas(normalizedDstRect)) { - c->drawImage(cachedImage->imageForRenderer(image->renderer()), ColorSpaceDeviceRGB, normalizedDstRect, normalizedSrcRect, op, blendMode, ImageOrientationDescription()); + c->drawImage(*image, normalizedDstRect, normalizedSrcRect, ImagePaintingOptions(op, blendMode)); didDrawEntireCanvas(); } else if (isFullCanvasCompositeMode(op)) { - fullCanvasCompositedDrawImage(cachedImage->imageForRenderer(image->renderer()), ColorSpaceDeviceRGB, normalizedDstRect, normalizedSrcRect, op); + fullCanvasCompositedDrawImage(*image, normalizedDstRect, normalizedSrcRect, op); didDrawEntireCanvas(); } else if (op == CompositeCopy) { clearCanvas(); - c->drawImage(cachedImage->imageForRenderer(image->renderer()), ColorSpaceDeviceRGB, normalizedDstRect, normalizedSrcRect, op, blendMode, ImageOrientationDescription()); + c->drawImage(*image, normalizedDstRect, normalizedSrcRect, ImagePaintingOptions(op, blendMode)); didDrawEntireCanvas(); } else { - c->drawImage(cachedImage->imageForRenderer(image->renderer()), ColorSpaceDeviceRGB, normalizedDstRect, normalizedSrcRect, op, blendMode, ImageOrientationDescription()); + c->drawImage(*image, normalizedDstRect, normalizedSrcRect, ImagePaintingOptions(op, blendMode)); didDraw(normalizedDstRect); } + + if (image->isSVGImage()) + image->setImageObserver(observer); - checkOrigin(image); -} - -void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, float x, float y, ExceptionCode& ec) -{ - drawImage(sourceCanvas, 0, 0, sourceCanvas->width(), sourceCanvas->height(), x, y, sourceCanvas->width(), sourceCanvas->height(), ec); -} + checkOrigin(&imageElement); -void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, - float x, float y, float width, float height, ExceptionCode& ec) -{ - drawImage(sourceCanvas, FloatRect(0, 0, sourceCanvas->width(), sourceCanvas->height()), FloatRect(x, y, width, height), ec); -} - -void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, - float sx, float sy, float sw, float sh, - float dx, float dy, float dw, float dh, ExceptionCode& ec) -{ - drawImage(sourceCanvas, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), ec); + return { }; } -void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, const FloatRect& srcRect, - const FloatRect& dstRect, ExceptionCode& ec) +ExceptionOr<void> CanvasRenderingContext2D::drawImage(HTMLCanvasElement& sourceCanvas, const FloatRect& srcRect, const FloatRect& dstRect) { - if (!sourceCanvas) { - ec = TYPE_MISMATCH_ERR; - return; - } + FloatRect srcCanvasRect = FloatRect(FloatPoint(), sourceCanvas.size()); - FloatRect srcCanvasRect = FloatRect(FloatPoint(), sourceCanvas->size()); - - if (!srcCanvasRect.width() || !srcCanvasRect.height()) { - ec = INVALID_STATE_ERR; - return; - } - - if (!srcRect.width() || !srcRect.height()) { - ec = INDEX_SIZE_ERR; - return; - } + if (!srcCanvasRect.width() || !srcCanvasRect.height()) + return Exception { INVALID_STATE_ERR }; - ec = 0; + if (!srcRect.width() || !srcRect.height()) + return Exception { INDEX_SIZE_ERR }; if (!srcCanvasRect.contains(normalizeRect(srcRect)) || !dstRect.width() || !dstRect.height()) - return; + return { }; GraphicsContext* c = drawingContext(); if (!c) - return; - if (!state().m_hasInvertibleTransform) - return; + return { }; + if (!state().hasInvertibleTransform) + return { }; // FIXME: Do this through platform-independent GraphicsContext API. - ImageBuffer* buffer = sourceCanvas->buffer(); + ImageBuffer* buffer = sourceCanvas.buffer(); if (!buffer) - return; + return { }; - checkOrigin(sourceCanvas); + checkOrigin(&sourceCanvas); #if ENABLE(ACCELERATED_2D_CANVAS) - // If we're drawing from one accelerated canvas 2d to another, avoid calling sourceCanvas->makeRenderingResultsAvailable() + // If we're drawing from one accelerated canvas 2d to another, avoid calling sourceCanvas.makeRenderingResultsAvailable() // as that will do a readback to software. - CanvasRenderingContext* sourceContext = sourceCanvas->renderingContext(); + CanvasRenderingContext* sourceContext = sourceCanvas.renderingContext(); // FIXME: Implement an accelerated path for drawing from a WebGL canvas to a 2d canvas when possible. if (!isAccelerated() || !sourceContext || !sourceContext->isAccelerated() || !sourceContext->is2d()) - sourceCanvas->makeRenderingResultsAvailable(); + sourceCanvas.makeRenderingResultsAvailable(); #else - sourceCanvas->makeRenderingResultsAvailable(); + sourceCanvas.makeRenderingResultsAvailable(); #endif if (rectContainsCanvas(dstRect)) { - c->drawImageBuffer(buffer, ColorSpaceDeviceRGB, dstRect, srcRect, state().m_globalComposite, state().m_globalBlend); + c->drawImageBuffer(*buffer, dstRect, srcRect, ImagePaintingOptions(state().globalComposite, state().globalBlend)); didDrawEntireCanvas(); - } else if (isFullCanvasCompositeMode(state().m_globalComposite)) { - fullCanvasCompositedDrawImage(buffer, ColorSpaceDeviceRGB, dstRect, srcRect, state().m_globalComposite); + } else if (isFullCanvasCompositeMode(state().globalComposite)) { + fullCanvasCompositedDrawImage(*buffer, dstRect, srcRect, state().globalComposite); didDrawEntireCanvas(); - } else if (state().m_globalComposite == CompositeCopy) { + } else if (state().globalComposite == CompositeCopy) { clearCanvas(); - c->drawImageBuffer(buffer, ColorSpaceDeviceRGB, dstRect, srcRect, state().m_globalComposite, state().m_globalBlend); + c->drawImageBuffer(*buffer, dstRect, srcRect, ImagePaintingOptions(state().globalComposite, state().globalBlend)); didDrawEntireCanvas(); } else { - c->drawImageBuffer(buffer, ColorSpaceDeviceRGB, dstRect, srcRect, state().m_globalComposite, state().m_globalBlend); + c->drawImageBuffer(*buffer, dstRect, srcRect, ImagePaintingOptions(state().globalComposite, state().globalBlend)); didDraw(dstRect); } -} -#if ENABLE(VIDEO) -void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, float x, float y, ExceptionCode& ec) -{ - if (!video) { - ec = TYPE_MISMATCH_ERR; - return; - } - IntSize s = size(video); - drawImage(video, x, y, s.width(), s.height(), ec); -} - -void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, - float x, float y, float width, float height, ExceptionCode& ec) -{ - if (!video) { - ec = TYPE_MISMATCH_ERR; - return; - } - IntSize s = size(video); - drawImage(video, FloatRect(0, 0, s.width(), s.height()), FloatRect(x, y, width, height), ec); + return { }; } -void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, - float sx, float sy, float sw, float sh, - float dx, float dy, float dw, float dh, ExceptionCode& ec) -{ - drawImage(video, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), ec); -} +#if ENABLE(VIDEO) -void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, const FloatRect& srcRect, const FloatRect& dstRect, - ExceptionCode& ec) +ExceptionOr<void> CanvasRenderingContext2D::drawImage(HTMLVideoElement& video, const FloatRect& srcRect, const FloatRect& dstRect) { - if (!video) { - ec = TYPE_MISMATCH_ERR; - return; - } - - ec = 0; - - if (video->readyState() == HTMLMediaElement::HAVE_NOTHING || video->readyState() == HTMLMediaElement::HAVE_METADATA) - return; + if (video.readyState() == HTMLMediaElement::HAVE_NOTHING || video.readyState() == HTMLMediaElement::HAVE_METADATA) + return { }; FloatRect videoRect = FloatRect(FloatPoint(), size(video)); - if (!srcRect.width() || !srcRect.height()) { - ec = INDEX_SIZE_ERR; - return; - } + if (!srcRect.width() || !srcRect.height()) + return Exception { INDEX_SIZE_ERR }; if (!videoRect.contains(normalizeRect(srcRect)) || !dstRect.width() || !dstRect.height()) - return; + return { }; GraphicsContext* c = drawingContext(); if (!c) - return; - if (!state().m_hasInvertibleTransform) - return; + return { }; + if (!state().hasInvertibleTransform) + return { }; - checkOrigin(video); + checkOrigin(&video); -#if USE(CG) - if (PassNativeImagePtr image = video->nativeImageForCurrentTime()) { - c->drawNativeImage(image, FloatSize(video->videoWidth(), video->videoHeight()), ColorSpaceDeviceRGB, dstRect, srcRect); +#if USE(CG) || (ENABLE(ACCELERATED_2D_CANVAS) && USE(GSTREAMER_GL) && USE(CAIRO)) + if (NativeImagePtr image = video.nativeImageForCurrentTime()) { + c->drawNativeImage(image, FloatSize(video.videoWidth(), video.videoHeight()), dstRect, srcRect); if (rectContainsCanvas(dstRect)) didDrawEntireCanvas(); else didDraw(dstRect); - return; + return { }; } #endif @@ -1473,23 +1548,22 @@ void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, const FloatRec c->translate(dstRect.x(), dstRect.y()); c->scale(FloatSize(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height())); c->translate(-srcRect.x(), -srcRect.y()); - video->paintCurrentFrameInContext(c, IntRect(IntPoint(), size(video))); + video.paintCurrentFrameInContext(*c, FloatRect(FloatPoint(), size(video))); stateSaver.restore(); didDraw(dstRect); + + return { }; } + #endif -void CanvasRenderingContext2D::drawImageFromRect(HTMLImageElement* image, - float sx, float sy, float sw, float sh, - float dx, float dy, float dw, float dh, - const String& compositeOperation) +void CanvasRenderingContext2D::drawImageFromRect(HTMLImageElement& imageElement, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, const String& compositeOperation) { CompositeOperator op; - BlendMode blendOp = BlendModeNormal; + auto blendOp = BlendModeNormal; if (!parseCompositeAndBlendOperator(compositeOperation, op, blendOp) || blendOp != BlendModeNormal) op = CompositeSourceOver; - - drawImage(image, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), op, BlendModeNormal, IGNORE_EXCEPTION); + drawImage(imageElement, FloatRect { sx, sy, sw, sh }, FloatRect { dx, dy, dw, dh }, op, BlendModeNormal); } void CanvasRenderingContext2D::setAlpha(float alpha) @@ -1504,22 +1578,21 @@ void CanvasRenderingContext2D::setCompositeOperation(const String& operation) void CanvasRenderingContext2D::clearCanvas() { - FloatRect canvasRect(0, 0, canvas()->width(), canvas()->height()); - GraphicsContext* c = drawingContext(); + auto* c = drawingContext(); if (!c) return; c->save(); - c->setCTM(canvas()->baseTransform()); - c->clearRect(canvasRect); + c->setCTM(canvas().baseTransform()); + c->clearRect(FloatRect(0, 0, canvas().width(), canvas().height())); c->restore(); } Path CanvasRenderingContext2D::transformAreaToDevice(const Path& path) const { Path transformed(path); - transformed.transform(state().m_transform); - transformed.transform(canvas()->baseTransform()); + transformed.transform(state().transform); + transformed.transform(canvas().baseTransform()); return transformed; } @@ -1533,14 +1606,14 @@ Path CanvasRenderingContext2D::transformAreaToDevice(const FloatRect& rect) cons bool CanvasRenderingContext2D::rectContainsCanvas(const FloatRect& rect) const { FloatQuad quad(rect); - FloatQuad canvasQuad(FloatRect(0, 0, canvas()->width(), canvas()->height())); - return state().m_transform.mapQuad(quad).containsQuad(canvasQuad); + FloatQuad canvasQuad(FloatRect(0, 0, canvas().width(), canvas().height())); + return state().transform.mapQuad(quad).containsQuad(canvasQuad); } template<class T> IntRect CanvasRenderingContext2D::calculateCompositingBufferRect(const T& area, IntSize* croppedOffset) { - IntRect canvasRect(0, 0, canvas()->width(), canvas()->height()); - canvasRect = canvas()->baseTransform().mapRect(canvasRect); + IntRect canvasRect(0, 0, canvas().width(), canvas().height()); + canvasRect = canvas().baseTransform().mapRect(canvasRect); Path path = transformAreaToDevice(area); IntRect bufferRect = enclosingIntRect(path.fastBoundingRect()); IntPoint originalLocation = bufferRect.location(); @@ -1552,16 +1625,15 @@ template<class T> IntRect CanvasRenderingContext2D::calculateCompositingBufferRe std::unique_ptr<ImageBuffer> CanvasRenderingContext2D::createCompositingBuffer(const IntRect& bufferRect) { - RenderingMode renderMode = isAccelerated() ? Accelerated : Unaccelerated; - return ImageBuffer::create(bufferRect.size(), 1, ColorSpaceDeviceRGB, renderMode); + return ImageBuffer::create(bufferRect.size(), isAccelerated() ? Accelerated : Unaccelerated); } -void CanvasRenderingContext2D::compositeBuffer(ImageBuffer* buffer, const IntRect& bufferRect, CompositeOperator op) +void CanvasRenderingContext2D::compositeBuffer(ImageBuffer& buffer, const IntRect& bufferRect, CompositeOperator op) { - IntRect canvasRect(0, 0, canvas()->width(), canvas()->height()); - canvasRect = canvas()->baseTransform().mapRect(canvasRect); + IntRect canvasRect(0, 0, canvas().width(), canvas().height()); + canvasRect = canvas().baseTransform().mapRect(canvasRect); - GraphicsContext* c = drawingContext(); + auto* c = drawingContext(); if (!c) return; @@ -1573,37 +1645,36 @@ void CanvasRenderingContext2D::compositeBuffer(ImageBuffer* buffer, const IntRec c->clipOut(bufferRect); c->clearRect(canvasRect); c->restore(); - - c->drawImageBuffer(buffer, ColorSpaceDeviceRGB, bufferRect.location(), state().m_globalComposite); + c->drawImageBuffer(buffer, bufferRect.location(), state().globalComposite); c->restore(); } -static void drawImageToContext(Image* image, GraphicsContext* context, ColorSpace styleColorSpace, const FloatRect& dest, const FloatRect& src, CompositeOperator op) +static void drawImageToContext(Image& image, GraphicsContext& context, const FloatRect& dest, const FloatRect& src, CompositeOperator op) { - context->drawImage(image, styleColorSpace, dest, src, op, ImageOrientationDescription()); + context.drawImage(image, dest, src, op); } -static void drawImageToContext(ImageBuffer* imageBuffer, GraphicsContext* context, ColorSpace styleColorSpace, const FloatRect& dest, const FloatRect& src, CompositeOperator op) +static void drawImageToContext(ImageBuffer& imageBuffer, GraphicsContext& context, const FloatRect& dest, const FloatRect& src, CompositeOperator op) { - context->drawImageBuffer(imageBuffer, styleColorSpace, dest, src, op); + context.drawImageBuffer(imageBuffer, dest, src, op); } -template<class T> void CanvasRenderingContext2D::fullCanvasCompositedDrawImage(T* image, ColorSpace styleColorSpace, const FloatRect& dest, const FloatRect& src, CompositeOperator op) +template<class T> void CanvasRenderingContext2D::fullCanvasCompositedDrawImage(T& image, const FloatRect& dest, const FloatRect& src, CompositeOperator op) { ASSERT(isFullCanvasCompositeMode(op)); IntSize croppedOffset; - IntRect bufferRect = calculateCompositingBufferRect(dest, &croppedOffset); + auto bufferRect = calculateCompositingBufferRect(dest, &croppedOffset); if (bufferRect.isEmpty()) { clearCanvas(); return; } - std::unique_ptr<ImageBuffer> buffer = createCompositingBuffer(bufferRect); + auto buffer = createCompositingBuffer(bufferRect); if (!buffer) return; - GraphicsContext* c = drawingContext(); + auto* c = drawingContext(); if (!c) return; @@ -1611,142 +1682,172 @@ template<class T> void CanvasRenderingContext2D::fullCanvasCompositedDrawImage( adjustedDest.setLocation(FloatPoint(0, 0)); AffineTransform effectiveTransform = c->getCTM(); IntRect transformedAdjustedRect = enclosingIntRect(effectiveTransform.mapRect(adjustedDest)); - buffer->context()->translate(-transformedAdjustedRect.location().x(), -transformedAdjustedRect.location().y()); - buffer->context()->translate(croppedOffset.width(), croppedOffset.height()); - buffer->context()->concatCTM(effectiveTransform); - drawImageToContext(image, buffer->context(), styleColorSpace, adjustedDest, src, CompositeSourceOver); + buffer->context().translate(-transformedAdjustedRect.location().x(), -transformedAdjustedRect.location().y()); + buffer->context().translate(croppedOffset.width(), croppedOffset.height()); + buffer->context().concatCTM(effectiveTransform); + drawImageToContext(image, buffer->context(), adjustedDest, src, CompositeSourceOver); - compositeBuffer(buffer.get(), bufferRect, op); + compositeBuffer(*buffer, bufferRect, op); } -template<class T> void CanvasRenderingContext2D::fullCanvasCompositedFill(const T& area) +void CanvasRenderingContext2D::prepareGradientForDashboard(CanvasGradient& gradient) const { - ASSERT(isFullCanvasCompositeMode(state().m_globalComposite)); - - IntRect bufferRect = calculateCompositingBufferRect(area, 0); - if (bufferRect.isEmpty()) { - clearCanvas(); - return; - } +#if ENABLE(DASHBOARD_SUPPORT) + if (m_usesDashboardCompatibilityMode) + gradient.setDashboardCompatibilityMode(); +#else + UNUSED_PARAM(gradient); +#endif +} - std::unique_ptr<ImageBuffer> buffer = createCompositingBuffer(bufferRect); - if (!buffer) - return; +static CanvasRenderingContext2D::Style toStyle(const CanvasStyle& style) +{ + if (auto* gradient = style.canvasGradient()) + return RefPtr<CanvasGradient> { gradient }; + if (auto* pattern = style.canvasPattern()) + return RefPtr<CanvasPattern> { pattern }; + return style.color(); +} - Path path = transformAreaToDevice(area); - path.translate(FloatSize(-bufferRect.x(), -bufferRect.y())); +CanvasRenderingContext2D::Style CanvasRenderingContext2D::strokeStyle() const +{ + return toStyle(state().strokeStyle); +} - buffer->context()->setCompositeOperation(CompositeSourceOver); - modifiableState().m_fillStyle.applyFillColor(buffer->context()); - buffer->context()->fillPath(path); +void CanvasRenderingContext2D::setStrokeStyle(CanvasRenderingContext2D::Style&& style) +{ + WTF::switchOn(style, + [this] (const String& string) { this->setStrokeColor(string); }, + [this] (const RefPtr<CanvasGradient>& gradient) { this->setStrokeStyle(CanvasStyle(*gradient)); }, + [this] (const RefPtr<CanvasPattern>& pattern) { this->setStrokeStyle(CanvasStyle(*pattern)); } + ); +} - compositeBuffer(buffer.get(), bufferRect, state().m_globalComposite); +CanvasRenderingContext2D::Style CanvasRenderingContext2D::fillStyle() const +{ + return toStyle(state().fillStyle); } -void CanvasRenderingContext2D::prepareGradientForDashboard(CanvasGradient* gradient) const +void CanvasRenderingContext2D::setFillStyle(CanvasRenderingContext2D::Style&& style) { -#if ENABLE(DASHBOARD_SUPPORT) - if (m_usesDashboardCompatibilityMode) - gradient->setDashboardCompatibilityMode(); -#else - UNUSED_PARAM(gradient); -#endif + WTF::switchOn(style, + [this] (const String& string) { this->setFillColor(string); }, + [this] (const RefPtr<CanvasGradient>& gradient) { this->setFillStyle(CanvasStyle(*gradient)); }, + [this] (const RefPtr<CanvasPattern>& pattern) { this->setFillStyle(CanvasStyle(*pattern)); } + ); } -PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createLinearGradient(float x0, float y0, float x1, float y1, ExceptionCode& ec) +ExceptionOr<Ref<CanvasGradient>> CanvasRenderingContext2D::createLinearGradient(float x0, float y0, float x1, float y1) { - if (!std::isfinite(x0) || !std::isfinite(y0) || !std::isfinite(x1) || !std::isfinite(y1)) { - ec = NOT_SUPPORTED_ERR; - return 0; - } + if (!std::isfinite(x0) || !std::isfinite(y0) || !std::isfinite(x1) || !std::isfinite(y1)) + return Exception { NOT_SUPPORTED_ERR }; - RefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), FloatPoint(x1, y1)); + auto gradient = CanvasGradient::create(FloatPoint(x0, y0), FloatPoint(x1, y1)); prepareGradientForDashboard(gradient.get()); - return gradient.release(); + return WTFMove(gradient); } -PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1, ExceptionCode& ec) +ExceptionOr<Ref<CanvasGradient>> CanvasRenderingContext2D::createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1) { - if (!std::isfinite(x0) || !std::isfinite(y0) || !std::isfinite(r0) || !std::isfinite(x1) || !std::isfinite(y1) || !std::isfinite(r1)) { - ec = NOT_SUPPORTED_ERR; - return 0; - } + if (!std::isfinite(x0) || !std::isfinite(y0) || !std::isfinite(r0) || !std::isfinite(x1) || !std::isfinite(y1) || !std::isfinite(r1)) + return Exception { NOT_SUPPORTED_ERR }; - if (r0 < 0 || r1 < 0) { - ec = INDEX_SIZE_ERR; - return 0; - } + if (r0 < 0 || r1 < 0) + return Exception { INDEX_SIZE_ERR }; - RefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), r0, FloatPoint(x1, y1), r1); + auto gradient = CanvasGradient::create(FloatPoint(x0, y0), r0, FloatPoint(x1, y1), r1); prepareGradientForDashboard(gradient.get()); - return gradient.release(); + return WTFMove(gradient); } -PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLImageElement* image, - const String& repetitionType, ExceptionCode& ec) +ExceptionOr<RefPtr<CanvasPattern>> CanvasRenderingContext2D::createPattern(CanvasImageSource&& image, const String& repetition) { - if (!image) { - ec = TYPE_MISMATCH_ERR; - return 0; - } bool repeatX, repeatY; - ec = 0; - CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, ec); - if (ec) - return 0; + if (!CanvasPattern::parseRepetitionType(repetition, repeatX, repeatY)) + return Exception { SYNTAX_ERR }; + + return WTF::switchOn(image, + [&] (auto& element) -> ExceptionOr<RefPtr<CanvasPattern>> { return this->createPattern(*element, repeatX, repeatY); } + ); +} + +ExceptionOr<RefPtr<CanvasPattern>> CanvasRenderingContext2D::createPattern(HTMLImageElement& imageElement, bool repeatX, bool repeatY) +{ + auto* cachedImage = imageElement.cachedImage(); - if (!image->complete()) - return 0; + // If the image loading hasn't started or the image is not complete, it is not fully decodable. + if (!cachedImage || !imageElement.complete()) + return nullptr; - CachedImage* cachedImage = image->cachedImage(); - if (!cachedImage || !image->cachedImage()->imageForRenderer(image->renderer())) - return CanvasPattern::create(Image::nullImage(), repeatX, repeatY, true); + if (cachedImage->status() == CachedResource::LoadError) + return Exception { INVALID_STATE_ERR }; - bool originClean = cachedImage->isOriginClean(canvas()->securityOrigin()); - return CanvasPattern::create(cachedImage->imageForRenderer(image->renderer()), repeatX, repeatY, originClean); + bool originClean = cachedImage->isOriginClean(canvas().securityOrigin()); + + // FIXME: SVG images with animations can switch between clean and dirty (leaking cross-origin + // data). We should either: + // 1) Take a fixed snapshot of an SVG image when creating a pattern and determine then whether + // the origin is clean. + // 2) Dynamically verify the origin checks at draw time, and dirty the canvas accordingly. + // To be on the safe side, taint the origin for all patterns containing SVG images for now. + if (cachedImage->image()->isSVGImage()) + originClean = false; + + return RefPtr<CanvasPattern> { CanvasPattern::create(*cachedImage->imageForRenderer(imageElement.renderer()), repeatX, repeatY, originClean) }; } -PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLCanvasElement* canvas, - const String& repetitionType, ExceptionCode& ec) +ExceptionOr<RefPtr<CanvasPattern>> CanvasRenderingContext2D::createPattern(HTMLCanvasElement& canvas, bool repeatX, bool repeatY) { - if (!canvas) { - ec = TYPE_MISMATCH_ERR; - return 0; - } - if (!canvas->width() || !canvas->height()) { - ec = INVALID_STATE_ERR; - return 0; - } + if (!canvas.width() || !canvas.height() || !canvas.buffer()) + return Exception { INVALID_STATE_ERR }; - bool repeatX, repeatY; - ec = 0; - CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, ec); - if (ec) - return 0; - return CanvasPattern::create(canvas->copiedImage(), repeatX, repeatY, canvas->originClean()); + return RefPtr<CanvasPattern> { CanvasPattern::create(*canvas.copiedImage(), repeatX, repeatY, canvas.originClean()) }; +} + +#if ENABLE(VIDEO) + +ExceptionOr<RefPtr<CanvasPattern>> CanvasRenderingContext2D::createPattern(HTMLVideoElement& videoElement, bool repeatX, bool repeatY) +{ + if (videoElement.readyState() < HTMLMediaElement::HAVE_CURRENT_DATA) + return nullptr; + + checkOrigin(&videoElement); + bool originClean = canvas().originClean(); + +#if USE(CG) || (ENABLE(ACCELERATED_2D_CANVAS) && USE(GSTREAMER_GL) && USE(CAIRO)) + if (auto nativeImage = videoElement.nativeImageForCurrentTime()) + return RefPtr<CanvasPattern> { CanvasPattern::create(BitmapImage::create(WTFMove(nativeImage)), repeatX, repeatY, originClean) }; +#endif + + auto imageBuffer = ImageBuffer::create(size(videoElement), drawingContext() ? drawingContext()->renderingMode() : Accelerated); + videoElement.paintCurrentFrameInContext(imageBuffer->context(), FloatRect(FloatPoint(), size(videoElement))); + + return RefPtr<CanvasPattern> { CanvasPattern::create(ImageBuffer::sinkIntoImage(WTFMove(imageBuffer), Unscaled).releaseNonNull(), repeatX, repeatY, originClean) }; } +#endif + void CanvasRenderingContext2D::didDrawEntireCanvas() { - didDraw(FloatRect(FloatPoint::zero(), canvas()->size()), CanvasDidDrawApplyClip); + didDraw(FloatRect(FloatPoint::zero(), canvas().size()), CanvasDidDrawApplyClip); } void CanvasRenderingContext2D::didDraw(const FloatRect& r, unsigned options) { - GraphicsContext* c = drawingContext(); + auto* c = drawingContext(); if (!c) return; - if (!state().m_hasInvertibleTransform) + if (!state().hasInvertibleTransform) return; -#if ENABLE(ACCELERATED_2D_CANVAS) && USE(ACCELERATED_COMPOSITING) +#if ENABLE(ACCELERATED_2D_CANVAS) // If we are drawing to hardware and we have a composited layer, just call contentChanged(). if (isAccelerated()) { - RenderBox* renderBox = canvas()->renderBox(); + RenderBox* renderBox = canvas().renderBox(); if (renderBox && renderBox->hasAcceleratedCompositing()) { renderBox->contentChanged(CanvasPixelsChanged); - canvas()->clearCopiedImage(); - canvas()->notifyObserversCanvasChanged(r); + canvas().clearCopiedImage(); + canvas().notifyObserversCanvasChanged(r); return; } } @@ -1754,15 +1855,15 @@ void CanvasRenderingContext2D::didDraw(const FloatRect& r, unsigned options) FloatRect dirtyRect = r; if (options & CanvasDidDrawApplyTransform) { - AffineTransform ctm = state().m_transform; + AffineTransform ctm = state().transform; dirtyRect = ctm.mapRect(r); } - if (options & CanvasDidDrawApplyShadow && alphaChannel(state().m_shadowColor)) { + if (options & CanvasDidDrawApplyShadow && state().shadowColor.isVisible()) { // The shadow gets applied after transformation FloatRect shadowRect(dirtyRect); - shadowRect.move(state().m_shadowOffset); - shadowRect.inflate(state().m_shadowBlur); + shadowRect.move(state().shadowOffset); + shadowRect.inflate(state().shadowBlur); dirtyRect.unite(shadowRect); } @@ -1772,61 +1873,88 @@ void CanvasRenderingContext2D::didDraw(const FloatRect& r, unsigned options) // we'd have to keep the clip path around. } - canvas()->didDraw(dirtyRect); + canvas().didDraw(dirtyRect); } -GraphicsContext* CanvasRenderingContext2D::drawingContext() const +void CanvasRenderingContext2D::setTracksDisplayListReplay(bool tracksDisplayListReplay) { - return canvas()->drawingContext(); + if (tracksDisplayListReplay == m_tracksDisplayListReplay) + return; + + m_tracksDisplayListReplay = tracksDisplayListReplay; + if (!m_tracksDisplayListReplay) + contextDisplayListMap().remove(this); } -static PassRefPtr<ImageData> createEmptyImageData(const IntSize& size) +String CanvasRenderingContext2D::displayListAsText(DisplayList::AsTextFlags flags) const { - Checked<int, RecordOverflow> dataSize = 4; - dataSize *= size.width(); - dataSize *= size.height(); - if (dataSize.hasOverflowed()) - return 0; + if (!m_recordingContext) + return { }; + return m_recordingContext->displayList.asText(flags); +} - RefPtr<ImageData> data = ImageData::create(size); - data->data()->zeroFill(); - return data.release(); +String CanvasRenderingContext2D::replayDisplayListAsText(DisplayList::AsTextFlags flags) const +{ + auto* displayList = contextDisplayListMap().get(this); + if (!displayList) + return { }; + return displayList->asText(flags); } -PassRefPtr<ImageData> CanvasRenderingContext2D::createImageData(PassRefPtr<ImageData> imageData, ExceptionCode& ec) const +void CanvasRenderingContext2D::paintRenderingResultsToCanvas() { - if (!imageData) { - ec = NOT_SUPPORTED_ERR; - return 0; - } + if (UNLIKELY(m_usesDisplayListDrawing)) { + if (!m_recordingContext) + return; - return createEmptyImageData(imageData->size()); + FloatRect clip(FloatPoint::zero(), canvas().size()); + DisplayList::Replayer replayer(*canvas().drawingContext(), m_recordingContext->displayList); + + if (UNLIKELY(m_tracksDisplayListReplay)) { + auto replayList = replayer.replay(clip, m_tracksDisplayListReplay); + contextDisplayListMap().add(this, WTFMove(replayList)); + } else + replayer.replay(clip); + + m_recordingContext->displayList.clear(); + } } -PassRefPtr<ImageData> CanvasRenderingContext2D::createImageData(float sw, float sh, ExceptionCode& ec) const +GraphicsContext* CanvasRenderingContext2D::drawingContext() const { - ec = 0; - if (!sw || !sh) { - ec = INDEX_SIZE_ERR; - return 0; - } - if (!std::isfinite(sw) || !std::isfinite(sh)) { - ec = NOT_SUPPORTED_ERR; - return 0; + if (UNLIKELY(m_usesDisplayListDrawing)) { + if (!m_recordingContext) + m_recordingContext = std::make_unique<DisplayListDrawingContext>(FloatRect(FloatPoint::zero(), canvas().size())); + return &m_recordingContext->context; } -#if PLATFORM(IOS) - // If the canvas element was created before Document had a Frame, - // then no maximumDecodedImageSize was set. - if (!canvas()->maximumDecodedImageSize()) { - if (Settings* settings = canvas()->document().settings()) - canvas()->setMaximumDecodedImageSize(settings->maximumDecodedImageSize()); - } -#endif + return canvas().drawingContext(); +} + +static RefPtr<ImageData> createEmptyImageData(const IntSize& size) +{ + auto data = ImageData::create(size); + if (data) + data->data()->zeroFill(); + return data; +} + +ExceptionOr<RefPtr<ImageData>> CanvasRenderingContext2D::createImageData(ImageData* imageData) const +{ + if (!imageData) + return Exception { NOT_SUPPORTED_ERR }; + + return createEmptyImageData(imageData->size()); +} - FloatSize logicalSize(fabs(sw), fabs(sh)); +ExceptionOr<RefPtr<ImageData>> CanvasRenderingContext2D::createImageData(float sw, float sh) const +{ + if (!sw || !sh) + return Exception { INDEX_SIZE_ERR }; + + FloatSize logicalSize(std::abs(sw), std::abs(sh)); if (!logicalSize.isExpressibleAsIntSize()) - return 0; + return nullptr; IntSize size = expandedIntSize(logicalSize); if (size.width() < 1) @@ -1837,33 +1965,26 @@ PassRefPtr<ImageData> CanvasRenderingContext2D::createImageData(float sw, float return createEmptyImageData(size); } -PassRefPtr<ImageData> CanvasRenderingContext2D::getImageData(float sx, float sy, float sw, float sh, ExceptionCode& ec) const +ExceptionOr<RefPtr<ImageData>> CanvasRenderingContext2D::getImageData(float sx, float sy, float sw, float sh) const { - return getImageData(ImageBuffer::LogicalCoordinateSystem, sx, sy, sw, sh, ec); + return getImageData(ImageBuffer::LogicalCoordinateSystem, sx, sy, sw, sh); } -PassRefPtr<ImageData> CanvasRenderingContext2D::webkitGetImageDataHD(float sx, float sy, float sw, float sh, ExceptionCode& ec) const +ExceptionOr<RefPtr<ImageData>> CanvasRenderingContext2D::webkitGetImageDataHD(float sx, float sy, float sw, float sh) const { - return getImageData(ImageBuffer::BackingStoreCoordinateSystem, sx, sy, sw, sh, ec); + return getImageData(ImageBuffer::BackingStoreCoordinateSystem, sx, sy, sw, sh); } -PassRefPtr<ImageData> CanvasRenderingContext2D::getImageData(ImageBuffer::CoordinateSystem coordinateSystem, float sx, float sy, float sw, float sh, ExceptionCode& ec) const +ExceptionOr<RefPtr<ImageData>> CanvasRenderingContext2D::getImageData(ImageBuffer::CoordinateSystem coordinateSystem, float sx, float sy, float sw, float sh) const { - if (!canvas()->originClean()) { - DEFINE_STATIC_LOCAL(String, consoleMessage, (ASCIILiteral("Unable to get image data from canvas because the canvas has been tainted by cross-origin data."))); - canvas()->document().addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, consoleMessage); - ec = SECURITY_ERR; - return 0; + if (!canvas().originClean()) { + static NeverDestroyed<String> consoleMessage(ASCIILiteral("Unable to get image data from canvas because the canvas has been tainted by cross-origin data.")); + canvas().document().addConsoleMessage(MessageSource::Security, MessageLevel::Error, consoleMessage); + return Exception { SECURITY_ERR }; } - if (!sw || !sh) { - ec = INDEX_SIZE_ERR; - return 0; - } - if (!std::isfinite(sx) || !std::isfinite(sy) || !std::isfinite(sw) || !std::isfinite(sh)) { - ec = NOT_SUPPORTED_ERR; - return 0; - } + if (!sw || !sh) + return Exception { INDEX_SIZE_ERR }; if (sw < 0) { sx += sw; @@ -1874,77 +1995,75 @@ PassRefPtr<ImageData> CanvasRenderingContext2D::getImageData(ImageBuffer::Coordi sh = -sh; } -#if PLATFORM(IOS) - // If the canvas element was created before Document had a Frame, - // then no maximumDecodedImageSize was set. - if (!canvas()->maximumDecodedImageSize()) { - if (Settings* settings = canvas()->document().settings()) - canvas()->setMaximumDecodedImageSize(settings->maximumDecodedImageSize()); - } -#endif - FloatRect logicalRect(sx, sy, sw, sh); if (logicalRect.width() < 1) logicalRect.setWidth(1); if (logicalRect.height() < 1) logicalRect.setHeight(1); if (!logicalRect.isExpressibleAsIntRect()) - return 0; + return nullptr; IntRect imageDataRect = enclosingIntRect(logicalRect); - ImageBuffer* buffer = canvas()->buffer(); + ImageBuffer* buffer = canvas().buffer(); if (!buffer) return createEmptyImageData(imageDataRect.size()); - RefPtr<Uint8ClampedArray> byteArray = buffer->getUnmultipliedImageData(imageDataRect, coordinateSystem); - if (!byteArray) - return 0; + auto byteArray = buffer->getUnmultipliedImageData(imageDataRect, coordinateSystem); + if (!byteArray) { + StringBuilder consoleMessage; + consoleMessage.appendLiteral("Unable to get image data from canvas. Requested size was "); + consoleMessage.appendNumber(imageDataRect.width()); + consoleMessage.appendLiteral(" x "); + consoleMessage.appendNumber(imageDataRect.height()); - return ImageData::create(imageDataRect.size(), byteArray.release()); + canvas().document().addConsoleMessage(MessageSource::Rendering, MessageLevel::Error, consoleMessage.toString()); + return Exception { INVALID_STATE_ERR }; + } + + return ImageData::create(imageDataRect.size(), byteArray.releaseNonNull()); } -void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy, ExceptionCode& ec) +void CanvasRenderingContext2D::putImageData(ImageData& data, float dx, float dy) { - if (!data) { - ec = TYPE_MISMATCH_ERR; - return; - } - putImageData(data, dx, dy, 0, 0, data->width(), data->height(), ec); + putImageData(data, dx, dy, 0, 0, data.width(), data.height()); } -void CanvasRenderingContext2D::webkitPutImageDataHD(ImageData* data, float dx, float dy, ExceptionCode& ec) +void CanvasRenderingContext2D::webkitPutImageDataHD(ImageData& data, float dx, float dy) { - if (!data) { - ec = TYPE_MISMATCH_ERR; - return; - } - webkitPutImageDataHD(data, dx, dy, 0, 0, data->width(), data->height(), ec); + webkitPutImageDataHD(data, dx, dy, 0, 0, data.width(), data.height()); } -void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy, float dirtyX, float dirtyY, - float dirtyWidth, float dirtyHeight, ExceptionCode& ec) +void CanvasRenderingContext2D::putImageData(ImageData& data, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight) { - putImageData(data, ImageBuffer::LogicalCoordinateSystem, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight, ec); + putImageData(data, ImageBuffer::LogicalCoordinateSystem, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight); } -void CanvasRenderingContext2D::webkitPutImageDataHD(ImageData* data, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight, ExceptionCode& ec) +void CanvasRenderingContext2D::webkitPutImageDataHD(ImageData& data, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight) { - putImageData(data, ImageBuffer::BackingStoreCoordinateSystem, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight, ec); + putImageData(data, ImageBuffer::BackingStoreCoordinateSystem, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight); } -void CanvasRenderingContext2D::putImageData(ImageData* data, ImageBuffer::CoordinateSystem coordinateSystem, float dx, float dy, float dirtyX, float dirtyY, - float dirtyWidth, float dirtyHeight, ExceptionCode& ec) +void CanvasRenderingContext2D::drawFocusIfNeeded(Element& element) { - if (!data) { - ec = TYPE_MISMATCH_ERR; - return; - } - if (!std::isfinite(dx) || !std::isfinite(dy) || !std::isfinite(dirtyX) || !std::isfinite(dirtyY) || !std::isfinite(dirtyWidth) || !std::isfinite(dirtyHeight)) { - ec = NOT_SUPPORTED_ERR; + drawFocusIfNeededInternal(m_path, element); +} + +void CanvasRenderingContext2D::drawFocusIfNeeded(DOMPath& path, Element& element) +{ + drawFocusIfNeededInternal(path.path(), element); +} + +void CanvasRenderingContext2D::drawFocusIfNeededInternal(const Path& path, Element& element) +{ + auto* context = drawingContext(); + if (!element.focused() || !state().hasInvertibleTransform || path.isEmpty() || !element.isDescendantOf(canvas()) || !context) return; - } + context->drawFocusRing(path, 1, 1, RenderTheme::focusRingColor()); +} - ImageBuffer* buffer = canvas()->buffer(); +void CanvasRenderingContext2D::putImageData(ImageData& data, ImageBuffer::CoordinateSystem coordinateSystem, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight) +{ + ImageBuffer* buffer = canvas().buffer(); if (!buffer) return; @@ -1959,7 +2078,7 @@ void CanvasRenderingContext2D::putImageData(ImageData* data, ImageBuffer::Coordi } FloatRect clipRect(dirtyX, dirtyY, dirtyWidth, dirtyHeight); - clipRect.intersect(IntRect(0, 0, data->width(), data->height())); + clipRect.intersect(IntRect(0, 0, data.width(), data.height())); IntSize destOffset(static_cast<int>(dx), static_cast<int>(dy)); IntRect destRect = enclosingIntRect(clipRect); destRect.move(destOffset); @@ -1968,38 +2087,35 @@ void CanvasRenderingContext2D::putImageData(ImageData* data, ImageBuffer::Coordi return; IntRect sourceRect(destRect); sourceRect.move(-destOffset); + sourceRect.intersect(IntRect(0, 0, data.width(), data.height())); - buffer->putByteArray(Unmultiplied, data->data(), IntSize(data->width(), data->height()), sourceRect, IntPoint(destOffset), coordinateSystem); + if (!sourceRect.isEmpty()) + buffer->putByteArray(Unmultiplied, data.data(), IntSize(data.width(), data.height()), sourceRect, IntPoint(destOffset), coordinateSystem); - if (coordinateSystem == ImageBuffer::BackingStoreCoordinateSystem) { - FloatRect dirtyRect = destRect; - dirtyRect.scale(1 / canvas()->deviceScaleFactor()); - destRect = enclosingIntRect(dirtyRect); - } didDraw(destRect, CanvasDidDrawApplyNone); // ignore transform, shadow and clip } String CanvasRenderingContext2D::font() const { - if (!state().m_realizedFont) + if (!state().font.realized()) return defaultFont; StringBuilder serializedFont; - const FontDescription& fontDescription = state().m_font.fontDescription(); + const auto& fontDescription = state().font.fontDescription(); if (fontDescription.italic()) serializedFont.appendLiteral("italic "); - if (fontDescription.smallCaps() == FontSmallCapsOn) + if (fontDescription.variantCaps() == FontVariantCaps::Small) serializedFont.appendLiteral("small-caps "); serializedFont.appendNumber(fontDescription.computedPixelSize()); serializedFont.appendLiteral("px"); - for (unsigned i = 0; i < state().m_font.familyCount(); ++i) { + for (unsigned i = 0; i < fontDescription.familyCount(); ++i) { if (i) serializedFont.append(','); // FIXME: We should append family directly to serializedFont rather than building a temporary string. - String family = state().m_font.familyAt(i); + String family = fontDescription.familyAt(i); if (family.startsWith("-webkit-")) family = family.substring(8); if (family.contains(' ')) @@ -2014,11 +2130,11 @@ String CanvasRenderingContext2D::font() const void CanvasRenderingContext2D::setFont(const String& newFont) { - if (newFont == state().m_unparsedFont && state().m_realizedFont) + if (newFont == state().unparsedFont && state().font.realized()) return; - RefPtr<MutableStyleProperties> parsedStyle = MutableStyleProperties::create(); - CSSParser::parseValue(parsedStyle.get(), CSSPropertyFont, newFont, true, strictToCSSParserMode(!m_usesCSSCompatibilityParseMode), 0); + auto parsedStyle = MutableStyleProperties::create(); + CSSParser::parseValue(parsedStyle, CSSPropertyFont, newFont, true, strictToCSSParserMode(!m_usesCSSCompatibilityParseMode)); if (parsedStyle->isEmpty()) return; @@ -2032,15 +2148,19 @@ void CanvasRenderingContext2D::setFont(const String& newFont) // The parse succeeded. String newFontSafeCopy(newFont); // Create a string copy since newFont can be deleted inside realizeSaves. realizeSaves(); - modifiableState().m_unparsedFont = newFontSafeCopy; + modifiableState().unparsedFont = newFontSafeCopy; // Map the <canvas> font into the text style. If the font uses keywords like larger/smaller, these will work // relative to the canvas. - RefPtr<RenderStyle> newStyle = RenderStyle::create(); - if (RenderStyle* computedStyle = canvas()->computedStyle()) + auto newStyle = RenderStyle::createPtr(); + + Document& document = canvas().document(); + document.updateStyleIfNeeded(); + + if (auto* computedStyle = canvas().computedStyle()) newStyle->setFontDescription(computedStyle->fontDescription()); else { - FontDescription defaultFontDescription; + FontCascadeDescription defaultFontDescription; defaultFontDescription.setOneFamily(defaultFontFamily); defaultFontDescription.setSpecifiedSize(defaultFontSize); defaultFontDescription.setComputedSize(defaultFontSize); @@ -2048,13 +2168,13 @@ void CanvasRenderingContext2D::setFont(const String& newFont) newStyle->setFontDescription(defaultFontDescription); } - newStyle->font().update(newStyle->font().fontSelector()); + newStyle->fontCascade().update(&document.fontSelector()); // Now map the font property longhands into the style. - StyleResolver& styleResolver = canvas()->document().ensureStyleResolver(); - styleResolver.applyPropertyToStyle(CSSPropertyFontFamily, parsedStyle->getPropertyCSSValue(CSSPropertyFontFamily).get(), newStyle.get()); + StyleResolver& styleResolver = canvas().styleResolver(); + styleResolver.applyPropertyToStyle(CSSPropertyFontFamily, parsedStyle->getPropertyCSSValue(CSSPropertyFontFamily).get(), WTFMove(newStyle)); styleResolver.applyPropertyToCurrentStyle(CSSPropertyFontStyle, parsedStyle->getPropertyCSSValue(CSSPropertyFontStyle).get()); - styleResolver.applyPropertyToCurrentStyle(CSSPropertyFontVariant, parsedStyle->getPropertyCSSValue(CSSPropertyFontVariant).get()); + styleResolver.applyPropertyToCurrentStyle(CSSPropertyFontVariantCaps, parsedStyle->getPropertyCSSValue(CSSPropertyFontVariantCaps).get()); styleResolver.applyPropertyToCurrentStyle(CSSPropertyFontWeight, parsedStyle->getPropertyCSSValue(CSSPropertyFontWeight).get()); // As described in BUG66291, setting font-size and line-height on a font may entail a CSSPrimitiveValue::computeLengthDouble call, @@ -2065,15 +2185,12 @@ void CanvasRenderingContext2D::setFont(const String& newFont) styleResolver.updateFont(); styleResolver.applyPropertyToCurrentStyle(CSSPropertyLineHeight, parsedStyle->getPropertyCSSValue(CSSPropertyLineHeight).get()); - modifiableState().m_font = newStyle->font(); - modifiableState().m_font.update(styleResolver.fontSelector()); - modifiableState().m_realizedFont = true; - styleResolver.fontSelector()->registerForInvalidationCallbacks(&modifiableState()); + modifiableState().font.initialize(document.fontSelector(), *styleResolver.style()); } String CanvasRenderingContext2D::textAlign() const { - return textAlignName(state().m_textAlign); + return textAlignName(state().textAlign); } void CanvasRenderingContext2D::setTextAlign(const String& s) @@ -2081,15 +2198,15 @@ void CanvasRenderingContext2D::setTextAlign(const String& s) TextAlign align; if (!parseTextAlign(s, align)) return; - if (state().m_textAlign == align) + if (state().textAlign == align) return; realizeSaves(); - modifiableState().m_textAlign = align; + modifiableState().textAlign = align; } String CanvasRenderingContext2D::textBaseline() const { - return textBaselineName(state().m_textBaseline); + return textBaselineName(state().textBaseline); } void CanvasRenderingContext2D::setTextBaseline(const String& s) @@ -2097,30 +2214,63 @@ void CanvasRenderingContext2D::setTextBaseline(const String& s) TextBaseline baseline; if (!parseTextBaseline(s, baseline)) return; - if (state().m_textBaseline == baseline) + if (state().textBaseline == baseline) return; realizeSaves(); - modifiableState().m_textBaseline = baseline; + modifiableState().textBaseline = baseline; } -void CanvasRenderingContext2D::fillText(const String& text, float x, float y) +inline TextDirection CanvasRenderingContext2D::toTextDirection(Direction direction, const RenderStyle** computedStyle) const { - drawTextInternal(text, x, y, true); + auto* style = (computedStyle || direction == Direction::Inherit) ? canvas().computedStyle() : nullptr; + if (computedStyle) + *computedStyle = style; + switch (direction) { + case Direction::Inherit: + return style ? style->direction() : LTR; + case Direction::RTL: + return RTL; + case Direction::LTR: + return LTR; + } + ASSERT_NOT_REACHED(); + return LTR; } -void CanvasRenderingContext2D::fillText(const String& text, float x, float y, float maxWidth) +String CanvasRenderingContext2D::direction() const { - drawTextInternal(text, x, y, true, maxWidth, true); + if (state().direction == Direction::Inherit) + canvas().document().updateStyleIfNeeded(); + return toTextDirection(state().direction) == RTL ? ASCIILiteral("rtl") : ASCIILiteral("ltr"); } -void CanvasRenderingContext2D::strokeText(const String& text, float x, float y) +void CanvasRenderingContext2D::setDirection(const String& directionString) { - drawTextInternal(text, x, y, false); + Direction direction; + if (directionString == "inherit") + direction = Direction::Inherit; + else if (directionString == "rtl") + direction = Direction::RTL; + else if (directionString == "ltr") + direction = Direction::LTR; + else + return; + + if (state().direction == direction) + return; + + realizeSaves(); + modifiableState().direction = direction; +} + +void CanvasRenderingContext2D::fillText(const String& text, float x, float y, std::optional<float> maxWidth) +{ + drawTextInternal(text, x, y, true, maxWidth); } -void CanvasRenderingContext2D::strokeText(const String& text, float x, float y, float maxWidth) +void CanvasRenderingContext2D::strokeText(const String& text, float x, float y, std::optional<float> maxWidth) { - drawTextInternal(text, x, y, false, maxWidth, true); + drawTextInternal(text, x, y, false, maxWidth); } static inline bool isSpaceThatNeedsReplacing(UChar c) @@ -2137,13 +2287,12 @@ static inline bool isSpaceThatNeedsReplacing(UChar c) static void normalizeSpaces(String& text) { size_t i = text.find(isSpaceThatNeedsReplacing); - if (i == notFound) return; unsigned textLength = text.length(); Vector<UChar> charVector(textLength); - memcpy(charVector.data(), text.deprecatedCharacters(), textLength * sizeof(UChar)); + StringView(text).getCharactersWithUpconvert(charVector.data()); charVector[i++] = ' '; @@ -2151,37 +2300,38 @@ static void normalizeSpaces(String& text) if (isSpaceThatNeedsReplacing(charVector[i])) charVector[i] = ' '; } - text = String::adopt(charVector); + text = String::adopt(WTFMove(charVector)); } -PassRefPtr<TextMetrics> CanvasRenderingContext2D::measureText(const String& text) +Ref<TextMetrics> CanvasRenderingContext2D::measureText(const String& text) { - FontCachePurgePreventer fontCachePurgePreventer; - - RefPtr<TextMetrics> metrics = TextMetrics::create(); + Ref<TextMetrics> metrics = TextMetrics::create(); String normalizedText = text; normalizeSpaces(normalizedText); - metrics->setWidth(accessFont().width(TextRun(normalizedText))); + metrics->setWidth(fontProxy().width(TextRun(normalizedText))); - return metrics.release(); + return metrics; } -void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, float y, bool fill, float maxWidth, bool useMaxWidth) +void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, float y, bool fill, std::optional<float> maxWidth) { - GraphicsContext* c = drawingContext(); + auto& fontProxy = this->fontProxy(); + const auto& fontMetrics = fontProxy.fontMetrics(); + + auto* c = drawingContext(); if (!c) return; - if (!state().m_hasInvertibleTransform) + if (!state().hasInvertibleTransform) return; if (!std::isfinite(x) | !std::isfinite(y)) return; - if (useMaxWidth && (!std::isfinite(maxWidth) || maxWidth <= 0)) + if (maxWidth && (!std::isfinite(maxWidth.value()) || maxWidth.value() <= 0)) return; // If gradient size is zero, then paint nothing. - Gradient* gradient = c->strokeGradient(); + auto* gradient = c->strokeGradient(); if (!fill && gradient && gradient->isZeroSize()) return; @@ -2189,25 +2339,20 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo if (fill && gradient && gradient->isZeroSize()) return; - FontCachePurgePreventer fontCachePurgePreventer; - - const Font& font = accessFont(); - const FontMetrics& fontMetrics = font.fontMetrics(); - String normalizedText = text; normalizeSpaces(normalizedText); // FIXME: Need to turn off font smoothing. - RenderStyle* computedStyle = canvas()->computedStyle(); - TextDirection direction = computedStyle ? computedStyle->direction() : LTR; + const RenderStyle* computedStyle; + auto direction = toTextDirection(state().direction, &computedStyle); bool isRTL = direction == RTL; bool override = computedStyle ? isOverride(computedStyle->unicodeBidi()) : false; - TextRun textRun(normalizedText, 0, 0, TextRun::AllowTrailingExpansion, direction, override, true, TextRun::NoRounding); + TextRun textRun(normalizedText, 0, 0, AllowTrailingExpansion, direction, override, true); // Draw the item text at the correct point. FloatPoint location(x, y); - switch (state().m_textBaseline) { + switch (state().textBaseline) { case TopTextBaseline: case HangingTextBaseline: location.setY(y + fontMetrics.ascent()); @@ -2225,12 +2370,12 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo break; } - float fontWidth = font.width(TextRun(normalizedText, 0, 0, TextRun::AllowTrailingExpansion, direction, override)); + float fontWidth = fontProxy.width(TextRun(normalizedText, 0, 0, AllowTrailingExpansion, direction, override)); - useMaxWidth = (useMaxWidth && maxWidth < fontWidth); - float width = useMaxWidth ? maxWidth : fontWidth; + bool useMaxWidth = maxWidth && maxWidth.value() < fontWidth; + float width = useMaxWidth ? maxWidth.value() : fontWidth; - TextAlign align = state().m_textAlign; + auto align = state().textAlign; if (align == StartTextAlign) align = isRTL ? RightTextAlign : LeftTextAlign; else if (align == EndTextAlign) @@ -2249,41 +2394,73 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo // The slop built in to this mask rect matches the heuristic used in FontCGWin.cpp for GDI text. FloatRect textRect = FloatRect(location.x() - fontMetrics.height() / 2, location.y() - fontMetrics.ascent() - fontMetrics.lineGap(), - width + fontMetrics.height(), fontMetrics.lineSpacing()); + width + fontMetrics.height(), fontMetrics.lineSpacing()); if (!fill) inflateStrokeRect(textRect); #if USE(CG) - const CanvasStyle& drawStyle = fill ? state().m_fillStyle : state().m_strokeStyle; + const CanvasStyle& drawStyle = fill ? state().fillStyle : state().strokeStyle; if (drawStyle.canvasGradient() || drawStyle.canvasPattern()) { IntRect maskRect = enclosingIntRect(textRect); - std::unique_ptr<ImageBuffer> maskImage = c->createCompatibleBuffer(maskRect.size()); + // If we have a shadow, we need to draw it before the mask operation. + // Follow a procedure similar to paintTextWithShadows in TextPainter. + + if (shouldDrawShadows()) { + GraphicsContextStateSaver stateSaver(*c); - GraphicsContext* maskImageContext = maskImage->context(); + FloatSize offset(0, 2 * maskRect.height()); + + FloatSize shadowOffset; + float shadowRadius; + Color shadowColor; + c->getShadow(shadowOffset, shadowRadius, shadowColor); + + FloatRect shadowRect(maskRect); + shadowRect.inflate(shadowRadius * 1.4); + shadowRect.move(shadowOffset * -1); + c->clip(shadowRect); + + shadowOffset += offset; + + c->setLegacyShadow(shadowOffset, shadowRadius, shadowColor); + + if (fill) + c->setFillColor(Color::black); + else + c->setStrokeColor(Color::black); + + fontProxy.drawBidiText(*c, textRun, location + offset, FontCascade::UseFallbackIfFontNotReady); + } + + auto maskImage = ImageBuffer::createCompatibleBuffer(maskRect.size(), ColorSpaceSRGB, *c); + if (!maskImage) + return; + + auto& maskImageContext = maskImage->context(); if (fill) - maskImageContext->setFillColor(Color::black, ColorSpaceDeviceRGB); + maskImageContext.setFillColor(Color::black); else { - maskImageContext->setStrokeColor(Color::black, ColorSpaceDeviceRGB); - maskImageContext->setStrokeThickness(c->strokeThickness()); + maskImageContext.setStrokeColor(Color::black); + maskImageContext.setStrokeThickness(c->strokeThickness()); } - maskImageContext->setTextDrawingMode(fill ? TextModeFill : TextModeStroke); + maskImageContext.setTextDrawingMode(fill ? TextModeFill : TextModeStroke); if (useMaxWidth) { - maskImageContext->translate(location.x() - maskRect.x(), location.y() - maskRect.y()); + maskImageContext.translate(location.x() - maskRect.x(), location.y() - maskRect.y()); // We draw when fontWidth is 0 so compositing operations (eg, a "copy" op) still work. - maskImageContext->scale(FloatSize((fontWidth > 0 ? (width / fontWidth) : 0), 1)); - maskImageContext->drawBidiText(font, textRun, FloatPoint(0, 0), Font::UseFallbackIfFontNotReady); + maskImageContext.scale(FloatSize((fontWidth > 0 ? (width / fontWidth) : 0), 1)); + fontProxy.drawBidiText(maskImageContext, textRun, FloatPoint(0, 0), FontCascade::UseFallbackIfFontNotReady); } else { - maskImageContext->translate(-maskRect.x(), -maskRect.y()); - maskImageContext->drawBidiText(font, textRun, location, Font::UseFallbackIfFontNotReady); + maskImageContext.translate(-maskRect.x(), -maskRect.y()); + fontProxy.drawBidiText(maskImageContext, textRun, location, FontCascade::UseFallbackIfFontNotReady); } GraphicsContextStateSaver stateSaver(*c); - c->clipToImageBuffer(maskImage.get(), maskRect); - drawStyle.applyFillColor(c); + c->clipToImageBuffer(*maskImage, maskRect); + drawStyle.applyFillColor(*c); c->fillRect(maskRect); return; } @@ -2291,16 +2468,27 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo c->setTextDrawingMode(fill ? TextModeFill : TextModeStroke); + GraphicsContextStateSaver stateSaver(*c); if (useMaxWidth) { - GraphicsContextStateSaver stateSaver(*c); c->translate(location.x(), location.y()); // We draw when fontWidth is 0 so compositing operations (eg, a "copy" op) still work. c->scale(FloatSize((fontWidth > 0 ? (width / fontWidth) : 0), 1)); - c->drawBidiText(font, textRun, FloatPoint(0, 0), Font::UseFallbackIfFontNotReady); - } else - c->drawBidiText(font, textRun, location, Font::UseFallbackIfFontNotReady); + location = FloatPoint(); + } - didDraw(textRect); + if (isFullCanvasCompositeMode(state().globalComposite)) { + beginCompositeLayer(); + fontProxy.drawBidiText(*c, textRun, location, FontCascade::UseFallbackIfFontNotReady); + endCompositeLayer(); + didDrawEntireCanvas(); + } else if (state().globalComposite == CompositeCopy) { + clearCanvas(); + fontProxy.drawBidiText(*c, textRun, location, FontCascade::UseFallbackIfFontNotReady); + didDrawEntireCanvas(); + } else { + fontProxy.drawBidiText(*c, textRun, location, FontCascade::UseFallbackIfFontNotReady); + didDraw(textRect); + } } void CanvasRenderingContext2D::inflateStrokeRect(FloatRect& rect) const @@ -2309,46 +2497,81 @@ void CanvasRenderingContext2D::inflateStrokeRect(FloatRect& rect) const // This yields a slightly oversized rect but is very fast // compared to Path::strokeBoundingRect(). static const float root2 = sqrtf(2); - float delta = state().m_lineWidth / 2; - if (state().m_lineJoin == MiterJoin) - delta *= state().m_miterLimit; - else if (state().m_lineCap == SquareCap) + float delta = state().lineWidth / 2; + if (state().lineJoin == MiterJoin) + delta *= state().miterLimit; + else if (state().lineCap == SquareCap) delta *= root2; - rect.inflate(delta); } -const Font& CanvasRenderingContext2D::accessFont() +auto CanvasRenderingContext2D::fontProxy() -> const FontProxy& { - canvas()->document().updateStyleIfNeeded(); - - if (!state().m_realizedFont) - setFont(state().m_unparsedFont); - return state().m_font; + canvas().document().updateStyleIfNeeded(); + if (!state().font.realized()) + setFont(state().unparsedFont); + return state().font; } -#if ENABLE(ACCELERATED_2D_CANVAS) && USE(ACCELERATED_COMPOSITING) +#if ENABLE(ACCELERATED_2D_CANVAS) + PlatformLayer* CanvasRenderingContext2D::platformLayer() const { - return canvas()->buffer() ? canvas()->buffer()->platformLayer() : 0; + return canvas().buffer() ? canvas().buffer()->platformLayer() : nullptr; } + #endif -bool CanvasRenderingContext2D::webkitImageSmoothingEnabled() const +static inline InterpolationQuality smoothingToInterpolationQuality(CanvasRenderingContext2D::ImageSmoothingQuality quality) +{ + switch (quality) { + case CanvasRenderingContext2D::ImageSmoothingQuality::Low: + return InterpolationLow; + case CanvasRenderingContext2D::ImageSmoothingQuality::Medium: + return InterpolationMedium; + case CanvasRenderingContext2D::ImageSmoothingQuality::High: + return InterpolationHigh; + } + + ASSERT_NOT_REACHED(); + return InterpolationLow; +}; + +auto CanvasRenderingContext2D::imageSmoothingQuality() const -> ImageSmoothingQuality { - return state().m_imageSmoothingEnabled; + return state().imageSmoothingQuality; } -void CanvasRenderingContext2D::setWebkitImageSmoothingEnabled(bool enabled) +void CanvasRenderingContext2D::setImageSmoothingQuality(ImageSmoothingQuality quality) { - if (enabled == state().m_imageSmoothingEnabled) + if (quality == state().imageSmoothingQuality) return; realizeSaves(); - modifiableState().m_imageSmoothingEnabled = enabled; - GraphicsContext* c = drawingContext(); + modifiableState().imageSmoothingQuality = quality; + + if (!state().imageSmoothingEnabled) + return; + + if (auto* context = drawingContext()) + context->setImageInterpolationQuality(smoothingToInterpolationQuality(quality)); +} + +bool CanvasRenderingContext2D::imageSmoothingEnabled() const +{ + return state().imageSmoothingEnabled; +} + +void CanvasRenderingContext2D::setImageSmoothingEnabled(bool enabled) +{ + if (enabled == state().imageSmoothingEnabled) + return; + + realizeSaves(); + modifiableState().imageSmoothingEnabled = enabled; + auto* c = drawingContext(); if (c) - c->setImageInterpolationQuality(enabled ? DefaultInterpolationQuality : InterpolationNone); + c->setImageInterpolationQuality(enabled ? smoothingToInterpolationQuality(state().imageSmoothingQuality) : InterpolationNone); } } // namespace WebCore diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext2D.h b/Source/WebCore/html/canvas/CanvasRenderingContext2D.h index 27b7e33c8..13bdc553b 100644 --- a/Source/WebCore/html/canvas/CanvasRenderingContext2D.h +++ b/Source/WebCore/html/canvas/CanvasRenderingContext2D.h @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,27 +23,25 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CanvasRenderingContext2D_h -#define CanvasRenderingContext2D_h +#pragma once #include "AffineTransform.h" -#include "CanvasPathMethods.h" +#include "CanvasPath.h" #include "CanvasRenderingContext.h" #include "CanvasStyle.h" #include "Color.h" -#include "ColorSpace.h" #include "FloatSize.h" -#include "Font.h" +#include "FontCascade.h" +#include "FontSelectorClient.h" +#include "GraphicsContext.h" #include "GraphicsTypes.h" #include "ImageBuffer.h" #include "Path.h" +#include "PlatformLayer.h" +#include "TextFlags.h" #include <wtf/Vector.h> #include <wtf/text/WTFString.h> -#if USE(ACCELERATED_COMPOSITING) -#include "PlatformLayer.h" -#endif - namespace WebCore { class CanvasGradient; @@ -57,22 +55,17 @@ class HTMLVideoElement; class ImageData; class TextMetrics; -typedef int ExceptionCode; +#if ENABLE(VIDEO) +using CanvasImageSource = Variant<RefPtr<HTMLImageElement>, RefPtr<HTMLVideoElement>, RefPtr<HTMLCanvasElement>>; +#else +using CanvasImageSource = Variant<RefPtr<HTMLImageElement>, RefPtr<HTMLCanvasElement>>; +#endif -class CanvasRenderingContext2D : public CanvasRenderingContext, public CanvasPathMethods { +class CanvasRenderingContext2D final : public CanvasRenderingContext, public CanvasPath { public: - static OwnPtr<CanvasRenderingContext2D> create(HTMLCanvasElement* canvas, bool usesCSSCompatibilityParseMode, bool usesDashboardCompatibilityMode) - { - return adoptPtr(new CanvasRenderingContext2D(canvas, usesCSSCompatibilityParseMode, usesDashboardCompatibilityMode)); - } + CanvasRenderingContext2D(HTMLCanvasElement&, bool usesCSSCompatibilityParseMode, bool usesDashboardCompatibilityMode); virtual ~CanvasRenderingContext2D(); - const CanvasStyle& strokeStyle() const { return state().m_strokeStyle; } - void setStrokeStyle(CanvasStyle); - - const CanvasStyle& fillStyle() const { return state().m_fillStyle; } - void setFillStyle(CanvasStyle); - float lineWidth() const; void setLineWidth(float); @@ -87,12 +80,11 @@ public: const Vector<float>& getLineDash() const; void setLineDash(const Vector<float>&); + const Vector<float>& webkitLineDash() const { return getLineDash(); } void setWebkitLineDash(const Vector<float>&); float lineDashOffset() const; void setLineDashOffset(float); - float webkitLineDashOffset() const; - void setWebkitLineDashOffset(float); float shadowOffsetX() const; void setShadowOffsetX(float); @@ -115,92 +107,88 @@ public: void save() { ++m_unrealizedSaveCount; } void restore(); + // This is a no-op in a direct-2d canvas. + void commit() { } + void scale(float sx, float sy); void rotate(float angleInRadians); void translate(float tx, float ty); void transform(float m11, float m12, float m21, float m22, float dx, float dy); void setTransform(float m11, float m12, float m21, float m22, float dx, float dy); + void resetTransform(); - void setStrokeColor(const String& color); - void setStrokeColor(float grayLevel); - void setStrokeColor(const String& color, float alpha); - void setStrokeColor(float grayLevel, float alpha); + void setStrokeColor(const String& color, std::optional<float> alpha = std::nullopt); + void setStrokeColor(float grayLevel, float alpha = 1.0); void setStrokeColor(float r, float g, float b, float a); void setStrokeColor(float c, float m, float y, float k, float a); - void setFillColor(const String& color); - void setFillColor(float grayLevel); - void setFillColor(const String& color, float alpha); - void setFillColor(float grayLevel, float alpha); + void setFillColor(const String& color, std::optional<float> alpha = std::nullopt); + void setFillColor(float grayLevel, float alpha = 1.0f); void setFillColor(float r, float g, float b, float a); void setFillColor(float c, float m, float y, float k, float a); void beginPath(); -#if ENABLE(CANVAS_PATH) - PassRefPtr<DOMPath> currentPath(); - void setCurrentPath(DOMPath*); -#endif + enum class WindingRule { Nonzero, Evenodd }; - void fill(const String& winding = "nonzero"); + void fill(WindingRule = WindingRule::Nonzero); void stroke(); - void clip(const String& winding = "nonzero"); + void clip(WindingRule = WindingRule::Nonzero); - bool isPointInPath(const float x, const float y, const String& winding = "nonzero"); - bool isPointInStroke(const float x, const float y); + void fill(DOMPath&, WindingRule = WindingRule::Nonzero); + void stroke(DOMPath&); + void clip(DOMPath&, WindingRule = WindingRule::Nonzero); + + bool isPointInPath(float x, float y, WindingRule = WindingRule::Nonzero); + bool isPointInStroke(float x, float y); + + bool isPointInPath(DOMPath&, float x, float y, WindingRule = WindingRule::Nonzero); + bool isPointInStroke(DOMPath&, float x, float y); void clearRect(float x, float y, float width, float height); void fillRect(float x, float y, float width, float height); void strokeRect(float x, float y, float width, float height); - void setShadow(float width, float height, float blur); - void setShadow(float width, float height, float blur, const String& color); - void setShadow(float width, float height, float blur, float grayLevel); - void setShadow(float width, float height, float blur, const String& color, float alpha); - void setShadow(float width, float height, float blur, float grayLevel, float alpha); + void setShadow(float width, float height, float blur, const String& color = String(), std::optional<float> alpha = std::nullopt); + void setShadow(float width, float height, float blur, float grayLevel, float alpha = 1.0); void setShadow(float width, float height, float blur, float r, float g, float b, float a); void setShadow(float width, float height, float blur, float c, float m, float y, float k, float a); void clearShadow(); - void drawImage(HTMLImageElement*, float x, float y, ExceptionCode&); - void drawImage(HTMLImageElement*, float x, float y, float width, float height, ExceptionCode&); - void drawImage(HTMLImageElement*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionCode&); - void drawImage(HTMLImageElement*, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionCode&); - void drawImage(HTMLCanvasElement*, float x, float y, ExceptionCode&); - void drawImage(HTMLCanvasElement*, float x, float y, float width, float height, ExceptionCode&); - void drawImage(HTMLCanvasElement*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionCode&); - void drawImage(HTMLCanvasElement*, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionCode&); - void drawImage(HTMLImageElement*, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator&, const BlendMode&, ExceptionCode&); -#if ENABLE(VIDEO) - void drawImage(HTMLVideoElement*, float x, float y, ExceptionCode&); - void drawImage(HTMLVideoElement*, float x, float y, float width, float height, ExceptionCode&); - void drawImage(HTMLVideoElement*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionCode&); - void drawImage(HTMLVideoElement*, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionCode&); -#endif + ExceptionOr<void> drawImage(CanvasImageSource&&, float dx, float dy); + ExceptionOr<void> drawImage(CanvasImageSource&&, float dx, float dy, float dw, float dh); + ExceptionOr<void> drawImage(CanvasImageSource&&, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh); - void drawImageFromRect(HTMLImageElement*, float sx = 0, float sy = 0, float sw = 0, float sh = 0, - float dx = 0, float dy = 0, float dw = 0, float dh = 0, const String& compositeOperation = emptyString()); + void drawImageFromRect(HTMLImageElement&, float sx = 0, float sy = 0, float sw = 0, float sh = 0, float dx = 0, float dy = 0, float dw = 0, float dh = 0, const String& compositeOperation = emptyString()); void setAlpha(float); void setCompositeOperation(const String&); - PassRefPtr<CanvasGradient> createLinearGradient(float x0, float y0, float x1, float y1, ExceptionCode&); - PassRefPtr<CanvasGradient> createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1, ExceptionCode&); - PassRefPtr<CanvasPattern> createPattern(HTMLImageElement*, const String& repetitionType, ExceptionCode&); - PassRefPtr<CanvasPattern> createPattern(HTMLCanvasElement*, const String& repetitionType, ExceptionCode&); + using Style = Variant<String, RefPtr<CanvasGradient>, RefPtr<CanvasPattern>>; + Style strokeStyle() const; + void setStrokeStyle(Style&&); + Style fillStyle() const; + void setFillStyle(Style&&); + + ExceptionOr<Ref<CanvasGradient>> createLinearGradient(float x0, float y0, float x1, float y1); + ExceptionOr<Ref<CanvasGradient>> createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1); + ExceptionOr<RefPtr<CanvasPattern>> createPattern(CanvasImageSource&&, const String& repetition); + + ExceptionOr<RefPtr<ImageData>> createImageData(ImageData*) const; + ExceptionOr<RefPtr<ImageData>> createImageData(float width, float height) const; + ExceptionOr<RefPtr<ImageData>> getImageData(float sx, float sy, float sw, float sh) const; + ExceptionOr<RefPtr<ImageData>> webkitGetImageDataHD(float sx, float sy, float sw, float sh) const; + void putImageData(ImageData&, float dx, float dy); + void putImageData(ImageData&, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight); + void webkitPutImageDataHD(ImageData&, float dx, float dy); + void webkitPutImageDataHD(ImageData&, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight); - PassRefPtr<ImageData> createImageData(PassRefPtr<ImageData>, ExceptionCode&) const; - PassRefPtr<ImageData> createImageData(float width, float height, ExceptionCode&) const; - PassRefPtr<ImageData> getImageData(float sx, float sy, float sw, float sh, ExceptionCode&) const; - PassRefPtr<ImageData> webkitGetImageDataHD(float sx, float sy, float sw, float sh, ExceptionCode&) const; - void putImageData(ImageData*, float dx, float dy, ExceptionCode&); - void putImageData(ImageData*, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight, ExceptionCode&); - void webkitPutImageDataHD(ImageData*, float dx, float dy, ExceptionCode&); - void webkitPutImageDataHD(ImageData*, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight, ExceptionCode&); + void drawFocusIfNeeded(Element&); + void drawFocusIfNeeded(DOMPath&, Element&); - float webkitBackingStorePixelRatio() const { return canvas()->deviceScaleFactor(); } + float webkitBackingStorePixelRatio() const { return 1; } void reset(); @@ -213,55 +201,94 @@ public: String textBaseline() const; void setTextBaseline(const String&); - void fillText(const String& text, float x, float y); - void fillText(const String& text, float x, float y, float maxWidth); - void strokeText(const String& text, float x, float y); - void strokeText(const String& text, float x, float y, float maxWidth); - PassRefPtr<TextMetrics> measureText(const String& text); + String direction() const; + void setDirection(const String&); + + void fillText(const String& text, float x, float y, std::optional<float> maxWidth = std::nullopt); + void strokeText(const String& text, float x, float y, std::optional<float> maxWidth = std::nullopt); + Ref<TextMetrics> measureText(const String& text); + + LineCap getLineCap() const { return state().lineCap; } + LineJoin getLineJoin() const { return state().lineJoin; } + + bool imageSmoothingEnabled() const; + void setImageSmoothingEnabled(bool); + + enum class ImageSmoothingQuality { Low, Medium, High }; + ImageSmoothingQuality imageSmoothingQuality() const; + void setImageSmoothingQuality(ImageSmoothingQuality); + + bool usesDisplayListDrawing() const { return m_usesDisplayListDrawing; }; + void setUsesDisplayListDrawing(bool flag) { m_usesDisplayListDrawing = flag; }; - LineCap getLineCap() const { return state().m_lineCap; } - LineJoin getLineJoin() const { return state().m_lineJoin; } + bool tracksDisplayListReplay() const { return m_tracksDisplayListReplay; } + void setTracksDisplayListReplay(bool); - bool webkitImageSmoothingEnabled() const; - void setWebkitImageSmoothingEnabled(bool); + String displayListAsText(DisplayList::AsTextFlags) const; + String replayDisplayListAsText(DisplayList::AsTextFlags) const; private: - struct State : FontSelectorClient { + enum class Direction { + Inherit, + RTL, + LTR + }; + + class FontProxy : public FontSelectorClient { + public: + FontProxy() = default; + virtual ~FontProxy(); + FontProxy(const FontProxy&); + FontProxy& operator=(const FontProxy&); + + bool realized() const { return m_font.fontSelector(); } + void initialize(FontSelector&, const RenderStyle&); + FontMetrics fontMetrics() const; + const FontCascadeDescription& fontDescription() const; + float width(const TextRun&) const; + void drawBidiText(GraphicsContext&, const TextRun&, const FloatPoint&, FontCascade::CustomFontNotReadyAction) const; + + private: + void update(FontSelector&); + void fontsNeedUpdate(FontSelector&) override; + + FontCascade m_font; + }; + + struct State final { State(); - virtual ~State(); State(const State&); State& operator=(const State&); - virtual void fontsNeedUpdate(FontSelector*) override; - - String m_unparsedStrokeColor; - String m_unparsedFillColor; - CanvasStyle m_strokeStyle; - CanvasStyle m_fillStyle; - float m_lineWidth; - LineCap m_lineCap; - LineJoin m_lineJoin; - float m_miterLimit; - FloatSize m_shadowOffset; - float m_shadowBlur; - RGBA32 m_shadowColor; - float m_globalAlpha; - CompositeOperator m_globalComposite; - BlendMode m_globalBlend; - AffineTransform m_transform; - bool m_hasInvertibleTransform; - Vector<float> m_lineDash; - float m_lineDashOffset; - bool m_imageSmoothingEnabled; + String unparsedStrokeColor; + String unparsedFillColor; + CanvasStyle strokeStyle; + CanvasStyle fillStyle; + float lineWidth; + LineCap lineCap; + LineJoin lineJoin; + float miterLimit; + FloatSize shadowOffset; + float shadowBlur; + Color shadowColor; + float globalAlpha; + CompositeOperator globalComposite; + BlendMode globalBlend; + AffineTransform transform; + bool hasInvertibleTransform; + Vector<float> lineDash; + float lineDashOffset; + bool imageSmoothingEnabled; + ImageSmoothingQuality imageSmoothingQuality; // Text state. - TextAlign m_textAlign; - TextBaseline m_textBaseline; + TextAlign textAlign; + TextBaseline textBaseline; + Direction direction; - String m_unparsedFont; - Font m_font; - bool m_realizedFont; + String unparsedFont; + FontProxy font; }; enum CanvasDidDrawOption { @@ -272,40 +299,64 @@ private: CanvasDidDrawApplyAll = 0xffffffff }; - CanvasRenderingContext2D(HTMLCanvasElement*, bool usesCSSCompatibilityParseMode, bool usesDashboardCompatibilityMode); - - State& modifiableState() { ASSERT(!m_unrealizedSaveCount); return m_stateStack.last(); } + State& modifiableState() { ASSERT(!m_unrealizedSaveCount || m_stateStack.size() >= MaxSaveCount); return m_stateStack.last(); } const State& state() const { return m_stateStack.last(); } void applyLineDash() const; - void setShadow(const FloatSize& offset, float blur, RGBA32 color); + void setShadow(const FloatSize& offset, float blur, const Color&); void applyShadow(); bool shouldDrawShadows() const; void didDraw(const FloatRect&, unsigned options = CanvasDidDrawApplyAll); void didDrawEntireCanvas(); + void paintRenderingResultsToCanvas() override; + GraphicsContext* drawingContext() const; void unwindStateStack(); - void realizeSaves() - { - if (m_unrealizedSaveCount) - realizeSavesLoop(); - } + void realizeSaves(); void realizeSavesLoop(); void applyStrokePattern(); void applyFillPattern(); - void drawTextInternal(const String& text, float x, float y, bool fill, float maxWidth = 0, bool useMaxWidth = false); + void setStrokeStyle(CanvasStyle); + void setFillStyle(CanvasStyle); - const Font& accessFont(); + ExceptionOr<RefPtr<CanvasPattern>> createPattern(HTMLImageElement&, bool repeatX, bool repeatY); + ExceptionOr<RefPtr<CanvasPattern>> createPattern(HTMLCanvasElement&, bool repeatX, bool repeatY); +#if ENABLE(VIDEO) + ExceptionOr<RefPtr<CanvasPattern>> createPattern(HTMLVideoElement&, bool repeatX, bool repeatY); +#endif -#if ENABLE(DASHBOARD_SUPPORT) - void clearPathForDashboardBackwardCompatibilityMode(); + ExceptionOr<void> drawImage(HTMLImageElement&, const FloatRect& srcRect, const FloatRect& dstRect); + ExceptionOr<void> drawImage(HTMLImageElement&, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator&, const BlendMode&); + ExceptionOr<void> drawImage(HTMLCanvasElement&, const FloatRect& srcRect, const FloatRect& dstRect); +#if ENABLE(VIDEO) + ExceptionOr<void> drawImage(HTMLVideoElement&, const FloatRect& srcRect, const FloatRect& dstRect); #endif + void drawTextInternal(const String& text, float x, float y, bool fill, std::optional<float> maxWidth = std::nullopt); + + // The relationship between FontCascade and CanvasRenderingContext2D::FontProxy must hold certain invariants. + // Therefore, all font operations must pass through the State. + const FontProxy& fontProxy(); + + void clearPathForDashboardBackwardCompatibilityMode(); + + void beginCompositeLayer(); + void endCompositeLayer(); + + void fillInternal(const Path&, WindingRule); + void strokeInternal(const Path&); + void clipInternal(const Path&, WindingRule); + + bool isPointInPathInternal(const Path&, float x, float y, WindingRule); + bool isPointInStrokeInternal(const Path&, float x, float y); + + void drawFocusIfNeededInternal(const Path&, Element&); + void clearCanvas(); Path transformAreaToDevice(const Path&) const; Path transformAreaToDevice(const FloatRect&) const; @@ -313,35 +364,39 @@ private: template<class T> IntRect calculateCompositingBufferRect(const T&, IntSize*); std::unique_ptr<ImageBuffer> createCompositingBuffer(const IntRect&); - void compositeBuffer(ImageBuffer*, const IntRect&, CompositeOperator); + void compositeBuffer(ImageBuffer&, const IntRect&, CompositeOperator); void inflateStrokeRect(FloatRect&) const; - template<class T> void fullCanvasCompositedFill(const T&); - template<class T> void fullCanvasCompositedDrawImage(T*, ColorSpace, const FloatRect&, const FloatRect&, CompositeOperator); + template<class T> void fullCanvasCompositedDrawImage(T&, const FloatRect&, const FloatRect&, CompositeOperator); - void prepareGradientForDashboard(CanvasGradient* gradient) const; + void prepareGradientForDashboard(CanvasGradient& gradient) const; - PassRefPtr<ImageData> getImageData(ImageBuffer::CoordinateSystem, float sx, float sy, float sw, float sh, ExceptionCode&) const; - void putImageData(ImageData*, ImageBuffer::CoordinateSystem, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight, ExceptionCode&); + ExceptionOr<RefPtr<ImageData>> getImageData(ImageBuffer::CoordinateSystem, float sx, float sy, float sw, float sh) const; + void putImageData(ImageData&, ImageBuffer::CoordinateSystem, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight); - virtual bool is2d() const override { return true; } - virtual bool isAccelerated() const override; + bool is2d() const override { return true; } + bool isAccelerated() const override; - virtual bool hasInvertibleTransform() const override { return state().m_hasInvertibleTransform; } + bool hasInvertibleTransform() const override { return state().hasInvertibleTransform; } + TextDirection toTextDirection(Direction, const RenderStyle** computedStyle = nullptr) const; -#if ENABLE(ACCELERATED_2D_CANVAS) && USE(ACCELERATED_COMPOSITING) - virtual PlatformLayer* platformLayer() const override; +#if ENABLE(ACCELERATED_2D_CANVAS) + PlatformLayer* platformLayer() const override; #endif + static const unsigned MaxSaveCount = 1024 * 16; Vector<State, 1> m_stateStack; - unsigned m_unrealizedSaveCount; + unsigned m_unrealizedSaveCount { 0 }; bool m_usesCSSCompatibilityParseMode; #if ENABLE(DASHBOARD_SUPPORT) bool m_usesDashboardCompatibilityMode; #endif + bool m_usesDisplayListDrawing { false }; + bool m_tracksDisplayListReplay { false }; + mutable std::unique_ptr<struct DisplayListDrawingContext> m_recordingContext; }; } // namespace WebCore -#endif +SPECIALIZE_TYPE_TRAITS_CANVASRENDERINGCONTEXT(WebCore::CanvasRenderingContext2D, is2d()) diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext2D.idl b/Source/WebCore/html/canvas/CanvasRenderingContext2D.idl index ffac89618..6dbb17553 100644 --- a/Source/WebCore/html/canvas/CanvasRenderingContext2D.idl +++ b/Source/WebCore/html/canvas/CanvasRenderingContext2D.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,146 +23,168 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +enum ImageSmoothingQuality { "low", "medium", "high" }; enum CanvasWindingRule { "nonzero", "evenodd" }; -interface CanvasRenderingContext2D : CanvasRenderingContext { +// FIXME: This should include SVGImageElement and ImageBitmap. +#if defined(ENABLE_VIDEO) && ENABLE_VIDEO +typedef (HTMLImageElement or HTMLVideoElement or HTMLCanvasElement) CanvasImageSource; +#else +typedef (HTMLImageElement or HTMLCanvasElement) CanvasImageSource; +#endif + +[ + CustomIsReachable, + JSGenerateToJSObject, + JSCustomMarkFunction, +] interface CanvasRenderingContext2D { + + // back-reference to the canvas + readonly attribute HTMLCanvasElement canvas; void save(); void restore(); - void scale(float sx, float sy); - void rotate(float angle); - void translate(float tx, float ty); - void transform(float m11, float m12, float m21, float m22, float dx, float dy); - void setTransform(float m11, float m12, float m21, float m22, float dx, float dy); + void commit(); + + void scale(unrestricted float sx, unrestricted float sy); + void rotate(unrestricted float angle); + void translate(unrestricted float tx, unrestricted float ty); + void transform(unrestricted float m11, unrestricted float m12, unrestricted float m21, unrestricted float m22, + unrestricted float dx, unrestricted float dy); + void setTransform(unrestricted float m11, unrestricted float m12, unrestricted float m21, unrestricted float m22, + unrestricted float dx, unrestricted float dy); + void resetTransform(); - attribute float globalAlpha; - [TreatNullAs=NullString] attribute DOMString globalCompositeOperation; + attribute unrestricted float globalAlpha; - [RaisesException] CanvasGradient createLinearGradient(float x0, float y0, float x1, float y1); - [RaisesException] CanvasGradient createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1); + attribute DOMString globalCompositeOperation; - attribute float lineWidth; - [TreatNullAs=NullString] attribute DOMString lineCap; - [TreatNullAs=NullString] attribute DOMString lineJoin; - attribute float miterLimit; + attribute unrestricted float lineWidth; + attribute DOMString lineCap; + attribute DOMString lineJoin; + attribute unrestricted float miterLimit; - attribute float shadowOffsetX; - attribute float shadowOffsetY; - attribute float shadowBlur; - [TreatNullAs=NullString] attribute DOMString shadowColor; + attribute unrestricted float shadowOffsetX; + attribute unrestricted float shadowOffsetY; + attribute unrestricted float shadowBlur; + attribute DOMString shadowColor; - void setLineDash(sequence<float> dash); - sequence<float> getLineDash(); - attribute float lineDashOffset; + void setLineDash(sequence<unrestricted float> dash); + sequence<unrestricted float> getLineDash(); + attribute unrestricted float lineDashOffset; - [Custom] attribute Array webkitLineDash; - attribute float webkitLineDashOffset; + attribute sequence<unrestricted float> webkitLineDash; + [ImplementedAs=lineDashOffset] attribute unrestricted float webkitLineDashOffset; - void clearRect(float x, float y, float width, float height); - void fillRect(float x, float y, float width, float height); + void clearRect(unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height); + void fillRect(unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height); void beginPath(); -#if defined(ENABLE_CANVAS_PATH) && ENABLE_CANVAS_PATH - attribute DOMPath currentPath; -#endif + void fill(DOMPath path, optional CanvasWindingRule winding = "nonzero"); + void stroke(DOMPath path); + void clip(DOMPath path, optional CanvasWindingRule winding = "nonzero"); - // FIXME: These methods should be shared with CanvasRenderingContext2D in the CanvasPathMethods interface. - void closePath(); - void moveTo(float x, float y); - void lineTo(float x, float y); - void quadraticCurveTo(float cpx, float cpy, float x, float y); - void bezierCurveTo(float cp1x, float cp1y, float cp2x, float cp2y, float x, float y); - [RaisesException] void arcTo(float x1, float y1, float x2, float y2, float radius); - void rect(float x, float y, float width, float height); - [RaisesException] void arc(float x, float y, float radius, float startAngle, float endAngle, [Default=Undefined] optional boolean anticlockwise); - - void fill(optional CanvasWindingRule winding); + void fill(optional CanvasWindingRule winding = "nonzero"); void stroke(); - void clip(optional CanvasWindingRule winding); - boolean isPointInPath(float x, float y, optional CanvasWindingRule winding); - boolean isPointInStroke(float x, float y); + void clip(optional CanvasWindingRule winding = "nonzero"); + + boolean isPointInPath(DOMPath path, unrestricted float x, unrestricted float y, optional CanvasWindingRule winding = "nonzero"); + boolean isPointInStroke(DOMPath path, unrestricted float x, unrestricted float y); + + boolean isPointInPath(unrestricted float x, unrestricted float y, optional CanvasWindingRule winding = "nonzero"); + boolean isPointInStroke(unrestricted float x, unrestricted float y); // text attribute DOMString font; attribute DOMString textAlign; attribute DOMString textBaseline; + attribute DOMString direction; TextMetrics measureText(DOMString text); // other - void setAlpha([Default=Undefined] optional float alpha); - void setCompositeOperation([Default=Undefined] optional DOMString compositeOperation); + void setAlpha(optional unrestricted float alpha = NaN); -#if !defined(LANGUAGE_CPP) || !LANGUAGE_CPP - void setLineWidth([Default=Undefined] optional float width); - void setLineCap([Default=Undefined] optional DOMString cap); - void setLineJoin([Default=Undefined] optional DOMString join); - void setMiterLimit([Default=Undefined] optional float limit); -#endif + // FIXME: Using "undefined" as default parameter value is wrong. + void setCompositeOperation(optional DOMString compositeOperation = "undefined"); - void clearShadow(); - - void fillText(DOMString text, float x, float y, optional float maxWidth); - void strokeText(DOMString text, float x, float y, optional float maxWidth); + void setLineWidth(optional unrestricted float width = NaN); - void setStrokeColor([StrictTypeChecking] DOMString color, optional float alpha); - void setStrokeColor(float grayLevel, optional float alpha); - void setStrokeColor(float r, float g, float b, float a); - void setStrokeColor(float c, float m, float y, float k, float a); + // FIXME: Using "undefined" as default parameter value is wrong. + void setLineCap(optional DOMString cap = "undefined"); + void setLineJoin(optional DOMString join = "undefined"); - void setFillColor([StrictTypeChecking] DOMString color, optional float alpha); - void setFillColor(float grayLevel, optional float alpha); - void setFillColor(float r, float g, float b, float a); - void setFillColor(float c, float m, float y, float k, float a); + void setMiterLimit(optional unrestricted float limit = NaN); - void strokeRect(float x, float y, float width, float height); + void clearShadow(); - [RaisesException] void drawImage(HTMLImageElement? image, float x, float y); - [RaisesException] void drawImage(HTMLImageElement? image, float x, float y, float width, float height); - [RaisesException] void drawImage(HTMLImageElement? image, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh); - [RaisesException] void drawImage(HTMLCanvasElement? canvas, float x, float y); - [RaisesException] void drawImage(HTMLCanvasElement? canvas, float x, float y, float width, float height); - [RaisesException] void drawImage(HTMLCanvasElement? canvas, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh); -#if defined(ENABLE_VIDEO) && ENABLE_VIDEO - [RaisesException] void drawImage(HTMLVideoElement? video, float x, float y); - [RaisesException] void drawImage(HTMLVideoElement? video, float x, float y, float width, float height); - [RaisesException] void drawImage(HTMLVideoElement? video, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh); -#endif + void fillText(DOMString text, unrestricted float x, unrestricted float y, optional unrestricted float maxWidth); + void strokeText(DOMString text, unrestricted float x, unrestricted float y, optional unrestricted float maxWidth); - void drawImageFromRect(HTMLImageElement image, - optional float sx, optional float sy, optional float sw, optional float sh, - optional float dx, optional float dy, optional float dw, optional float dh, - optional DOMString compositeOperation); + void setStrokeColor(DOMString color, optional unrestricted float alpha); + void setStrokeColor(unrestricted float grayLevel, optional float alpha = 1); + void setStrokeColor(unrestricted float r, unrestricted float g, unrestricted float b, unrestricted float a); + void setStrokeColor(unrestricted float c, unrestricted float m, unrestricted float y, unrestricted float k, unrestricted float a); - void setShadow(float width, float height, float blur, [StrictTypeChecking] optional DOMString color, optional float alpha); - void setShadow(float width, float height, float blur, float grayLevel, optional float alpha); - void setShadow(float width, float height, float blur, float r, float g, float b, float a); - void setShadow(float width, float height, float blur, float c, float m, float y, float k, float a); + void setFillColor(DOMString color, optional unrestricted float alpha); + void setFillColor(unrestricted float grayLevel, optional unrestricted float alpha = 1); + void setFillColor(unrestricted float r, unrestricted float g, unrestricted float b, unrestricted float a); + void setFillColor(unrestricted float c, unrestricted float m, unrestricted float y, unrestricted float k, unrestricted float a); - [RaisesException] void putImageData(ImageData? imagedata, float dx, float dy); - [RaisesException] void putImageData(ImageData? imagedata, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight); + void strokeRect(unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height); - [RaisesException] void webkitPutImageDataHD(ImageData? imagedata, float dx, float dy); - [RaisesException] void webkitPutImageDataHD(ImageData? imagedata, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight); + // FIXME: This should move to the CanvasDrawImage interface. + // FIXME: All the unrestricted float arguments below should be unrestricted doubles. + [MayThrowException] void drawImage(CanvasImageSource image, unrestricted float x, unrestricted float y); + [MayThrowException] void drawImage(CanvasImageSource image, unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height); + [MayThrowException] void drawImage(CanvasImageSource image, unrestricted float sx, unrestricted float sy, unrestricted float sw, unrestricted float sh, unrestricted float dx, unrestricted float dy, unrestricted float dw, unrestricted float dh); - [RaisesException] CanvasPattern createPattern(HTMLCanvasElement? canvas, [TreatNullAs=NullString] DOMString repetitionType); - [RaisesException] CanvasPattern createPattern(HTMLImageElement? image, [TreatNullAs=NullString] DOMString repetitionType); - [RaisesException] ImageData createImageData(ImageData? imagedata); - [RaisesException] ImageData createImageData(float sw, float sh); - [Custom] attribute custom strokeStyle; - [Custom] attribute custom fillStyle; + void drawImageFromRect(HTMLImageElement image, + optional unrestricted float sx = 0, optional unrestricted float sy = 0, optional unrestricted float sw = 0, optional unrestricted float sh = 0, + optional unrestricted float dx = 0, optional unrestricted float dy = 0, optional unrestricted float dw = 0, optional unrestricted float dh = 0, + optional DOMString compositeOperation = ""); + + void setShadow(unrestricted float width, unrestricted float height, unrestricted float blur, + optional DOMString color, optional unrestricted float alpha); + void setShadow(unrestricted float width, unrestricted float height, unrestricted float blur, unrestricted float grayLevel, + optional unrestricted float alpha = 1); + void setShadow(unrestricted float width, unrestricted float height, unrestricted float blur, unrestricted float r, + unrestricted float g, unrestricted float b, unrestricted float a); + void setShadow(float width, unrestricted float height, unrestricted float blur, unrestricted float c, unrestricted float m, + unrestricted float y, unrestricted float k, unrestricted float a); + + void putImageData(ImageData imagedata, float dx, float dy); + void putImageData(ImageData imagedata, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight); + + void webkitPutImageDataHD(ImageData imagedata, float dx, float dy); + void webkitPutImageDataHD(ImageData imagedata, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight); + + [MayThrowException] ImageData createImageData(ImageData? imagedata); + [MayThrowException] ImageData createImageData(float sw, float sh); + + attribute (DOMString or CanvasGradient or CanvasPattern) strokeStyle; + attribute (DOMString or CanvasGradient or CanvasPattern) fillStyle; + [MayThrowException] CanvasGradient createLinearGradient(float x0, float y0, float x1, float y1); + [MayThrowException] CanvasGradient createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1); + [MayThrowException] CanvasPattern? createPattern(CanvasImageSource image, [TreatNullAs=EmptyString] DOMString repetition); // pixel manipulation - [RaisesException] ImageData getImageData(float sx, float sy, float sw, float sh); - - [RaisesException] ImageData webkitGetImageDataHD(float sx, float sy, float sw, float sh); + [MayThrowException] ImageData getImageData(float sx, float sy, float sw, float sh); + [MayThrowException] ImageData webkitGetImageDataHD(float sx, float sy, float sw, float sh); + + // Focus rings + void drawFocusIfNeeded(Element element); + void drawFocusIfNeeded(DOMPath path, Element element); readonly attribute float webkitBackingStorePixelRatio; - attribute boolean webkitImageSmoothingEnabled; + attribute boolean imageSmoothingEnabled; + [ImplementedAs=imageSmoothingEnabled] attribute boolean webkitImageSmoothingEnabled; + attribute ImageSmoothingQuality imageSmoothingQuality; }; +CanvasRenderingContext2D implements CanvasPath; diff --git a/Source/WebCore/html/canvas/CanvasStyle.cpp b/Source/WebCore/html/canvas/CanvasStyle.cpp index 8b0883951..052fa3164 100644 --- a/Source/WebCore/html/canvas/CanvasStyle.cpp +++ b/Source/WebCore/html/canvas/CanvasStyle.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2008, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2006-2017 Apple Inc. All rights reserved. * Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies) * Copyright (C) 2007 Alp Toker <alp@atoker.com> * Copyright (C) 2008 Eric Seidel <eric@webkit.org> @@ -13,10 +13,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -43,260 +43,182 @@ namespace WebCore { -enum ColorParseResult { ParsedRGBA, ParsedCurrentColor, ParsedSystemColor, ParseFailed }; +static bool isCurrentColorString(const String& colorString) +{ + return equalLettersIgnoringASCIICase(colorString, "currentcolor"); +} -static ColorParseResult parseColor(RGBA32& parsedColor, const String& colorString, Document* document = 0) +static Color parseColor(const String& colorString, Document* document = nullptr) { - if (equalIgnoringCase(colorString, "currentcolor")) - return ParsedCurrentColor; - if (CSSParser::parseColor(parsedColor, colorString)) - return ParsedRGBA; - if (CSSParser::parseSystemColor(parsedColor, colorString, document)) - return ParsedSystemColor; - return ParseFailed; + Color color = CSSParser::parseColor(colorString); + if (color.isValid()) + return color; + return CSSParser::parseSystemColor(colorString, document); } -RGBA32 currentColor(HTMLCanvasElement* canvas) +Color currentColor(HTMLCanvasElement* canvas) { - if (!canvas || !canvas->inDocument() || !canvas->inlineStyle()) + if (!canvas || !canvas->isConnected() || !canvas->inlineStyle()) return Color::black; - RGBA32 rgba = Color::black; - CSSParser::parseColor(rgba, canvas->inlineStyle()->getPropertyValue(CSSPropertyColor)); - return rgba; + Color color = CSSParser::parseColor(canvas->inlineStyle()->getPropertyValue(CSSPropertyColor)); + if (!color.isValid()) + return Color::black; + return color; } -bool parseColorOrCurrentColor(RGBA32& parsedColor, const String& colorString, HTMLCanvasElement* canvas) +Color parseColorOrCurrentColor(const String& colorString, HTMLCanvasElement* canvas) { - ColorParseResult parseResult = parseColor(parsedColor, colorString, canvas ? &canvas->document() : 0); - switch (parseResult) { - case ParsedRGBA: - case ParsedSystemColor: - return true; - case ParsedCurrentColor: - parsedColor = currentColor(canvas); - return true; - case ParseFailed: - return false; - default: - ASSERT_NOT_REACHED(); - return false; - } + if (isCurrentColorString(colorString)) + return currentColor(canvas); + + return parseColor(colorString, canvas ? &canvas->document() : nullptr); } -CanvasStyle::CanvasStyle(RGBA32 rgba) - : m_rgba(rgba) - , m_type(RGBA) +CanvasStyle::CanvasStyle(Color color) + : m_style(color) { } CanvasStyle::CanvasStyle(float grayLevel, float alpha) - : m_rgba(makeRGBA32FromFloats(grayLevel, grayLevel, grayLevel, alpha)) - , m_type(RGBA) + : m_style(Color { grayLevel, grayLevel, grayLevel, alpha }) { } CanvasStyle::CanvasStyle(float r, float g, float b, float a) - : m_rgba(makeRGBA32FromFloats(r, g, b, a)) - , m_type(RGBA) + : m_style(Color { r, g, b, a }) { } CanvasStyle::CanvasStyle(float c, float m, float y, float k, float a) - : m_cmyka(new CMYKAValues(makeRGBAFromCMYKA(c, m, y, k, a), c, m, y, k, a)) - , m_type(CMYKA) + : m_style(CMYKAColor { Color { c, m, y, k, a }, c, m, y, k, a }) { } -CanvasStyle::CanvasStyle(PassRefPtr<CanvasGradient> gradient) - : m_gradient(gradient.leakRef()) - , m_type(Gradient) +CanvasStyle::CanvasStyle(CanvasGradient& gradient) + : m_style(makeRefPtr(gradient)) { - if (!m_gradient) - m_type = Invalid; } -CanvasStyle::CanvasStyle(PassRefPtr<CanvasPattern> pattern) - : m_pattern(pattern.leakRef()) - , m_type(ImagePattern) +CanvasStyle::CanvasStyle(CanvasPattern& pattern) + : m_style(makeRefPtr(pattern)) { - if (!m_pattern) - m_type = Invalid; } -CanvasStyle::~CanvasStyle() +inline CanvasStyle::CanvasStyle(CurrentColor color) + : m_style(color) { - if (m_type == Gradient) - m_gradient->deref(); - else if (m_type == ImagePattern) - m_pattern->deref(); - else if (m_type == CMYKA) - delete m_cmyka; } -CanvasStyle CanvasStyle::createFromString(const String& color, Document* document) +CanvasStyle CanvasStyle::createFromString(const String& colorString, Document* document) { - RGBA32 rgba; - ColorParseResult parseResult = parseColor(rgba, color, document); - switch (parseResult) { - case ParsedRGBA: - case ParsedSystemColor: - return CanvasStyle(rgba); - case ParsedCurrentColor: - return CanvasStyle(ConstructCurrentColor); - case ParseFailed: - return CanvasStyle(); - default: - ASSERT_NOT_REACHED(); - return CanvasStyle(); - } + if (isCurrentColorString(colorString)) + return CurrentColor { std::nullopt }; + + Color color = parseColor(colorString, document); + if (!color.isValid()) + return { }; + + return color; } -CanvasStyle CanvasStyle::createFromStringWithOverrideAlpha(const String& color, float alpha) +CanvasStyle CanvasStyle::createFromStringWithOverrideAlpha(const String& colorString, float alpha) { - RGBA32 rgba; - ColorParseResult parseResult = parseColor(rgba, color); - switch (parseResult) { - case ParsedRGBA: - return CanvasStyle(colorWithOverrideAlpha(rgba, alpha)); - case ParsedCurrentColor: - return CanvasStyle(CurrentColorWithOverrideAlpha, alpha); - case ParseFailed: - return CanvasStyle(); - default: - ASSERT_NOT_REACHED(); - return CanvasStyle(); - } + if (isCurrentColorString(colorString)) + return CurrentColor { alpha }; + + Color color = parseColor(colorString); + if (!color.isValid()) + return { }; + + return Color { colorWithOverrideAlpha(color.rgb(), alpha) }; } bool CanvasStyle::isEquivalentColor(const CanvasStyle& other) const { - if (m_type != other.m_type) - return false; + if (WTF::holds_alternative<Color>(m_style) && WTF::holds_alternative<Color>(other.m_style)) + return WTF::get<Color>(m_style) == WTF::get<Color>(other.m_style); - switch (m_type) { - case RGBA: - return m_rgba == other.m_rgba; - case CMYKA: - return m_cmyka->c == other.m_cmyka->c - && m_cmyka->m == other.m_cmyka->m - && m_cmyka->y == other.m_cmyka->y - && m_cmyka->k == other.m_cmyka->k - && m_cmyka->a == other.m_cmyka->a; - case Gradient: - case ImagePattern: - case CurrentColor: - case CurrentColorWithOverrideAlpha: - return false; - case Invalid: - break; + if (WTF::holds_alternative<CMYKAColor>(m_style) && WTF::holds_alternative<CMYKAColor>(other.m_style)) { + auto& a = WTF::get<CMYKAColor>(m_style); + auto& b = WTF::get<CMYKAColor>(other.m_style); + return a.c == b.c && a.m == b.m && a.y == b.y && a.k == b.k && a.a == b.a; } - ASSERT_NOT_REACHED(); return false; } bool CanvasStyle::isEquivalentRGBA(float r, float g, float b, float a) const { - if (m_type != RGBA) - return false; - - return m_rgba == makeRGBA32FromFloats(r, g, b, a); + return WTF::holds_alternative<Color>(m_style) && WTF::get<Color>(m_style) == Color { r, g, b, a }; } bool CanvasStyle::isEquivalentCMYKA(float c, float m, float y, float k, float a) const { - if (m_type != CMYKA) + if (!WTF::holds_alternative<CMYKAColor>(m_style)) return false; - return c == m_cmyka->c - && m == m_cmyka->m - && y == m_cmyka->y - && k == m_cmyka->k - && a == m_cmyka->a; -} - -CanvasStyle::CanvasStyle(const CanvasStyle& other) -{ - memcpy(this, &other, sizeof(CanvasStyle)); - if (m_type == Gradient) - m_gradient->ref(); - else if (m_type == ImagePattern) - m_pattern->ref(); - else if (m_type == CMYKA) - m_cmyka = new CMYKAValues(other.m_cmyka->rgba, other.m_cmyka->c, other.m_cmyka->m, other.m_cmyka->y, other.m_cmyka->k, other.m_cmyka->a); -} - -CanvasStyle& CanvasStyle::operator=(const CanvasStyle& other) -{ - if (this != &other) { - this->~CanvasStyle(); - new (this) CanvasStyle(other); - } - return *this; + auto& channels = WTF::get<CMYKAColor>(m_style); + return c == channels.c && m == channels.m && y == channels.y && k == channels.k && a == channels.a; } -void CanvasStyle::applyStrokeColor(GraphicsContext* context) const +void CanvasStyle::applyStrokeColor(GraphicsContext& context) const { - if (!context) - return; - switch (m_type) { - case RGBA: - context->setStrokeColor(m_rgba, ColorSpaceDeviceRGB); - break; - case CMYKA: { - // FIXME: Do this through platform-independent GraphicsContext API. - // We'll need a fancier Color abstraction to support CMYKA correctly + WTF::switchOn(m_style, + [&context] (const Color& color) { + context.setStrokeColor(color); + }, + [&context] (const CMYKAColor& color) { + // FIXME: Do this through platform-independent GraphicsContext API. + // We'll need a fancier Color abstraction to support CMYKA correctly #if USE(CG) - CGContextSetCMYKStrokeColor(context->platformContext(), m_cmyka->c, m_cmyka->m, m_cmyka->y, m_cmyka->k, m_cmyka->a); + CGContextSetCMYKStrokeColor(context.platformContext(), color.c, color.m, color.y, color.k, color.a); #else - context->setStrokeColor(m_cmyka->rgba, ColorSpaceDeviceRGB); + context.setStrokeColor(color.color); #endif - break; - } - case Gradient: - context->setStrokeGradient(canvasGradient()->gradient()); - break; - case ImagePattern: - context->setStrokePattern(canvasPattern()->pattern()); - break; - case CurrentColor: - case CurrentColorWithOverrideAlpha: - case Invalid: - ASSERT_NOT_REACHED(); - break; - } -} - -void CanvasStyle::applyFillColor(GraphicsContext* context) const -{ - if (!context) - return; - switch (m_type) { - case RGBA: - context->setFillColor(m_rgba, ColorSpaceDeviceRGB); - break; - case CMYKA: { - // FIXME: Do this through platform-independent GraphicsContext API. - // We'll need a fancier Color abstraction to support CMYKA correctly + }, + [&context] (const RefPtr<CanvasGradient>& gradient) { + context.setStrokeGradient(gradient->gradient()); + }, + [&context] (const RefPtr<CanvasPattern>& pattern) { + context.setStrokePattern(pattern->pattern()); + }, + [] (const CurrentColor&) { + ASSERT_NOT_REACHED(); + }, + [] (const Invalid&) { + ASSERT_NOT_REACHED(); + } + ); +} + +void CanvasStyle::applyFillColor(GraphicsContext& context) const +{ + WTF::switchOn(m_style, + [&context] (const Color& color) { + context.setFillColor(color); + }, + [&context] (const CMYKAColor& color) { + // FIXME: Do this through platform-independent GraphicsContext API. + // We'll need a fancier Color abstraction to support CMYKA correctly #if USE(CG) - CGContextSetCMYKFillColor(context->platformContext(), m_cmyka->c, m_cmyka->m, m_cmyka->y, m_cmyka->k, m_cmyka->a); + CGContextSetCMYKFillColor(context.platformContext(), color.c, color.m, color.y, color.k, color.a); #else - context->setFillColor(m_cmyka->rgba, ColorSpaceDeviceRGB); + context.setFillColor(color.color); #endif - break; - } - case Gradient: - context->setFillGradient(canvasGradient()->gradient()); - break; - case ImagePattern: - context->setFillPattern(canvasPattern()->pattern()); - break; - case CurrentColor: - case CurrentColorWithOverrideAlpha: - case Invalid: - ASSERT_NOT_REACHED(); - break; - } + }, + [&context] (const RefPtr<CanvasGradient>& gradient) { + context.setFillGradient(gradient->gradient()); + }, + [&context] (const RefPtr<CanvasPattern>& pattern) { + context.setFillPattern(pattern->pattern()); + }, + [] (const CurrentColor&) { + ASSERT_NOT_REACHED(); + }, + [] (const Invalid&) { + ASSERT_NOT_REACHED(); + } + ); } } diff --git a/Source/WebCore/html/canvas/CanvasStyle.h b/Source/WebCore/html/canvas/CanvasStyle.h index a5d3e5166..d78030ac9 100644 --- a/Source/WebCore/html/canvas/CanvasStyle.h +++ b/Source/WebCore/html/canvas/CanvasStyle.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2008, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2006-2017 Apple Inc. All rights reserved. * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) * * Redistribution and use in source and binary forms, with or without @@ -11,10 +11,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,136 +24,102 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CanvasStyle_h -#define CanvasStyle_h +#pragma once +#include "CanvasGradient.h" +#include "CanvasPattern.h" #include "Color.h" -#include <wtf/Assertions.h> -#include <wtf/RefCounted.h> -#include <wtf/text/WTFString.h> +#include <wtf/Variant.h> namespace WebCore { - class CanvasGradient; - class CanvasPattern; - class Document; - class GraphicsContext; - class HTMLCanvasElement; - - class CanvasStyle { - public: - CanvasStyle(); - explicit CanvasStyle(RGBA32); - CanvasStyle(float grayLevel, float alpha); - CanvasStyle(float r, float g, float b, float alpha); - CanvasStyle(float c, float m, float y, float k, float alpha); - explicit CanvasStyle(PassRefPtr<CanvasGradient>); - explicit CanvasStyle(PassRefPtr<CanvasPattern>); - ~CanvasStyle(); - - static CanvasStyle createFromString(const String& color, Document* = 0); - static CanvasStyle createFromStringWithOverrideAlpha(const String& color, float alpha); - - bool isValid() const { return m_type != Invalid; } - bool isCurrentColor() const { return m_type == CurrentColor || m_type == CurrentColorWithOverrideAlpha; } - bool hasOverrideAlpha() const { return m_type == CurrentColorWithOverrideAlpha; } - float overrideAlpha() const { ASSERT(m_type == CurrentColorWithOverrideAlpha); return m_overrideAlpha; } - - String color() const; - CanvasGradient* canvasGradient() const; - CanvasPattern* canvasPattern() const; - - void applyFillColor(GraphicsContext*) const; - void applyStrokeColor(GraphicsContext*) const; - - bool isEquivalentColor(const CanvasStyle&) const; - bool isEquivalentRGBA(float r, float g, float b, float a) const; - bool isEquivalentCMYKA(float c, float m, float y, float k, float a) const; - - CanvasStyle(const CanvasStyle&); - CanvasStyle& operator=(const CanvasStyle&); - CanvasStyle(CanvasStyle&&); - CanvasStyle& operator=(CanvasStyle&&); - - private: - enum Type { RGBA, CMYKA, Gradient, ImagePattern, CurrentColor, CurrentColorWithOverrideAlpha, Invalid }; - struct CMYKAValues { - WTF_MAKE_FAST_ALLOCATED; - WTF_MAKE_NONCOPYABLE(CMYKAValues); - public: - CMYKAValues() : rgba(0), c(0), m(0), y(0), k(0), a(0) { } - CMYKAValues(RGBA32 rgba, float cyan, float magenta, float yellow, float black, float alpha) : rgba(rgba), c(cyan), m(magenta), y(yellow), k(black), a(alpha) { } - RGBA32 rgba; - float c; - float m; - float y; - float k; - float a; - }; - - enum ConstructCurrentColorTag { ConstructCurrentColor }; - CanvasStyle(ConstructCurrentColorTag) : m_type(CurrentColor) { } - CanvasStyle(Type type, float overrideAlpha) - : m_overrideAlpha(overrideAlpha) - , m_type(type) +class Document; +class GraphicsContext; +class HTMLCanvasElement; + +class CanvasStyle { +public: + CanvasStyle(); + CanvasStyle(Color); + CanvasStyle(float grayLevel, float alpha); + CanvasStyle(float r, float g, float b, float alpha); + CanvasStyle(float c, float m, float y, float k, float alpha); + CanvasStyle(CanvasGradient&); + CanvasStyle(CanvasPattern&); + + static CanvasStyle createFromString(const String& color, Document* = nullptr); + static CanvasStyle createFromStringWithOverrideAlpha(const String& color, float alpha); + + bool isValid() const { return !WTF::holds_alternative<Invalid>(m_style); } + bool isCurrentColor() const { return WTF::holds_alternative<CurrentColor>(m_style); } + bool hasOverrideAlpha() const { return isCurrentColor() && WTF::get<CurrentColor>(m_style).overrideAlpha; } + float overrideAlpha() const { return WTF::get<CurrentColor>(m_style).overrideAlpha.value(); } + + String color() const; + CanvasGradient* canvasGradient() const; + CanvasPattern* canvasPattern() const; + + void applyFillColor(GraphicsContext&) const; + void applyStrokeColor(GraphicsContext&) const; + + bool isEquivalentColor(const CanvasStyle&) const; + bool isEquivalentRGBA(float red, float green, float blue, float alpha) const; + bool isEquivalentCMYKA(float cyan, float magenta, float yellow, float black, float alpha) const; + +private: + struct Invalid { }; + + struct CMYKAColor { + CMYKAColor() = default; + + CMYKAColor(Color color, float cyan, float magenta, float yellow, float black, float alpha) + : color(color), c(cyan), m(magenta), y(yellow), k(black), a(alpha) { } - union { - RGBA32 m_rgba; - float m_overrideAlpha; - CanvasGradient* m_gradient; - CanvasPattern* m_pattern; - CMYKAValues* m_cmyka; - }; - Type m_type; + Color color; + float c { 0 }; + float m { 0 }; + float y { 0 }; + float k { 0 }; + float a { 0 }; }; - RGBA32 currentColor(HTMLCanvasElement*); - bool parseColorOrCurrentColor(RGBA32& parsedColor, const String& colorString, HTMLCanvasElement*); - - inline CanvasStyle::CanvasStyle() - : m_type(Invalid) - { - } - - inline CanvasGradient* CanvasStyle::canvasGradient() const - { - if (m_type == Gradient) - return m_gradient; - return 0; - } - - inline CanvasPattern* CanvasStyle::canvasPattern() const - { - if (m_type == ImagePattern) - return m_pattern; - return 0; - } - - inline String CanvasStyle::color() const - { - ASSERT(m_type == RGBA || m_type == CMYKA); - if (m_type == RGBA) - return Color(m_rgba).serialized(); - return Color(m_cmyka->rgba).serialized(); - } - - inline CanvasStyle::CanvasStyle(CanvasStyle&& other) - { - memcpy(this, &other, sizeof(CanvasStyle)); - other.m_type = Invalid; - } - - inline CanvasStyle& CanvasStyle::operator=(CanvasStyle&& other) - { - if (this != &other) { - memcpy(this, &other, sizeof(CanvasStyle)); - other.m_type = Invalid; - } - return *this; - } + struct CurrentColor { + std::optional<float> overrideAlpha; + }; -} // namespace WebCore + CanvasStyle(CurrentColor); + + Variant<Invalid, Color, CMYKAColor, RefPtr<CanvasGradient>, RefPtr<CanvasPattern>, CurrentColor> m_style; +}; + +Color currentColor(HTMLCanvasElement*); +Color parseColorOrCurrentColor(const String& colorString, HTMLCanvasElement*); + +inline CanvasStyle::CanvasStyle() + : m_style(Invalid { }) +{ +} -#endif +inline CanvasGradient* CanvasStyle::canvasGradient() const +{ + if (!WTF::holds_alternative<RefPtr<CanvasGradient>>(m_style)) + return nullptr; + return WTF::get<RefPtr<CanvasGradient>>(m_style).get(); +} + +inline CanvasPattern* CanvasStyle::canvasPattern() const +{ + if (!WTF::holds_alternative<RefPtr<CanvasPattern>>(m_style)) + return nullptr; + return WTF::get<RefPtr<CanvasPattern>>(m_style).get(); +} + +inline String CanvasStyle::color() const +{ + auto& color = WTF::holds_alternative<Color>(m_style) ? WTF::get<Color>(m_style) : WTF::get<CMYKAColor>(m_style).color; + return color.serialized(); +} + +} // namespace WebCore diff --git a/Source/WebCore/html/canvas/DOMPath.cpp b/Source/WebCore/html/canvas/DOMPath.cpp new file mode 100644 index 000000000..d51b78ada --- /dev/null +++ b/Source/WebCore/html/canvas/DOMPath.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2015 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" +#include "DOMPath.h" + +namespace WebCore { + +DOMPath::~DOMPath() +{ +} + +} diff --git a/Source/WebCore/html/canvas/DOMPath.h b/Source/WebCore/html/canvas/DOMPath.h index 6358e4602..0bbff134f 100644 --- a/Source/WebCore/html/canvas/DOMPath.h +++ b/Source/WebCore/html/canvas/DOMPath.h @@ -25,46 +25,49 @@ * SUCH DAMAGE. */ -#ifndef DOMPath_h -#define DOMPath_h +#pragma once -#if ENABLE(CANVAS_PATH) - -#include "CanvasPathMethods.h" -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> - -#if ENABLE(SVG) +#include "CanvasPath.h" +#include "SVGMatrix.h" #include "SVGPathUtilities.h" -#endif +#include <wtf/RefCounted.h> namespace WebCore { -class DOMPath : public RefCounted<DOMPath>, public CanvasPathMethods { +class WEBCORE_EXPORT DOMPath final : public RefCounted<DOMPath>, public CanvasPath { WTF_MAKE_FAST_ALLOCATED; public: - static PassRefPtr<DOMPath> create() { return adoptRef(new DOMPath); } - static PassRefPtr<DOMPath> create(const Path& path) { return adoptRef(new DOMPath(path)); } - static PassRefPtr<DOMPath> create(const DOMPath* path) { return create(path->path()); } + virtual ~DOMPath(); -#if ENABLE(SVG) - static PassRefPtr<DOMPath> create(const String& pathData) + static Ref<DOMPath> create() { return adoptRef(*new DOMPath); } + static Ref<DOMPath> create(const Path& path) { return adoptRef(*new DOMPath(path)); } + static Ref<DOMPath> create(const DOMPath& path) { return create(path.path()); } + + static Ref<DOMPath> create(const String& pathData) { Path path; buildPathFromString(pathData, path); return create(path); } + +#if ENABLE(CANVAS_PATH) + void addPath(const DOMPath* path) { addPath(path, AffineTransform()); } + void addPath(const DOMPath* path, SVGMatrix& matrix) { addPath(path, matrix.propertyReference()); } + void addPath(const DOMPath* path, const AffineTransform& transform) + { + if (!path || !transform.isInvertible()) + return; + m_path.addPath(path->path(), transform); + } #endif const Path& path() const { return m_path; } private: DOMPath() { } - DOMPath(const Path& path) : CanvasPathMethods(path) { } + DOMPath(const Path& path) + : CanvasPath(path) + { } }; -} - -#endif - -#endif +} // namespace WebCore diff --git a/Source/WebCore/html/canvas/DOMPath.idl b/Source/WebCore/html/canvas/DOMPath.idl index 0c262c681..40bd2ba5c 100644 --- a/Source/WebCore/html/canvas/DOMPath.idl +++ b/Source/WebCore/html/canvas/DOMPath.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Apple Inc. All rights reserved. * Copyright (C) 2012, 2013 Adobe Systems Incorporated. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,42 +29,14 @@ [ Constructor, Constructor(DOMPath path), -#if defined(ENABLE_SVG) && ENABLE_SVG Constructor(DOMString text), -#endif - Conditional=CANVAS_PATH, - InterfaceName=Path, + ExportMacro=WEBCORE_EXPORT, + InterfaceName=Path2D, ] interface DOMPath { - - // FIXME: These methods should be shared with CanvasRenderingContext2D in the CanvasPathMethods interface. - void closePath(); - void moveTo([Default=Undefined] optional float x, - [Default=Undefined] optional float y); - void lineTo([Default=Undefined] optional float x, - [Default=Undefined] optional float y); - void quadraticCurveTo([Default=Undefined] optional float cpx, - [Default=Undefined] optional float cpy, - [Default=Undefined] optional float x, - [Default=Undefined] optional float y); - void bezierCurveTo([Default=Undefined] optional float cp1x, - [Default=Undefined] optional float cp1y, - [Default=Undefined] optional float cp2x, - [Default=Undefined] optional float cp2y, - [Default=Undefined] optional float x, - [Default=Undefined] optional float y); - [RaisesException] void arcTo([Default=Undefined] optional float x1, - [Default=Undefined] optional float y1, - [Default=Undefined] optional float x2, - [Default=Undefined] optional float y2, - [Default=Undefined] optional float radius); - void rect([Default=Undefined] optional float x, - [Default=Undefined] optional float y, - [Default=Undefined] optional float width, - [Default=Undefined] optional float height); - [RaisesException] void arc([Default=Undefined] optional float x, - [Default=Undefined] optional float y, - [Default=Undefined] optional float radius, - [Default=Undefined] optional float startAngle, - [Default=Undefined] optional float endAngle, - [Default=Undefined] optional boolean anticlockwise); + // FIXME: This should be: + // [Conditional=CANVAS_PATH] void addPath(DOMPath path, optional SVGMatrix transform); + [Conditional=CANVAS_PATH] void addPath(DOMPath? path); + [Conditional=CANVAS_PATH] void addPath(DOMPath? path, SVGMatrix transform); }; + +DOMPath implements CanvasPath; diff --git a/Source/WebCore/html/canvas/EXTBlendMinMax.cpp b/Source/WebCore/html/canvas/EXTBlendMinMax.cpp new file mode 100644 index 000000000..762a5d9f6 --- /dev/null +++ b/Source/WebCore/html/canvas/EXTBlendMinMax.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2014 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(WEBGL) +#include "EXTBlendMinMax.h" + +namespace WebCore { + +EXTBlendMinMax::EXTBlendMinMax(WebGLRenderingContextBase& context) + : WebGLExtension(context) +{ +} + +EXTBlendMinMax::~EXTBlendMinMax() +{ +} + +WebGLExtension::ExtensionName EXTBlendMinMax::getName() const +{ + return EXTBlendMinMaxName; +} + +} // namespace WebCore + +#endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/EXTBlendMinMax.h b/Source/WebCore/html/canvas/EXTBlendMinMax.h new file mode 100644 index 000000000..59596844e --- /dev/null +++ b/Source/WebCore/html/canvas/EXTBlendMinMax.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2014 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "WebGLExtension.h" + +namespace WebCore { + +class EXTBlendMinMax final : public WebGLExtension { +public: + explicit EXTBlendMinMax(WebGLRenderingContextBase&); + virtual ~EXTBlendMinMax(); + + ExtensionName getName() const override; +}; + +} // namespace WebCore diff --git a/Source/WebCore/html/canvas/EXTBlendMinMax.idl b/Source/WebCore/html/canvas/EXTBlendMinMax.idl new file mode 100644 index 000000000..c1a8c19a0 --- /dev/null +++ b/Source/WebCore/html/canvas/EXTBlendMinMax.idl @@ -0,0 +1,33 @@ +/* +* Copyright (C) 2014 Apple Inc. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +[ + Conditional=WEBGL, + GenerateIsReachable=ImplWebGLRenderingContext, + NoInterfaceObject, +] interface EXTBlendMinMax { + const unsigned long MIN_EXT = 0x8007; + const unsigned long MAX_EXT = 0x8008; +}; diff --git a/Source/WebCore/html/canvas/EXTDrawBuffers.idl b/Source/WebCore/html/canvas/EXTDrawBuffers.idl deleted file mode 100644 index 864e5504e..000000000 --- a/Source/WebCore/html/canvas/EXTDrawBuffers.idl +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2013 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -typedef unsigned long GLenum; - -[ - NoInterfaceObject, - Conditional=WEBGL, - GenerateIsReachable=ImplWebGLRenderingContext, - DoNotCheckConstants, -] interface EXTDrawBuffers { - const GLenum COLOR_ATTACHMENT0_EXT = 0x8CE0; - const GLenum COLOR_ATTACHMENT1_EXT = 0x8CE1; - const GLenum COLOR_ATTACHMENT2_EXT = 0x8CE2; - const GLenum COLOR_ATTACHMENT3_EXT = 0x8CE3; - const GLenum COLOR_ATTACHMENT4_EXT = 0x8CE4; - const GLenum COLOR_ATTACHMENT5_EXT = 0x8CE5; - const GLenum COLOR_ATTACHMENT6_EXT = 0x8CE6; - const GLenum COLOR_ATTACHMENT7_EXT = 0x8CE7; - const GLenum COLOR_ATTACHMENT8_EXT = 0x8CE8; - const GLenum COLOR_ATTACHMENT9_EXT = 0x8CE9; - const GLenum COLOR_ATTACHMENT10_EXT = 0x8CEA; - const GLenum COLOR_ATTACHMENT11_EXT = 0x8CEB; - const GLenum COLOR_ATTACHMENT12_EXT = 0x8CEC; - const GLenum COLOR_ATTACHMENT13_EXT = 0x8CED; - const GLenum COLOR_ATTACHMENT14_EXT = 0x8CEE; - const GLenum COLOR_ATTACHMENT15_EXT = 0x8CEF; - - const GLenum DRAW_BUFFER0_EXT = 0x8825; - const GLenum DRAW_BUFFER1_EXT = 0x8826; - const GLenum DRAW_BUFFER2_EXT = 0x8827; - const GLenum DRAW_BUFFER3_EXT = 0x8828; - const GLenum DRAW_BUFFER4_EXT = 0x8829; - const GLenum DRAW_BUFFER5_EXT = 0x882A; - const GLenum DRAW_BUFFER6_EXT = 0x882B; - const GLenum DRAW_BUFFER7_EXT = 0x882C; - const GLenum DRAW_BUFFER8_EXT = 0x882D; - const GLenum DRAW_BUFFER9_EXT = 0x882E; - const GLenum DRAW_BUFFER10_EXT = 0x882F; - const GLenum DRAW_BUFFER11_EXT = 0x8830; - const GLenum DRAW_BUFFER12_EXT = 0x8831; - const GLenum DRAW_BUFFER13_EXT = 0x8832; - const GLenum DRAW_BUFFER14_EXT = 0x8833; - const GLenum DRAW_BUFFER15_EXT = 0x8834; - - const GLenum MAX_COLOR_ATTACHMENTS_EXT = 0x8CDF; - const GLenum MAX_DRAW_BUFFERS_EXT = 0x8824; - - void drawBuffersEXT(sequence<GLenum> buffers); -}; diff --git a/Source/WebCore/html/canvas/EXTFragDepth.cpp b/Source/WebCore/html/canvas/EXTFragDepth.cpp new file mode 100644 index 000000000..626309c83 --- /dev/null +++ b/Source/WebCore/html/canvas/EXTFragDepth.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2014 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(WEBGL) +#include "EXTFragDepth.h" + +namespace WebCore { + +EXTFragDepth::EXTFragDepth(WebGLRenderingContextBase& context) + : WebGLExtension(context) +{ +} + +EXTFragDepth::~EXTFragDepth() +{ +} + +WebGLExtension::ExtensionName EXTFragDepth::getName() const +{ + return EXTFragDepthName; +} + +} // namespace WebCore + +#endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/EXTFragDepth.h b/Source/WebCore/html/canvas/EXTFragDepth.h new file mode 100644 index 000000000..5e8a4f9c2 --- /dev/null +++ b/Source/WebCore/html/canvas/EXTFragDepth.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2014 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "WebGLExtension.h" + +namespace WebCore { + +class EXTFragDepth final : public WebGLExtension { +public: + explicit EXTFragDepth(WebGLRenderingContextBase&); + virtual ~EXTFragDepth(); + + ExtensionName getName() const override; +}; + +} // namespace WebCore diff --git a/Source/WebCore/html/canvas/EXTFragDepth.idl b/Source/WebCore/html/canvas/EXTFragDepth.idl new file mode 100644 index 000000000..5edc4aa30 --- /dev/null +++ b/Source/WebCore/html/canvas/EXTFragDepth.idl @@ -0,0 +1,31 @@ +/* +* Copyright (C) 2014 Apple Inc. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +[ + NoInterfaceObject, + Conditional=WEBGL, + GenerateIsReachable=ImplWebGLRenderingContext +] interface EXTFragDepth { +}; diff --git a/Source/WebCore/html/canvas/EXTShaderTextureLOD.cpp b/Source/WebCore/html/canvas/EXTShaderTextureLOD.cpp new file mode 100644 index 000000000..46e406a43 --- /dev/null +++ b/Source/WebCore/html/canvas/EXTShaderTextureLOD.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2014 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(WEBGL) +#include "EXTShaderTextureLOD.h" + +namespace WebCore { + +EXTShaderTextureLOD::EXTShaderTextureLOD(WebGLRenderingContextBase& context) + : WebGLExtension(context) +{ +} + +EXTShaderTextureLOD::~EXTShaderTextureLOD() +{ +} + +WebGLExtension::ExtensionName EXTShaderTextureLOD::getName() const +{ + return EXTShaderTextureLODName; +} + +} // namespace WebCore + +#endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/EXTShaderTextureLOD.h b/Source/WebCore/html/canvas/EXTShaderTextureLOD.h new file mode 100644 index 000000000..47c192f20 --- /dev/null +++ b/Source/WebCore/html/canvas/EXTShaderTextureLOD.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2014 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "WebGLExtension.h" + +namespace WebCore { + +class EXTShaderTextureLOD final : public WebGLExtension { +public: + explicit EXTShaderTextureLOD(WebGLRenderingContextBase&); + virtual ~EXTShaderTextureLOD(); + + ExtensionName getName() const override; +}; + +} // namespace WebCore diff --git a/Source/WebCore/html/canvas/EXTShaderTextureLOD.idl b/Source/WebCore/html/canvas/EXTShaderTextureLOD.idl new file mode 100644 index 000000000..3baa298a3 --- /dev/null +++ b/Source/WebCore/html/canvas/EXTShaderTextureLOD.idl @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2014 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +[ + NoInterfaceObject, + Conditional=WEBGL, + GenerateIsReachable=ImplWebGLRenderingContext +] interface EXTShaderTextureLOD { +}; diff --git a/Source/WebCore/html/canvas/EXTTextureFilterAnisotropic.cpp b/Source/WebCore/html/canvas/EXTTextureFilterAnisotropic.cpp index 8ae249456..0bd3dfa2b 100644 --- a/Source/WebCore/html/canvas/EXTTextureFilterAnisotropic.cpp +++ b/Source/WebCore/html/canvas/EXTTextureFilterAnisotropic.cpp @@ -31,7 +31,7 @@ namespace WebCore { -EXTTextureFilterAnisotropic::EXTTextureFilterAnisotropic(WebGLRenderingContext* context) +EXTTextureFilterAnisotropic::EXTTextureFilterAnisotropic(WebGLRenderingContextBase& context) : WebGLExtension(context) { } @@ -45,11 +45,6 @@ WebGLExtension::ExtensionName EXTTextureFilterAnisotropic::getName() const return EXTTextureFilterAnisotropicName; } -OwnPtr<EXTTextureFilterAnisotropic> EXTTextureFilterAnisotropic::create(WebGLRenderingContext* context) -{ - return adoptPtr(new EXTTextureFilterAnisotropic(context)); -} - } // namespace WebCore #endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/EXTTextureFilterAnisotropic.h b/Source/WebCore/html/canvas/EXTTextureFilterAnisotropic.h index 5e76ebb01..4197d5fbb 100644 --- a/Source/WebCore/html/canvas/EXTTextureFilterAnisotropic.h +++ b/Source/WebCore/html/canvas/EXTTextureFilterAnisotropic.h @@ -23,25 +23,18 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef EXTTextureFilterAnisotropic_h -#define EXTTextureFilterAnisotropic_h +#pragma once #include "WebGLExtension.h" -#include <wtf/PassOwnPtr.h> namespace WebCore { -class EXTTextureFilterAnisotropic : public WebGLExtension { +class EXTTextureFilterAnisotropic final : public WebGLExtension { public: - static OwnPtr<EXTTextureFilterAnisotropic> create(WebGLRenderingContext*); - + explicit EXTTextureFilterAnisotropic(WebGLRenderingContextBase&); virtual ~EXTTextureFilterAnisotropic(); - virtual ExtensionName getName() const override; -private: - EXTTextureFilterAnisotropic(WebGLRenderingContext*); + ExtensionName getName() const override; }; } // namespace WebCore - -#endif // EXTTextureFilterAnisotropic_h diff --git a/Source/WebCore/html/canvas/EXTTextureFilterAnisotropic.idl b/Source/WebCore/html/canvas/EXTTextureFilterAnisotropic.idl index 45ac89515..9002231c5 100644 --- a/Source/WebCore/html/canvas/EXTTextureFilterAnisotropic.idl +++ b/Source/WebCore/html/canvas/EXTTextureFilterAnisotropic.idl @@ -24,11 +24,10 @@ */ [ - NoInterfaceObject, Conditional=WEBGL, GenerateIsReachable=ImplWebGLRenderingContext, - DoNotCheckConstants + NoInterfaceObject, ] interface EXTTextureFilterAnisotropic { - const unsigned int TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE; - const unsigned int MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF; + const unsigned long TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE; + const unsigned long MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF; }; diff --git a/Source/WebCore/html/canvas/EXTsRGB.cpp b/Source/WebCore/html/canvas/EXTsRGB.cpp new file mode 100644 index 000000000..e4edf51c7 --- /dev/null +++ b/Source/WebCore/html/canvas/EXTsRGB.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2014 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(WEBGL) +#include "EXTsRGB.h" + +namespace WebCore { + +EXTsRGB::EXTsRGB(WebGLRenderingContextBase& context) + : WebGLExtension(context) +{ +} + +EXTsRGB::~EXTsRGB() +{ +} + +WebGLExtension::ExtensionName EXTsRGB::getName() const +{ + return EXTsRGBName; +} + +} // namespace WebCore + +#endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/EXTsRGB.h b/Source/WebCore/html/canvas/EXTsRGB.h new file mode 100644 index 000000000..4a69cba75 --- /dev/null +++ b/Source/WebCore/html/canvas/EXTsRGB.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2014 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "WebGLExtension.h" + +namespace WebCore { + +class EXTsRGB final : public WebGLExtension { +public: + explicit EXTsRGB(WebGLRenderingContextBase&); + virtual ~EXTsRGB(); + + ExtensionName getName() const override; +}; + +} // namespace WebCore diff --git a/Source/WebCore/html/canvas/EXTsRGB.idl b/Source/WebCore/html/canvas/EXTsRGB.idl new file mode 100644 index 000000000..cb0da3e9e --- /dev/null +++ b/Source/WebCore/html/canvas/EXTsRGB.idl @@ -0,0 +1,35 @@ +/* +* Copyright (C) 2014 Apple Inc. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +[ + Conditional=WEBGL, + GenerateIsReachable=ImplWebGLRenderingContext, + NoInterfaceObject, +] interface EXTsRGB { + const unsigned long SRGB_EXT = 0x8C40; + const unsigned long SRGB_ALPHA_EXT = 0x8C42; + const unsigned long SRGB8_ALPHA8_EXT = 0x8C43; + const unsigned long FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT = 0x8210; +}; diff --git a/Source/WebCore/html/canvas/OESElementIndexUint.cpp b/Source/WebCore/html/canvas/OESElementIndexUint.cpp index 66024153a..101c5f10d 100644 --- a/Source/WebCore/html/canvas/OESElementIndexUint.cpp +++ b/Source/WebCore/html/canvas/OESElementIndexUint.cpp @@ -31,7 +31,7 @@ namespace WebCore { -OESElementIndexUint::OESElementIndexUint(WebGLRenderingContext* context) +OESElementIndexUint::OESElementIndexUint(WebGLRenderingContextBase& context) : WebGLExtension(context) { } @@ -45,11 +45,6 @@ WebGLExtension::ExtensionName OESElementIndexUint::getName() const return OESElementIndexUintName; } -OwnPtr<OESElementIndexUint> OESElementIndexUint::create(WebGLRenderingContext* context) -{ - return adoptPtr(new OESElementIndexUint(context)); -} - } // namespace WebCore #endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/OESElementIndexUint.h b/Source/WebCore/html/canvas/OESElementIndexUint.h index 83ce56a8d..460321d44 100644 --- a/Source/WebCore/html/canvas/OESElementIndexUint.h +++ b/Source/WebCore/html/canvas/OESElementIndexUint.h @@ -23,25 +23,18 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef OESElementIndexUint_h -#define OESElementIndexUint_h +#pragma once #include "WebGLExtension.h" -#include <wtf/PassOwnPtr.h> namespace WebCore { -class OESElementIndexUint : public WebGLExtension { +class OESElementIndexUint final : public WebGLExtension { public: - static OwnPtr<OESElementIndexUint> create(WebGLRenderingContext*); - + explicit OESElementIndexUint(WebGLRenderingContextBase&); virtual ~OESElementIndexUint(); - virtual ExtensionName getName() const override; -private: - OESElementIndexUint(WebGLRenderingContext*); + ExtensionName getName() const override; }; } // namespace WebCore - -#endif // OESElementIndexUint_h diff --git a/Source/WebCore/html/canvas/OESStandardDerivatives.cpp b/Source/WebCore/html/canvas/OESStandardDerivatives.cpp index 0f2c876c7..dcbb819e3 100644 --- a/Source/WebCore/html/canvas/OESStandardDerivatives.cpp +++ b/Source/WebCore/html/canvas/OESStandardDerivatives.cpp @@ -31,7 +31,7 @@ namespace WebCore { -OESStandardDerivatives::OESStandardDerivatives(WebGLRenderingContext* context) +OESStandardDerivatives::OESStandardDerivatives(WebGLRenderingContextBase& context) : WebGLExtension(context) { } @@ -45,11 +45,6 @@ WebGLExtension::ExtensionName OESStandardDerivatives::getName() const return OESStandardDerivativesName; } -OwnPtr<OESStandardDerivatives> OESStandardDerivatives::create(WebGLRenderingContext* context) -{ - return adoptPtr(new OESStandardDerivatives(context)); -} - } // namespace WebCore #endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/OESStandardDerivatives.h b/Source/WebCore/html/canvas/OESStandardDerivatives.h index a21dfd89c..ccfc88406 100644 --- a/Source/WebCore/html/canvas/OESStandardDerivatives.h +++ b/Source/WebCore/html/canvas/OESStandardDerivatives.h @@ -23,25 +23,18 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef OESStandardDerivatives_h -#define OESStandardDerivatives_h +#pragma once #include "WebGLExtension.h" -#include <wtf/PassOwnPtr.h> namespace WebCore { -class OESStandardDerivatives : public WebGLExtension { +class OESStandardDerivatives final : public WebGLExtension { public: - static OwnPtr<OESStandardDerivatives> create(WebGLRenderingContext*); - + explicit OESStandardDerivatives(WebGLRenderingContextBase&); virtual ~OESStandardDerivatives(); - virtual ExtensionName getName() const override; -private: - OESStandardDerivatives(WebGLRenderingContext*); + ExtensionName getName() const override; }; } // namespace WebCore - -#endif // OESStandardDerivatives_h diff --git a/Source/WebCore/html/canvas/OESStandardDerivatives.idl b/Source/WebCore/html/canvas/OESStandardDerivatives.idl index 850260bfe..d9d99838b 100644 --- a/Source/WebCore/html/canvas/OESStandardDerivatives.idl +++ b/Source/WebCore/html/canvas/OESStandardDerivatives.idl @@ -24,10 +24,10 @@ */ [ - NoInterfaceObject, Conditional=WEBGL, + DoNotCheckConstants, GenerateIsReachable=ImplWebGLRenderingContext, - DoNotCheckConstants + NoInterfaceObject, ] interface OESStandardDerivatives { - const unsigned int FRAGMENT_SHADER_DERIVATIVE_HINT_OES = 0x8B8B; + const unsigned long FRAGMENT_SHADER_DERIVATIVE_HINT_OES = 0x8B8B; }; diff --git a/Source/WebCore/html/canvas/OESTextureFloat.cpp b/Source/WebCore/html/canvas/OESTextureFloat.cpp index 223136c42..60d2f7b50 100644 --- a/Source/WebCore/html/canvas/OESTextureFloat.cpp +++ b/Source/WebCore/html/canvas/OESTextureFloat.cpp @@ -31,7 +31,7 @@ namespace WebCore { -OESTextureFloat::OESTextureFloat(WebGLRenderingContext* context) +OESTextureFloat::OESTextureFloat(WebGLRenderingContextBase& context) : WebGLExtension(context) { } @@ -45,11 +45,6 @@ WebGLExtension::ExtensionName OESTextureFloat::getName() const return OESTextureFloatName; } -OwnPtr<OESTextureFloat> OESTextureFloat::create(WebGLRenderingContext* context) -{ - return adoptPtr(new OESTextureFloat(context)); -} - } // namespace WebCore #endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/OESTextureFloat.h b/Source/WebCore/html/canvas/OESTextureFloat.h index 6c67ea11b..e7c0715dd 100644 --- a/Source/WebCore/html/canvas/OESTextureFloat.h +++ b/Source/WebCore/html/canvas/OESTextureFloat.h @@ -23,25 +23,18 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef OESTextureFloat_h -#define OESTextureFloat_h +#pragma once #include "WebGLExtension.h" -#include <wtf/PassOwnPtr.h> namespace WebCore { -class OESTextureFloat : public WebGLExtension { +class OESTextureFloat final : public WebGLExtension { public: - static OwnPtr<OESTextureFloat> create(WebGLRenderingContext*); - + OESTextureFloat(WebGLRenderingContextBase&); virtual ~OESTextureFloat(); - virtual ExtensionName getName() const override; -private: - OESTextureFloat(WebGLRenderingContext*); + ExtensionName getName() const override; }; } // namespace WebCore - -#endif // OESTextureFloat_h diff --git a/Source/WebCore/html/canvas/OESTextureFloatLinear.cpp b/Source/WebCore/html/canvas/OESTextureFloatLinear.cpp index d93491608..fce917908 100644 --- a/Source/WebCore/html/canvas/OESTextureFloatLinear.cpp +++ b/Source/WebCore/html/canvas/OESTextureFloatLinear.cpp @@ -30,7 +30,7 @@ namespace WebCore { -OESTextureFloatLinear::OESTextureFloatLinear(WebGLRenderingContext* context) +OESTextureFloatLinear::OESTextureFloatLinear(WebGLRenderingContextBase& context) : WebGLExtension(context) { } @@ -44,11 +44,6 @@ WebGLExtension::ExtensionName OESTextureFloatLinear::getName() const return OESTextureFloatLinearName; } -OwnPtr<OESTextureFloatLinear> OESTextureFloatLinear::create(WebGLRenderingContext* context) -{ - return adoptPtr(new OESTextureFloatLinear(context)); -} - } // namespace WebCore #endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/OESTextureFloatLinear.h b/Source/WebCore/html/canvas/OESTextureFloatLinear.h index 3e9fe87cc..93dd13460 100644 --- a/Source/WebCore/html/canvas/OESTextureFloatLinear.h +++ b/Source/WebCore/html/canvas/OESTextureFloatLinear.h @@ -23,25 +23,18 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef OESTextureFloatLinear_h -#define OESTextureFloatLinear_h +#pragma once #include "WebGLExtension.h" -#include <wtf/PassOwnPtr.h> namespace WebCore { -class OESTextureFloatLinear : public WebGLExtension { +class OESTextureFloatLinear final : public WebGLExtension { public: - static OwnPtr<OESTextureFloatLinear> create(WebGLRenderingContext*); - + explicit OESTextureFloatLinear(WebGLRenderingContextBase&); virtual ~OESTextureFloatLinear(); - virtual ExtensionName getName() const override; -private: - OESTextureFloatLinear(WebGLRenderingContext*); + ExtensionName getName() const override; }; } // namespace WebCore - -#endif // OESTextureFloat_h diff --git a/Source/WebCore/html/canvas/OESTextureHalfFloat.cpp b/Source/WebCore/html/canvas/OESTextureHalfFloat.cpp index fd2e25bd2..f1f7496dd 100644 --- a/Source/WebCore/html/canvas/OESTextureHalfFloat.cpp +++ b/Source/WebCore/html/canvas/OESTextureHalfFloat.cpp @@ -31,7 +31,7 @@ namespace WebCore { -OESTextureHalfFloat::OESTextureHalfFloat(WebGLRenderingContext* context) +OESTextureHalfFloat::OESTextureHalfFloat(WebGLRenderingContextBase& context) : WebGLExtension(context) { } @@ -45,11 +45,6 @@ WebGLExtension::ExtensionName OESTextureHalfFloat::getName() const return OESTextureHalfFloatName; } -OwnPtr<OESTextureHalfFloat> OESTextureHalfFloat::create(WebGLRenderingContext* context) -{ - return adoptPtr(new OESTextureHalfFloat(context)); -} - } // namespace WebCore #endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/OESTextureHalfFloat.h b/Source/WebCore/html/canvas/OESTextureHalfFloat.h index c8ab9feb1..b3f676dd7 100644 --- a/Source/WebCore/html/canvas/OESTextureHalfFloat.h +++ b/Source/WebCore/html/canvas/OESTextureHalfFloat.h @@ -23,25 +23,18 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef OESTextureHalfFloat_h -#define OESTextureHalfFloat_h +#pragma once #include "WebGLExtension.h" -#include <wtf/PassOwnPtr.h> namespace WebCore { -class OESTextureHalfFloat : public WebGLExtension { +class OESTextureHalfFloat final : public WebGLExtension { public: - static OwnPtr<OESTextureHalfFloat> create(WebGLRenderingContext*); - + OESTextureHalfFloat(WebGLRenderingContextBase&); virtual ~OESTextureHalfFloat(); - virtual ExtensionName getName() const override; -private: - OESTextureHalfFloat(WebGLRenderingContext*); + ExtensionName getName() const override; }; } // namespace WebCore - -#endif // OESTextureHalfFloat_h diff --git a/Source/WebCore/html/canvas/OESTextureHalfFloatLinear.cpp b/Source/WebCore/html/canvas/OESTextureHalfFloatLinear.cpp index e2ec8b250..359e30016 100644 --- a/Source/WebCore/html/canvas/OESTextureHalfFloatLinear.cpp +++ b/Source/WebCore/html/canvas/OESTextureHalfFloatLinear.cpp @@ -30,7 +30,7 @@ namespace WebCore { -OESTextureHalfFloatLinear::OESTextureHalfFloatLinear(WebGLRenderingContext* context) +OESTextureHalfFloatLinear::OESTextureHalfFloatLinear(WebGLRenderingContextBase& context) : WebGLExtension(context) { } @@ -44,11 +44,6 @@ WebGLExtension::ExtensionName OESTextureHalfFloatLinear::getName() const return OESTextureHalfFloatLinearName; } -OwnPtr<OESTextureHalfFloatLinear> OESTextureHalfFloatLinear::create(WebGLRenderingContext* context) -{ - return adoptPtr(new OESTextureHalfFloatLinear(context)); -} - } // namespace WebCore #endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/OESTextureHalfFloatLinear.h b/Source/WebCore/html/canvas/OESTextureHalfFloatLinear.h index 073b48a9f..4810a112b 100644 --- a/Source/WebCore/html/canvas/OESTextureHalfFloatLinear.h +++ b/Source/WebCore/html/canvas/OESTextureHalfFloatLinear.h @@ -23,25 +23,18 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef OESTextureHalfFloatLinear_h -#define OESTextureHalfFloatLinear_h +#pragma once #include "WebGLExtension.h" -#include <wtf/PassOwnPtr.h> namespace WebCore { -class OESTextureHalfFloatLinear : public WebGLExtension { +class OESTextureHalfFloatLinear final : public WebGLExtension { public: - static OwnPtr<OESTextureHalfFloatLinear> create(WebGLRenderingContext*); - + OESTextureHalfFloatLinear(WebGLRenderingContextBase&); virtual ~OESTextureHalfFloatLinear(); - virtual ExtensionName getName() const override; -private: - OESTextureHalfFloatLinear(WebGLRenderingContext*); + ExtensionName getName() const override; }; } // namespace WebCore - -#endif // OESTextureHalfFloatLinear_h diff --git a/Source/WebCore/html/canvas/OESVertexArrayObject.cpp b/Source/WebCore/html/canvas/OESVertexArrayObject.cpp index 36ab832d9..111bc3be6 100644 --- a/Source/WebCore/html/canvas/OESVertexArrayObject.cpp +++ b/Source/WebCore/html/canvas/OESVertexArrayObject.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,90 +24,72 @@ */ #include "config.h" +#include "OESVertexArrayObject.h" #if ENABLE(WEBGL) -#include "OESVertexArrayObject.h" - #include "Extensions3D.h" +#include "WebGLRenderingContext.h" namespace WebCore { -OESVertexArrayObject::OESVertexArrayObject(WebGLRenderingContext* context) +OESVertexArrayObject::OESVertexArrayObject(WebGLRenderingContextBase& context) : WebGLExtension(context) { } -OESVertexArrayObject::~OESVertexArrayObject() -{ -} - WebGLExtension::ExtensionName OESVertexArrayObject::getName() const { return OESVertexArrayObjectName; } -OwnPtr<OESVertexArrayObject> OESVertexArrayObject::create(WebGLRenderingContext* context) +RefPtr<WebGLVertexArrayObjectOES> OESVertexArrayObject::createVertexArrayOES() { - return adoptPtr(new OESVertexArrayObject(context)); -} + if (m_context.isContextLost()) + return nullptr; -PassRefPtr<WebGLVertexArrayObjectOES> OESVertexArrayObject::createVertexArrayOES() -{ - if (m_context->isContextLost()) - return 0; - - RefPtr<WebGLVertexArrayObjectOES> o = WebGLVertexArrayObjectOES::create(m_context, WebGLVertexArrayObjectOES::VaoTypeUser); - m_context->addContextObject(o.get()); - return o.release(); + auto object = WebGLVertexArrayObjectOES::create(m_context, WebGLVertexArrayObjectOES::Type::User); + m_context.addContextObject(object.get()); + return WTFMove(object); } void OESVertexArrayObject::deleteVertexArrayOES(WebGLVertexArrayObjectOES* arrayObject) { - if (!arrayObject || m_context->isContextLost()) + if (!arrayObject || m_context.isContextLost()) return; - - if (!arrayObject->isDefaultObject() && arrayObject == m_context->m_boundVertexArrayObject) - m_context->setBoundVertexArrayObject(0); - arrayObject->deleteObject(m_context->graphicsContext3D()); + if (!arrayObject->isDefaultObject() && arrayObject == static_cast<WebGLRenderingContext&>(m_context).m_boundVertexArrayObject) + static_cast<WebGLRenderingContext&>(m_context).setBoundVertexArrayObject(nullptr); + + arrayObject->deleteObject(m_context.graphicsContext3D()); } GC3Dboolean OESVertexArrayObject::isVertexArrayOES(WebGLVertexArrayObjectOES* arrayObject) { - if (!arrayObject || m_context->isContextLost()) - return 0; - - if (!arrayObject->hasEverBeenBound()) - return 0; - - Extensions3D* extensions = m_context->graphicsContext3D()->getExtensions(); - return extensions->isVertexArrayOES(arrayObject->object()); + return arrayObject && !m_context.isContextLost() && arrayObject->hasEverBeenBound() + && m_context.graphicsContext3D()->getExtensions().isVertexArrayOES(arrayObject->object()); } -void OESVertexArrayObject::bindVertexArrayOES(WebGLVertexArrayObjectOES* arrayObject, ExceptionCode& ec) +void OESVertexArrayObject::bindVertexArrayOES(WebGLVertexArrayObjectOES* arrayObject) { - UNUSED_PARAM(ec); - if (m_context->isContextLost()) + if (m_context.isContextLost()) return; - - if (arrayObject && (arrayObject->isDeleted() || !arrayObject->validate(0, context()))) { - m_context->graphicsContext3D()->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); + + if (arrayObject && (arrayObject->isDeleted() || !arrayObject->validate(nullptr, context()))) { + m_context.graphicsContext3D()->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); return; } - - Extensions3D* extensions = m_context->graphicsContext3D()->getExtensions(); + + auto& extensions = m_context.graphicsContext3D()->getExtensions(); + auto& context = downcast<WebGLRenderingContext>(m_context); if (arrayObject && !arrayObject->isDefaultObject() && arrayObject->object()) { - extensions->bindVertexArrayOES(arrayObject->object()); - + extensions.bindVertexArrayOES(arrayObject->object()); arrayObject->setHasEverBeenBound(); - m_context->setBoundVertexArrayObject(arrayObject); + context.setBoundVertexArrayObject(arrayObject); } else { - extensions->bindVertexArrayOES(0); - m_context->setBoundVertexArrayObject(0); + extensions.bindVertexArrayOES(0); + context.setBoundVertexArrayObject(nullptr); } - - m_context->cleanupAfterGraphicsCall(false); } } // namespace WebCore diff --git a/Source/WebCore/html/canvas/OESVertexArrayObject.h b/Source/WebCore/html/canvas/OESVertexArrayObject.h index b9f859929..0654954c1 100644 --- a/Source/WebCore/html/canvas/OESVertexArrayObject.h +++ b/Source/WebCore/html/canvas/OESVertexArrayObject.h @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,36 +23,27 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef OESVertexArrayObject_h -#define OESVertexArrayObject_h +#pragma once #include "GraphicsTypes3D.h" #include "WebGLExtension.h" -#include <wtf/PassOwnPtr.h> namespace WebCore { -class WebGLRenderingContext; +class WebGLRenderingContextBase; class WebGLVertexArrayObjectOES; -typedef int ExceptionCode; - -class OESVertexArrayObject : public WebGLExtension { +class OESVertexArrayObject final : public WebGLExtension { public: - static OwnPtr<OESVertexArrayObject> create(WebGLRenderingContext*); + explicit OESVertexArrayObject(WebGLRenderingContextBase&); - virtual ~OESVertexArrayObject(); - virtual ExtensionName getName() const override; - - PassRefPtr<WebGLVertexArrayObjectOES> createVertexArrayOES(); + RefPtr<WebGLVertexArrayObjectOES> createVertexArrayOES(); void deleteVertexArrayOES(WebGLVertexArrayObjectOES*); GC3Dboolean isVertexArrayOES(WebGLVertexArrayObjectOES*); - void bindVertexArrayOES(WebGLVertexArrayObjectOES*, ExceptionCode&); + void bindVertexArrayOES(WebGLVertexArrayObjectOES*); private: - OESVertexArrayObject(WebGLRenderingContext*); + ExtensionName getName() const final; }; } // namespace WebCore - -#endif // OESVertexArrayObject_h diff --git a/Source/WebCore/html/canvas/OESVertexArrayObject.idl b/Source/WebCore/html/canvas/OESVertexArrayObject.idl index 53f475d94..62bdd0456 100644 --- a/Source/WebCore/html/canvas/OESVertexArrayObject.idl +++ b/Source/WebCore/html/canvas/OESVertexArrayObject.idl @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,15 +24,15 @@ */ [ - NoInterfaceObject, Conditional=WEBGL, - GenerateIsReachable=ImplWebGLRenderingContext, DoNotCheckConstants, + GenerateIsReachable=ImplWebGLRenderingContext, + NoInterfaceObject, ] interface OESVertexArrayObject { - const unsigned int VERTEX_ARRAY_BINDING_OES = 0x85B5; - - [StrictTypeChecking] WebGLVertexArrayObjectOES createVertexArrayOES(); - [StrictTypeChecking] void deleteVertexArrayOES([Default=Undefined] optional WebGLVertexArrayObjectOES arrayObject); - [StrictTypeChecking] boolean isVertexArrayOES([Default=Undefined] optional WebGLVertexArrayObjectOES arrayObject); - [StrictTypeChecking, RaisesException] void bindVertexArrayOES([Default=Undefined] optional WebGLVertexArrayObjectOES arrayObject); + const unsigned long VERTEX_ARRAY_BINDING_OES = 0x85B5; + + WebGLVertexArrayObjectOES createVertexArrayOES(); + void deleteVertexArrayOES(optional WebGLVertexArrayObjectOES? arrayObject = null); + boolean isVertexArrayOES(optional WebGLVertexArrayObjectOES? arrayObject = null); + void bindVertexArrayOES(optional WebGLVertexArrayObjectOES? arrayObject = null); }; diff --git a/Source/WebCore/html/canvas/WebGL2RenderingContext.cpp b/Source/WebCore/html/canvas/WebGL2RenderingContext.cpp new file mode 100644 index 000000000..92eefac0c --- /dev/null +++ b/Source/WebCore/html/canvas/WebGL2RenderingContext.cpp @@ -0,0 +1,1830 @@ +/* + * Copyright (C) 2015-2017 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebGL2RenderingContext.h" + +#if ENABLE(WEBGL2) + +#include "CachedImage.h" +#include "EXTTextureFilterAnisotropic.h" +#include "Extensions3D.h" +#include "HTMLCanvasElement.h" +#include "HTMLImageElement.h" +#include "HTMLVideoElement.h" +#include "ImageData.h" +#include "OESTextureFloat.h" +#include "OESTextureFloatLinear.h" +#include "OESTextureHalfFloat.h" +#include "OESTextureHalfFloatLinear.h" +#include "RenderBox.h" +#include "WebGLActiveInfo.h" +#include "WebGLCompressedTextureATC.h" +#include "WebGLCompressedTexturePVRTC.h" +#include "WebGLCompressedTextureS3TC.h" +#include "WebGLDebugRendererInfo.h" +#include "WebGLDebugShaders.h" +#include "WebGLDepthTexture.h" +#include "WebGLLoseContext.h" +#include "WebGLQuery.h" +#include "WebGLSampler.h" +#include "WebGLSync.h" +#include "WebGLTransformFeedback.h" +#include "WebGLVertexArrayObject.h" +#include <JavaScriptCore/GenericTypedArrayViewInlines.h> +#include <JavaScriptCore/JSGenericTypedArrayViewInlines.h> + +namespace WebCore { + +WebGL2RenderingContext::WebGL2RenderingContext(HTMLCanvasElement& passedCanvas, GraphicsContext3DAttributes attributes) + : WebGLRenderingContextBase(passedCanvas, attributes) +{ +} + +WebGL2RenderingContext::WebGL2RenderingContext(HTMLCanvasElement& passedCanvas, Ref<GraphicsContext3D>&& context, GraphicsContext3DAttributes attributes) + : WebGLRenderingContextBase(passedCanvas, WTFMove(context), attributes) +{ + initializeShaderExtensions(); + initializeVertexArrayObjects(); +} + +void WebGL2RenderingContext::initializeVertexArrayObjects() +{ + m_defaultVertexArrayObject = WebGLVertexArrayObject::create(*this, WebGLVertexArrayObject::Type::Default); + addContextObject(*m_defaultVertexArrayObject); + m_boundVertexArrayObject = m_defaultVertexArrayObject; + if (!isGLES2Compliant()) + initVertexAttrib0(); +} + +void WebGL2RenderingContext::initializeShaderExtensions() +{ + m_context->getExtensions().ensureEnabled("GL_OES_standard_derivatives"); + m_context->getExtensions().ensureEnabled("GL_EXT_draw_buffers"); + m_context->getExtensions().ensureEnabled("GL_EXT_shader_texture_lod"); + m_context->getExtensions().ensureEnabled("GL_EXT_frag_depth"); +} + +inline static std::optional<unsigned> arrayBufferViewElementSize(const ArrayBufferView& data) +{ + switch (data.getType()) { + case JSC::NotTypedArray: + case JSC::TypeDataView: + return std::nullopt; + case JSC::TypeInt8: + case JSC::TypeUint8: + case JSC::TypeUint8Clamped: + case JSC::TypeInt16: + case JSC::TypeUint16: + case JSC::TypeInt32: + case JSC::TypeUint32: + case JSC::TypeFloat32: + case JSC::TypeFloat64: + return elementSize(data.getType()); + } +} + +void WebGL2RenderingContext::bufferData(GC3Denum target, const ArrayBufferView& data, GC3Denum usage, GC3Duint srcOffset, GC3Duint length) +{ + auto optionalElementSize = arrayBufferViewElementSize(data); + if (!optionalElementSize) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bufferData", "Invalid type of Array Buffer View"); + return; + } + auto elementSize = optionalElementSize.value(); + Checked<GC3Duint, RecordOverflow> checkedElementSize(elementSize); + + Checked<GC3Duint, RecordOverflow> checkedSrcOffset(srcOffset); + Checked<GC3Duint, RecordOverflow> checkedByteSrcOffset = checkedSrcOffset * checkedElementSize; + Checked<GC3Duint, RecordOverflow> checkedlength(length); + Checked<GC3Duint, RecordOverflow> checkedByteLength = checkedlength * checkedElementSize; + + if (checkedByteSrcOffset.hasOverflowed() + || checkedByteLength.hasOverflowed() + || checkedByteSrcOffset.unsafeGet() > data.byteLength() + || checkedByteLength.unsafeGet() > data.byteLength() - checkedByteSrcOffset.unsafeGet()) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "srcOffset or length is out of bounds"); + return; + } + + auto slice = Uint8Array::create(data.possiblySharedBuffer(), data.byteOffset() + checkedByteSrcOffset.unsafeGet(), checkedByteLength.unsafeGet()); + if (!slice) { + synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY, "bufferData", "Could not create intermediate ArrayBufferView"); + return; + } + WebGLRenderingContextBase::bufferData(target, BufferDataSource(slice.get()), usage); +} + +void WebGL2RenderingContext::bufferSubData(GC3Denum target, long long offset, const ArrayBufferView& data, GC3Duint srcOffset, GC3Duint length) +{ + auto optionalElementSize = arrayBufferViewElementSize(data); + if (!optionalElementSize) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bufferSubData", "Invalid type of Array Buffer View"); + return; + } + auto elementSize = optionalElementSize.value(); + Checked<GC3Duint, RecordOverflow> checkedElementSize(elementSize); + + Checked<GC3Duint, RecordOverflow> checkedSrcOffset(srcOffset); + Checked<GC3Duint, RecordOverflow> checkedByteSrcOffset = checkedSrcOffset * checkedElementSize; + Checked<GC3Duint, RecordOverflow> checkedlength(length); + Checked<GC3Duint, RecordOverflow> checkedByteLength = checkedlength * checkedElementSize; + + if (checkedByteSrcOffset.hasOverflowed() + || checkedByteLength.hasOverflowed() + || checkedByteSrcOffset.unsafeGet() > data.byteLength() + || checkedByteLength.unsafeGet() > data.byteLength() - checkedByteSrcOffset.unsafeGet()) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "srcOffset or length is out of bounds"); + return; + } + + auto slice = Uint8Array::create(data.possiblySharedBuffer(), data.byteOffset() + checkedByteSrcOffset.unsafeGet(), checkedByteLength.unsafeGet()); + if (!slice) { + synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY, "bufferSubData", "Could not create intermediate ArrayBufferView"); + return; + } + + WebGLRenderingContextBase::bufferSubData(target, offset, BufferDataSource(slice.get())); +} + +void WebGL2RenderingContext::copyBufferSubData(GC3Denum readTarget, GC3Denum writeTarget, GC3Dint64 readOffset, GC3Dint64 writeOffset, GC3Dint64 size) +{ + if (isContextLostOrPending()) + return; + if ((readTarget == GraphicsContext3D::ELEMENT_ARRAY_BUFFER && writeTarget != GraphicsContext3D::ELEMENT_ARRAY_BUFFER) + || (writeTarget == GraphicsContext3D::ELEMENT_ARRAY_BUFFER && readTarget != GraphicsContext3D::ELEMENT_ARRAY_BUFFER)) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyBufferSubData", "Either both targets need to be ELEMENT_ARRAY_BUFFER or neither should be ELEMENT_ARRAY_BUFFER."); + return; + } + if (readOffset < 0 || writeOffset < 0 || size < 0) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyBufferSubData", "offset < 0"); + return; + } + WebGLBuffer* readBuffer = validateBufferDataParameters("copyBufferSubData", readTarget, GraphicsContext3D::STATIC_DRAW); + WebGLBuffer* writeBuffer = validateBufferDataParameters("copyBufferSubData", writeTarget, GraphicsContext3D::STATIC_DRAW); + if (!readBuffer || !writeBuffer) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyBufferSubData", "Invalid readTarget or writeTarget"); + return; + } + + Checked<GC3Dintptr, RecordOverflow> checkedReadOffset(readOffset); + Checked<GC3Dintptr, RecordOverflow> checkedWriteOffset(writeOffset); + Checked<GC3Dsizeiptr, RecordOverflow> checkedSize(size); + if (checkedReadOffset.hasOverflowed() || checkedWriteOffset.hasOverflowed() || checkedSize.hasOverflowed()) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyBufferSubData", "Offset or size is too big"); + return; + } + + if (!writeBuffer->associateCopyBufferSubData(*readBuffer, checkedReadOffset.unsafeGet(), checkedWriteOffset.unsafeGet(), checkedSize.unsafeGet())) { + this->synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyBufferSubData", "offset out of range"); + return; + } + + m_context->moveErrorsToSyntheticErrorList(); +#if PLATFORM(COCOA) + m_context->copyBufferSubData(readTarget, writeTarget, checkedReadOffset.unsafeGet(), checkedWriteOffset.unsafeGet(), checkedSize.unsafeGet()); +#endif + if (m_context->moveErrorsToSyntheticErrorList()) { + // The bufferSubData function failed. Tell the buffer it doesn't have the data it thinks it does. + writeBuffer->disassociateBufferData(); + } +} + +void WebGL2RenderingContext::getBufferSubData(GC3Denum target, long long srcByteOffset, RefPtr<ArrayBufferView>&& dstData, GC3Duint dstOffset, GC3Duint length) +{ + if (isContextLostOrPending()) + return; + WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GraphicsContext3D::STATIC_DRAW); + if (!buffer) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getBufferSubData", "No WebGLBuffer is bound to target"); + return; + } + + // FIXME: Implement "If target is TRANSFORM_FEEDBACK_BUFFER, and any transform feedback object is currently active, an INVALID_OPERATION error is generated." + + if (!dstData) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getBufferSubData", "Null dstData"); + return; + } + + auto optionalElementSize = arrayBufferViewElementSize(*dstData); + if (!optionalElementSize) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getBufferSubData", "Invalid type of Array Buffer View"); + return; + } + auto elementSize = optionalElementSize.value(); + auto dstDataLength = dstData->byteLength() / elementSize; + + if (dstOffset > dstDataLength) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getBufferSubData", "dstOffset is larger than the length of the destination buffer."); + return; + } + + GC3Duint copyLength = length ? length : dstDataLength - dstOffset; + + Checked<GC3Duint, RecordOverflow> checkedDstOffset(dstOffset); + Checked<GC3Duint, RecordOverflow> checkedCopyLength(copyLength); + auto checkedDestinationEnd = checkedDstOffset + checkedCopyLength; + if (checkedDestinationEnd.hasOverflowed()) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getBufferSubData", "dstOffset + copyLength is too high"); + return; + } + + if (checkedDestinationEnd.unsafeGet() > dstDataLength) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getBufferSubData", "end of written destination is past the end of the buffer"); + return; + } + + if (srcByteOffset < 0) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getBufferSubData", "srcByteOffset is less than 0"); + return; + } + + Checked<GC3Dintptr, RecordOverflow> checkedSrcByteOffset(srcByteOffset); + Checked<GC3Dintptr, RecordOverflow> checkedCopyLengthPtr(copyLength); + Checked<GC3Dintptr, RecordOverflow> checkedElementSize(elementSize); + auto checkedSourceEnd = checkedSrcByteOffset + checkedCopyLengthPtr * checkedElementSize; + if (checkedSourceEnd.hasOverflowed() || checkedSourceEnd.unsafeGet() > buffer->byteLength()) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getBufferSubData", "Parameters would read outside the bounds of the source buffer"); + return; + } + + m_context->moveErrorsToSyntheticErrorList(); +#if PLATFORM(COCOA) + // FIXME: Coalesce multiple getBufferSubData() calls to use a single map() call + void* ptr = m_context->mapBufferRange(target, checkedSrcByteOffset.unsafeGet(), static_cast<GC3Dsizeiptr>(checkedCopyLengthPtr.unsafeGet() * checkedElementSize.unsafeGet()), GraphicsContext3D::MAP_READ_BIT); + memcpy(static_cast<char*>(dstData->baseAddress()) + dstData->byteOffset() + dstOffset * elementSize, ptr, copyLength * elementSize); + bool success = m_context->unmapBuffer(target); + ASSERT_UNUSED(success, success); +#endif + m_context->moveErrorsToSyntheticErrorList(); +} + +void WebGL2RenderingContext::blitFramebuffer(GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dbitfield, GC3Denum) +{ +} + +void WebGL2RenderingContext::framebufferTextureLayer(GC3Denum, GC3Denum, GC3Duint, GC3Dint, GC3Dint) +{ +} + +WebGLAny WebGL2RenderingContext::getInternalformatParameter(GC3Denum, GC3Denum, GC3Denum) +{ + return nullptr; +} + +void WebGL2RenderingContext::invalidateFramebuffer(GC3Denum, const Vector<GC3Denum>&) +{ +} + +void WebGL2RenderingContext::invalidateSubFramebuffer(GC3Denum, const Vector<GC3Denum>&, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei) +{ +} + +void WebGL2RenderingContext::readBuffer(GC3Denum) +{ +} + +void WebGL2RenderingContext::renderbufferStorageMultisample(GC3Denum, GC3Dsizei, GC3Denum, GC3Dsizei, GC3Dsizei) +{ +} + +bool WebGL2RenderingContext::validateTexStorageFuncParameters(GC3Denum target, GC3Dsizei levels, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, const char* functionName) +{ + if (width < 0 || height < 0) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0"); + return false; + } + + if (width > m_maxTextureSize || height > m_maxTextureSize) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "texture dimensions are larger than the maximum texture size"); + return false; + } + + if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) { + if (width != height) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width != height for cube map"); + return false; + } + } else if (target != GraphicsContext3D::TEXTURE_2D) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target"); + return false; + } + + if (levels < 0 || levels > m_maxTextureLevel) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "number of levels is out of bounds"); + return false; + } + + switch (internalFormat) { + case GraphicsContext3D::R8: + case GraphicsContext3D::R8_SNORM: + case GraphicsContext3D::R16F: + case GraphicsContext3D::R32F: + case GraphicsContext3D::R8UI: + case GraphicsContext3D::R8I: + case GraphicsContext3D::R16UI: + case GraphicsContext3D::R16I: + case GraphicsContext3D::R32UI: + case GraphicsContext3D::R32I: + case GraphicsContext3D::RG8: + case GraphicsContext3D::RG8_SNORM: + case GraphicsContext3D::RG16F: + case GraphicsContext3D::RG32F: + case GraphicsContext3D::RG8UI: + case GraphicsContext3D::RG8I: + case GraphicsContext3D::RG16UI: + case GraphicsContext3D::RG16I: + case GraphicsContext3D::RG32UI: + case GraphicsContext3D::RG32I: + case GraphicsContext3D::RGB8: + case GraphicsContext3D::SRGB8: + case GraphicsContext3D::RGB565: + case GraphicsContext3D::RGB8_SNORM: + case GraphicsContext3D::R11F_G11F_B10F: + case GraphicsContext3D::RGB9_E5: + case GraphicsContext3D::RGB16F: + case GraphicsContext3D::RGB32F: + case GraphicsContext3D::RGB8UI: + case GraphicsContext3D::RGB8I: + case GraphicsContext3D::RGB16UI: + case GraphicsContext3D::RGB16I: + case GraphicsContext3D::RGB32UI: + case GraphicsContext3D::RGB32I: + case GraphicsContext3D::RGBA8: + case GraphicsContext3D::SRGB8_ALPHA8: + case GraphicsContext3D::RGBA8_SNORM: + case GraphicsContext3D::RGB5_A1: + case GraphicsContext3D::RGBA4: + case GraphicsContext3D::RGB10_A2: + case GraphicsContext3D::RGBA16F: + case GraphicsContext3D::RGBA32F: + case GraphicsContext3D::RGBA8UI: + case GraphicsContext3D::RGBA8I: + case GraphicsContext3D::RGB10_A2UI: + case GraphicsContext3D::RGBA16UI: + case GraphicsContext3D::RGBA16I: + case GraphicsContext3D::RGBA32I: + case GraphicsContext3D::RGBA32UI: + case GraphicsContext3D::DEPTH_COMPONENT16: + case GraphicsContext3D::DEPTH_COMPONENT24: + case GraphicsContext3D::DEPTH_COMPONENT32F: + case GraphicsContext3D::DEPTH24_STENCIL8: + case GraphicsContext3D::DEPTH32F_STENCIL8: + break; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "Unknown internalFormat"); + return false; + } + + return true; +} + +void WebGL2RenderingContext::texStorage2D(GC3Denum target, GC3Dsizei levels, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height) +{ + if (isContextLostOrPending()) + return; + + auto* texture = validateTextureBinding("texStorage2D", target, false); + if (!texture) + return; + + if (!validateTexStorageFuncParameters(target, levels, internalFormat, width, height, "texStorage2D")) + return; + + if (!validateNPOTTextureLevel(width, height, levels, "texStorage2D")) + return; + + if (texture->immutable()) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "texStorage2D", "texStorage2D already called on this texture"); + return; + } + texture->setImmutable(); + + m_context->texStorage2D(target, levels, internalFormat, width, height); + + { + GC3Denum format; + GC3Denum type; + if (!GraphicsContext3D::possibleFormatAndTypeForInternalFormat(internalFormat, format, type)) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texStorage2D", "Texture has unknown internal format"); + return; + } + + GC3Dsizei levelWidth = width; + GC3Dsizei levelHeight = height; + + unsigned size; + GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &size, nullptr); + if (error != GraphicsContext3D::NO_ERROR) { + synthesizeGLError(error, "texStorage2D", "bad dimensions"); + return; + } + + Vector<char> data(size); + memset(data.data(), 0, size); + + for (GC3Dsizei level = 0; level < levels; ++level) { + if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) { + m_context->texSubImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X, level, 0, 0, levelWidth, levelHeight, format, type, data.data()); + m_context->texSubImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X, level, 0, 0, levelWidth, levelHeight, format, type, data.data()); + m_context->texSubImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y, level, 0, 0, levelWidth, levelHeight, format, type, data.data()); + m_context->texSubImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y, level, 0, 0, levelWidth, levelHeight, format, type, data.data()); + m_context->texSubImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z, level, 0, 0, levelWidth, levelHeight, format, type, data.data()); + m_context->texSubImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z, level, 0, 0, levelWidth, levelHeight, format, type, data.data()); + } else + m_context->texSubImage2D(target, level, 0, 0, levelWidth, levelHeight, format, type, data.data()); + levelWidth = std::max(1, levelWidth / 2); + levelHeight = std::max(1, levelHeight / 2); + } + } + + for (GC3Dsizei level = 0; level < levels; ++level) { + if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) { + texture->setLevelInfo(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE); + texture->setLevelInfo(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE); + texture->setLevelInfo(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE); + texture->setLevelInfo(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE); + texture->setLevelInfo(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE); + texture->setLevelInfo(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE); + } else + texture->setLevelInfo(target, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE); + } +} + +void WebGL2RenderingContext::texStorage3D(GC3Denum, GC3Dsizei, GC3Denum, GC3Dsizei, GC3Dsizei, GC3Dsizei) +{ +} + +void WebGL2RenderingContext::texImage3D(GC3Denum, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei, GC3Dsizei, GC3Dint, GC3Denum, GC3Denum, RefPtr<ArrayBufferView>&&) +{ +} + +void WebGL2RenderingContext::texSubImage3D(GC3Denum, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei, GC3Dsizei, GC3Denum, GC3Denum, RefPtr<ArrayBufferView>&&) +{ +} + +void WebGL2RenderingContext::texSubImage3D(GC3Denum, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Denum, GC3Denum, TexImageSource&&) +{ +} + +void WebGL2RenderingContext::copyTexSubImage3D(GC3Denum, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei) +{ +} + +void WebGL2RenderingContext::compressedTexImage3D(GC3Denum, GC3Dint, GC3Denum, GC3Dsizei, GC3Dsizei, GC3Dsizei, GC3Dint, GC3Dsizei, RefPtr<ArrayBufferView>&&) +{ +} + +void WebGL2RenderingContext::compressedTexSubImage3D(GC3Denum, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei, GC3Dsizei, GC3Denum, GC3Dsizei, RefPtr<ArrayBufferView>&&) +{ +} + +GC3Dint WebGL2RenderingContext::getFragDataLocation(WebGLProgram*, const String&) +{ + return 0; +} + +void WebGL2RenderingContext::uniform1ui(WebGLUniformLocation*, GC3Duint) +{ +} + +void WebGL2RenderingContext::uniform2ui(WebGLUniformLocation*, GC3Duint, GC3Duint) +{ +} + +void WebGL2RenderingContext::uniform3ui(WebGLUniformLocation*, GC3Duint, GC3Duint, GC3Duint) +{ +} + +void WebGL2RenderingContext::uniform4ui(WebGLUniformLocation*, GC3Duint, GC3Duint, GC3Duint, GC3Duint) +{ +} + +void WebGL2RenderingContext::uniform1uiv(WebGLUniformLocation*, RefPtr<Uint32Array>&&) +{ +} + +void WebGL2RenderingContext::uniform2uiv(WebGLUniformLocation*, RefPtr<Uint32Array>&&) +{ +} + +void WebGL2RenderingContext::uniform3uiv(WebGLUniformLocation*, RefPtr<Uint32Array>&&) +{ +} + +void WebGL2RenderingContext::uniform4uiv(WebGLUniformLocation*, RefPtr<Uint32Array>&&) +{ +} + +void WebGL2RenderingContext::uniformMatrix2x3fv(WebGLUniformLocation*, GC3Dboolean, RefPtr<Float32Array>&&) +{ +} + +void WebGL2RenderingContext::uniformMatrix3x2fv(WebGLUniformLocation*, GC3Dboolean, RefPtr<Float32Array>&&) +{ +} + +void WebGL2RenderingContext::uniformMatrix2x4fv(WebGLUniformLocation*, GC3Dboolean, RefPtr<Float32Array>&&) +{ +} + +void WebGL2RenderingContext::uniformMatrix4x2fv(WebGLUniformLocation*, GC3Dboolean, RefPtr<Float32Array>&&) +{ +} + +void WebGL2RenderingContext::uniformMatrix3x4fv(WebGLUniformLocation*, GC3Dboolean, RefPtr<Float32Array>&&) +{ +} + +void WebGL2RenderingContext::uniformMatrix4x3fv(WebGLUniformLocation*, GC3Dboolean, RefPtr<Float32Array>&&) +{ +} + +void WebGL2RenderingContext::vertexAttribI4i(GC3Duint, GC3Dint, GC3Dint, GC3Dint, GC3Dint) +{ +} + +void WebGL2RenderingContext::vertexAttribI4iv(GC3Duint, RefPtr<Int32Array>&&) +{ +} + +void WebGL2RenderingContext::vertexAttribI4ui(GC3Duint, GC3Duint, GC3Duint, GC3Duint, GC3Duint) +{ +} + +void WebGL2RenderingContext::vertexAttribI4uiv(GC3Duint, RefPtr<Uint32Array>&&) +{ +} + +void WebGL2RenderingContext::vertexAttribIPointer(GC3Duint, GC3Dint, GC3Denum, GC3Dsizei, GC3Dint64) +{ +} + +void WebGL2RenderingContext::clear(GC3Dbitfield mask) +{ + if (isContextLostOrPending()) + return; + if (mask & ~(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clear", "invalid mask"); + return; + } + if (m_framebufferBinding && (mask & GraphicsContext3D::COLOR_BUFFER_BIT) && isIntegerFormat(m_framebufferBinding->getColorBufferFormat())) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "clear", "cannot clear an integer buffer"); + return; + } + const char* reason = "framebuffer incomplete"; + if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { + synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "clear", reason); + return; + } + if (!clearIfComposited(mask)) + m_context->clear(mask); + markContextChanged(); +} + +void WebGL2RenderingContext::vertexAttribDivisor(GC3Duint index, GC3Duint divisor) +{ + if (isContextLostOrPending()) + return; + + WebGLRenderingContextBase::vertexAttribDivisor(index, divisor); +} + +void WebGL2RenderingContext::drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei instanceCount) +{ + if (isContextLostOrPending()) + return; + + WebGLRenderingContextBase::drawArraysInstanced(mode, first, count, instanceCount); +} + +void WebGL2RenderingContext::drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dint64 offset, GC3Dsizei instanceCount) +{ + if (isContextLostOrPending()) + return; + + WebGLRenderingContextBase::drawElementsInstanced(mode, count, type, offset, instanceCount); +} + +void WebGL2RenderingContext::drawRangeElements(GC3Denum, GC3Duint, GC3Duint, GC3Dsizei, GC3Denum, GC3Dint64) +{ +} + +void WebGL2RenderingContext::drawBuffers(const Vector<GC3Denum>& buffers) +{ + if (isContextLost()) + return; + GC3Dsizei n = buffers.size(); + const GC3Denum* bufs = buffers.data(); + if (!m_framebufferBinding) { + if (n != 1) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "drawBuffers", "more than one buffer"); + return; + } + if (bufs[0] != GraphicsContext3D::BACK && bufs[0] != GraphicsContext3D::NONE) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawBuffers", "BACK or NONE"); + return; + } + // Because the backbuffer is simulated on all current WebKit ports, we need to change BACK to COLOR_ATTACHMENT0. + GC3Denum value = (bufs[0] == GraphicsContext3D::BACK) ? GraphicsContext3D::COLOR_ATTACHMENT0 : GraphicsContext3D::NONE; + graphicsContext3D()->getExtensions().drawBuffersEXT(1, &value); + setBackDrawBuffer(bufs[0]); + } else { + if (n > getMaxDrawBuffers()) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "drawBuffers", "more than max draw buffers"); + return; + } + for (GC3Dsizei i = 0; i < n; ++i) { + if (bufs[i] != GraphicsContext3D::NONE && bufs[i] != static_cast<GC3Denum>(GraphicsContext3D::COLOR_ATTACHMENT0 + i)) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawBuffers", "COLOR_ATTACHMENTi or NONE"); + return; + } + } + m_framebufferBinding->drawBuffers(buffers); + } +} + +void WebGL2RenderingContext::clearBufferiv(GC3Denum buffer, GC3Dint drawbuffer, RefPtr<Int32Array>&&) +{ + switch (buffer) { + case GraphicsContext3D::COLOR: + if (drawbuffer < 0 || drawbuffer >= getMaxDrawBuffers()) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clearBufferiv", "buffer index out of range"); + return; + } + // TODO: Call clearBufferiv, requires gl3.h and ES3/gl.h + break; + case GraphicsContext3D::STENCIL: + if (drawbuffer) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clearBufferiv", "buffer index must be 0"); + return; + } + // TODO: Call clearBufferiv, requires gl3.h and ES3/gl.h + break; + case GraphicsContext3D::DEPTH: + case GraphicsContext3D::DEPTH_STENCIL: + default: + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "clearBufferiv", "buffer argument must be COLOR or STENCIL"); + break; + } +} + +void WebGL2RenderingContext::clearBufferuiv(GC3Denum buffer, GC3Dint drawbuffer, RefPtr<Uint32Array>&&) +{ + switch (buffer) { + case GraphicsContext3D::COLOR: + if (drawbuffer < 0 || drawbuffer >= getMaxDrawBuffers()) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clearBufferuiv", "buffer index out of range"); + return; + } + // TODO: Call clearBufferuiv, requires gl3.h and ES3/gl.h + break; + case GraphicsContext3D::DEPTH: + case GraphicsContext3D::STENCIL: + case GraphicsContext3D::DEPTH_STENCIL: + default: + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "clearBufferuiv", "buffer argument must be COLOR"); + break; + } +} + +void WebGL2RenderingContext::clearBufferfv(GC3Denum buffer, GC3Dint drawbuffer, RefPtr<Float32Array>&&) +{ + switch (buffer) { + case GraphicsContext3D::COLOR: + if (drawbuffer < 0 || drawbuffer >= getMaxDrawBuffers()) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clearBufferfv", "buffer index out of range"); + return; + } + // TODO: Call clearBufferfv, requires gl3.h and ES3/gl.h + break; + case GraphicsContext3D::DEPTH: + if (drawbuffer) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clearBufferfv", "buffer index must be 0"); + return; + } + // TODO: Call clearBufferfv, requires gl3.h and ES3/gl.h + break; + case GraphicsContext3D::STENCIL: + case GraphicsContext3D::DEPTH_STENCIL: + default: + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "clearBufferfv", "buffer argument must be COLOR OR DEPTH"); + break; + } +} + +void WebGL2RenderingContext::clearBufferfi(GC3Denum buffer, GC3Dint drawbuffer, GC3Dfloat, GC3Dint) +{ + switch (buffer) { + case GraphicsContext3D::DEPTH_STENCIL: + if (drawbuffer) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clearBufferfv", "buffer index must be 0"); + return; + } + // TODO: Call clearBufferfi, requires gl3.h and ES3/gl.h + break; + case GraphicsContext3D::COLOR: + case GraphicsContext3D::DEPTH: + case GraphicsContext3D::STENCIL: + default: + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "clearBufferfv", "buffer argument must be DEPTH_STENCIL"); + break; + } +} + +RefPtr<WebGLQuery> WebGL2RenderingContext::createQuery() +{ + return nullptr; +} + +void WebGL2RenderingContext::deleteQuery(WebGLQuery*) +{ +} + +GC3Dboolean WebGL2RenderingContext::isQuery(WebGLQuery*) +{ + return false; +} + +void WebGL2RenderingContext::beginQuery(GC3Denum, WebGLQuery*) +{ +} + +void WebGL2RenderingContext::endQuery(GC3Denum) +{ +} + +RefPtr<WebGLQuery> WebGL2RenderingContext::getQuery(GC3Denum, GC3Denum) +{ + return nullptr; +} + +WebGLAny WebGL2RenderingContext::getQueryParameter(WebGLQuery*, GC3Denum) +{ + return nullptr; +} + +RefPtr<WebGLSampler> WebGL2RenderingContext::createSampler() +{ + return nullptr; +} + +void WebGL2RenderingContext::deleteSampler(WebGLSampler*) +{ +} + +GC3Dboolean WebGL2RenderingContext::isSampler(WebGLSampler*) +{ + return false; +} + +void WebGL2RenderingContext::bindSampler(GC3Duint, WebGLSampler*) +{ +} + +void WebGL2RenderingContext::samplerParameteri(WebGLSampler*, GC3Denum, GC3Dint) +{ +} + +void WebGL2RenderingContext::samplerParameterf(WebGLSampler*, GC3Denum, GC3Dfloat) +{ +} + +WebGLAny WebGL2RenderingContext::getSamplerParameter(WebGLSampler*, GC3Denum) +{ + return nullptr; +} + +RefPtr<WebGLSync> WebGL2RenderingContext::fenceSync(GC3Denum, GC3Dbitfield) +{ + return nullptr; +} + +GC3Dboolean WebGL2RenderingContext::isSync(WebGLSync*) +{ + return false; +} + +void WebGL2RenderingContext::deleteSync(WebGLSync*) +{ +} + +GC3Denum WebGL2RenderingContext::clientWaitSync(WebGLSync*, GC3Dbitfield, GC3Duint64) +{ + return 0; +} + +void WebGL2RenderingContext::waitSync(WebGLSync*, GC3Dbitfield, GC3Duint64) +{ +} + +WebGLAny WebGL2RenderingContext::getSyncParameter(WebGLSync*, GC3Denum) +{ + return nullptr; +} + +RefPtr<WebGLTransformFeedback> WebGL2RenderingContext::createTransformFeedback() +{ + return nullptr; +} + +void WebGL2RenderingContext::deleteTransformFeedback(WebGLTransformFeedback*) +{ +} + +GC3Dboolean WebGL2RenderingContext::isTransformFeedback(WebGLTransformFeedback*) +{ + return false; +} + +void WebGL2RenderingContext::bindTransformFeedback(GC3Denum, WebGLTransformFeedback*) +{ +} + +void WebGL2RenderingContext::beginTransformFeedback(GC3Denum) +{ +} + +void WebGL2RenderingContext::endTransformFeedback() +{ +} + +void WebGL2RenderingContext::transformFeedbackVaryings(WebGLProgram*, const Vector<String>&, GC3Denum) +{ +} + +RefPtr<WebGLActiveInfo> WebGL2RenderingContext::getTransformFeedbackVarying(WebGLProgram*, GC3Duint) +{ + return nullptr; +} + +void WebGL2RenderingContext::pauseTransformFeedback() +{ +} + +void WebGL2RenderingContext::resumeTransformFeedback() +{ +} + +void WebGL2RenderingContext::bindBufferBase(GC3Denum, GC3Duint, WebGLBuffer*) +{ +} + +void WebGL2RenderingContext::bindBufferRange(GC3Denum, GC3Duint, WebGLBuffer*, GC3Dint64, GC3Dint64) +{ +} + +WebGLAny WebGL2RenderingContext::getIndexedParameter(GC3Denum target, GC3Duint) +{ + switch (target) { + case GraphicsContext3D::TRANSFORM_FEEDBACK_BUFFER_BINDING: + case GraphicsContext3D::TRANSFORM_FEEDBACK_BUFFER_SIZE: + case GraphicsContext3D::TRANSFORM_FEEDBACK_BUFFER_START: + case GraphicsContext3D::UNIFORM_BUFFER_BINDING: + case GraphicsContext3D::UNIFORM_BUFFER_SIZE: + case GraphicsContext3D::UNIFORM_BUFFER_START: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getIndexedParameter", "parameter name not yet supported"); + return nullptr; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getIndexedParameter", "invalid parameter name"); + return nullptr; + } +} + +Uint32Array* WebGL2RenderingContext::getUniformIndices(WebGLProgram*, const Vector<String>&) +{ + return nullptr; +} + +Int32Array* WebGL2RenderingContext::getActiveUniforms(WebGLProgram*, RefPtr<Uint32Array>&&, GC3Denum) +{ + return nullptr; +} + +GC3Duint WebGL2RenderingContext::getUniformBlockIndex(WebGLProgram*, const String&) +{ + return 0; +} + +WebGLAny WebGL2RenderingContext::getActiveUniformBlockParameter(WebGLProgram*, GC3Duint, GC3Denum) +{ + return nullptr; +} + +WebGLAny WebGL2RenderingContext::getActiveUniformBlockName(WebGLProgram*, GC3Duint) +{ + return nullptr; +} + +void WebGL2RenderingContext::uniformBlockBinding(WebGLProgram*, GC3Duint, GC3Duint) +{ +} + +RefPtr<WebGLVertexArrayObject> WebGL2RenderingContext::createVertexArray() +{ + if (isContextLost()) + return nullptr; + + auto object = WebGLVertexArrayObject::create(*this, WebGLVertexArrayObject::Type::User); + addContextObject(object.get()); + return WTFMove(object); +} + +void WebGL2RenderingContext::deleteVertexArray(WebGLVertexArrayObject* arrayObject) +{ + if (!arrayObject || isContextLost()) + return; + + if (arrayObject->isDeleted()) + return; + + if (!arrayObject->isDefaultObject() && arrayObject == m_boundVertexArrayObject) + setBoundVertexArrayObject(nullptr); + + arrayObject->deleteObject(graphicsContext3D()); +} + +GC3Dboolean WebGL2RenderingContext::isVertexArray(WebGLVertexArrayObject* arrayObject) +{ + if (!arrayObject || isContextLost()) + return false; + + if (!arrayObject->hasEverBeenBound() || !arrayObject->validate(0, *this)) + return false; + + return m_context->isVertexArray(arrayObject->object()); +} + +void WebGL2RenderingContext::bindVertexArray(WebGLVertexArrayObject* arrayObject) +{ + if (isContextLost()) + return; + + if (arrayObject && (arrayObject->isDeleted() || !arrayObject->validate(0, *this) || !m_contextObjects.contains(arrayObject))) { + m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); + return; + } + if (arrayObject && !arrayObject->isDefaultObject() && arrayObject->object()) { + m_context->bindVertexArray(arrayObject->object()); + + arrayObject->setHasEverBeenBound(); + setBoundVertexArrayObject(arrayObject); + } else { + m_context->bindVertexArray(m_defaultVertexArrayObject->object()); + setBoundVertexArrayObject(m_defaultVertexArrayObject.get()); + } +} + +WebGLExtension* WebGL2RenderingContext::getExtension(const String& name) +{ + if (isContextLostOrPending()) + return nullptr; + + if (equalIgnoringASCIICase(name, "EXT_texture_filter_anisotropic") || equalIgnoringASCIICase(name, "WEBKIT_EXT_texture_filter_anisotropic")) { + if (!m_extTextureFilterAnisotropic) { + m_extTextureFilterAnisotropic = enableSupportedExtension("GL_EXT_texture_filter_anisotropic") + ? std::make_unique<EXTTextureFilterAnisotropic>(*this) : nullptr; + } + return m_extTextureFilterAnisotropic.get(); + } + if (equalIgnoringASCIICase(name, "OES_texture_float")) { + if (!m_oesTextureFloat) { + m_oesTextureFloat = enableSupportedExtension("GL_OES_texture_float") + ? std::make_unique<OESTextureFloat>(*this) : nullptr; + } + return m_oesTextureFloat.get(); + } + if (equalIgnoringASCIICase(name, "OES_texture_float_linear")) { + if (!m_oesTextureFloatLinear) { + m_oesTextureFloatLinear = enableSupportedExtension("GL_OES_texture_float_linear") + ? std::make_unique<OESTextureFloatLinear>(*this) : nullptr; + } + return m_oesTextureFloatLinear.get(); + } + if (equalIgnoringASCIICase(name, "OES_texture_half_float")) { + if (!m_oesTextureHalfFloat) { + m_oesTextureHalfFloat = enableSupportedExtension("GL_OES_texture_half_float") + ? std::make_unique<OESTextureHalfFloat>(*this) : nullptr; + } + return m_oesTextureHalfFloat.get(); + } + if (equalIgnoringASCIICase(name, "OES_texture_half_float_linear")) { + if (!m_oesTextureHalfFloatLinear) { + m_oesTextureHalfFloatLinear = enableSupportedExtension("GL_OES_texture_half_float_linear") + ? std::make_unique<OESTextureHalfFloatLinear>(*this) : nullptr; + } + return m_oesTextureHalfFloatLinear.get(); + } + if (equalIgnoringASCIICase(name, "WEBGL_lose_context")) { + if (!m_webglLoseContext) + m_webglLoseContext = std::make_unique<WebGLLoseContext>(*this); + return m_webglLoseContext.get(); + } + if (equalIgnoringASCIICase(name, "WEBKIT_WEBGL_compressed_texture_atc")) { + if (!m_webglCompressedTextureATC) { + if (WebGLCompressedTextureATC::supported(*this)) + m_webglCompressedTextureATC = std::make_unique<WebGLCompressedTextureATC>(*this); + } + return m_webglCompressedTextureATC.get(); + } + if (equalIgnoringASCIICase(name, "WEBKIT_WEBGL_compressed_texture_pvrtc")) { + if (!m_webglCompressedTexturePVRTC) { + m_webglCompressedTexturePVRTC = WebGLCompressedTexturePVRTC::supported(*this) + ? std::make_unique<WebGLCompressedTexturePVRTC>(*this) : nullptr; + } + return m_webglCompressedTexturePVRTC.get(); + } + if (equalIgnoringASCIICase(name, "WEBGL_compressed_texture_s3tc")) { + if (!m_webglCompressedTextureS3TC) { + m_webglCompressedTextureS3TC = WebGLCompressedTextureS3TC::supported(*this) + ? std::make_unique<WebGLCompressedTextureS3TC>(*this) : nullptr; + } + return m_webglCompressedTextureS3TC.get(); + } + if (equalIgnoringASCIICase(name, "WEBGL_depth_texture")) { + if (!m_webglDepthTexture) { + m_webglDepthTexture = WebGLDepthTexture::supported(*graphicsContext3D()) + ? std::make_unique<WebGLDepthTexture>(*this) : nullptr; + } + return m_webglDepthTexture.get(); + } + if (equalIgnoringASCIICase(name, "WEBGL_debug_renderer_info")) { + if (!m_webglDebugRendererInfo) + m_webglDebugRendererInfo = std::make_unique<WebGLDebugRendererInfo>(*this); + return m_webglDebugRendererInfo.get(); + } + if (equalIgnoringASCIICase(name, "WEBGL_debug_shaders")) { + if (!m_webglDebugShaders) { + m_webglDebugShaders = m_context->getExtensions().supports(ASCIILiteral { "GL_ANGLE_translated_shader_source" }) + ? std::make_unique<WebGLDebugShaders>(*this) : nullptr; + } + return m_webglDebugShaders.get(); + } + + return nullptr; +} + +std::optional<Vector<String>> WebGL2RenderingContext::getSupportedExtensions() +{ + if (isContextLost()) + return std::nullopt; + + Vector<String> result; + + if (m_isPendingPolicyResolution) + return result; + + auto& extensions = m_context->getExtensions(); + if (extensions.supports(ASCIILiteral { "GL_OES_texture_float" })) + result.append(ASCIILiteral { "OES_texture_float" }); + if (extensions.supports(ASCIILiteral { "GL_OES_texture_float_linear" })) + result.append(ASCIILiteral { "OES_texture_float_linear" }); + if (extensions.supports(ASCIILiteral { "GL_OES_texture_half_float" })) + result.append(ASCIILiteral { "OES_texture_half_float" }); + if (extensions.supports(ASCIILiteral { "GL_OES_texture_half_float_linear" })) + result.append(ASCIILiteral { "OES_texture_half_float_linear" }); + if (extensions.supports(ASCIILiteral { "GL_EXT_texture_filter_anisotropic" })) + result.append(ASCIILiteral { "WEBKIT_EXT_texture_filter_anisotropic" }); + if (WebGLCompressedTextureATC::supported(*this)) + result.append(ASCIILiteral { "WEBKIT_WEBGL_compressed_texture_atc" }); + if (WebGLCompressedTexturePVRTC::supported(*this)) + result.append(ASCIILiteral { "WEBKIT_WEBGL_compressed_texture_pvrtc" }); + if (WebGLCompressedTextureS3TC::supported(*this)) + result.append(ASCIILiteral { "WEBGL_compressed_texture_s3tc" }); + if (WebGLDepthTexture::supported(*graphicsContext3D())) + result.append(ASCIILiteral { "WEBGL_depth_texture" }); + result.append(ASCIILiteral { "WEBGL_lose_context" }); + if (extensions.supports(ASCIILiteral { "GL_ANGLE_translated_shader_source" })) + result.append(ASCIILiteral { "WEBGL_debug_shaders" }); + result.append(ASCIILiteral { "WEBGL_debug_renderer_info" }); + + return result; +} + +WebGLAny WebGL2RenderingContext::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname) +{ + if (isContextLostOrPending() || !validateFramebufferFuncParameters("getFramebufferAttachmentParameter", target, attachment)) + return nullptr; + + if (!m_framebufferBinding || !m_framebufferBinding->object()) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getFramebufferAttachmentParameter", "no framebuffer bound"); + return nullptr; + } + + auto* object = m_framebufferBinding->getAttachmentObject(attachment); + if (!object) { + if (pname == GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) + return static_cast<unsigned>(GraphicsContext3D::NONE); + // OpenGL ES 2.0 specifies INVALID_ENUM in this case, while desktop GL specifies INVALID_OPERATION. + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name"); + return nullptr; + } + + if (object->isTexture()) { + switch (pname) { + case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + return static_cast<unsigned>(GraphicsContext3D::TEXTURE); + case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + return makeRefPtr(reinterpret_cast<WebGLTexture&>(*object)); + case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: + case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: + case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: { + GC3Dint value = 0; + m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value); + return value; + } + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for texture attachment"); + return nullptr; + } + } else { + ASSERT(object->isRenderbuffer()); + switch (pname) { + case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + return static_cast<unsigned>(GraphicsContext3D::RENDERBUFFER); + case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + return makeRefPtr(reinterpret_cast<WebGLRenderbuffer&>(*object)); + case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING : { + auto& renderBuffer = reinterpret_cast<WebGLRenderbuffer&>(*object); + auto format = renderBuffer.getInternalFormat(); + if (format == GraphicsContext3D::SRGB8_ALPHA8 + || format == GraphicsContext3D::COMPRESSED_SRGB8_ETC2 + || format == GraphicsContext3D::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC + || format == GraphicsContext3D::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2) { + return static_cast<unsigned>(GraphicsContext3D::SRGB); + } + return static_cast<unsigned>(GraphicsContext3D::LINEAR); + } + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for renderbuffer attachment"); + return nullptr; + } + } +} + +bool WebGL2RenderingContext::validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment) +{ + if (target != GraphicsContext3D::FRAMEBUFFER) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target"); + return false; + } + switch (attachment) { + case GraphicsContext3D::DEPTH_ATTACHMENT: + case GraphicsContext3D::STENCIL_ATTACHMENT: + case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT: + return true; + default: + if (attachment >= GraphicsContext3D::COLOR_ATTACHMENT0 && attachment < static_cast<GC3Denum>(GraphicsContext3D::COLOR_ATTACHMENT0 + getMaxColorAttachments())) + return true; + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid attachment"); + return false; + } +} + +GC3Dint WebGL2RenderingContext::getMaxDrawBuffers() +{ + if (!m_maxDrawBuffers) + m_context->getIntegerv(GraphicsContext3D::MAX_DRAW_BUFFERS, &m_maxDrawBuffers); + return m_maxDrawBuffers; +} + +GC3Dint WebGL2RenderingContext::getMaxColorAttachments() +{ + // DrawBuffers requires MAX_COLOR_ATTACHMENTS == MAX_DRAW_BUFFERS + if (!m_maxColorAttachments) + m_context->getIntegerv(GraphicsContext3D::MAX_DRAW_BUFFERS, &m_maxColorAttachments); + return m_maxColorAttachments; +} + +void WebGL2RenderingContext::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) +{ + if (isContextLostOrPending()) + return; + if (target != GraphicsContext3D::RENDERBUFFER) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid target"); + return; + } + if (!m_renderbufferBinding || !m_renderbufferBinding->object()) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "renderbufferStorage", "no bound renderbuffer"); + return; + } + if (!validateSize("renderbufferStorage", width, height)) + return; + switch (internalformat) { + case GraphicsContext3D::DEPTH_COMPONENT16: + case GraphicsContext3D::DEPTH_COMPONENT32F: + case GraphicsContext3D::DEPTH_COMPONENT24: + case GraphicsContext3D::RGBA32I: + case GraphicsContext3D::RGBA32UI: + case GraphicsContext3D::RGBA16I: + case GraphicsContext3D::RGBA16UI: + case GraphicsContext3D::RGBA8: + case GraphicsContext3D::RGBA8I: + case GraphicsContext3D::RGBA8UI: + case GraphicsContext3D::RGB10_A2: + case GraphicsContext3D::RGB10_A2UI: + case GraphicsContext3D::RGBA4: + case GraphicsContext3D::RG32I: + case GraphicsContext3D::RG32UI: + case GraphicsContext3D::RG16I: + case GraphicsContext3D::RG16UI: + case GraphicsContext3D::RG8: + case GraphicsContext3D::RG8I: + case GraphicsContext3D::RG8UI: + case GraphicsContext3D::R32I: + case GraphicsContext3D::R32UI: + case GraphicsContext3D::R16I: + case GraphicsContext3D::R16UI: + case GraphicsContext3D::R8: + case GraphicsContext3D::R8I: + case GraphicsContext3D::R8UI: + case GraphicsContext3D::RGB5_A1: + case GraphicsContext3D::RGB565: + case GraphicsContext3D::STENCIL_INDEX8: + case GraphicsContext3D::SRGB8_ALPHA8: + m_context->renderbufferStorage(target, internalformat, width, height); + m_renderbufferBinding->setInternalFormat(internalformat); + m_renderbufferBinding->setIsValid(true); + m_renderbufferBinding->setSize(width, height); + break; + case GraphicsContext3D::DEPTH32F_STENCIL8: + case GraphicsContext3D::DEPTH24_STENCIL8: + if (!isDepthStencilSupported()) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid internalformat"); + return; + } + m_context->renderbufferStorage(target, internalformat, width, height); + m_renderbufferBinding->setSize(width, height); + m_renderbufferBinding->setIsValid(isDepthStencilSupported()); + m_renderbufferBinding->setInternalFormat(internalformat); + break; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid internalformat"); + return; + } + applyStencilTest(); +} + +void WebGL2RenderingContext::hint(GC3Denum target, GC3Denum mode) +{ + if (isContextLostOrPending()) + return; + bool isValid = false; + switch (target) { + case GraphicsContext3D::GENERATE_MIPMAP_HINT: + case GraphicsContext3D::FRAGMENT_SHADER_DERIVATIVE_HINT: + isValid = true; + break; + } + if (!isValid) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "hint", "invalid target"); + return; + } + m_context->hint(target, mode); +} + +GC3Denum WebGL2RenderingContext::baseInternalFormatFromInternalFormat(GC3Denum internalformat) +{ + // Handles sized, unsized, and compressed internal formats. + switch (internalformat) { + case GraphicsContext3D::R8: + case GraphicsContext3D::R8_SNORM: + case GraphicsContext3D::R16F: + case GraphicsContext3D::R32F: + case GraphicsContext3D::R8I: + case GraphicsContext3D::R8UI: + case GraphicsContext3D::R16I: + case GraphicsContext3D::R16UI: + case GraphicsContext3D::R32I: + case GraphicsContext3D::R32UI: + case GraphicsContext3D::COMPRESSED_R11_EAC: + case GraphicsContext3D::COMPRESSED_SIGNED_R11_EAC: + return GraphicsContext3D::RED; + case GraphicsContext3D::RG8: + case GraphicsContext3D::RG8_SNORM: + case GraphicsContext3D::RG16F: + case GraphicsContext3D::RG32F: + case GraphicsContext3D::RG8I: + case GraphicsContext3D::RG8UI: + case GraphicsContext3D::RG16I: + case GraphicsContext3D::RG16UI: + case GraphicsContext3D::RG32I: + case GraphicsContext3D::RG32UI: + case GraphicsContext3D::COMPRESSED_RG11_EAC: + case GraphicsContext3D::COMPRESSED_SIGNED_RG11_EAC: + return GraphicsContext3D::RG; + case GraphicsContext3D::RGB8: + case GraphicsContext3D::RGB8_SNORM: + case GraphicsContext3D::RGB565: + case GraphicsContext3D::SRGB8: + case GraphicsContext3D::RGB16F: + case GraphicsContext3D::RGB32F: + case GraphicsContext3D::RGB8I: + case GraphicsContext3D::RGB8UI: + case GraphicsContext3D::RGB16I: + case GraphicsContext3D::RGB16UI: + case GraphicsContext3D::RGB32I: + case GraphicsContext3D::RGB32UI: + case GraphicsContext3D::RGB: + case GraphicsContext3D::COMPRESSED_RGB8_ETC2: + case GraphicsContext3D::COMPRESSED_SRGB8_ETC2: + return GraphicsContext3D::RGB; + case GraphicsContext3D::RGBA4: + case GraphicsContext3D::RGB5_A1: + case GraphicsContext3D::RGBA8: + case GraphicsContext3D::RGBA8_SNORM: + case GraphicsContext3D::RGB10_A2: + case GraphicsContext3D::RGB10_A2UI: + case GraphicsContext3D::SRGB8_ALPHA8: + case GraphicsContext3D::RGBA16F: + case GraphicsContext3D::RGBA32F: + case GraphicsContext3D::RGBA8I: + case GraphicsContext3D::RGBA8UI: + case GraphicsContext3D::RGBA16I: + case GraphicsContext3D::RGBA16UI: + case GraphicsContext3D::RGBA32I: + case GraphicsContext3D::RGBA32UI: + case GraphicsContext3D::RGBA: + case GraphicsContext3D::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case GraphicsContext3D::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case GraphicsContext3D::COMPRESSED_RGBA8_ETC2_EAC: + case GraphicsContext3D::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: + return GraphicsContext3D::RGBA; + case GraphicsContext3D::DEPTH_COMPONENT16: + case GraphicsContext3D::DEPTH_COMPONENT24: + case GraphicsContext3D::DEPTH_COMPONENT32F: + return GraphicsContext3D::DEPTH_COMPONENT; + case GraphicsContext3D::DEPTH24_STENCIL8: + case GraphicsContext3D::DEPTH32F_STENCIL8: + return GraphicsContext3D::DEPTH_STENCIL; + case GraphicsContext3D::LUMINANCE: + case GraphicsContext3D::LUMINANCE_ALPHA: + case GraphicsContext3D::ALPHA: + return internalformat; + default: + ASSERT_NOT_REACHED(); + return GraphicsContext3D::NONE; + } +} + +bool WebGL2RenderingContext::isIntegerFormat(GC3Denum internalformat) +{ + // FIXME: baseInternalFormatFromInternalFormat() never returns any of these enums. + // Because of that, this function erroneously always returns false! + switch (baseInternalFormatFromInternalFormat(internalformat)) { + case GraphicsContext3D::RED_INTEGER: + case GraphicsContext3D::RG_INTEGER: + case GraphicsContext3D::RGB_INTEGER: + case GraphicsContext3D::RGBA_INTEGER: + return true; + } + return false; +} + +WebGLAny WebGL2RenderingContext::getParameter(GC3Denum pname) +{ + if (isContextLostOrPending()) + return nullptr; + switch (pname) { + case GraphicsContext3D::ACTIVE_TEXTURE: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE: + return getWebGLFloatArrayParameter(pname); + case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE: + return getWebGLFloatArrayParameter(pname); + case GraphicsContext3D::ALPHA_BITS: + return getIntParameter(pname); + case GraphicsContext3D::ARRAY_BUFFER_BINDING: + return m_boundArrayBuffer; + case GraphicsContext3D::BLEND: + return getBooleanParameter(pname); + case GraphicsContext3D::BLEND_COLOR: + return getWebGLFloatArrayParameter(pname); + case GraphicsContext3D::BLEND_DST_ALPHA: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::BLEND_DST_RGB: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::BLEND_EQUATION_ALPHA: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::BLEND_EQUATION_RGB: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::BLEND_SRC_ALPHA: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::BLEND_SRC_RGB: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::BLUE_BITS: + return getIntParameter(pname); + case GraphicsContext3D::COLOR_CLEAR_VALUE: + return getWebGLFloatArrayParameter(pname); + case GraphicsContext3D::COLOR_WRITEMASK: + return getBooleanArrayParameter(pname); + case GraphicsContext3D::COMPRESSED_TEXTURE_FORMATS: + return Uint32Array::create(m_compressedTextureFormats.data(), m_compressedTextureFormats.size()); + case GraphicsContext3D::CULL_FACE: + return getBooleanParameter(pname); + case GraphicsContext3D::CULL_FACE_MODE: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::CURRENT_PROGRAM: + return m_currentProgram; + case GraphicsContext3D::DEPTH_BITS: + if (!m_framebufferBinding && !m_attributes.depth) + return 0; + return getIntParameter(pname); + case GraphicsContext3D::DEPTH_CLEAR_VALUE: + return getFloatParameter(pname); + case GraphicsContext3D::DEPTH_FUNC: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::DEPTH_RANGE: + return getWebGLFloatArrayParameter(pname); + case GraphicsContext3D::DEPTH_TEST: + return getBooleanParameter(pname); + case GraphicsContext3D::DEPTH_WRITEMASK: + return getBooleanParameter(pname); + case GraphicsContext3D::DITHER: + return getBooleanParameter(pname); + case GraphicsContext3D::ELEMENT_ARRAY_BUFFER_BINDING: + return makeRefPtr(m_boundVertexArrayObject->getElementArrayBuffer()); + case GraphicsContext3D::FRAMEBUFFER_BINDING: + return m_framebufferBinding; + case GraphicsContext3D::FRONT_FACE: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::GENERATE_MIPMAP_HINT: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::GREEN_BITS: + return getIntParameter(pname); + case GraphicsContext3D::IMPLEMENTATION_COLOR_READ_FORMAT: + return getIntParameter(pname); + case GraphicsContext3D::IMPLEMENTATION_COLOR_READ_TYPE: + return getIntParameter(pname); + case GraphicsContext3D::LINE_WIDTH: + return getFloatParameter(pname); + case GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS: + return getIntParameter(pname); + case GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE: + return getIntParameter(pname); + case GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS: + return getIntParameter(pname); + case GraphicsContext3D::MAX_RENDERBUFFER_SIZE: + return getIntParameter(pname); + case GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS: + return getIntParameter(pname); + case GraphicsContext3D::MAX_TEXTURE_SIZE: + return getIntParameter(pname); + case GraphicsContext3D::MAX_VARYING_VECTORS: + return getIntParameter(pname); + case GraphicsContext3D::MAX_VERTEX_ATTRIBS: + return getIntParameter(pname); + case GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS: + return getIntParameter(pname); + case GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS: + return getIntParameter(pname); + case GraphicsContext3D::MAX_VIEWPORT_DIMS: + return getWebGLIntArrayParameter(pname); + case GraphicsContext3D::NUM_SHADER_BINARY_FORMATS: + return getIntParameter(pname); + case GraphicsContext3D::PACK_ALIGNMENT: + return getIntParameter(pname); + case GraphicsContext3D::POLYGON_OFFSET_FACTOR: + return getFloatParameter(pname); + case GraphicsContext3D::POLYGON_OFFSET_FILL: + return getBooleanParameter(pname); + case GraphicsContext3D::POLYGON_OFFSET_UNITS: + return getFloatParameter(pname); + case GraphicsContext3D::RED_BITS: + return getIntParameter(pname); + case GraphicsContext3D::RENDERBUFFER_BINDING: + return m_renderbufferBinding; + case GraphicsContext3D::RENDERER: + return String { ASCIILiteral { "WebKit WebGL" } }; + case GraphicsContext3D::SAMPLE_BUFFERS: + return getIntParameter(pname); + case GraphicsContext3D::SAMPLE_COVERAGE_INVERT: + return getBooleanParameter(pname); + case GraphicsContext3D::SAMPLE_COVERAGE_VALUE: + return getFloatParameter(pname); + case GraphicsContext3D::SAMPLES: + return getIntParameter(pname); + case GraphicsContext3D::SCISSOR_BOX: + return getWebGLIntArrayParameter(pname); + case GraphicsContext3D::SCISSOR_TEST: + return getBooleanParameter(pname); + case GraphicsContext3D::SHADING_LANGUAGE_VERSION: + return "WebGL GLSL ES 1.0 (" + m_context->getString(GraphicsContext3D::SHADING_LANGUAGE_VERSION) + ")"; + case GraphicsContext3D::STENCIL_BACK_FAIL: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::STENCIL_BACK_FUNC: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_FAIL: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_PASS: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::STENCIL_BACK_REF: + return getIntParameter(pname); + case GraphicsContext3D::STENCIL_BACK_VALUE_MASK: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::STENCIL_BACK_WRITEMASK: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::STENCIL_BITS: + if (!m_framebufferBinding && !m_attributes.stencil) + return 0; + return getIntParameter(pname); + case GraphicsContext3D::STENCIL_CLEAR_VALUE: + return getIntParameter(pname); + case GraphicsContext3D::STENCIL_FAIL: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::STENCIL_FUNC: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::STENCIL_PASS_DEPTH_FAIL: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::STENCIL_PASS_DEPTH_PASS: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::STENCIL_REF: + return getIntParameter(pname); + case GraphicsContext3D::STENCIL_TEST: + return getBooleanParameter(pname); + case GraphicsContext3D::STENCIL_VALUE_MASK: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::STENCIL_WRITEMASK: + return getUnsignedIntParameter(pname); + case GraphicsContext3D::SUBPIXEL_BITS: + return getIntParameter(pname); + case GraphicsContext3D::TEXTURE_BINDING_2D: + return m_textureUnits[m_activeTextureUnit].texture2DBinding; + case GraphicsContext3D::TEXTURE_BINDING_CUBE_MAP: + return m_textureUnits[m_activeTextureUnit].textureCubeMapBinding; + case GraphicsContext3D::UNPACK_ALIGNMENT: + return getIntParameter(pname); + case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL: + return m_unpackFlipY; + case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL: + return m_unpackPremultiplyAlpha; + case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL: + return m_unpackColorspaceConversion; + case GraphicsContext3D::VENDOR: + return String { ASCIILiteral { "WebKit" } }; + case GraphicsContext3D::VERSION: + return "WebGL 2.0 (" + m_context->getString(GraphicsContext3D::VERSION) + ")"; + case GraphicsContext3D::VIEWPORT: + return getWebGLIntArrayParameter(pname); + case WebGLDebugRendererInfo::UNMASKED_RENDERER_WEBGL: + if (m_webglDebugRendererInfo) + return m_context->getString(GraphicsContext3D::RENDERER); + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled"); + return nullptr; + case WebGLDebugRendererInfo::UNMASKED_VENDOR_WEBGL: + if (m_webglDebugRendererInfo) + return m_context->getString(GraphicsContext3D::VENDOR); + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled"); + return nullptr; + case Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic + if (m_extTextureFilterAnisotropic) + return getUnsignedIntParameter(Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT); + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled"); + return nullptr; + case GraphicsContext3D::FRAGMENT_SHADER_DERIVATIVE_HINT: + return getIntParameter(pname); + case GraphicsContext3D::MAX_3D_TEXTURE_SIZE: + return getIntParameter(pname); + case GraphicsContext3D::MAX_ARRAY_TEXTURE_LAYERS: + return getIntParameter(pname); + case GraphicsContext3D::MAX_COLOR_ATTACHMENTS: + return getIntParameter(pname); + case GraphicsContext3D::MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS: + return getInt64Parameter(pname); + case GraphicsContext3D::MAX_COMBINED_UNIFORM_BLOCKS: + return getIntParameter(pname); + case GraphicsContext3D::MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS: + return getInt64Parameter(pname); + case GraphicsContext3D::MAX_DRAW_BUFFERS: + return getIntParameter(pname); + case GraphicsContext3D::MAX_ELEMENT_INDEX: + return getInt64Parameter(pname); + case GraphicsContext3D::MAX_ELEMENTS_INDICES: + return getIntParameter(pname); + case GraphicsContext3D::MAX_ELEMENTS_VERTICES: + return getIntParameter(pname); + case GraphicsContext3D::MAX_FRAGMENT_UNIFORM_COMPONENTS: + return getIntParameter(pname); + case GraphicsContext3D::MAX_FRAGMENT_UNIFORM_BLOCKS: + return getIntParameter(pname); + case GraphicsContext3D::MAX_PROGRAM_TEXEL_OFFSET: + return getIntParameter(pname); + case GraphicsContext3D::MAX_SAMPLES: + return getIntParameter(pname); + case GraphicsContext3D::MAX_SERVER_WAIT_TIMEOUT: + return getInt64Parameter(pname); + case GraphicsContext3D::MAX_TEXTURE_LOD_BIAS: + return getIntParameter(pname); + case GraphicsContext3D::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: + return getIntParameter(pname); + case GraphicsContext3D::MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: + return getIntParameter(pname); + case GraphicsContext3D::MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: + return getIntParameter(pname); + case GraphicsContext3D::MAX_UNIFORM_BLOCK_SIZE: + return getInt64Parameter(pname); + case GraphicsContext3D::MAX_UNIFORM_BUFFER_BINDINGS: + return getIntParameter(pname); + case GraphicsContext3D::MAX_VARYING_COMPONENTS: + return getIntParameter(pname); + case GraphicsContext3D::MAX_VERTEX_OUTPUT_COMPONENTS: + return getIntParameter(pname); + case GraphicsContext3D::MAX_VERTEX_UNIFORM_BLOCKS: + return getIntParameter(pname); + case GraphicsContext3D::MAX_VERTEX_UNIFORM_COMPONENTS: + return getIntParameter(pname); + case GraphicsContext3D::MIN_PROGRAM_TEXEL_OFFSET: + return getIntParameter(pname); + case GraphicsContext3D::PACK_ROW_LENGTH: + return getIntParameter(pname); + case GraphicsContext3D::PACK_SKIP_PIXELS: + return getIntParameter(pname); + case GraphicsContext3D::PACK_SKIP_ROWS: + return getIntParameter(pname); + case GraphicsContext3D::UNPACK_IMAGE_HEIGHT: + return getIntParameter(pname); + case GraphicsContext3D::UNPACK_ROW_LENGTH: + return getIntParameter(pname); + case GraphicsContext3D::UNPACK_SKIP_IMAGES: + return getIntParameter(pname); + case GraphicsContext3D::UNPACK_SKIP_PIXELS: + return getIntParameter(pname); + case GraphicsContext3D::UNPACK_SKIP_ROWS: + return getIntParameter(pname); + case GraphicsContext3D::RASTERIZER_DISCARD: + return getBooleanParameter(pname); + case GraphicsContext3D::SAMPLE_ALPHA_TO_COVERAGE: + return getBooleanParameter(pname); + case GraphicsContext3D::SAMPLE_COVERAGE: + return getBooleanParameter(pname); + case GraphicsContext3D::TRANSFORM_FEEDBACK_ACTIVE: + return getBooleanParameter(pname); + case GraphicsContext3D::TRANSFORM_FEEDBACK_PAUSED: + return getBooleanParameter(pname); + case GraphicsContext3D::UNIFORM_BUFFER_OFFSET_ALIGNMENT: + return getIntParameter(pname); + case GraphicsContext3D::VERTEX_ARRAY_BINDING: + if (m_boundVertexArrayObject->isDefaultObject()) + return nullptr; + return makeRefPtr(static_cast<WebGLVertexArrayObject&>(*m_boundVertexArrayObject)); + case GraphicsContext3D::DRAW_BUFFER0: + case GraphicsContext3D::DRAW_BUFFER1: + case GraphicsContext3D::DRAW_BUFFER2: + case GraphicsContext3D::DRAW_BUFFER3: + case GraphicsContext3D::DRAW_BUFFER4: + case GraphicsContext3D::DRAW_BUFFER5: + case GraphicsContext3D::DRAW_BUFFER6: + case GraphicsContext3D::DRAW_BUFFER7: + case GraphicsContext3D::DRAW_BUFFER8: + case GraphicsContext3D::DRAW_BUFFER9: + case GraphicsContext3D::DRAW_BUFFER10: + case GraphicsContext3D::DRAW_BUFFER11: + case GraphicsContext3D::DRAW_BUFFER12: + case GraphicsContext3D::DRAW_BUFFER13: + case GraphicsContext3D::DRAW_BUFFER14: + case GraphicsContext3D::DRAW_BUFFER15: + if (m_framebufferBinding) + return m_framebufferBinding->getDrawBuffer(pname); + return m_backDrawBuffer; // emulated backbuffer + case GraphicsContext3D::COPY_READ_BUFFER: + case GraphicsContext3D::COPY_WRITE_BUFFER: + case GraphicsContext3D::PIXEL_PACK_BUFFER_BINDING: + case GraphicsContext3D::PIXEL_UNPACK_BUFFER_BINDING: + case GraphicsContext3D::READ_BUFFER: + case GraphicsContext3D::SAMPLER_BINDING: + case GraphicsContext3D::TEXTURE_BINDING_2D_ARRAY: + case GraphicsContext3D::TEXTURE_BINDING_3D: + case GraphicsContext3D::READ_FRAMEBUFFER_BINDING: + case GraphicsContext3D::TRANSFORM_FEEDBACK_BUFFER_BINDING: + case GraphicsContext3D::UNIFORM_BUFFER_BINDING: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "parameter name not yet supported"); + return nullptr; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name"); + return nullptr; + } +} + +bool WebGL2RenderingContext::validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired) +{ + // Performs conservative validation by caching a maximum index of + // the given type per element array buffer. If all of the bound + // array buffers have enough elements to satisfy that maximum + // index, skips the expensive per-draw-call iteration in + // validateIndexArrayPrecise. + + RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer(); + + if (!elementArrayBuffer) + return false; + + GC3Dsizeiptr numElements = elementArrayBuffer->byteLength(); + // The case count==0 is already dealt with in drawElements before validateIndexArrayConservative. + if (!numElements) + return false; + auto* buffer = elementArrayBuffer->elementArrayBuffer(); + ASSERT(buffer); + + std::optional<unsigned> maxIndex = elementArrayBuffer->getCachedMaxIndex(type); + if (!maxIndex) { + // Compute the maximum index in the entire buffer for the given type of index. + switch (type) { + case GraphicsContext3D::UNSIGNED_BYTE: { + const GC3Dubyte* p = static_cast<const GC3Dubyte*>(buffer->data()); + for (GC3Dsizeiptr i = 0; i < numElements; i++) + maxIndex = maxIndex ? std::max(maxIndex.value(), static_cast<unsigned>(p[i])) : static_cast<unsigned>(p[i]); + break; + } + case GraphicsContext3D::UNSIGNED_SHORT: { + numElements /= sizeof(GC3Dushort); + const GC3Dushort* p = static_cast<const GC3Dushort*>(buffer->data()); + for (GC3Dsizeiptr i = 0; i < numElements; i++) + maxIndex = maxIndex ? std::max(maxIndex.value(), static_cast<unsigned>(p[i])) : static_cast<unsigned>(p[i]); + break; + } + case GraphicsContext3D::UNSIGNED_INT: { + numElements /= sizeof(GC3Duint); + const GC3Duint* p = static_cast<const GC3Duint*>(buffer->data()); + for (GC3Dsizeiptr i = 0; i < numElements; i++) + maxIndex = maxIndex ? std::max(maxIndex.value(), static_cast<unsigned>(p[i])) : static_cast<unsigned>(p[i]); + break; + } + default: + return false; + } + if (maxIndex) + elementArrayBuffer->setCachedMaxIndex(type, maxIndex.value()); + } + + if (!maxIndex) + return false; + + // The number of required elements is one more than the maximum + // index that will be accessed. + numElementsRequired = maxIndex.value() + 1; + + // Check for overflow. + return numElementsRequired > 0; +} + +bool WebGL2RenderingContext::validateBlendEquation(const char* functionName, GC3Denum mode) +{ + switch (mode) { + case GraphicsContext3D::FUNC_ADD: + case GraphicsContext3D::FUNC_SUBTRACT: + case GraphicsContext3D::FUNC_REVERSE_SUBTRACT: + case GraphicsContext3D::MIN: + case GraphicsContext3D::MAX: + return true; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid mode"); + return false; + } +} + +bool WebGL2RenderingContext::validateCapability(const char* functionName, GC3Denum cap) +{ + switch (cap) { + case GraphicsContext3D::BLEND: + case GraphicsContext3D::CULL_FACE: + case GraphicsContext3D::DEPTH_TEST: + case GraphicsContext3D::DITHER: + case GraphicsContext3D::POLYGON_OFFSET_FILL: + case GraphicsContext3D::SAMPLE_ALPHA_TO_COVERAGE: + case GraphicsContext3D::SAMPLE_COVERAGE: + case GraphicsContext3D::SCISSOR_TEST: + case GraphicsContext3D::STENCIL_TEST: + case GraphicsContext3D::RASTERIZER_DISCARD: + return true; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid capability"); + return false; + } +} + +} // namespace WebCore + +#endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/WebGL2RenderingContext.h b/Source/WebCore/html/canvas/WebGL2RenderingContext.h new file mode 100644 index 000000000..720b13269 --- /dev/null +++ b/Source/WebCore/html/canvas/WebGL2RenderingContext.h @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2015-2017 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(WEBGL2) + +#include "WebGLRenderingContextBase.h" + +namespace WebCore { + +class WebGLQuery; +class WebGLSampler; +class WebGLSync; +class WebGLTransformFeedback; +class WebGLVertexArrayObject; + +class WebGL2RenderingContext final : public WebGLRenderingContextBase { +public: + WebGL2RenderingContext(HTMLCanvasElement&, WebGLContextAttributes); + WebGL2RenderingContext(HTMLCanvasElement&, Ref<GraphicsContext3D>&&, WebGLContextAttributes); + + // Buffer objects + using WebGLRenderingContextBase::bufferData; + using WebGLRenderingContextBase::bufferSubData; + void bufferData(GC3Denum target, const ArrayBufferView& data, GC3Denum usage, GC3Duint srcOffset, GC3Duint length); + void bufferSubData(GC3Denum target, long long offset, const ArrayBufferView& data, GC3Duint srcOffset, GC3Duint length); + void copyBufferSubData(GC3Denum readTarget, GC3Denum writeTarget, GC3Dint64 readOffset, GC3Dint64 writeOffset, GC3Dint64 size); + void getBufferSubData(GC3Denum target, long long srcByteOffset, RefPtr<ArrayBufferView>&& dstData, GC3Duint dstOffset = 0, GC3Duint length = 0); + + // Framebuffer objects + WebGLAny getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname) final; + void blitFramebuffer(GC3Dint srcX0, GC3Dint srcY0, GC3Dint srcX1, GC3Dint srcY1, GC3Dint dstX0, GC3Dint dstY0, GC3Dint dstX1, GC3Dint dstY1, GC3Dbitfield mask, GC3Denum filter); + void framebufferTextureLayer(GC3Denum target, GC3Denum attachment, GC3Duint texture, GC3Dint level, GC3Dint layer); + WebGLAny getInternalformatParameter(GC3Denum target, GC3Denum internalformat, GC3Denum pname); + void invalidateFramebuffer(GC3Denum target, const Vector<GC3Denum>& attachments); + void invalidateSubFramebuffer(GC3Denum target, const Vector<GC3Denum>& attachments, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height); + void readBuffer(GC3Denum src); + + // Renderbuffer objects + void renderbufferStorageMultisample(GC3Denum target, GC3Dsizei samples, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height); + + // Texture objects + void texStorage2D(GC3Denum target, GC3Dsizei levels, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height); + void texStorage3D(GC3Denum target, GC3Dsizei levels, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, GC3Dsizei depth); + void texImage3D(GC3Denum target, GC3Dint level, GC3Dint internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dsizei depth, GC3Dint border, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&& pixels); + + void texSubImage3D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint zoffset, GC3Dsizei width, GC3Dsizei height, GC3Dsizei depth, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&& pixels); + using TexImageSource = WTF::Variant<RefPtr<ImageData>, RefPtr<HTMLImageElement>, RefPtr<HTMLCanvasElement>, RefPtr<HTMLVideoElement>>; + void texSubImage3D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint zoffset, GC3Denum format, GC3Denum type, TexImageSource&&); + + void copyTexSubImage3D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint zoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height); + void compressedTexImage3D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dsizei depth, GC3Dint border, GC3Dsizei imageSize, RefPtr<ArrayBufferView>&& data); + void compressedTexSubImage3D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint zoffset, GC3Dsizei width, GC3Dsizei height, GC3Dsizei depth, GC3Denum format, GC3Dsizei imageSize, RefPtr<ArrayBufferView>&& data); + + // Programs and shaders + GC3Dint getFragDataLocation(WebGLProgram*, const String& name); + + // Uniforms and attributes + void uniform1ui(WebGLUniformLocation*, GC3Duint v0); + void uniform2ui(WebGLUniformLocation*, GC3Duint v0, GC3Duint v1); + void uniform3ui(WebGLUniformLocation*, GC3Duint v0, GC3Duint v1, GC3Duint v2); + void uniform4ui(WebGLUniformLocation*, GC3Duint v0, GC3Duint v1, GC3Duint v2, GC3Duint v3); + void uniform1uiv(WebGLUniformLocation*, RefPtr<Uint32Array>&& value); + void uniform2uiv(WebGLUniformLocation*, RefPtr<Uint32Array>&& value); + void uniform3uiv(WebGLUniformLocation*, RefPtr<Uint32Array>&& value); + void uniform4uiv(WebGLUniformLocation*, RefPtr<Uint32Array>&& value); + void uniformMatrix2x3fv(WebGLUniformLocation*, GC3Dboolean transpose, RefPtr<Float32Array>&& value); + void uniformMatrix3x2fv(WebGLUniformLocation*, GC3Dboolean transpose, RefPtr<Float32Array>&& value); + void uniformMatrix2x4fv(WebGLUniformLocation*, GC3Dboolean transpose, RefPtr<Float32Array>&& value); + void uniformMatrix4x2fv(WebGLUniformLocation*, GC3Dboolean transpose, RefPtr<Float32Array>&& value); + void uniformMatrix3x4fv(WebGLUniformLocation*, GC3Dboolean transpose, RefPtr<Float32Array>&& value); + void uniformMatrix4x3fv(WebGLUniformLocation*, GC3Dboolean transpose, RefPtr<Float32Array>&& value); + void vertexAttribI4i(GC3Duint index, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w); + void vertexAttribI4iv(GC3Duint index, RefPtr<Int32Array>&& v); + void vertexAttribI4ui(GC3Duint index, GC3Duint x, GC3Duint y, GC3Duint z, GC3Duint w); + void vertexAttribI4uiv(GC3Duint index, RefPtr<Uint32Array>&& v); + void vertexAttribIPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dsizei stride, GC3Dint64 offset); + + // Writing to the drawing buffer + void clear(GC3Dbitfield mask) final; + void vertexAttribDivisor(GC3Duint index, GC3Duint divisor); + void drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei instanceCount); + void drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dint64 offset, GC3Dsizei instanceCount); + void drawRangeElements(GC3Denum mode, GC3Duint start, GC3Duint end, GC3Dsizei count, GC3Denum type, GC3Dint64 offset); + + // Multiple render targets + void drawBuffers(const Vector<GC3Denum>& buffers); + void clearBufferiv(GC3Denum buffer, GC3Dint drawbuffer, RefPtr<Int32Array>&& value); + void clearBufferuiv(GC3Denum buffer, GC3Dint drawbuffer, RefPtr<Uint32Array>&& value); + void clearBufferfv(GC3Denum buffer, GC3Dint drawbuffer, RefPtr<Float32Array>&& value); + void clearBufferfi(GC3Denum buffer, GC3Dint drawbuffer, GC3Dfloat depth, GC3Dint stencil); + + // Query objects + RefPtr<WebGLQuery> createQuery(); + void deleteQuery(WebGLQuery*); + GC3Dboolean isQuery(WebGLQuery*); + void beginQuery(GC3Denum target, WebGLQuery*); + void endQuery(GC3Denum target); + RefPtr<WebGLQuery> getQuery(GC3Denum target, GC3Denum pname); + WebGLAny getQueryParameter(WebGLQuery*, GC3Denum pname); + + // Sampler objects + RefPtr<WebGLSampler> createSampler(); + void deleteSampler(WebGLSampler*); + GC3Dboolean isSampler(WebGLSampler*); + void bindSampler(GC3Duint unit, WebGLSampler*); + void samplerParameteri(WebGLSampler*, GC3Denum pname, GC3Dint param); + void samplerParameterf(WebGLSampler*, GC3Denum pname, GC3Dfloat param); + WebGLAny getSamplerParameter(WebGLSampler*, GC3Denum pname); + + // Sync objects + RefPtr<WebGLSync> fenceSync(GC3Denum condition, GC3Dbitfield flags); + GC3Dboolean isSync(WebGLSync*); + void deleteSync(WebGLSync*); + GC3Denum clientWaitSync(WebGLSync*, GC3Dbitfield flags, GC3Duint64 timeout); + void waitSync(WebGLSync*, GC3Dbitfield flags, GC3Duint64 timeout); + WebGLAny getSyncParameter(WebGLSync*, GC3Denum pname); + + // Transform feedback + RefPtr<WebGLTransformFeedback> createTransformFeedback(); + void deleteTransformFeedback(WebGLTransformFeedback* id); + GC3Dboolean isTransformFeedback(WebGLTransformFeedback* id); + void bindTransformFeedback(GC3Denum target, WebGLTransformFeedback* id); + void beginTransformFeedback(GC3Denum primitiveMode); + void endTransformFeedback(); + void transformFeedbackVaryings(WebGLProgram*, const Vector<String>& varyings, GC3Denum bufferMode); + RefPtr<WebGLActiveInfo> getTransformFeedbackVarying(WebGLProgram*, GC3Duint index); + void pauseTransformFeedback(); + void resumeTransformFeedback(); + + // Uniform buffer objects and transform feedback buffers + void bindBufferBase(GC3Denum target, GC3Duint index, WebGLBuffer*); + void bindBufferRange(GC3Denum target, GC3Duint index, WebGLBuffer*, GC3Dint64 offset, GC3Dint64 size); + WebGLAny getIndexedParameter(GC3Denum target, GC3Duint index); + Uint32Array* getUniformIndices(WebGLProgram*, const Vector<String>& uniformNames); + Int32Array* getActiveUniforms(WebGLProgram*, RefPtr<Uint32Array>&& uniformIndices, GC3Denum pname); + GC3Duint getUniformBlockIndex(WebGLProgram*, const String& uniformBlockName); + WebGLAny getActiveUniformBlockParameter(WebGLProgram*, GC3Duint uniformBlockIndex, GC3Denum pname); + WebGLAny getActiveUniformBlockName(WebGLProgram*, GC3Duint uniformBlockIndex); + void uniformBlockBinding(WebGLProgram*, GC3Duint uniformBlockIndex, GC3Duint uniformBlockBinding); + + // Vertex array objects + RefPtr<WebGLVertexArrayObject> createVertexArray(); + void deleteVertexArray(WebGLVertexArrayObject* vertexArray); + GC3Dboolean isVertexArray(WebGLVertexArrayObject* vertexArray); + void bindVertexArray(WebGLVertexArrayObject* vertexArray); + +private: + bool isWebGL2() const final { return true; } + + // Extensions + WebGLExtension* getExtension(const String&) final; + std::optional<Vector<String>> getSupportedExtensions() final; + WebGLAny getParameter(GC3Denum pname) final; + + void renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) final; + void hint(GC3Denum target, GC3Denum mode) final; + + void initializeVertexArrayObjects() final; + GC3Dint getMaxDrawBuffers() final; + GC3Dint getMaxColorAttachments() final; + bool validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired) final; + bool validateBlendEquation(const char* functionName, GC3Denum mode) final; + bool validateCapability(const char* functionName, GC3Denum cap) final; + bool validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment) final; + + GC3Denum baseInternalFormatFromInternalFormat(GC3Denum internalformat); + bool isIntegerFormat(GC3Denum internalformat); + void initializeShaderExtensions(); + + bool validateTexStorageFuncParameters(GC3Denum target, GC3Dsizei levels, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, const char* functionName); +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CANVASRENDERINGCONTEXT(WebCore::WebGL2RenderingContext, isWebGL2()) + +#endif // WEBGL2 diff --git a/Source/WebCore/html/canvas/WebGL2RenderingContext.idl b/Source/WebCore/html/canvas/WebGL2RenderingContext.idl new file mode 100644 index 000000000..15c2f4ed5 --- /dev/null +++ b/Source/WebCore/html/canvas/WebGL2RenderingContext.idl @@ -0,0 +1,468 @@ +/* + * Copyright (C) 2015 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +typedef unsigned long GLenum; +typedef boolean GLboolean; +typedef unsigned long GLbitfield; +typedef byte GLbyte; +typedef short GLshort; +typedef long GLint; +typedef long GLsizei; +typedef long long GLintptr; +typedef long long GLsizeiptr; +typedef long long GLint64; +typedef octet GLubyte; +typedef unsigned short GLushort; +typedef unsigned long GLuint; +typedef unsigned long long GLuint64; +typedef unrestricted float GLfloat; +typedef unrestricted float GLclampf; +typedef (ArrayBuffer or ArrayBufferView) BufferDataSource; + +// FIXME: Should allow ImageBitmap too. +typedef (ImageData or HTMLImageElement or HTMLCanvasElement or HTMLVideoElement) TexImageSource; + +[ + Conditional=WEBGL2, + EnabledAtRuntime=WebGL2, + JSCustomMarkFunction, + JSGenerateToJSObject, + DoNotCheckConstants, +] interface WebGL2RenderingContext : WebGLRenderingContextBase { + const GLenum READ_BUFFER = 0x0C02; + const GLenum UNPACK_ROW_LENGTH = 0x0CF2; + const GLenum UNPACK_SKIP_ROWS = 0x0CF3; + const GLenum UNPACK_SKIP_PIXELS = 0x0CF4; + const GLenum PACK_ROW_LENGTH = 0x0D02; + const GLenum PACK_SKIP_ROWS = 0x0D03; + const GLenum PACK_SKIP_PIXELS = 0x0D04; + const GLenum COLOR = 0x1800; + const GLenum DEPTH = 0x1801; + const GLenum STENCIL = 0x1802; + const GLenum RED = 0x1903; + const GLenum RGB8 = 0x8051; + const GLenum RGBA8 = 0x8058; + const GLenum RGB10_A2 = 0x8059; + const GLenum TEXTURE_BINDING_3D = 0x806A; + const GLenum UNPACK_SKIP_IMAGES = 0x806D; + const GLenum UNPACK_IMAGE_HEIGHT = 0x806E; + const GLenum TEXTURE_3D = 0x806F; + const GLenum TEXTURE_WRAP_R = 0x8072; + const GLenum MAX_3D_TEXTURE_SIZE = 0x8073; + const GLenum UNSIGNED_INT_2_10_10_10_REV = 0x8368; + const GLenum MAX_ELEMENTS_VERTICES = 0x80E8; + const GLenum MAX_ELEMENTS_INDICES = 0x80E9; + const GLenum TEXTURE_MIN_LOD = 0x813A; + const GLenum TEXTURE_MAX_LOD = 0x813B; + const GLenum TEXTURE_BASE_LEVEL = 0x813C; + const GLenum TEXTURE_MAX_LEVEL = 0x813D; + const GLenum MIN = 0x8007; + const GLenum MAX = 0x8008; + const GLenum DEPTH_COMPONENT24 = 0x81A6; + const GLenum MAX_TEXTURE_LOD_BIAS = 0x84FD; + const GLenum TEXTURE_COMPARE_MODE = 0x884C; + const GLenum TEXTURE_COMPARE_FUNC = 0x884D; + const GLenum CURRENT_QUERY = 0x8865; + const GLenum QUERY_RESULT = 0x8866; + const GLenum QUERY_RESULT_AVAILABLE = 0x8867; + const GLenum STREAM_READ = 0x88E1; + const GLenum STREAM_COPY = 0x88E2; + const GLenum STATIC_READ = 0x88E5; + const GLenum STATIC_COPY = 0x88E6; + const GLenum DYNAMIC_READ = 0x88E9; + const GLenum DYNAMIC_COPY = 0x88EA; + const GLenum MAX_DRAW_BUFFERS = 0x8824; + const GLenum DRAW_BUFFER0 = 0x8825; + const GLenum DRAW_BUFFER1 = 0x8826; + const GLenum DRAW_BUFFER2 = 0x8827; + const GLenum DRAW_BUFFER3 = 0x8828; + const GLenum DRAW_BUFFER4 = 0x8829; + const GLenum DRAW_BUFFER5 = 0x882A; + const GLenum DRAW_BUFFER6 = 0x882B; + const GLenum DRAW_BUFFER7 = 0x882C; + const GLenum DRAW_BUFFER8 = 0x882D; + const GLenum DRAW_BUFFER9 = 0x882E; + const GLenum DRAW_BUFFER10 = 0x882F; + const GLenum DRAW_BUFFER11 = 0x8830; + const GLenum DRAW_BUFFER12 = 0x8831; + const GLenum DRAW_BUFFER13 = 0x8832; + const GLenum DRAW_BUFFER14 = 0x8833; + const GLenum DRAW_BUFFER15 = 0x8834; + const GLenum MAX_FRAGMENT_UNIFORM_COMPONENTS = 0x8B49; + const GLenum MAX_VERTEX_UNIFORM_COMPONENTS = 0x8B4A; + const GLenum SAMPLER_3D = 0x8B5F; + const GLenum SAMPLER_2D_SHADOW = 0x8B62; + const GLenum FRAGMENT_SHADER_DERIVATIVE_HINT = 0x8B8B; + const GLenum PIXEL_PACK_BUFFER = 0x88EB; + const GLenum PIXEL_UNPACK_BUFFER = 0x88EC; + const GLenum PIXEL_PACK_BUFFER_BINDING = 0x88ED; + const GLenum PIXEL_UNPACK_BUFFER_BINDING = 0x88EF; + const GLenum FLOAT_MAT2x3 = 0x8B65; + const GLenum FLOAT_MAT2x4 = 0x8B66; + const GLenum FLOAT_MAT3x2 = 0x8B67; + const GLenum FLOAT_MAT3x4 = 0x8B68; + const GLenum FLOAT_MAT4x2 = 0x8B69; + const GLenum FLOAT_MAT4x3 = 0x8B6A; + const GLenum SRGB = 0x8C40; + const GLenum SRGB8 = 0x8C41; + const GLenum SRGB8_ALPHA8 = 0x8C43; + const GLenum COMPARE_REF_TO_TEXTURE = 0x884E; + const GLenum RGBA32F = 0x8814; + const GLenum RGB32F = 0x8815; + const GLenum RGBA16F = 0x881A; + const GLenum RGB16F = 0x881B; + const GLenum VERTEX_ATTRIB_ARRAY_INTEGER = 0x88FD; + const GLenum MAX_ARRAY_TEXTURE_LAYERS = 0x88FF; + const GLenum MIN_PROGRAM_TEXEL_OFFSET = 0x8904; + const GLenum MAX_PROGRAM_TEXEL_OFFSET = 0x8905; + const GLenum MAX_VARYING_COMPONENTS = 0x8B4B; + const GLenum TEXTURE_2D_ARRAY = 0x8C1A; + const GLenum TEXTURE_BINDING_2D_ARRAY = 0x8C1D; + const GLenum R11F_G11F_B10F = 0x8C3A; + const GLenum UNSIGNED_INT_10F_11F_11F_REV = 0x8C3B; + const GLenum RGB9_E5 = 0x8C3D; + const GLenum UNSIGNED_INT_5_9_9_9_REV = 0x8C3E; + const GLenum TRANSFORM_FEEDBACK_BUFFER_MODE = 0x8C7F; + const GLenum MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS = 0x8C80; + const GLenum TRANSFORM_FEEDBACK_VARYINGS = 0x8C83; + const GLenum TRANSFORM_FEEDBACK_BUFFER_START = 0x8C84; + const GLenum TRANSFORM_FEEDBACK_BUFFER_SIZE = 0x8C85; + const GLenum TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN = 0x8C88; + const GLenum RASTERIZER_DISCARD = 0x8C89; + const GLenum MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS = 0x8C8A; + const GLenum MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS = 0x8C8B; + const GLenum INTERLEAVED_ATTRIBS = 0x8C8C; + const GLenum SEPARATE_ATTRIBS = 0x8C8D; + const GLenum TRANSFORM_FEEDBACK_BUFFER = 0x8C8E; + const GLenum TRANSFORM_FEEDBACK_BUFFER_BINDING = 0x8C8F; + const GLenum RGBA32UI = 0x8D70; + const GLenum RGB32UI = 0x8D71; + const GLenum RGBA16UI = 0x8D76; + const GLenum RGB16UI = 0x8D77; + const GLenum RGBA8UI = 0x8D7C; + const GLenum RGB8UI = 0x8D7D; + const GLenum RGBA32I = 0x8D82; + const GLenum RGB32I = 0x8D83; + const GLenum RGBA16I = 0x8D88; + const GLenum RGB16I = 0x8D89; + const GLenum RGBA8I = 0x8D8E; + const GLenum RGB8I = 0x8D8F; + const GLenum RED_INTEGER = 0x8D94; + const GLenum RGB_INTEGER = 0x8D98; + const GLenum RGBA_INTEGER = 0x8D99; + const GLenum SAMPLER_2D_ARRAY = 0x8DC1; + const GLenum SAMPLER_2D_ARRAY_SHADOW = 0x8DC4; + const GLenum SAMPLER_CUBE_SHADOW = 0x8DC5; + const GLenum UNSIGNED_INT_VEC2 = 0x8DC6; + const GLenum UNSIGNED_INT_VEC3 = 0x8DC7; + const GLenum UNSIGNED_INT_VEC4 = 0x8DC8; + const GLenum INT_SAMPLER_2D = 0x8DCA; + const GLenum INT_SAMPLER_3D = 0x8DCB; + const GLenum INT_SAMPLER_CUBE = 0x8DCC; + const GLenum INT_SAMPLER_2D_ARRAY = 0x8DCF; + const GLenum UNSIGNED_INT_SAMPLER_2D = 0x8DD2; + const GLenum UNSIGNED_INT_SAMPLER_3D = 0x8DD3; + const GLenum UNSIGNED_INT_SAMPLER_CUBE = 0x8DD4; + const GLenum UNSIGNED_INT_SAMPLER_2D_ARRAY = 0x8DD7; + const GLenum DEPTH_COMPONENT32F = 0x8CAC; + const GLenum DEPTH32F_STENCIL8 = 0x8CAD; + const GLenum FLOAT_32_UNSIGNED_INT_24_8_REV = 0x8DAD; + const GLenum FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING = 0x8210; + const GLenum FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE = 0x8211; + const GLenum FRAMEBUFFER_ATTACHMENT_RED_SIZE = 0x8212; + const GLenum FRAMEBUFFER_ATTACHMENT_GREEN_SIZE = 0x8213; + const GLenum FRAMEBUFFER_ATTACHMENT_BLUE_SIZE = 0x8214; + const GLenum FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE = 0x8215; + const GLenum FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE = 0x8216; + const GLenum FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE = 0x8217; + const GLenum FRAMEBUFFER_DEFAULT = 0x8218; + const GLenum DEPTH_STENCIL_ATTACHMENT = 0x821A; + const GLenum DEPTH_STENCIL = 0x84F9; + const GLenum UNSIGNED_INT_24_8 = 0x84FA; + const GLenum DEPTH24_STENCIL8 = 0x88F0; + const GLenum UNSIGNED_NORMALIZED = 0x8C17; + const GLenum DRAW_FRAMEBUFFER_BINDING = 0x8CA6; /* Same as FRAMEBUFFER_BINDING */ + const GLenum READ_FRAMEBUFFER = 0x8CA8; + const GLenum DRAW_FRAMEBUFFER = 0x8CA9; + const GLenum READ_FRAMEBUFFER_BINDING = 0x8CAA; + const GLenum RENDERBUFFER_SAMPLES = 0x8CAB; + const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER = 0x8CD4; + const GLenum MAX_COLOR_ATTACHMENTS = 0x8CDF; + const GLenum COLOR_ATTACHMENT1 = 0x8CE1; + const GLenum COLOR_ATTACHMENT2 = 0x8CE2; + const GLenum COLOR_ATTACHMENT3 = 0x8CE3; + const GLenum COLOR_ATTACHMENT4 = 0x8CE4; + const GLenum COLOR_ATTACHMENT5 = 0x8CE5; + const GLenum COLOR_ATTACHMENT6 = 0x8CE6; + const GLenum COLOR_ATTACHMENT7 = 0x8CE7; + const GLenum COLOR_ATTACHMENT8 = 0x8CE8; + const GLenum COLOR_ATTACHMENT9 = 0x8CE9; + const GLenum COLOR_ATTACHMENT10 = 0x8CEA; + const GLenum COLOR_ATTACHMENT11 = 0x8CEB; + const GLenum COLOR_ATTACHMENT12 = 0x8CEC; + const GLenum COLOR_ATTACHMENT13 = 0x8CED; + const GLenum COLOR_ATTACHMENT14 = 0x8CEE; + const GLenum COLOR_ATTACHMENT15 = 0x8CEF; + const GLenum FRAMEBUFFER_INCOMPLETE_MULTISAMPLE = 0x8D56; + const GLenum MAX_SAMPLES = 0x8D57; + const GLenum HALF_FLOAT = 0x140B; + const GLenum RG = 0x8227; + const GLenum RG_INTEGER = 0x8228; + const GLenum R8 = 0x8229; + const GLenum RG8 = 0x822B; + const GLenum R16F = 0x822D; + const GLenum R32F = 0x822E; + const GLenum RG16F = 0x822F; + const GLenum RG32F = 0x8230; + const GLenum R8I = 0x8231; + const GLenum R8UI = 0x8232; + const GLenum R16I = 0x8233; + const GLenum R16UI = 0x8234; + const GLenum R32I = 0x8235; + const GLenum R32UI = 0x8236; + const GLenum RG8I = 0x8237; + const GLenum RG8UI = 0x8238; + const GLenum RG16I = 0x8239; + const GLenum RG16UI = 0x823A; + const GLenum RG32I = 0x823B; + const GLenum RG32UI = 0x823C; + const GLenum VERTEX_ARRAY_BINDING = 0x85B5; + const GLenum R8_SNORM = 0x8F94; + const GLenum RG8_SNORM = 0x8F95; + const GLenum RGB8_SNORM = 0x8F96; + const GLenum RGBA8_SNORM = 0x8F97; + const GLenum SIGNED_NORMALIZED = 0x8F9C; + const GLenum PRIMITIVE_RESTART_FIXED_INDEX = 0x8D69; + const GLenum COPY_READ_BUFFER = 0x8F36; + const GLenum COPY_WRITE_BUFFER = 0x8F37; + const GLenum COPY_READ_BUFFER_BINDING = 0x8F36; /* Same as COPY_READ_BUFFER */ + const GLenum COPY_WRITE_BUFFER_BINDING = 0x8F37; /* Same as COPY_WRITE_BUFFER */ + const GLenum UNIFORM_BUFFER = 0x8A11; + const GLenum UNIFORM_BUFFER_BINDING = 0x8A28; + const GLenum UNIFORM_BUFFER_START = 0x8A29; + const GLenum UNIFORM_BUFFER_SIZE = 0x8A2A; + const GLenum MAX_VERTEX_UNIFORM_BLOCKS = 0x8A2B; + const GLenum MAX_FRAGMENT_UNIFORM_BLOCKS = 0x8A2D; + const GLenum MAX_COMBINED_UNIFORM_BLOCKS = 0x8A2E; + const GLenum MAX_UNIFORM_BUFFER_BINDINGS = 0x8A2F; + const GLenum MAX_UNIFORM_BLOCK_SIZE = 0x8A30; + const GLenum MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS = 0x8A31; + const GLenum MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS = 0x8A33; + const GLenum UNIFORM_BUFFER_OFFSET_ALIGNMENT = 0x8A34; + const GLenum ACTIVE_UNIFORM_BLOCKS = 0x8A36; + const GLenum UNIFORM_TYPE = 0x8A37; + const GLenum UNIFORM_SIZE = 0x8A38; + const GLenum UNIFORM_BLOCK_INDEX = 0x8A3A; + const GLenum UNIFORM_OFFSET = 0x8A3B; + const GLenum UNIFORM_ARRAY_STRIDE = 0x8A3C; + const GLenum UNIFORM_MATRIX_STRIDE = 0x8A3D; + const GLenum UNIFORM_IS_ROW_MAJOR = 0x8A3E; + const GLenum UNIFORM_BLOCK_BINDING = 0x8A3F; + const GLenum UNIFORM_BLOCK_DATA_SIZE = 0x8A40; + const GLenum UNIFORM_BLOCK_ACTIVE_UNIFORMS = 0x8A42; + const GLenum UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES = 0x8A43; + const GLenum UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER = 0x8A44; + const GLenum UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER = 0x8A46; + const GLenum INVALID_INDEX = 0xFFFFFFFF; + const GLenum MAX_VERTEX_OUTPUT_COMPONENTS = 0x9122; + const GLenum MAX_FRAGMENT_INPUT_COMPONENTS = 0x9125; + const GLenum MAX_SERVER_WAIT_TIMEOUT = 0x9111; + const GLenum OBJECT_TYPE = 0x9112; + const GLenum SYNC_CONDITION = 0x9113; + const GLenum SYNC_STATUS = 0x9114; + const GLenum SYNC_FLAGS = 0x9115; + const GLenum SYNC_FENCE = 0x9116; + const GLenum SYNC_GPU_COMMANDS_COMPLETE = 0x9117; + const GLenum UNSIGNALED = 0x9118; + const GLenum SIGNALED = 0x9119; + const GLenum ALREADY_SIGNALED = 0x911A; + const GLenum TIMEOUT_EXPIRED = 0x911B; + const GLenum CONDITION_SATISFIED = 0x911C; + const GLenum WAIT_FAILED = 0x911D; + const GLenum SYNC_FLUSH_COMMANDS_BIT = 0x00000001; + const GLenum VERTEX_ATTRIB_ARRAY_DIVISOR = 0x88FE; + const GLenum ANY_SAMPLES_PASSED = 0x8C2F; + const GLenum ANY_SAMPLES_PASSED_CONSERVATIVE = 0x8D6A; + const GLenum SAMPLER_BINDING = 0x8919; + const GLenum RGB10_A2UI = 0x906F; + const GLenum TEXTURE_SWIZZLE_R = 0x8E42; + const GLenum TEXTURE_SWIZZLE_G = 0x8E43; + const GLenum TEXTURE_SWIZZLE_B = 0x8E44; + const GLenum TEXTURE_SWIZZLE_A = 0x8E45; + const GLenum GREEN = 0x1904; + const GLenum BLUE = 0x1905; + const GLenum INT_2_10_10_10_REV = 0x8D9F; + const GLenum TRANSFORM_FEEDBACK = 0x8E22; + const GLenum TRANSFORM_FEEDBACK_PAUSED = 0x8E23; + const GLenum TRANSFORM_FEEDBACK_ACTIVE = 0x8E24; + const GLenum TRANSFORM_FEEDBACK_BINDING = 0x8E25; + const GLenum COMPRESSED_R11_EAC = 0x9270; + const GLenum COMPRESSED_SIGNED_R11_EAC = 0x9271; + const GLenum COMPRESSED_RG11_EAC = 0x9272; + const GLenum COMPRESSED_SIGNED_RG11_EAC = 0x9273; + const GLenum COMPRESSED_RGB8_ETC2 = 0x9274; + const GLenum COMPRESSED_SRGB8_ETC2 = 0x9275; + const GLenum COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9276; + const GLenum COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9277; + const GLenum COMPRESSED_RGBA8_ETC2_EAC = 0x9278; + const GLenum COMPRESSED_SRGB8_ALPHA8_ETC2_EAC = 0x9279; + const GLenum TEXTURE_IMMUTABLE_FORMAT = 0x912F; + const GLenum MAX_ELEMENT_INDEX = 0x8D6B; + const GLenum NUM_SAMPLE_COUNTS = 0x9380; + const GLenum TEXTURE_IMMUTABLE_LEVELS = 0x82DF; + const GLenum VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE = 0x88FE; + + const GLuint64 TIMEOUT_IGNORED = 0xFFFFFFFFFFFFFFFF; + + /* Buffer objects */ + // WebGL1: + void bufferData(GLenum target, GLsizeiptr size, GLenum usage); + void bufferData(GLenum target, BufferDataSource? srcData, GLenum usage); + void bufferSubData(GLenum target, GLintptr dstByteOffset, BufferDataSource? srcData); + // WebGL2: + void bufferData(GLenum target, ArrayBufferView data, GLenum usage, GLuint srcOffset, optional GLuint length = 0); + void bufferSubData(GLenum target, GLintptr dstByteOffset, ArrayBufferView srcData, GLuint srcOffset, optional GLuint length = 0); + + void copyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); + // MapBufferRange, in particular its read-only and write-only modes, + // can not be exposed safely to JavaScript. GetBufferSubData + // replaces it for the purpose of fetching data back from the GPU. + void getBufferSubData(GLenum target, GLintptr srcByteOffset, ArrayBufferView dstData, optional GLuint dstOffset = 0, optional GLuint length = 0); + + /* Framebuffer objects */ + void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); + void framebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); + [OverrideIDLType=IDLWebGLAny] any getInternalformatParameter(GLenum target, GLenum internalformat, GLenum pname); + void invalidateFramebuffer(GLenum target, sequence<GLenum> attachments); + void invalidateSubFramebuffer(GLenum target, sequence<GLenum> attachments, GLint x, GLint y, GLsizei width, GLsizei height); + void readBuffer(GLenum src); + + /* Renderbuffer objects */ + void renderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + + /* Texture objects */ + void texStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); + void texStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + void texImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, ArrayBufferView? pixels); + + void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, ArrayBufferView? pixels); + void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLenum format, GLenum type, TexImageSource source); + + void copyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); + void compressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, ArrayBufferView? data); + void compressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, ArrayBufferView? data); + + /* Programs and shaders */ + GLint getFragDataLocation(WebGLProgram? program, DOMString name); + + /* Uniforms and attributes */ + void uniform1ui(WebGLUniformLocation? location, GLuint v0); + void uniform2ui(WebGLUniformLocation? location, GLuint v0, GLuint v1); + void uniform3ui(WebGLUniformLocation? location, GLuint v0, GLuint v1, GLuint v2); + void uniform4ui(WebGLUniformLocation? location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); + void uniform1uiv(WebGLUniformLocation? location, Uint32Array? value); + void uniform2uiv(WebGLUniformLocation? location, Uint32Array? value); + void uniform3uiv(WebGLUniformLocation? location, Uint32Array? value); + void uniform4uiv(WebGLUniformLocation? location, Uint32Array? value); + void uniformMatrix2x3fv(WebGLUniformLocation? location, GLboolean transpose, Float32Array? value); + void uniformMatrix3x2fv(WebGLUniformLocation? location, GLboolean transpose, Float32Array? value); + void uniformMatrix2x4fv(WebGLUniformLocation? location, GLboolean transpose, Float32Array? value); + void uniformMatrix4x2fv(WebGLUniformLocation? location, GLboolean transpose, Float32Array? value); + void uniformMatrix3x4fv(WebGLUniformLocation? location, GLboolean transpose, Float32Array? value); + void uniformMatrix4x3fv(WebGLUniformLocation? location, GLboolean transpose, Float32Array? value); + void vertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w); + void vertexAttribI4iv(GLuint index, Int32Array? v); + void vertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); + void vertexAttribI4uiv(GLuint index, Uint32Array? v); + void vertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); + + /* Writing to the drawing buffer */ + void vertexAttribDivisor(GLuint index, GLuint divisor); + void drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount); + void drawElementsInstanced(GLenum mode, GLsizei count, GLenum type, GLintptr offset, GLsizei instanceCount); + void drawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, GLintptr offset); + + /* Multiple Render Targets */ + void drawBuffers(sequence<GLenum> buffers); + void clearBufferiv(GLenum buffer, GLint drawbuffer, Int32Array? value); + void clearBufferuiv(GLenum buffer, GLint drawbuffer, Uint32Array? value); + void clearBufferfv(GLenum buffer, GLint drawbuffer, Float32Array? value); + void clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); + + /* Query Objects */ + WebGLQuery createQuery(); + void deleteQuery(WebGLQuery? query); + GLboolean isQuery(WebGLQuery? query); + void beginQuery(GLenum target, WebGLQuery? query); + void endQuery(GLenum target); + WebGLQuery getQuery(GLenum target, GLenum pname); + [OverrideIDLType=IDLWebGLAny] any getQueryParameter(WebGLQuery? query, GLenum pname); + + /* Sampler Objects */ + WebGLSampler createSampler(); + void deleteSampler(WebGLSampler? sampler); + GLboolean isSampler(WebGLSampler? sampler); + void bindSampler(GLuint unit, WebGLSampler? sampler); + void samplerParameteri(WebGLSampler? sampler, GLenum pname, GLint param); + void samplerParameterf(WebGLSampler? sampler, GLenum pname, GLfloat param); + [OverrideIDLType=IDLWebGLAny] any getSamplerParameter(WebGLSampler? sampler, GLenum pname); + + /* Sync objects */ + WebGLSync fenceSync(GLenum condition, GLbitfield flags); + GLboolean isSync(WebGLSync? sync); + void deleteSync(WebGLSync? sync); + GLenum clientWaitSync(WebGLSync? sync, GLbitfield flags, GLuint64 timeout); + void waitSync(WebGLSync? sync, GLbitfield flags, GLuint64 timeout); + [OverrideIDLType=IDLWebGLAny] any getSyncParameter(WebGLSync? sync, GLenum pname); + + /* Transform Feedback */ + WebGLTransformFeedback createTransformFeedback(); + void deleteTransformFeedback(WebGLTransformFeedback? id); + GLboolean isTransformFeedback(WebGLTransformFeedback? id); + void bindTransformFeedback(GLenum target, WebGLTransformFeedback? id); + void beginTransformFeedback(GLenum primitiveMode); + void endTransformFeedback(); + void transformFeedbackVaryings(WebGLProgram? program, sequence<DOMString> varyings, GLenum bufferMode); + WebGLActiveInfo getTransformFeedbackVarying(WebGLProgram? program, GLuint index); + void pauseTransformFeedback(); + void resumeTransformFeedback(); + + /* Uniform Buffer Objects and Transform Feedback Buffers */ + void bindBufferBase(GLenum target, GLuint index, WebGLBuffer? buffer); + void bindBufferRange(GLenum target, GLuint index, WebGLBuffer? buffer, GLintptr offset, GLsizeiptr size); + [OverrideIDLType=IDLWebGLAny] any getIndexedParameter(GLenum target, GLuint index); + Uint32Array getUniformIndices(WebGLProgram? program, sequence<DOMString> uniformNames); + Int32Array getActiveUniforms(WebGLProgram? program, Uint32Array? uniformIndices, GLenum pname); + GLuint getUniformBlockIndex(WebGLProgram? program, DOMString uniformBlockName); + [OverrideIDLType=IDLWebGLAny] any getActiveUniformBlockParameter(WebGLProgram? program, GLuint uniformBlockIndex, GLenum pname); + [OverrideIDLType=IDLWebGLAny] any getActiveUniformBlockName(WebGLProgram? program, GLuint uniformBlockIndex); + void uniformBlockBinding(WebGLProgram? program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); + + /* Vertex Array Objects */ + WebGLVertexArrayObject createVertexArray(); + void deleteVertexArray(WebGLVertexArrayObject? vertexArray); + GLboolean isVertexArray(WebGLVertexArrayObject? vertexArray); + void bindVertexArray(WebGLVertexArrayObject? vertexArray); +}; diff --git a/Source/WebCore/html/canvas/WebGLActiveInfo.h b/Source/WebCore/html/canvas/WebGLActiveInfo.h index 0938a2366..843cb73a2 100644 --- a/Source/WebCore/html/canvas/WebGLActiveInfo.h +++ b/Source/WebCore/html/canvas/WebGLActiveInfo.h @@ -23,11 +23,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLActiveInfo_h -#define WebGLActiveInfo_h +#pragma once #include "GraphicsContext3D.h" -#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/text/WTFString.h> @@ -35,9 +33,9 @@ namespace WebCore { class WebGLActiveInfo : public RefCounted<WebGLActiveInfo> { public: - static PassRefPtr<WebGLActiveInfo> create(const String& name, GC3Denum type, GC3Dint size) + static Ref<WebGLActiveInfo> create(const String& name, GC3Denum type, GC3Dint size) { - return adoptRef(new WebGLActiveInfo(name, type, size)); + return adoptRef(*new WebGLActiveInfo(name, type, size)); } String name() const { return m_name; } GC3Denum type() const { return m_type; } @@ -58,6 +56,4 @@ private: GC3Dint m_size; }; -} - -#endif // WebGLActiveInfo_h +} // namespace WebCore diff --git a/Source/WebCore/html/canvas/WebGLAny.cpp b/Source/WebCore/html/canvas/WebGLAny.cpp new file mode 100644 index 000000000..75ce05139 --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLAny.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2017 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebGLAny.h" + +#if ENABLE(WEBGL) + +#include "JSDOMConvert.h" +#include "JSWebGLBuffer.h" +#include "JSWebGLFramebuffer.h" +#include "JSWebGLProgram.h" +#include "JSWebGLRenderbuffer.h" +#include "JSWebGLTexture.h" +#include "JSWebGLVertexArrayObjectOES.h" +#include <wtf/Variant.h> + +#if ENABLE(WEBGL2) +#include "JSWebGLVertexArrayObject.h" +#endif + +namespace WebCore { + +using namespace JSC; + +// FIXME: This should use the IDLUnion JSConverter. +JSValue convertToJSValue(ExecState& state, JSDOMGlobalObject& globalObject, const WebGLAny& any) +{ + return WTF::switchOn(any, + [] (std::nullptr_t) { + return jsNull(); + }, + [] (bool value) { + return jsBoolean(value); + }, + [] (int value) { + return jsNumber(value); + }, + [] (unsigned value) { + return jsNumber(value); + }, + [] (long long value) { + return jsNumber(value); + }, + [] (float value) { + return jsNumber(value); + }, + [&] (const String& value) { + return jsStringWithCache(&state, value); + }, + [&] (const Vector<bool>& values) { + MarkedArgumentBuffer list; + for (auto& value : values) + list.append(jsBoolean(value)); + return constructArray(&state, 0, &globalObject, list); + }, + [&] (const RefPtr<Float32Array>& array) { + return toJS(&state, &globalObject, array.get()); + }, + [&] (const RefPtr<Int32Array>& array) { + return toJS(&state, &globalObject, array.get()); + }, + [&] (const RefPtr<Uint8Array>& array) { + return toJS(&state, &globalObject, array.get()); + }, + [&] (const RefPtr<Uint32Array>& array) { + return toJS(&state, &globalObject, array.get()); + }, + [&] (const RefPtr<WebGLBuffer>& buffer) { + return toJS(&state, &globalObject, buffer.get()); + }, + [&] (const RefPtr<WebGLFramebuffer>& buffer) { + return toJS(&state, &globalObject, buffer.get()); + }, + [&] (const RefPtr<WebGLProgram>& program) { + return toJS(&state, &globalObject, program.get()); + }, + [&] (const RefPtr<WebGLRenderbuffer>& buffer) { + return toJS(&state, &globalObject, buffer.get()); + }, + [&] (const RefPtr<WebGLTexture>& texture) { + return toJS(&state, &globalObject, texture.get()); + }, + [&] (const RefPtr<WebGLVertexArrayObjectOES>& array) { + return toJS(&state, &globalObject, array.get()); + } +#if ENABLE(WEBGL2) + , + [&] (const RefPtr<WebGLVertexArrayObject>& array) { + return toJS(&state, &globalObject, array.get()); + } +#endif + ); +} + +} + +#endif diff --git a/Source/WebCore/html/canvas/WebGLAny.h b/Source/WebCore/html/canvas/WebGLAny.h new file mode 100644 index 000000000..c773b080b --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLAny.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2017 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(WEBGL) + +#include <runtime/Float32Array.h> +#include <runtime/Int32Array.h> +#include <runtime/Uint32Array.h> +#include <runtime/Uint8Array.h> + +namespace JSC { +class ExecState; +class JSValue; +} + +namespace WebCore { + +class JSDOMGlobalObject; +class WebGLBuffer; +class WebGLFramebuffer; +class WebGLProgram; +class WebGLRenderbuffer; +class WebGLTexture; +class WebGLVertexArrayObject; +class WebGLVertexArrayObjectOES; + +using WebGLAny = Variant< + std::nullptr_t, + bool, + int, + unsigned, + long long, + float, + String, + Vector<bool>, + RefPtr<Float32Array>, + RefPtr<Int32Array>, + RefPtr<Uint32Array>, + RefPtr<Uint8Array>, + RefPtr<WebGLBuffer>, + RefPtr<WebGLFramebuffer>, + RefPtr<WebGLProgram>, + RefPtr<WebGLRenderbuffer>, + RefPtr<WebGLTexture>, + RefPtr<WebGLVertexArrayObjectOES> +#if ENABLE(WEBGL2) + , RefPtr<WebGLVertexArrayObject> +#endif +>; + +JSC::JSValue convertToJSValue(JSC::ExecState&, JSDOMGlobalObject&, const WebGLAny&); + +} // namespace WebCore + +#endif diff --git a/Source/WebCore/html/canvas/WebGLBuffer.cpp b/Source/WebCore/html/canvas/WebGLBuffer.cpp index 3421e979c..bc914a4a7 100644 --- a/Source/WebCore/html/canvas/WebGLBuffer.cpp +++ b/Source/WebCore/html/canvas/WebGLBuffer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,28 +24,24 @@ */ #include "config.h" +#include "WebGLBuffer.h" #if ENABLE(WEBGL) -#include "WebGLBuffer.h" - #include "WebGLContextGroup.h" -#include "WebGLRenderingContext.h" +#include "WebGLRenderingContextBase.h" namespace WebCore { -PassRefPtr<WebGLBuffer> WebGLBuffer::create(WebGLRenderingContext* ctx) +Ref<WebGLBuffer> WebGLBuffer::create(WebGLRenderingContextBase& ctx) { - return adoptRef(new WebGLBuffer(ctx)); + return adoptRef(*new WebGLBuffer(ctx)); } -WebGLBuffer::WebGLBuffer(WebGLRenderingContext* ctx) +WebGLBuffer::WebGLBuffer(WebGLRenderingContextBase& ctx) : WebGLSharedObject(ctx) - , m_target(0) - , m_byteLength(0) - , m_nextAvailableCacheEntry(0) { - setObject(ctx->graphicsContext3D()->createBuffer()); + setObject(ctx.graphicsContext3D()->createBuffer()); clearCachedMaxIndices(); } @@ -56,7 +52,7 @@ WebGLBuffer::~WebGLBuffer() void WebGLBuffer::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object) { - context3d->deleteBuffer(object); + context3d->deleteBuffer(object); } bool WebGLBuffer::associateBufferDataImpl(const void* data, GC3Dsizeiptr byteLength) @@ -69,7 +65,7 @@ bool WebGLBuffer::associateBufferDataImpl(const void* data, GC3Dsizeiptr byteLen m_byteLength = byteLength; clearCachedMaxIndices(); if (byteLength) { - m_elementArrayBuffer = ArrayBuffer::create(byteLength, 1); + m_elementArrayBuffer = ArrayBuffer::tryCreate(byteLength, 1); if (!m_elementArrayBuffer) { m_byteLength = 0; return false; @@ -81,19 +77,31 @@ bool WebGLBuffer::associateBufferDataImpl(const void* data, GC3Dsizeiptr byteLen memcpy(m_elementArrayBuffer->data(), data, byteLength); } } else - m_elementArrayBuffer = 0; + m_elementArrayBuffer = nullptr; return true; case GraphicsContext3D::ARRAY_BUFFER: m_byteLength = byteLength; return true; default: +#if ENABLE(WEBGL2) + switch (m_target) { + case GraphicsContext3D::COPY_READ_BUFFER: + case GraphicsContext3D::COPY_WRITE_BUFFER: + case GraphicsContext3D::PIXEL_PACK_BUFFER: + case GraphicsContext3D::PIXEL_UNPACK_BUFFER: + case GraphicsContext3D::TRANSFORM_FEEDBACK_BUFFER: + case GraphicsContext3D::UNIFORM_BUFFER: + m_byteLength = byteLength; + return true; + } +#endif return false; } } bool WebGLBuffer::associateBufferData(GC3Dsizeiptr size) { - return associateBufferDataImpl(0, size); + return associateBufferDataImpl(nullptr, size); } bool WebGLBuffer::associateBufferData(ArrayBuffer* array) @@ -135,6 +143,17 @@ bool WebGLBuffer::associateBufferSubDataImpl(GC3Dintptr offset, const void* data case GraphicsContext3D::ARRAY_BUFFER: return true; default: +#if ENABLE(WEBGL2) + switch (m_target) { + case GraphicsContext3D::COPY_READ_BUFFER: + case GraphicsContext3D::COPY_WRITE_BUFFER: + case GraphicsContext3D::PIXEL_PACK_BUFFER: + case GraphicsContext3D::PIXEL_UNPACK_BUFFER: + case GraphicsContext3D::TRANSFORM_FEEDBACK_BUFFER: + case GraphicsContext3D::UNIFORM_BUFFER: + return true; + } +#endif return false; } } @@ -153,39 +172,104 @@ bool WebGLBuffer::associateBufferSubData(GC3Dintptr offset, ArrayBufferView* arr return associateBufferSubDataImpl(offset, array->baseAddress(), array->byteLength()); } +bool WebGLBuffer::associateCopyBufferSubData(const WebGLBuffer& readBuffer, GC3Dintptr readOffset, GC3Dintptr writeOffset, GC3Dsizeiptr size) +{ + if (readOffset < 0 || writeOffset < 0 || size < 0) + return false; + + if (size) { + Checked<GC3Dintptr, RecordOverflow> checkedReadBufferOffset(readOffset); + Checked<GC3Dsizeiptr, RecordOverflow> checkedDataLength(size); + Checked<GC3Dintptr, RecordOverflow> checkedReadBufferMax = checkedReadBufferOffset + checkedDataLength; + if (checkedReadBufferMax.hasOverflowed() || readOffset > readBuffer.byteLength() || checkedReadBufferMax.unsafeGet() > readBuffer.byteLength()) + return false; + + Checked<GC3Dintptr, RecordOverflow> checkedWriteBufferOffset(writeOffset); + Checked<GC3Dintptr, RecordOverflow> checkedWriteBufferMax = checkedWriteBufferOffset + checkedDataLength; + if (checkedWriteBufferMax.hasOverflowed() || writeOffset > m_byteLength || checkedWriteBufferMax.unsafeGet() > m_byteLength) + return false; + } + + switch (m_target) { + case GraphicsContext3D::ELEMENT_ARRAY_BUFFER: + clearCachedMaxIndices(); + if (size) { + if (!m_elementArrayBuffer) + return false; + memcpy(static_cast<unsigned char*>(m_elementArrayBuffer->data()) + writeOffset, static_cast<const unsigned char*>(readBuffer.elementArrayBuffer()->data()) + readOffset, size); + } + return true; + case GraphicsContext3D::ARRAY_BUFFER: + return true; + default: +#if ENABLE(WEBGL2) + switch (m_target) { + case GraphicsContext3D::COPY_READ_BUFFER: + case GraphicsContext3D::COPY_WRITE_BUFFER: + case GraphicsContext3D::PIXEL_PACK_BUFFER: + case GraphicsContext3D::PIXEL_UNPACK_BUFFER: + case GraphicsContext3D::TRANSFORM_FEEDBACK_BUFFER: + case GraphicsContext3D::UNIFORM_BUFFER: + return true; + } +#endif + return false; + } +} + +void WebGLBuffer::disassociateBufferData() +{ + m_byteLength = 0; + clearCachedMaxIndices(); +} + GC3Dsizeiptr WebGLBuffer::byteLength() const { return m_byteLength; } -int WebGLBuffer::getCachedMaxIndex(GC3Denum type) +std::optional<unsigned> WebGLBuffer::getCachedMaxIndex(GC3Denum type) { - for (size_t i = 0; i < WTF_ARRAY_LENGTH(m_maxIndexCache); ++i) - if (m_maxIndexCache[i].type == type) - return m_maxIndexCache[i].maxIndex; - return -1; + for (auto& cache : m_maxIndexCache) { + if (cache.type == type) + return cache.maxIndex; + } + return std::nullopt; } -void WebGLBuffer::setCachedMaxIndex(GC3Denum type, int value) +void WebGLBuffer::setCachedMaxIndex(GC3Denum type, unsigned value) { - size_t numEntries = WTF_ARRAY_LENGTH(m_maxIndexCache); - for (size_t i = 0; i < numEntries; ++i) - if (m_maxIndexCache[i].type == type) { - m_maxIndexCache[i].maxIndex = value; + for (auto& cache : m_maxIndexCache) { + if (cache.type == type) { + cache.maxIndex = value; return; } + } m_maxIndexCache[m_nextAvailableCacheEntry].type = type; m_maxIndexCache[m_nextAvailableCacheEntry].maxIndex = value; - m_nextAvailableCacheEntry = (m_nextAvailableCacheEntry + 1) % numEntries; + m_nextAvailableCacheEntry = (m_nextAvailableCacheEntry + 1) % WTF_ARRAY_LENGTH(m_maxIndexCache); } -void WebGLBuffer::setTarget(GC3Denum target) +void WebGLBuffer::setTarget(GC3Denum target, bool forWebGL2) { // In WebGL, a buffer is bound to one target in its lifetime if (m_target) return; if (target == GraphicsContext3D::ARRAY_BUFFER || target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER) m_target = target; + else if (forWebGL2) { +#if ENABLE(WEBGL2) + switch (target) { + case GraphicsContext3D::COPY_READ_BUFFER: + case GraphicsContext3D::COPY_WRITE_BUFFER: + case GraphicsContext3D::PIXEL_PACK_BUFFER: + case GraphicsContext3D::PIXEL_UNPACK_BUFFER: + case GraphicsContext3D::TRANSFORM_FEEDBACK_BUFFER: + case GraphicsContext3D::UNIFORM_BUFFER: + m_target = target; + } +#endif + } } void WebGLBuffer::clearCachedMaxIndices() diff --git a/Source/WebCore/html/canvas/WebGLBuffer.h b/Source/WebCore/html/canvas/WebGLBuffer.h index 3451bb68c..7b9ea55f0 100644 --- a/Source/WebCore/html/canvas/WebGLBuffer.h +++ b/Source/WebCore/html/canvas/WebGLBuffer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,11 +23,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLBuffer_h -#define WebGLBuffer_h +#pragma once #include "WebGLSharedObject.h" - #include <wtf/Forward.h> namespace JSC { @@ -37,44 +35,43 @@ class ArrayBufferView; namespace WebCore { -class WebGLBuffer : public WebGLSharedObject { +class WebGLBuffer final : public WebGLSharedObject { public: + static Ref<WebGLBuffer> create(WebGLRenderingContextBase&); virtual ~WebGLBuffer(); - static PassRefPtr<WebGLBuffer> create(WebGLRenderingContext*); - bool associateBufferData(GC3Dsizeiptr size); bool associateBufferData(JSC::ArrayBuffer*); bool associateBufferData(JSC::ArrayBufferView*); bool associateBufferSubData(GC3Dintptr offset, JSC::ArrayBuffer*); bool associateBufferSubData(GC3Dintptr offset, JSC::ArrayBufferView*); + bool associateCopyBufferSubData(const WebGLBuffer& readBuffer, GC3Dintptr readOffset, GC3Dintptr writeOffset, GC3Dsizeiptr); + + void disassociateBufferData(); GC3Dsizeiptr byteLength() const; const JSC::ArrayBuffer* elementArrayBuffer() const { return m_elementArrayBuffer.get(); } - // Gets the cached max index for the given type. Returns -1 if - // none has been set. - int getCachedMaxIndex(GC3Denum type); + // Gets the cached max index for the given type if one has been set. + std::optional<unsigned> getCachedMaxIndex(GC3Denum type); // Sets the cached max index for the given type. - void setCachedMaxIndex(GC3Denum type, int value); + void setCachedMaxIndex(GC3Denum type, unsigned value); GC3Denum getTarget() const { return m_target; } - void setTarget(GC3Denum); + void setTarget(GC3Denum, bool forWebGL2); bool hasEverBeenBound() const { return object() && m_target; } protected: - WebGLBuffer(WebGLRenderingContext*); + WebGLBuffer(WebGLRenderingContextBase&); - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override; + void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override; private: - virtual bool isBuffer() const override { return true; } - - GC3Denum m_target; + GC3Denum m_target { 0 }; RefPtr<JSC::ArrayBuffer> m_elementArrayBuffer; - GC3Dsizeiptr m_byteLength; + GC3Dsizeiptr m_byteLength { 0 }; // Optimization for index validation. For each type of index // (i.e., UNSIGNED_SHORT), cache the maximum index in the @@ -85,13 +82,12 @@ private: // that size. struct MaxIndexCacheEntry { GC3Denum type; - int maxIndex; + unsigned maxIndex; }; // OpenGL ES 2.0 only has two valid index types (UNSIGNED_BYTE - // and UNSIGNED_SHORT), but might as well leave open the - // possibility of adding others. + // and UNSIGNED_SHORT) plus one extension (UNSIGNED_INT). MaxIndexCacheEntry m_maxIndexCache[4]; - unsigned int m_nextAvailableCacheEntry; + unsigned m_nextAvailableCacheEntry { 0 }; // Clears all of the cached max indices. void clearCachedMaxIndices(); @@ -103,5 +99,3 @@ private: }; } // namespace WebCore - -#endif // WebGLBuffer_h diff --git a/Source/WebCore/html/canvas/WebGLBuffer.idl b/Source/WebCore/html/canvas/WebGLBuffer.idl index f43cd6353..6e2ab9c57 100644 --- a/Source/WebCore/html/canvas/WebGLBuffer.idl +++ b/Source/WebCore/html/canvas/WebGLBuffer.idl @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR diff --git a/Source/WebCore/html/canvas/WebGLCompressedTextureATC.cpp b/Source/WebCore/html/canvas/WebGLCompressedTextureATC.cpp index 71881ba09..eef19d375 100644 --- a/Source/WebCore/html/canvas/WebGLCompressedTextureATC.cpp +++ b/Source/WebCore/html/canvas/WebGLCompressedTextureATC.cpp @@ -33,12 +33,12 @@ namespace WebCore { -WebGLCompressedTextureATC::WebGLCompressedTextureATC(WebGLRenderingContext* context) +WebGLCompressedTextureATC::WebGLCompressedTextureATC(WebGLRenderingContextBase& context) : WebGLExtension(context) { - context->addCompressedTextureFormat(Extensions3D::COMPRESSED_ATC_RGB_AMD); - context->addCompressedTextureFormat(Extensions3D::COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD); - context->addCompressedTextureFormat(Extensions3D::COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD); + context.addCompressedTextureFormat(Extensions3D::COMPRESSED_ATC_RGB_AMD); + context.addCompressedTextureFormat(Extensions3D::COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD); + context.addCompressedTextureFormat(Extensions3D::COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD); } WebGLCompressedTextureATC::~WebGLCompressedTextureATC() @@ -50,15 +50,9 @@ WebGLExtension::ExtensionName WebGLCompressedTextureATC::getName() const return WebGLCompressedTextureATCName; } -OwnPtr<WebGLCompressedTextureATC> WebGLCompressedTextureATC::create(WebGLRenderingContext* context) +bool WebGLCompressedTextureATC::supported(WebGLRenderingContextBase& context) { - return adoptPtr(new WebGLCompressedTextureATC(context)); -} - -bool WebGLCompressedTextureATC::supported(WebGLRenderingContext* context) -{ - Extensions3D* extensions = context->graphicsContext3D()->getExtensions(); - return extensions->supports("GL_AMD_compressed_ATC_texture"); + return context.graphicsContext3D()->getExtensions().supports("GL_AMD_compressed_ATC_texture"); } } // namespace WebCore diff --git a/Source/WebCore/html/canvas/WebGLCompressedTextureATC.h b/Source/WebCore/html/canvas/WebGLCompressedTextureATC.h index 6a8d89d5d..e5b0560d3 100644 --- a/Source/WebCore/html/canvas/WebGLCompressedTextureATC.h +++ b/Source/WebCore/html/canvas/WebGLCompressedTextureATC.h @@ -23,29 +23,22 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLCompressedTextureATC_h -#define WebGLCompressedTextureATC_h +#pragma once #include "WebGLExtension.h" -#include <wtf/PassOwnPtr.h> namespace WebCore { class WebGLTexture; -class WebGLCompressedTextureATC : public WebGLExtension { +class WebGLCompressedTextureATC final : public WebGLExtension { public: - static OwnPtr<WebGLCompressedTextureATC> create(WebGLRenderingContext*); - - static bool supported(WebGLRenderingContext*); - + explicit WebGLCompressedTextureATC(WebGLRenderingContextBase&); virtual ~WebGLCompressedTextureATC(); - virtual ExtensionName getName() const override; -private: - WebGLCompressedTextureATC(WebGLRenderingContext*); + static bool supported(WebGLRenderingContextBase&); + + ExtensionName getName() const override; }; } // namespace WebCore - -#endif // WebGLCompressedTextureATC_h diff --git a/Source/WebCore/html/canvas/WebGLCompressedTextureATC.idl b/Source/WebCore/html/canvas/WebGLCompressedTextureATC.idl index ff415a756..ffd8d22e0 100644 --- a/Source/WebCore/html/canvas/WebGLCompressedTextureATC.idl +++ b/Source/WebCore/html/canvas/WebGLCompressedTextureATC.idl @@ -24,13 +24,12 @@ */ [ - NoInterfaceObject, Conditional=WEBGL, + DoNotCheckConstants, GenerateIsReachable=ImplWebGLRenderingContext, - DoNotCheckConstants + NoInterfaceObject, ] interface WebGLCompressedTextureATC { - /* Compressed Texture Formats */ - const unsigned int COMPRESSED_RGB_ATC_WEBGL = 0x8C92; - const unsigned int COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL = 0x8C93; - const unsigned int COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL = 0x87EE; + const unsigned long COMPRESSED_RGB_ATC_WEBGL = 0x8C92; + const unsigned long COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL = 0x8C93; + const unsigned long COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL = 0x87EE; }; diff --git a/Source/WebCore/html/canvas/WebGLCompressedTexturePVRTC.cpp b/Source/WebCore/html/canvas/WebGLCompressedTexturePVRTC.cpp index d05d4178b..14b66f5fc 100644 --- a/Source/WebCore/html/canvas/WebGLCompressedTexturePVRTC.cpp +++ b/Source/WebCore/html/canvas/WebGLCompressedTexturePVRTC.cpp @@ -30,17 +30,17 @@ #include "WebGLCompressedTexturePVRTC.h" #include "Extensions3D.h" -#include "WebGLRenderingContext.h" +#include "WebGLRenderingContextBase.h" namespace WebCore { -WebGLCompressedTexturePVRTC::WebGLCompressedTexturePVRTC(WebGLRenderingContext* context) +WebGLCompressedTexturePVRTC::WebGLCompressedTexturePVRTC(WebGLRenderingContextBase& context) : WebGLExtension(context) { - context->addCompressedTextureFormat(Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG); - context->addCompressedTextureFormat(Extensions3D::COMPRESSED_RGB_PVRTC_2BPPV1_IMG); - context->addCompressedTextureFormat(Extensions3D::COMPRESSED_RGBA_PVRTC_4BPPV1_IMG); - context->addCompressedTextureFormat(Extensions3D::COMPRESSED_RGBA_PVRTC_2BPPV1_IMG); + context.addCompressedTextureFormat(Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG); + context.addCompressedTextureFormat(Extensions3D::COMPRESSED_RGB_PVRTC_2BPPV1_IMG); + context.addCompressedTextureFormat(Extensions3D::COMPRESSED_RGBA_PVRTC_4BPPV1_IMG); + context.addCompressedTextureFormat(Extensions3D::COMPRESSED_RGBA_PVRTC_2BPPV1_IMG); } WebGLCompressedTexturePVRTC::~WebGLCompressedTexturePVRTC() @@ -52,15 +52,9 @@ WebGLExtension::ExtensionName WebGLCompressedTexturePVRTC::getName() const return WebGLCompressedTexturePVRTCName; } -OwnPtr<WebGLCompressedTexturePVRTC> WebGLCompressedTexturePVRTC::create(WebGLRenderingContext* context) +bool WebGLCompressedTexturePVRTC::supported(WebGLRenderingContextBase& context) { - return adoptPtr(new WebGLCompressedTexturePVRTC(context)); -} - -bool WebGLCompressedTexturePVRTC::supported(WebGLRenderingContext* context) -{ - Extensions3D* extensions = context->graphicsContext3D()->getExtensions(); - return extensions->supports("GL_IMG_texture_compression_pvrtc"); + return context.graphicsContext3D()->getExtensions().supports("GL_IMG_texture_compression_pvrtc"); } } // namespace WebCore diff --git a/Source/WebCore/html/canvas/WebGLCompressedTexturePVRTC.h b/Source/WebCore/html/canvas/WebGLCompressedTexturePVRTC.h index f20e2d25d..515e6e11f 100644 --- a/Source/WebCore/html/canvas/WebGLCompressedTexturePVRTC.h +++ b/Source/WebCore/html/canvas/WebGLCompressedTexturePVRTC.h @@ -23,27 +23,19 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLCompressedTexturePVRTC_h -#define WebGLCompressedTexturePVRTC_h +#pragma once #include "WebGLExtension.h" -#include <wtf/PassOwnPtr.h> namespace WebCore { -class WebGLCompressedTexturePVRTC : public WebGLExtension { +class WebGLCompressedTexturePVRTC final : public WebGLExtension { public: - static OwnPtr<WebGLCompressedTexturePVRTC> create(WebGLRenderingContext*); - - static bool supported(WebGLRenderingContext*); - + explicit WebGLCompressedTexturePVRTC(WebGLRenderingContextBase&); virtual ~WebGLCompressedTexturePVRTC(); - virtual ExtensionName getName() const override; -private: - WebGLCompressedTexturePVRTC(WebGLRenderingContext*); + static bool supported(WebGLRenderingContextBase&); + ExtensionName getName() const override; }; } // namespace WebCore - -#endif // WebGLCompressedTexturePVRTC_h diff --git a/Source/WebCore/html/canvas/WebGLCompressedTexturePVRTC.idl b/Source/WebCore/html/canvas/WebGLCompressedTexturePVRTC.idl index 5b61a20a2..2cfbf3131 100644 --- a/Source/WebCore/html/canvas/WebGLCompressedTexturePVRTC.idl +++ b/Source/WebCore/html/canvas/WebGLCompressedTexturePVRTC.idl @@ -24,14 +24,13 @@ */ [ - NoInterfaceObject, Conditional=WEBGL, + DoNotCheckConstants, GenerateIsReachable=ImplWebGLRenderingContext, - DoNotCheckConstants + NoInterfaceObject, ] interface WebGLCompressedTexturePVRTC { - /* Compressed Texture Formats */ - const unsigned int COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00; - const unsigned int COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01; - const unsigned int COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02; - const unsigned int COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03; + const unsigned long COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00; + const unsigned long COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01; + const unsigned long COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02; + const unsigned long COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03; }; diff --git a/Source/WebCore/html/canvas/WebGLCompressedTextureS3TC.cpp b/Source/WebCore/html/canvas/WebGLCompressedTextureS3TC.cpp index bcf1a3267..40b7f53a8 100644 --- a/Source/WebCore/html/canvas/WebGLCompressedTextureS3TC.cpp +++ b/Source/WebCore/html/canvas/WebGLCompressedTextureS3TC.cpp @@ -30,17 +30,17 @@ #include "WebGLCompressedTextureS3TC.h" #include "Extensions3D.h" -#include "WebGLRenderingContext.h" +#include "WebGLRenderingContextBase.h" namespace WebCore { -WebGLCompressedTextureS3TC::WebGLCompressedTextureS3TC(WebGLRenderingContext* context) +WebGLCompressedTextureS3TC::WebGLCompressedTextureS3TC(WebGLRenderingContextBase& context) : WebGLExtension(context) { - context->addCompressedTextureFormat(Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT); - context->addCompressedTextureFormat(Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT); - context->addCompressedTextureFormat(Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT); - context->addCompressedTextureFormat(Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT); + context.addCompressedTextureFormat(Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT); + context.addCompressedTextureFormat(Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT); + context.addCompressedTextureFormat(Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT); + context.addCompressedTextureFormat(Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT); } WebGLCompressedTextureS3TC::~WebGLCompressedTextureS3TC() @@ -52,18 +52,11 @@ WebGLExtension::ExtensionName WebGLCompressedTextureS3TC::getName() const return WebGLCompressedTextureS3TCName; } -OwnPtr<WebGLCompressedTextureS3TC> WebGLCompressedTextureS3TC::create(WebGLRenderingContext* context) +bool WebGLCompressedTextureS3TC::supported(WebGLRenderingContextBase& context) { - return adoptPtr(new WebGLCompressedTextureS3TC(context)); -} - -bool WebGLCompressedTextureS3TC::supported(WebGLRenderingContext* context) -{ - Extensions3D* extensions = context->graphicsContext3D()->getExtensions(); - return extensions->supports("GL_EXT_texture_compression_s3tc") - || (extensions->supports("GL_EXT_texture_compression_dxt1") - && extensions->supports("GL_CHROMIUM_texture_compression_dxt3") - && extensions->supports("GL_CHROMIUM_texture_compression_dxt5")); + auto& extensions = context.graphicsContext3D()->getExtensions(); + return extensions.supports("GL_EXT_texture_compression_s3tc") + || extensions.supports("GL_EXT_texture_compression_dxt1"); } } // namespace WebCore diff --git a/Source/WebCore/html/canvas/WebGLCompressedTextureS3TC.h b/Source/WebCore/html/canvas/WebGLCompressedTextureS3TC.h index c6c9edb45..251e592f7 100644 --- a/Source/WebCore/html/canvas/WebGLCompressedTextureS3TC.h +++ b/Source/WebCore/html/canvas/WebGLCompressedTextureS3TC.h @@ -23,29 +23,22 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLCompressedTextureS3TC_h -#define WebGLCompressedTextureS3TC_h +#pragma once #include "WebGLExtension.h" -#include <wtf/PassOwnPtr.h> namespace WebCore { class WebGLTexture; -class WebGLCompressedTextureS3TC : public WebGLExtension { +class WebGLCompressedTextureS3TC final : public WebGLExtension { public: - static OwnPtr<WebGLCompressedTextureS3TC> create(WebGLRenderingContext*); - - static bool supported(WebGLRenderingContext*); - + explicit WebGLCompressedTextureS3TC(WebGLRenderingContextBase&); virtual ~WebGLCompressedTextureS3TC(); - virtual ExtensionName getName() const override; -private: - WebGLCompressedTextureS3TC(WebGLRenderingContext*); + static bool supported(WebGLRenderingContextBase&); + + ExtensionName getName() const override; }; } // namespace WebCore - -#endif // WebGLCompressedTextureS3TC_h diff --git a/Source/WebCore/html/canvas/WebGLCompressedTextureS3TC.idl b/Source/WebCore/html/canvas/WebGLCompressedTextureS3TC.idl index e77303bde..f9718b839 100644 --- a/Source/WebCore/html/canvas/WebGLCompressedTextureS3TC.idl +++ b/Source/WebCore/html/canvas/WebGLCompressedTextureS3TC.idl @@ -24,14 +24,13 @@ */ [ - NoInterfaceObject, Conditional=WEBGL, + DoNotCheckConstants, GenerateIsReachable=ImplWebGLRenderingContext, - DoNotCheckConstants + NoInterfaceObject, ] interface WebGLCompressedTextureS3TC { - /* Compressed Texture Formats */ - const unsigned int COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0; - const unsigned int COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1; - const unsigned int COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2; - const unsigned int COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3; + const unsigned long COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0; + const unsigned long COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1; + const unsigned long COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2; + const unsigned long COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3; }; diff --git a/Source/WebCore/html/canvas/WebGLContextAttributes.cpp b/Source/WebCore/html/canvas/WebGLContextAttributes.cpp deleted file mode 100644 index e36e04ef0..000000000 --- a/Source/WebCore/html/canvas/WebGLContextAttributes.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2010, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(WEBGL) - -#include "WebGLContextAttributes.h" - -namespace WebCore { - -PassRefPtr<WebGLContextAttributes> WebGLContextAttributes::create() -{ - return adoptRef(new WebGLContextAttributes()); -} - -PassRefPtr<WebGLContextAttributes> WebGLContextAttributes::create(GraphicsContext3D::Attributes attributes) -{ - return adoptRef(new WebGLContextAttributes(attributes)); -} - -WebGLContextAttributes::WebGLContextAttributes() - : CanvasContextAttributes() -{ -} - -WebGLContextAttributes::WebGLContextAttributes(GraphicsContext3D::Attributes attributes) - : CanvasContextAttributes() - , m_attrs(attributes) -{ -} - -WebGLContextAttributes::~WebGLContextAttributes() -{ -} - -bool WebGLContextAttributes::alpha() const -{ - return m_attrs.alpha; -} - -void WebGLContextAttributes::setAlpha(bool alpha) -{ - m_attrs.alpha = alpha; -} - -bool WebGLContextAttributes::depth() const -{ - return m_attrs.depth; -} - -void WebGLContextAttributes::setDepth(bool depth) -{ - m_attrs.depth = depth; -} - -bool WebGLContextAttributes::stencil() const -{ - return m_attrs.stencil; -} - -void WebGLContextAttributes::setStencil(bool stencil) -{ - m_attrs.stencil = stencil; -} - -bool WebGLContextAttributes::antialias() const -{ - return m_attrs.antialias; -} - -void WebGLContextAttributes::setAntialias(bool antialias) -{ - m_attrs.antialias = antialias; -} - -bool WebGLContextAttributes::premultipliedAlpha() const -{ - return m_attrs.premultipliedAlpha; -} - -void WebGLContextAttributes::setPremultipliedAlpha(bool premultipliedAlpha) -{ - m_attrs.premultipliedAlpha = premultipliedAlpha; -} - -bool WebGLContextAttributes::preserveDrawingBuffer() const -{ - return m_attrs.preserveDrawingBuffer; -} - -void WebGLContextAttributes::setPreserveDrawingBuffer(bool preserveDrawingBuffer) -{ - m_attrs.preserveDrawingBuffer = preserveDrawingBuffer; -} - -GraphicsContext3D::Attributes WebGLContextAttributes::attributes() const -{ - return m_attrs; -} - -} // namespace WebCore - -#endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/WebGLContextAttributes.h b/Source/WebCore/html/canvas/WebGLContextAttributes.h index 5391a2b7d..a36dc9b07 100644 --- a/Source/WebCore/html/canvas/WebGLContextAttributes.h +++ b/Source/WebCore/html/canvas/WebGLContextAttributes.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2010, Google Inc. All rights reserved. + * Copyright (c) 2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,64 +25,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLContextAttributes_h -#define WebGLContextAttributes_h +#pragma once -#include "CanvasContextAttributes.h" -#include "GraphicsContext3D.h" -#include <wtf/PassRefPtr.h> +#include "GraphicsContext3DAttributes.h" namespace WebCore { -class WebGLContextAttributes : public CanvasContextAttributes { - public: - virtual ~WebGLContextAttributes(); - - // Create a new attributes object - static PassRefPtr<WebGLContextAttributes> create(); - - // Create a new attributes object initialized with preexisting attributes - static PassRefPtr<WebGLContextAttributes> create(GraphicsContext3D::Attributes attributes); - - // Whether or not the drawing buffer has an alpha channel; default=true - bool alpha() const; - void setAlpha(bool alpha); - - // Whether or not the drawing buffer has a depth buffer; default=true - bool depth() const; - void setDepth(bool depth); - - // Whether or not the drawing buffer has a stencil buffer; default=true - bool stencil() const; - void setStencil(bool stencil); - - // Whether or not the drawing buffer is antialiased; default=true - bool antialias() const; - void setAntialias(bool antialias); - - // Whether or not to treat the values in the drawing buffer as - // though their alpha channel has already been multiplied into the - // color channels; default=true - bool premultipliedAlpha() const; - void setPremultipliedAlpha(bool premultipliedAlpha); - - // Whether or not to preserve the drawing buffer after presentation to the - // screen; default=false - bool preserveDrawingBuffer() const; - void setPreserveDrawingBuffer(bool); - - // Fetches a copy of the attributes stored in this object in a - // form that can be used to initialize a GraphicsContext3D. - GraphicsContext3D::Attributes attributes() const; - - protected: - WebGLContextAttributes(); - WebGLContextAttributes(GraphicsContext3D::Attributes attributes); - - private: - GraphicsContext3D::Attributes m_attrs; -}; +using WebGLPowerPreference = GraphicsContext3DPowerPreference; +using WebGLContextAttributes = GraphicsContext3DAttributes; } // namespace WebCore - -#endif // WebGLContextAttributes_h diff --git a/Source/WebCore/html/canvas/WebGLContextAttributes.idl b/Source/WebCore/html/canvas/WebGLContextAttributes.idl index 41bf10234..3be5ac599 100644 --- a/Source/WebCore/html/canvas/WebGLContextAttributes.idl +++ b/Source/WebCore/html/canvas/WebGLContextAttributes.idl @@ -1,5 +1,6 @@ /* * Copyright (c) 2010, Google Inc. All rights reserved. + * Copyright (c) 2017, Apple, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -24,14 +25,24 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +typedef boolean GLboolean; + +enum WebGLPowerPreference { + "default", + "low-power", + "high-performance" +}; + [ - NoInterfaceObject, Conditional=WEBGL, -] interface WebGLContextAttributes { - attribute boolean alpha; - attribute boolean depth; - attribute boolean stencil; - attribute boolean antialias; - attribute boolean premultipliedAlpha; - attribute boolean preserveDrawingBuffer; + JSGenerateToJSObject +] dictionary WebGLContextAttributes { + GLboolean alpha = true; + GLboolean depth = true; + GLboolean stencil = false; + GLboolean antialias = true; + GLboolean premultipliedAlpha = true; + GLboolean preserveDrawingBuffer = false; + WebGLPowerPreference powerPreference = "default"; + GLboolean failIfMajorPerformanceCaveat = false; }; diff --git a/Source/WebCore/html/canvas/WebGLContextEvent.cpp b/Source/WebCore/html/canvas/WebGLContextEvent.cpp index 8e97fe349..13a12ee15 100644 --- a/Source/WebCore/html/canvas/WebGLContextEvent.cpp +++ b/Source/WebCore/html/canvas/WebGLContextEvent.cpp @@ -26,28 +26,18 @@ #include "config.h" #include "WebGLContextEvent.h" -#include "EventNames.h" - #if ENABLE(WEBGL) namespace WebCore { -WebGLContextEventInit::WebGLContextEventInit() -{ -} - -WebGLContextEvent::WebGLContextEvent() -{ -} - WebGLContextEvent::WebGLContextEvent(const AtomicString& type, bool canBubble, bool cancelable, const String& statusMessage) : Event(type, canBubble, cancelable) , m_statusMessage(statusMessage) { } -WebGLContextEvent::WebGLContextEvent(const AtomicString& type, const WebGLContextEventInit& initializer) - : Event(type, initializer) +WebGLContextEvent::WebGLContextEvent(const AtomicString& type, const Init& initializer, IsTrusted isTrusted) + : Event(type, initializer, isTrusted) , m_statusMessage(initializer.statusMessage) { } diff --git a/Source/WebCore/html/canvas/WebGLContextEvent.h b/Source/WebCore/html/canvas/WebGLContextEvent.h index fa1ebfbc8..4ba1ba4d7 100644 --- a/Source/WebCore/html/canvas/WebGLContextEvent.h +++ b/Source/WebCore/html/canvas/WebGLContextEvent.h @@ -23,47 +23,38 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLContextEvent_h -#define WebGLContextEvent_h +#pragma once #include "Event.h" namespace WebCore { -struct WebGLContextEventInit : public EventInit { - WebGLContextEventInit(); - - String statusMessage; -}; - -class WebGLContextEvent : public Event { +class WebGLContextEvent final : public Event { public: - static PassRefPtr<WebGLContextEvent> create() - { - return adoptRef(new WebGLContextEvent); - } - static PassRefPtr<WebGLContextEvent> create(const AtomicString& type, bool canBubble, bool cancelable, const String& statusMessage) + static Ref<WebGLContextEvent> create(const AtomicString& type, bool canBubble, bool cancelable, const String& statusMessage) { - return adoptRef(new WebGLContextEvent(type, canBubble, cancelable, statusMessage)); + return adoptRef(*new WebGLContextEvent(type, canBubble, cancelable, statusMessage)); } - static PassRefPtr<WebGLContextEvent> create(const AtomicString& type, const WebGLContextEventInit& initializer) + + struct Init : EventInit { + String statusMessage; + }; + + static Ref<WebGLContextEvent> create(const AtomicString& type, const Init& initializer, IsTrusted isTrusted = IsTrusted::No) { - return adoptRef(new WebGLContextEvent(type, initializer)); + return adoptRef(*new WebGLContextEvent(type, initializer, isTrusted)); } virtual ~WebGLContextEvent(); const String& statusMessage() const { return m_statusMessage; } - virtual EventInterface eventInterface() const override; + EventInterface eventInterface() const override; private: - WebGLContextEvent(); WebGLContextEvent(const AtomicString& type, bool canBubble, bool cancelable, const String& statusMessage); - WebGLContextEvent(const AtomicString&, const WebGLContextEventInit&); + WebGLContextEvent(const AtomicString&, const Init&, IsTrusted); String m_statusMessage; }; } // namespace WebCore - -#endif // WebGLContextEvent_h diff --git a/Source/WebCore/html/canvas/WebGLContextEvent.idl b/Source/WebCore/html/canvas/WebGLContextEvent.idl index c3eba1029..3cd03b1c1 100644 --- a/Source/WebCore/html/canvas/WebGLContextEvent.idl +++ b/Source/WebCore/html/canvas/WebGLContextEvent.idl @@ -25,8 +25,11 @@ [ Conditional=WEBGL, - ConstructorTemplate=Event + Constructor(DOMString type, optional WebGLContextEventInit eventInit), ] interface WebGLContextEvent : Event { - [InitializedByEventConstructor] readonly attribute DOMString statusMessage; + readonly attribute DOMString statusMessage; }; +dictionary WebGLContextEventInit : EventInit { + DOMString statusMessage = ""; +}; diff --git a/Source/WebCore/html/canvas/WebGLContextGroup.cpp b/Source/WebCore/html/canvas/WebGLContextGroup.cpp index 6f182e22d..9ddef158c 100644 --- a/Source/WebCore/html/canvas/WebGLContextGroup.cpp +++ b/Source/WebCore/html/canvas/WebGLContextGroup.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,25 +24,19 @@ */ #include "config.h" +#include "WebGLContextGroup.h" #if ENABLE(WEBGL) -#include "WebGLContextGroup.h" - #include "GraphicsContext3D.h" -#include "WebGLRenderingContext.h" +#include "WebGLRenderingContextBase.h" #include "WebGLSharedObject.h" namespace WebCore { -PassRefPtr<WebGLContextGroup> WebGLContextGroup::create() -{ - RefPtr<WebGLContextGroup> contextGroup = adoptRef(new WebGLContextGroup()); - return contextGroup.release(); -} - -WebGLContextGroup::WebGLContextGroup() +Ref<WebGLContextGroup> WebGLContextGroup::create() { + return adoptRef(*new WebGLContextGroup); } WebGLContextGroup::~WebGLContextGroup() @@ -50,49 +44,46 @@ WebGLContextGroup::~WebGLContextGroup() detachAndRemoveAllObjects(); } -GraphicsContext3D* WebGLContextGroup::getAGraphicsContext3D() +GraphicsContext3D& WebGLContextGroup::getAGraphicsContext3D() { ASSERT(!m_contexts.isEmpty()); - HashSet<WebGLRenderingContext*>::iterator it = m_contexts.begin(); - return (*it)->graphicsContext3D(); + return *(*m_contexts.begin())->graphicsContext3D(); } -void WebGLContextGroup::addContext(WebGLRenderingContext* context) +void WebGLContextGroup::addContext(WebGLRenderingContextBase& context) { - m_contexts.add(context); + m_contexts.add(&context); } -void WebGLContextGroup::removeContext(WebGLRenderingContext* context) +void WebGLContextGroup::removeContext(WebGLRenderingContextBase& context) { // We must call detachAndRemoveAllObjects before removing the last context. - if (m_contexts.size() == 1 && m_contexts.contains(context)) + if (m_contexts.size() == 1 && m_contexts.contains(&context)) detachAndRemoveAllObjects(); - m_contexts.remove(context); + m_contexts.remove(&context); } -void WebGLContextGroup::removeObject(WebGLSharedObject* object) +void WebGLContextGroup::removeObject(WebGLSharedObject& object) { - m_groupObjects.remove(object); + m_groupObjects.remove(&object); } -void WebGLContextGroup::addObject(WebGLSharedObject* object) +void WebGLContextGroup::addObject(WebGLSharedObject& object) { - m_groupObjects.add(object); + m_groupObjects.add(&object); } void WebGLContextGroup::detachAndRemoveAllObjects() { - while (!m_groupObjects.isEmpty()) { - HashSet<WebGLSharedObject*>::iterator it = m_groupObjects.begin(); - (*it)->detachContextGroup(); - } + while (!m_groupObjects.isEmpty()) + (*m_groupObjects.begin())->detachContextGroup(); } -void WebGLContextGroup::loseContextGroup(WebGLRenderingContext::LostContextMode mode) +void WebGLContextGroup::loseContextGroup(WebGLRenderingContextBase::LostContextMode mode) { - for (HashSet<WebGLRenderingContext*>::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it) - (*it)->loseContextImpl(mode); + for (auto& context : m_contexts) + context->loseContextImpl(mode); detachAndRemoveAllObjects(); } diff --git a/Source/WebCore/html/canvas/WebGLContextGroup.h b/Source/WebCore/html/canvas/WebGLContextGroup.h index aa7036ae6..11b737032 100644 --- a/Source/WebCore/html/canvas/WebGLContextGroup.h +++ b/Source/WebCore/html/canvas/WebGLContextGroup.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,49 +23,34 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLContextGroup_h -#define WebGLContextGroup_h +#pragma once -#include <WebGLRenderingContext.h> -#include <wtf/HashSet.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> +#include "WebGLRenderingContextBase.h" namespace WebCore { -class GraphicsContext3D; -class WebGLExtension; -class WebGLSharedObject; -class WebGLRenderingContext; - -typedef int ExceptionCode; - class WebGLContextGroup : public RefCounted<WebGLContextGroup> { public: - static PassRefPtr<WebGLContextGroup> create(); - virtual ~WebGLContextGroup(); + static Ref<WebGLContextGroup> create(); + ~WebGLContextGroup(); - void addContext(WebGLRenderingContext*); - void removeContext(WebGLRenderingContext*); + void addContext(WebGLRenderingContextBase&); + void removeContext(WebGLRenderingContextBase&); - void addObject(WebGLSharedObject*); - void removeObject(WebGLSharedObject*); + void addObject(WebGLSharedObject&); + void removeObject(WebGLSharedObject&); - GraphicsContext3D* getAGraphicsContext3D(); + GraphicsContext3D& getAGraphicsContext3D(); - void loseContextGroup(WebGLRenderingContext::LostContextMode); + void loseContextGroup(WebGLRenderingContextBase::LostContextMode); - private: - friend class WebGLObject; - - WebGLContextGroup(); +private: + WebGLContextGroup() = default; void detachAndRemoveAllObjects(); - HashSet<WebGLRenderingContext*> m_contexts; + HashSet<WebGLRenderingContextBase*> m_contexts; HashSet<WebGLSharedObject*> m_groupObjects; }; } // namespace WebCore - -#endif // WebGLContextGroup_h diff --git a/Source/WebCore/html/canvas/WebGLContextObject.cpp b/Source/WebCore/html/canvas/WebGLContextObject.cpp index 9b3ab0b9c..6a1c7ab29 100644 --- a/Source/WebCore/html/canvas/WebGLContextObject.cpp +++ b/Source/WebCore/html/canvas/WebGLContextObject.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,25 +24,23 @@ */ #include "config.h" +#include "WebGLContextObject.h" #if ENABLE(WEBGL) -#include "WebGLContextObject.h" - -#include "WebGLRenderingContext.h" +#include "WebGLRenderingContextBase.h" namespace WebCore { -WebGLContextObject::WebGLContextObject(WebGLRenderingContext* context) - : WebGLObject(context) - , m_context(context) +WebGLContextObject::WebGLContextObject(WebGLRenderingContextBase& context) + : m_context(&context) { } WebGLContextObject::~WebGLContextObject() { if (m_context) - m_context->removeContextObject(this); + m_context->removeContextObject(*this); } void WebGLContextObject::detachContext() @@ -50,14 +48,14 @@ void WebGLContextObject::detachContext() detach(); if (m_context) { deleteObject(m_context->graphicsContext3D()); - m_context->removeContextObject(this); - m_context = 0; + m_context->removeContextObject(*this); + m_context = nullptr; } } GraphicsContext3D* WebGLContextObject::getAGraphicsContext3D() const { - return m_context ? m_context->graphicsContext3D() : 0; + return m_context ? m_context->graphicsContext3D() : nullptr; } } diff --git a/Source/WebCore/html/canvas/WebGLContextObject.h b/Source/WebCore/html/canvas/WebGLContextObject.h index e674b1c64..ebe0fc6c5 100644 --- a/Source/WebCore/html/canvas/WebGLContextObject.h +++ b/Source/WebCore/html/canvas/WebGLContextObject.h @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,15 +23,14 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLContextObject_h -#define WebGLContextObject_h +#pragma once #include "WebGLObject.h" namespace WebCore { class GraphicsContext3D; -class WebGLRenderingContext; +class WebGLRenderingContextBase; // WebGLContextObject the base class for objects that are owned by a specific // WebGLRenderingContext. @@ -39,29 +38,27 @@ class WebGLContextObject : public WebGLObject { public: virtual ~WebGLContextObject(); - WebGLRenderingContext* context() const { return m_context; } + WebGLRenderingContextBase* context() const { return m_context; } - virtual bool validate(const WebGLContextGroup*, const WebGLRenderingContext* context) const override + bool validate(const WebGLContextGroup*, const WebGLRenderingContextBase& context) const override { - return context == m_context; + return &context == m_context; } void detachContext(); protected: - WebGLContextObject(WebGLRenderingContext*); + WebGLContextObject(WebGLRenderingContextBase&); - virtual bool hasGroupOrContext() const override + bool hasGroupOrContext() const override { return m_context; } - virtual GraphicsContext3D* getAGraphicsContext3D() const override; + GraphicsContext3D* getAGraphicsContext3D() const override; private: - WebGLRenderingContext* m_context; + WebGLRenderingContextBase* m_context; }; } // namespace WebCore - -#endif // WebGLContextObject_h diff --git a/Source/WebCore/html/canvas/WebGLDebugRendererInfo.cpp b/Source/WebCore/html/canvas/WebGLDebugRendererInfo.cpp index 2fe5f171d..9df7fbd51 100644 --- a/Source/WebCore/html/canvas/WebGLDebugRendererInfo.cpp +++ b/Source/WebCore/html/canvas/WebGLDebugRendererInfo.cpp @@ -29,11 +29,11 @@ #include "WebGLDebugRendererInfo.h" -#include "WebGLRenderingContext.h" +#include "WebGLRenderingContextBase.h" namespace WebCore { -WebGLDebugRendererInfo::WebGLDebugRendererInfo(WebGLRenderingContext* context) +WebGLDebugRendererInfo::WebGLDebugRendererInfo(WebGLRenderingContextBase& context) : WebGLExtension(context) { } @@ -47,11 +47,6 @@ WebGLExtension::ExtensionName WebGLDebugRendererInfo::getName() const return WebGLDebugRendererInfoName; } -OwnPtr<WebGLDebugRendererInfo> WebGLDebugRendererInfo::create(WebGLRenderingContext* context) -{ - return adoptPtr(new WebGLDebugRendererInfo(context)); -} - } // namespace WebCore #endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/WebGLDebugRendererInfo.h b/Source/WebCore/html/canvas/WebGLDebugRendererInfo.h index 4422f84de..3e5822d20 100644 --- a/Source/WebCore/html/canvas/WebGLDebugRendererInfo.h +++ b/Source/WebCore/html/canvas/WebGLDebugRendererInfo.h @@ -23,30 +23,23 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLDebugRendererInfo_h -#define WebGLDebugRendererInfo_h +#pragma once #include "WebGLExtension.h" -#include <wtf/PassOwnPtr.h> namespace WebCore { -class WebGLDebugRendererInfo : public WebGLExtension { +class WebGLDebugRendererInfo final : public WebGLExtension { public: enum EnumType { UNMASKED_VENDOR_WEBGL = 0x9245, UNMASKED_RENDERER_WEBGL = 0x9246 }; - static OwnPtr<WebGLDebugRendererInfo> create(WebGLRenderingContext*); - + explicit WebGLDebugRendererInfo(WebGLRenderingContextBase&); virtual ~WebGLDebugRendererInfo(); - virtual ExtensionName getName() const override; -private: - WebGLDebugRendererInfo(WebGLRenderingContext*); + ExtensionName getName() const override; }; } // namespace WebCore - -#endif // WebGLDebugRendererInfo_h diff --git a/Source/WebCore/html/canvas/WebGLDebugRendererInfo.idl b/Source/WebCore/html/canvas/WebGLDebugRendererInfo.idl index a4f953841..c9292de61 100644 --- a/Source/WebCore/html/canvas/WebGLDebugRendererInfo.idl +++ b/Source/WebCore/html/canvas/WebGLDebugRendererInfo.idl @@ -24,11 +24,11 @@ */ [ - NoInterfaceObject, Conditional=WEBGL, + DoNotCheckConstants, GenerateIsReachable=ImplWebGLRenderingContext, - DoNotCheckConstants + NoInterfaceObject, ] interface WebGLDebugRendererInfo { - const unsigned int UNMASKED_VENDOR_WEBGL = 0x9245; - const unsigned int UNMASKED_RENDERER_WEBGL = 0x9246; + const unsigned long UNMASKED_VENDOR_WEBGL = 0x9245; + const unsigned long UNMASKED_RENDERER_WEBGL = 0x9246; }; diff --git a/Source/WebCore/html/canvas/WebGLDebugShaders.cpp b/Source/WebCore/html/canvas/WebGLDebugShaders.cpp index 0c028265c..ed4281309 100644 --- a/Source/WebCore/html/canvas/WebGLDebugShaders.cpp +++ b/Source/WebCore/html/canvas/WebGLDebugShaders.cpp @@ -30,12 +30,12 @@ #include "WebGLDebugShaders.h" #include "Extensions3D.h" -#include "WebGLRenderingContext.h" +#include "WebGLRenderingContextBase.h" #include "WebGLShader.h" namespace WebCore { -WebGLDebugShaders::WebGLDebugShaders(WebGLRenderingContext* context) +WebGLDebugShaders::WebGLDebugShaders(WebGLRenderingContextBase& context) : WebGLExtension(context) { } @@ -49,19 +49,13 @@ WebGLExtension::ExtensionName WebGLDebugShaders::getName() const return WebGLDebugShadersName; } -OwnPtr<WebGLDebugShaders> WebGLDebugShaders::create(WebGLRenderingContext* context) +String WebGLDebugShaders::getTranslatedShaderSource(WebGLShader* shader) { - return adoptPtr(new WebGLDebugShaders(context)); -} - -String WebGLDebugShaders::getTranslatedShaderSource(WebGLShader* shader, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (m_context->isContextLost()) + if (m_context.isContextLost()) return String(); - if (!m_context->validateWebGLObject("getTranslatedShaderSource", shader)) - return ""; - return m_context->graphicsContext3D()->getExtensions()->getTranslatedShaderSourceANGLE(shader->object()); + if (!m_context.validateWebGLObject("getTranslatedShaderSource", shader)) + return emptyString(); + return m_context.graphicsContext3D()->getExtensions().getTranslatedShaderSourceANGLE(shader->object()); } } // namespace WebCore diff --git a/Source/WebCore/html/canvas/WebGLDebugShaders.h b/Source/WebCore/html/canvas/WebGLDebugShaders.h index 961f488ce..4b99f1aea 100644 --- a/Source/WebCore/html/canvas/WebGLDebugShaders.h +++ b/Source/WebCore/html/canvas/WebGLDebugShaders.h @@ -23,31 +23,22 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLDebugShaders_h -#define WebGLDebugShaders_h +#pragma once #include "WebGLExtension.h" -#include <wtf/PassOwnPtr.h> namespace WebCore { class WebGLShader; -typedef int ExceptionCode; - -class WebGLDebugShaders : public WebGLExtension { +class WebGLDebugShaders final : public WebGLExtension { public: - static OwnPtr<WebGLDebugShaders> create(WebGLRenderingContext*); - + explicit WebGLDebugShaders(WebGLRenderingContextBase&); virtual ~WebGLDebugShaders(); - virtual ExtensionName getName() const override; - String getTranslatedShaderSource(WebGLShader*, ExceptionCode&); + ExtensionName getName() const override; -private: - WebGLDebugShaders(WebGLRenderingContext*); + String getTranslatedShaderSource(WebGLShader*); }; } // namespace WebCore - -#endif // WebGLDebugShaders_h diff --git a/Source/WebCore/html/canvas/WebGLDebugShaders.idl b/Source/WebCore/html/canvas/WebGLDebugShaders.idl index 4b0e11311..97c5e36be 100644 --- a/Source/WebCore/html/canvas/WebGLDebugShaders.idl +++ b/Source/WebCore/html/canvas/WebGLDebugShaders.idl @@ -24,9 +24,9 @@ */ [ - NoInterfaceObject, Conditional=WEBGL, GenerateIsReachable=ImplWebGLRenderingContext, + NoInterfaceObject, ] interface WebGLDebugShaders { - [StrictTypeChecking, TreatReturnedNullStringAs=Null, RaisesException] DOMString getTranslatedShaderSource(WebGLShader shader); + DOMString? getTranslatedShaderSource(WebGLShader? shader); // FIXME: The return value and the parameter should not be nullable. }; diff --git a/Source/WebCore/html/canvas/WebGLDepthTexture.cpp b/Source/WebCore/html/canvas/WebGLDepthTexture.cpp index 71a8da7d4..29f9b64e4 100644 --- a/Source/WebCore/html/canvas/WebGLDepthTexture.cpp +++ b/Source/WebCore/html/canvas/WebGLDepthTexture.cpp @@ -33,7 +33,7 @@ namespace WebCore { -WebGLDepthTexture::WebGLDepthTexture(WebGLRenderingContext* context) +WebGLDepthTexture::WebGLDepthTexture(WebGLRenderingContextBase& context) : WebGLExtension(context) { } @@ -47,17 +47,11 @@ WebGLExtension::ExtensionName WebGLDepthTexture::getName() const return WebGLDepthTextureName; } -OwnPtr<WebGLDepthTexture> WebGLDepthTexture::create(WebGLRenderingContext* context) +bool WebGLDepthTexture::supported(GraphicsContext3D& context) { - return adoptPtr(new WebGLDepthTexture(context)); -} - -bool WebGLDepthTexture::supported(GraphicsContext3D* context) -{ - Extensions3D* extensions = context->getExtensions(); - return extensions->supports("GL_CHROMIUM_depth_texture") - || extensions->supports("GL_OES_depth_texture") - || extensions->supports("GL_ARB_depth_texture"); + Extensions3D& extensions = context.getExtensions(); + return extensions.supports("GL_OES_depth_texture") + || extensions.supports("GL_ARB_depth_texture"); } } // namespace WebCore diff --git a/Source/WebCore/html/canvas/WebGLDepthTexture.h b/Source/WebCore/html/canvas/WebGLDepthTexture.h index 8687c2543..16b3b60b4 100644 --- a/Source/WebCore/html/canvas/WebGLDepthTexture.h +++ b/Source/WebCore/html/canvas/WebGLDepthTexture.h @@ -23,27 +23,20 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLDepthTexture_h -#define WebGLDepthTexture_h +#pragma once #include "WebGLExtension.h" -#include <wtf/PassOwnPtr.h> namespace WebCore { -class WebGLDepthTexture : public WebGLExtension { +class WebGLDepthTexture final : public WebGLExtension { public: - static OwnPtr<WebGLDepthTexture> create(WebGLRenderingContext*); - - static bool supported(GraphicsContext3D*); - + explicit WebGLDepthTexture(WebGLRenderingContextBase&); virtual ~WebGLDepthTexture(); - virtual ExtensionName getName() const override; -private: - WebGLDepthTexture(WebGLRenderingContext*); + static bool supported(GraphicsContext3D&); + + ExtensionName getName() const override; }; } // namespace WebCore - -#endif // WebGLDepthTexture_h diff --git a/Source/WebCore/html/canvas/WebGLDepthTexture.idl b/Source/WebCore/html/canvas/WebGLDepthTexture.idl index 60fcca36f..53954cea0 100644 --- a/Source/WebCore/html/canvas/WebGLDepthTexture.idl +++ b/Source/WebCore/html/canvas/WebGLDepthTexture.idl @@ -24,10 +24,10 @@ */ [ - NoInterfaceObject, Conditional=WEBGL, + DoNotCheckConstants, GenerateIsReachable=ImplWebGLRenderingContext, - DoNotCheckConstants + NoInterfaceObject, ] interface WebGLDepthTexture { - const unsigned int UNSIGNED_INT_24_8_WEBGL = 0x84FA; + const unsigned long UNSIGNED_INT_24_8_WEBGL = 0x84FA; }; diff --git a/Source/WebCore/html/canvas/EXTDrawBuffers.cpp b/Source/WebCore/html/canvas/WebGLDrawBuffers.cpp index 1a2bbf1a9..0891c02a9 100644 --- a/Source/WebCore/html/canvas/EXTDrawBuffers.cpp +++ b/Source/WebCore/html/canvas/WebGLDrawBuffers.cpp @@ -26,82 +26,70 @@ #include "config.h" #if ENABLE(WEBGL) - -#include "EXTDrawBuffers.h" +#include "WebGLDrawBuffers.h" #include "Extensions3D.h" namespace WebCore { -EXTDrawBuffers::EXTDrawBuffers(WebGLRenderingContext* context) +WebGLDrawBuffers::WebGLDrawBuffers(WebGLRenderingContextBase& context) : WebGLExtension(context) { } -EXTDrawBuffers::~EXTDrawBuffers() +WebGLDrawBuffers::~WebGLDrawBuffers() { } -WebGLExtension::ExtensionName EXTDrawBuffers::getName() const +WebGLExtension::ExtensionName WebGLDrawBuffers::getName() const { - return WebGLExtension::EXTDrawBuffersName; + return WebGLExtension::WebGLDrawBuffersName; } -OwnPtr<EXTDrawBuffers> EXTDrawBuffers::create(WebGLRenderingContext* context) -{ - return adoptPtr(new EXTDrawBuffers(context)); -} - -// static -bool EXTDrawBuffers::supported(WebGLRenderingContext* context) +bool WebGLDrawBuffers::supported(WebGLRenderingContextBase& context) { -#if OS(DARWIN) - // https://bugs.webkit.org/show_bug.cgi?id=112486 - return false; -#endif - Extensions3D* extensions = context->graphicsContext3D()->getExtensions(); - return (extensions->supports("GL_EXT_draw_buffers") - && satisfiesWebGLRequirements(context)); + return context.graphicsContext3D()->getExtensions().supports("GL_EXT_draw_buffers") + && satisfiesWebGLRequirements(context); } -void EXTDrawBuffers::drawBuffersEXT(const Vector<GC3Denum>& buffers) +void WebGLDrawBuffers::drawBuffersWEBGL(const Vector<GC3Denum>& buffers) { - if (m_context->isContextLost()) + if (m_context.isContextLost()) return; GC3Dsizei n = buffers.size(); const GC3Denum* bufs = buffers.data(); - if (!m_context->m_framebufferBinding) { + if (!m_context.m_framebufferBinding) { if (n != 1) { - m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "drawBuffersEXT", "more than one buffer"); + m_context.synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "drawBuffersWEBGL", "more than one buffer"); return; } if (bufs[0] != GraphicsContext3D::BACK && bufs[0] != GraphicsContext3D::NONE) { - m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawBuffersEXT", "BACK or NONE"); + m_context.synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawBuffersWEBGL", "BACK or NONE"); return; } // Because the backbuffer is simulated on all current WebKit ports, we need to change BACK to COLOR_ATTACHMENT0. GC3Denum value = (bufs[0] == GraphicsContext3D::BACK) ? GraphicsContext3D::COLOR_ATTACHMENT0 : GraphicsContext3D::NONE; - m_context->graphicsContext3D()->getExtensions()->drawBuffersEXT(1, &value); - m_context->setBackDrawBuffer(bufs[0]); + m_context.graphicsContext3D()->getExtensions().drawBuffersEXT(1, &value); + m_context.setBackDrawBuffer(bufs[0]); } else { - if (n > m_context->getMaxDrawBuffers()) { - m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "drawBuffersEXT", "more than max draw buffers"); + if (n > m_context.getMaxDrawBuffers()) { + m_context.synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "drawBuffersWEBGL", "more than max draw buffers"); return; } for (GC3Dsizei i = 0; i < n; ++i) { if (bufs[i] != GraphicsContext3D::NONE && bufs[i] != static_cast<GC3Denum>(Extensions3D::COLOR_ATTACHMENT0_EXT + i)) { - m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawBuffersEXT", "COLOR_ATTACHMENTi_EXT or NONE"); + m_context.synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawBuffersWEBGL", "COLOR_ATTACHMENTi_EXT or NONE"); return; } } - m_context->m_framebufferBinding->drawBuffers(buffers); + m_context.m_framebufferBinding->drawBuffers(buffers); } } // static -bool EXTDrawBuffers::satisfiesWebGLRequirements(WebGLRenderingContext* webglContext) +bool WebGLDrawBuffers::satisfiesWebGLRequirements(WebGLRenderingContextBase& webglContext) { - GraphicsContext3D* context = webglContext->graphicsContext3D(); + GraphicsContext3D* context = webglContext.graphicsContext3D(); // This is called after we make sure GL_EXT_draw_buffers is supported. GC3Dint maxDrawBuffers = 0; @@ -115,11 +103,10 @@ bool EXTDrawBuffers::satisfiesWebGLRequirements(WebGLRenderingContext* webglCont context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, fbo); const unsigned char buffer[4] = { 0, 0, 0, 0 }; // textures are required to be initialized for other ports. - bool supportsDepth = (context->getExtensions()->supports("GL_CHROMIUM_depth_texture") - || context->getExtensions()->supports("GL_OES_depth_texture") - || context->getExtensions()->supports("GL_ARB_depth_texture")); - bool supportsDepthStencil = (context->getExtensions()->supports("GL_EXT_packed_depth_stencil") - || context->getExtensions()->supports("GL_OES_packed_depth_stencil")); + bool supportsDepth = context->getExtensions().supports("GL_OES_depth_texture") + || context->getExtensions().supports("GL_ARB_depth_texture"); + bool supportsDepthStencil = (context->getExtensions().supports("GL_EXT_packed_depth_stencil") + || context->getExtensions().supports("GL_OES_packed_depth_stencil")); Platform3DObject depthStencil = 0; if (supportsDepthStencil) { depthStencil = context->createTexture(); @@ -166,15 +153,15 @@ bool EXTDrawBuffers::satisfiesWebGLRequirements(WebGLRenderingContext* webglCont } } - webglContext->restoreCurrentFramebuffer(); + webglContext.restoreCurrentFramebuffer(); context->deleteFramebuffer(fbo); - webglContext->restoreCurrentTexture2D(); + webglContext.restoreCurrentTexture2D(); if (supportsDepth) context->deleteTexture(depth); if (supportsDepthStencil) context->deleteTexture(depthStencil); - for (size_t i = 0; i < colors.size(); ++i) - context->deleteTexture(colors[i]); + for (auto& color : colors) + context->deleteTexture(color); return ok; } diff --git a/Source/WebCore/html/canvas/EXTDrawBuffers.h b/Source/WebCore/html/canvas/WebGLDrawBuffers.h index b5963fb70..f69df9f63 100644 --- a/Source/WebCore/html/canvas/EXTDrawBuffers.h +++ b/Source/WebCore/html/canvas/WebGLDrawBuffers.h @@ -23,31 +23,25 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef EXTDrawBuffers_h -#define EXTDrawBuffers_h +#pragma once #include "WebGLExtension.h" -#include <wtf/PassOwnPtr.h> namespace WebCore { -class EXTDrawBuffers : public WebGLExtension { +class WebGLDrawBuffers final : public WebGLExtension { public: - static OwnPtr<EXTDrawBuffers> create(WebGLRenderingContext*); + explicit WebGLDrawBuffers(WebGLRenderingContextBase&); + virtual ~WebGLDrawBuffers(); - static bool supported(WebGLRenderingContext*); + static bool supported(WebGLRenderingContextBase&); - virtual ~EXTDrawBuffers(); - virtual ExtensionName getName() const override; + ExtensionName getName() const override; - void drawBuffersEXT(const Vector<GC3Denum>& buffers); + void drawBuffersWEBGL(const Vector<GC3Denum>& buffers); private: - EXTDrawBuffers(WebGLRenderingContext*); - - static bool satisfiesWebGLRequirements(WebGLRenderingContext*); + static bool satisfiesWebGLRequirements(WebGLRenderingContextBase&); }; } // namespace WebCore - -#endif // EXTDrawBuffers_h diff --git a/Source/WebCore/html/canvas/WebGLDrawBuffers.idl b/Source/WebCore/html/canvas/WebGLDrawBuffers.idl new file mode 100644 index 000000000..f8e783e84 --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLDrawBuffers.idl @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2013 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +typedef unsigned long GLenum; + +[ + NoInterfaceObject, + Conditional=WEBGL, + GenerateIsReachable=ImplWebGLRenderingContext, + DoNotCheckConstants, +] interface WebGLDrawBuffers { + const GLenum COLOR_ATTACHMENT0_WEBGL = 0x8CE0; + const GLenum COLOR_ATTACHMENT1_WEBGL = 0x8CE1; + const GLenum COLOR_ATTACHMENT2_WEBGL = 0x8CE2; + const GLenum COLOR_ATTACHMENT3_WEBGL = 0x8CE3; + const GLenum COLOR_ATTACHMENT4_WEBGL = 0x8CE4; + const GLenum COLOR_ATTACHMENT5_WEBGL = 0x8CE5; + const GLenum COLOR_ATTACHMENT6_WEBGL = 0x8CE6; + const GLenum COLOR_ATTACHMENT7_WEBGL = 0x8CE7; + const GLenum COLOR_ATTACHMENT8_WEBGL = 0x8CE8; + const GLenum COLOR_ATTACHMENT9_WEBGL = 0x8CE9; + const GLenum COLOR_ATTACHMENT10_WEBGL = 0x8CEA; + const GLenum COLOR_ATTACHMENT11_WEBGL = 0x8CEB; + const GLenum COLOR_ATTACHMENT12_WEBGL = 0x8CEC; + const GLenum COLOR_ATTACHMENT13_WEBGL = 0x8CED; + const GLenum COLOR_ATTACHMENT14_WEBGL = 0x8CEE; + const GLenum COLOR_ATTACHMENT15_WEBGL = 0x8CEF; + + const GLenum DRAW_BUFFER0_WEBGL = 0x8825; + const GLenum DRAW_BUFFER1_WEBGL = 0x8826; + const GLenum DRAW_BUFFER2_WEBGL = 0x8827; + const GLenum DRAW_BUFFER3_WEBGL = 0x8828; + const GLenum DRAW_BUFFER4_WEBGL = 0x8829; + const GLenum DRAW_BUFFER5_WEBGL = 0x882A; + const GLenum DRAW_BUFFER6_WEBGL = 0x882B; + const GLenum DRAW_BUFFER7_WEBGL = 0x882C; + const GLenum DRAW_BUFFER8_WEBGL = 0x882D; + const GLenum DRAW_BUFFER9_WEBGL = 0x882E; + const GLenum DRAW_BUFFER10_WEBGL = 0x882F; + const GLenum DRAW_BUFFER11_WEBGL = 0x8830; + const GLenum DRAW_BUFFER12_WEBGL = 0x8831; + const GLenum DRAW_BUFFER13_WEBGL = 0x8832; + const GLenum DRAW_BUFFER14_WEBGL = 0x8833; + const GLenum DRAW_BUFFER15_WEBGL = 0x8834; + + const GLenum MAX_COLOR_ATTACHMENTS_WEBGL = 0x8CDF; + const GLenum MAX_DRAW_BUFFERS_WEBGL = 0x8824; + + void drawBuffersWEBGL(sequence<GLenum> buffers); +}; diff --git a/Source/WebCore/html/canvas/WebGLExtension.cpp b/Source/WebCore/html/canvas/WebGLExtension.cpp index bf62eecec..c9f0a4251 100644 --- a/Source/WebCore/html/canvas/WebGLExtension.cpp +++ b/Source/WebCore/html/canvas/WebGLExtension.cpp @@ -31,7 +31,7 @@ namespace WebCore { -WebGLExtension::WebGLExtension(WebGLRenderingContext* context) +WebGLExtension::WebGLExtension(WebGLRenderingContextBase& context) : m_context(context) { } diff --git a/Source/WebCore/html/canvas/WebGLExtension.h b/Source/WebCore/html/canvas/WebGLExtension.h index e9100dba0..7f709b445 100644 --- a/Source/WebCore/html/canvas/WebGLExtension.h +++ b/Source/WebCore/html/canvas/WebGLExtension.h @@ -23,10 +23,9 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLExtension_h -#define WebGLExtension_h +#pragma once -#include "WebGLRenderingContext.h" +#include "WebGLRenderingContextBase.h" namespace WebCore { @@ -36,8 +35,11 @@ public: // Extension names are needed to properly wrap instances in JavaScript objects. enum ExtensionName { WebGLLoseContextName, - EXTDrawBuffersName, + EXTBlendMinMaxName, + EXTFragDepthName, + EXTShaderTextureLODName, EXTTextureFilterAnisotropicName, + EXTsRGBName, OESTextureFloatName, OESTextureFloatLinearName, OESTextureHalfFloatName, @@ -48,24 +50,23 @@ public: WebGLDebugShadersName, WebGLCompressedTextureS3TCName, WebGLDepthTextureName, + WebGLDrawBuffersName, OESElementIndexUintName, WebGLCompressedTextureATCName, WebGLCompressedTexturePVRTCName, ANGLEInstancedArraysName, }; - void ref() { m_context->ref(); } - void deref() { m_context->deref(); } - WebGLRenderingContext* context() { return m_context; } + void ref() { m_context.ref(); } + void deref() { m_context.deref(); } + WebGLRenderingContextBase& context() { return m_context; } virtual ~WebGLExtension(); virtual ExtensionName getName() const = 0; protected: - WebGLExtension(WebGLRenderingContext*); - WebGLRenderingContext* m_context; + WebGLExtension(WebGLRenderingContextBase&); + WebGLRenderingContextBase& m_context; }; } // namespace WebCore - -#endif // WebGLExtension_h diff --git a/Source/WebCore/html/canvas/WebGLFramebuffer.cpp b/Source/WebCore/html/canvas/WebGLFramebuffer.cpp index 7e1dc07f5..c2762b236 100644 --- a/Source/WebCore/html/canvas/WebGLFramebuffer.cpp +++ b/Source/WebCore/html/canvas/WebGLFramebuffer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,15 +24,14 @@ */ #include "config.h" +#include "WebGLFramebuffer.h" #if ENABLE(WEBGL) -#include "WebGLFramebuffer.h" - -#include "EXTDrawBuffers.h" #include "Extensions3D.h" #include "WebGLContextGroup.h" -#include "WebGLRenderingContext.h" +#include "WebGLDrawBuffers.h" +#include "WebGLRenderingContextBase.h" namespace WebCore { @@ -45,30 +44,30 @@ namespace { class WebGLRenderbufferAttachment : public WebGLFramebuffer::WebGLAttachment { public: - static PassRefPtr<WebGLFramebuffer::WebGLAttachment> create(WebGLRenderbuffer*); + static Ref<WebGLFramebuffer::WebGLAttachment> create(WebGLRenderbuffer*); private: WebGLRenderbufferAttachment(WebGLRenderbuffer*); - virtual GC3Dsizei getWidth() const override; - virtual GC3Dsizei getHeight() const override; - virtual GC3Denum getFormat() const override; - virtual WebGLSharedObject* getObject() const override; - virtual bool isSharedObject(WebGLSharedObject*) const override; - virtual bool isValid() const override; - virtual bool isInitialized() const override; - virtual void setInitialized() override; - virtual void onDetached(GraphicsContext3D*) override; - virtual void attach(GraphicsContext3D*, GC3Denum attachment) override; - virtual void unattach(GraphicsContext3D*, GC3Denum attachment) override; + GC3Dsizei getWidth() const override; + GC3Dsizei getHeight() const override; + GC3Denum getFormat() const override; + WebGLSharedObject* getObject() const override; + bool isSharedObject(WebGLSharedObject*) const override; + bool isValid() const override; + bool isInitialized() const override; + void setInitialized() override; + void onDetached(GraphicsContext3D*) override; + void attach(GraphicsContext3D*, GC3Denum attachment) override; + void unattach(GraphicsContext3D*, GC3Denum attachment) override; WebGLRenderbufferAttachment() { }; RefPtr<WebGLRenderbuffer> m_renderbuffer; }; - PassRefPtr<WebGLFramebuffer::WebGLAttachment> WebGLRenderbufferAttachment::create(WebGLRenderbuffer* renderbuffer) + Ref<WebGLFramebuffer::WebGLAttachment> WebGLRenderbufferAttachment::create(WebGLRenderbuffer* renderbuffer) { - return adoptRef(new WebGLRenderbufferAttachment(renderbuffer)); + return adoptRef(*new WebGLRenderbufferAttachment(renderbuffer)); } WebGLRenderbufferAttachment::WebGLRenderbufferAttachment(WebGLRenderbuffer* renderbuffer) @@ -139,21 +138,21 @@ namespace { class WebGLTextureAttachment : public WebGLFramebuffer::WebGLAttachment { public: - static PassRefPtr<WebGLFramebuffer::WebGLAttachment> create(WebGLTexture*, GC3Denum target, GC3Dint level); + static Ref<WebGLFramebuffer::WebGLAttachment> create(WebGLTexture*, GC3Denum target, GC3Dint level); private: WebGLTextureAttachment(WebGLTexture*, GC3Denum target, GC3Dint level); - virtual GC3Dsizei getWidth() const override; - virtual GC3Dsizei getHeight() const override; - virtual GC3Denum getFormat() const override; - virtual WebGLSharedObject* getObject() const override; - virtual bool isSharedObject(WebGLSharedObject*) const override; - virtual bool isValid() const override; - virtual bool isInitialized() const override; - virtual void setInitialized() override; - virtual void onDetached(GraphicsContext3D*) override; - virtual void attach(GraphicsContext3D*, GC3Denum attachment) override; - virtual void unattach(GraphicsContext3D*, GC3Denum attachment) override; + GC3Dsizei getWidth() const override; + GC3Dsizei getHeight() const override; + GC3Denum getFormat() const override; + WebGLSharedObject* getObject() const override; + bool isSharedObject(WebGLSharedObject*) const override; + bool isValid() const override; + bool isInitialized() const override; + void setInitialized() override; + void onDetached(GraphicsContext3D*) override; + void attach(GraphicsContext3D*, GC3Denum attachment) override; + void unattach(GraphicsContext3D*, GC3Denum attachment) override; WebGLTextureAttachment() { }; @@ -162,9 +161,9 @@ namespace { GC3Dint m_level; }; - PassRefPtr<WebGLFramebuffer::WebGLAttachment> WebGLTextureAttachment::create(WebGLTexture* texture, GC3Denum target, GC3Dint level) + Ref<WebGLFramebuffer::WebGLAttachment> WebGLTextureAttachment::create(WebGLTexture* texture, GC3Denum target, GC3Dint level) { - return adoptRef(new WebGLTextureAttachment(texture, target, level)); + return adoptRef(*new WebGLTextureAttachment(texture, target, level)); } WebGLTextureAttachment::WebGLTextureAttachment(WebGLTexture* texture, GC3Denum target, GC3Dint level) @@ -269,16 +268,16 @@ WebGLFramebuffer::WebGLAttachment::~WebGLAttachment() { } -PassRefPtr<WebGLFramebuffer> WebGLFramebuffer::create(WebGLRenderingContext* ctx) +Ref<WebGLFramebuffer> WebGLFramebuffer::create(WebGLRenderingContextBase& ctx) { - return adoptRef(new WebGLFramebuffer(ctx)); + return adoptRef(*new WebGLFramebuffer(ctx)); } -WebGLFramebuffer::WebGLFramebuffer(WebGLRenderingContext* ctx) +WebGLFramebuffer::WebGLFramebuffer(WebGLRenderingContextBase& ctx) : WebGLContextObject(ctx) , m_hasEverBeenBound(false) { - setObject(ctx->graphicsContext3D()->createFramebuffer()); + setObject(ctx.graphicsContext3D()->createFramebuffer()); } WebGLFramebuffer::~WebGLFramebuffer() @@ -369,19 +368,19 @@ void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer(WebGLSharedObject* a return; bool checkMore = true; - while (checkMore) { + do { checkMore = false; - for (AttachmentMap::iterator it = m_attachments.begin(); it != m_attachments.end(); ++it) { - WebGLAttachment* attachmentObject = it->value.get(); + for (auto& entry : m_attachments) { + WebGLAttachment* attachmentObject = entry.value.get(); if (attachmentObject->isSharedObject(attachment)) { - GC3Denum attachmentType = it->key; + GC3Denum attachmentType = entry.key; attachmentObject->unattach(context()->graphicsContext3D(), attachmentType); removeAttachmentFromBoundFramebuffer(attachmentType); checkMore = true; break; } } - } + } while (checkMore); } GC3Dsizei WebGLFramebuffer::getColorBufferWidth() const @@ -423,19 +422,25 @@ GC3Denum WebGLFramebuffer::checkStatus(const char** reason) const bool haveDepth = false; bool haveStencil = false; bool haveDepthStencil = false; - for (AttachmentMap::const_iterator it = m_attachments.begin(); it != m_attachments.end(); ++it) { - WebGLAttachment* attachment = it->value.get(); - if (!isAttachmentComplete(attachment, it->key, reason)) + for (auto& entry : m_attachments) { + WebGLAttachment* attachment = entry.value.get(); + if (!isAttachmentComplete(attachment, entry.key, reason)) return GraphicsContext3D::FRAMEBUFFER_INCOMPLETE_ATTACHMENT; if (!attachment->isValid()) { *reason = "attachment is not valid"; return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED; } - if (!attachment->getFormat()) { + GC3Denum attachmentFormat = attachment->getFormat(); + + // Attaching an SRGB_EXT format attachment to a framebuffer is invalid. + if (attachmentFormat == Extensions3D::SRGB_EXT) + attachmentFormat = 0; + + if (!attachmentFormat) { *reason = "attachment is an unsupported format"; return GraphicsContext3D::FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } - switch (it->key) { + switch (entry.key) { case GraphicsContext3D::DEPTH_ATTACHMENT: haveDepth = true; break; @@ -473,13 +478,11 @@ GC3Denum WebGLFramebuffer::checkStatus(const char** reason) const return GraphicsContext3D::FRAMEBUFFER_COMPLETE; } -bool WebGLFramebuffer::onAccess(GraphicsContext3D* context3d, bool needToInitializeAttachments, const char** reason) +bool WebGLFramebuffer::onAccess(GraphicsContext3D* context3d, const char** reason) { if (checkStatus(reason) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) return false; - if (needToInitializeAttachments) - return initializeAttachments(context3d, reason); - return true; + return initializeAttachments(context3d, reason); } bool WebGLFramebuffer::hasStencilBuffer() const @@ -492,8 +495,8 @@ bool WebGLFramebuffer::hasStencilBuffer() const void WebGLFramebuffer::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object) { - for (AttachmentMap::iterator it = m_attachments.begin(); it != m_attachments.end(); ++it) - it->value->onDetached(context3d); + for (auto& attachment : m_attachments.values()) + attachment->onDetached(context3d); context3d->deleteFramebuffer(object); } @@ -503,9 +506,9 @@ bool WebGLFramebuffer::initializeAttachments(GraphicsContext3D* g3d, const char* ASSERT(object()); GC3Dbitfield mask = 0; - for (AttachmentMap::iterator it = m_attachments.begin(); it != m_attachments.end(); ++it) { - GC3Denum attachmentType = it->key; - WebGLAttachment* attachment = it->value.get(); + for (auto& entry : m_attachments) { + GC3Denum attachmentType = entry.key; + WebGLAttachment* attachment = entry.value.get(); if (!attachment->isInitialized()) mask |= GraphicsContext3D::getClearBitsByAttachmentType(attachmentType); } @@ -594,15 +597,20 @@ void WebGLFramebuffer::drawBuffers(const Vector<GC3Denum>& bufs) { m_drawBuffers = bufs; m_filteredDrawBuffers.resize(m_drawBuffers.size()); - for (size_t i = 0; i < m_filteredDrawBuffers.size(); ++i) - m_filteredDrawBuffers[i] = GraphicsContext3D::NONE; + for (auto& buffer : m_filteredDrawBuffers) + buffer = GraphicsContext3D::NONE; drawBuffersIfNecessary(true); } void WebGLFramebuffer::drawBuffersIfNecessary(bool force) { - if (!context()->m_extDrawBuffers) +#if ENABLE(WEBGL2) + // FIXME: The logic here seems wrong. If we don't have WebGL 2 enabled at all, then + // we skip the m_webglDrawBuffers check. But if we do have WebGL 2 enabled, then we + // perform this check, for WebGL 1 contexts only. + if (!context()->m_webglDrawBuffers && !context()->isWebGL2()) return; +#endif bool reset = force; // This filtering works around graphics driver bugs on Mac OS X. for (size_t i = 0; i < m_drawBuffers.size(); ++i) { @@ -619,7 +627,7 @@ void WebGLFramebuffer::drawBuffersIfNecessary(bool force) } } if (reset) { - context()->graphicsContext3D()->getExtensions()->drawBuffersEXT( + context()->graphicsContext3D()->getExtensions().drawBuffersEXT( m_filteredDrawBuffers.size(), m_filteredDrawBuffers.data()); } } diff --git a/Source/WebCore/html/canvas/WebGLFramebuffer.h b/Source/WebCore/html/canvas/WebGLFramebuffer.h index a0ee31c69..baeeae66b 100644 --- a/Source/WebCore/html/canvas/WebGLFramebuffer.h +++ b/Source/WebCore/html/canvas/WebGLFramebuffer.h @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,13 +23,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLFramebuffer_h -#define WebGLFramebuffer_h +#pragma once #include "WebGLContextObject.h" #include "WebGLSharedObject.h" - -#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> namespace WebCore { @@ -37,7 +34,7 @@ namespace WebCore { class WebGLRenderbuffer; class WebGLTexture; -class WebGLFramebuffer : public WebGLContextObject { +class WebGLFramebuffer final : public WebGLContextObject { public: class WebGLAttachment : public RefCounted<WebGLAttachment> { public: @@ -61,7 +58,7 @@ public: virtual ~WebGLFramebuffer(); - static PassRefPtr<WebGLFramebuffer> create(WebGLRenderingContext*); + static Ref<WebGLFramebuffer> create(WebGLRenderingContextBase&); void setAttachmentForBoundFramebuffer(GC3Denum attachment, GC3Denum texTarget, WebGLTexture*, GC3Dint level); void setAttachmentForBoundFramebuffer(GC3Denum attachment, WebGLRenderbuffer*); @@ -81,7 +78,7 @@ public: // Return false if the framebuffer is incomplete; otherwise initialize // the buffers if they haven't been initialized and // needToInitializeAttachments is true. - bool onAccess(GraphicsContext3D*, bool needToInitializeAttachments, const char** reason); + bool onAccess(GraphicsContext3D*, const char** reason); // Software version of glCheckFramebufferStatus(), except that when // FRAMEBUFFER_COMPLETE is returned, it is still possible for @@ -101,13 +98,11 @@ public: GC3Denum getDrawBuffer(GC3Denum); protected: - WebGLFramebuffer(WebGLRenderingContext*); + WebGLFramebuffer(WebGLRenderingContextBase&); - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override; + void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override; private: - virtual bool isFramebuffer() const { return true; } - WebGLAttachment* getAttachment(GC3Denum) const; // Return false if framebuffer is incomplete. @@ -133,5 +128,3 @@ private: }; } // namespace WebCore - -#endif // WebGLFramebuffer_h diff --git a/Source/WebCore/html/canvas/WebGLFramebuffer.idl b/Source/WebCore/html/canvas/WebGLFramebuffer.idl index e609513b2..7c6cc4595 100644 --- a/Source/WebCore/html/canvas/WebGLFramebuffer.idl +++ b/Source/WebCore/html/canvas/WebGLFramebuffer.idl @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR diff --git a/Source/WebCore/html/canvas/WebGLGetInfo.cpp b/Source/WebCore/html/canvas/WebGLGetInfo.cpp deleted file mode 100644 index 8e27d3b9a..000000000 --- a/Source/WebCore/html/canvas/WebGLGetInfo.cpp +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Copyright (C) 2009 Apple Inc. All Rights Reserved. - * Copyright (C) 2009 Google Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(WEBGL) - -#include "WebGLGetInfo.h" - -#include "WebGLBuffer.h" -#include "WebGLFramebuffer.h" -#include "WebGLProgram.h" -#include "WebGLRenderbuffer.h" -#include "WebGLTexture.h" -#include "WebGLVertexArrayObjectOES.h" -#include <runtime/Float32Array.h> -#include <runtime/Int32Array.h> -#include <runtime/Uint32Array.h> -#include <runtime/Uint8Array.h> - -namespace WebCore { - -WebGLGetInfo::WebGLGetInfo(bool value) - : m_type(kTypeBool) - , m_bool(value) - , m_float(0) - , m_int(0) - , m_unsignedInt(0) -{ -} - -WebGLGetInfo::WebGLGetInfo(const bool* value, int size) - : m_type(kTypeBoolArray) - , m_bool(false) - , m_float(0) - , m_int(0) - , m_unsignedInt(0) -{ - if (!value || size <=0) - return; - m_boolArray.resize(size); - for (int ii = 0; ii < size; ++ii) - m_boolArray[ii] = value[ii]; -} - -WebGLGetInfo::WebGLGetInfo(float value) - : m_type(kTypeFloat) - , m_bool(false) - , m_float(value) - , m_int(0) - , m_unsignedInt(0) -{ -} - -WebGLGetInfo::WebGLGetInfo(int value) - : m_type(kTypeInt) - , m_bool(false) - , m_float(0) - , m_int(value) - , m_unsignedInt(0) -{ -} - -WebGLGetInfo::WebGLGetInfo() - : m_type(kTypeNull) - , m_bool(false) - , m_float(0) - , m_int(0) - , m_unsignedInt(0) -{ -} - -WebGLGetInfo::WebGLGetInfo(const String& value) - : m_type(kTypeString) - , m_bool(false) - , m_float(0) - , m_int(0) - , m_string(value) - , m_unsignedInt(0) -{ -} - -WebGLGetInfo::WebGLGetInfo(unsigned int value) - : m_type(kTypeUnsignedInt) - , m_bool(false) - , m_float(0) - , m_int(0) - , m_unsignedInt(value) -{ -} - -WebGLGetInfo::WebGLGetInfo(PassRefPtr<WebGLBuffer> value) - : m_type(kTypeWebGLBuffer) - , m_bool(false) - , m_float(0) - , m_int(0) - , m_unsignedInt(0) - , m_webglBuffer(value) -{ -} - -WebGLGetInfo::WebGLGetInfo(PassRefPtr<Float32Array> value) - : m_type(kTypeWebGLFloatArray) - , m_bool(false) - , m_float(0) - , m_int(0) - , m_unsignedInt(0) - , m_webglFloatArray(value) -{ -} - -WebGLGetInfo::WebGLGetInfo(PassRefPtr<WebGLFramebuffer> value) - : m_type(kTypeWebGLFramebuffer) - , m_bool(false) - , m_float(0) - , m_int(0) - , m_unsignedInt(0) - , m_webglFramebuffer(value) -{ -} - -WebGLGetInfo::WebGLGetInfo(PassRefPtr<Int32Array> value) - : m_type(kTypeWebGLIntArray) - , m_bool(false) - , m_float(0) - , m_int(0) - , m_unsignedInt(0) - , m_webglIntArray(value) -{ -} - -WebGLGetInfo::WebGLGetInfo(PassRefPtr<WebGLProgram> value) - : m_type(kTypeWebGLProgram) - , m_bool(false) - , m_float(0) - , m_int(0) - , m_unsignedInt(0) - , m_webglProgram(value) -{ -} - -WebGLGetInfo::WebGLGetInfo(PassRefPtr<WebGLRenderbuffer> value) - : m_type(kTypeWebGLRenderbuffer) - , m_bool(false) - , m_float(0) - , m_int(0) - , m_unsignedInt(0) - , m_webglRenderbuffer(value) -{ -} - -WebGLGetInfo::WebGLGetInfo(PassRefPtr<WebGLTexture> value) - : m_type(kTypeWebGLTexture) - , m_bool(false) - , m_float(0) - , m_int(0) - , m_unsignedInt(0) - , m_webglTexture(value) -{ -} - -WebGLGetInfo::WebGLGetInfo(PassRefPtr<Uint8Array> value) - : m_type(kTypeWebGLUnsignedByteArray) - , m_bool(false) - , m_float(0) - , m_int(0) - , m_unsignedInt(0) - , m_webglUnsignedByteArray(value) -{ -} - -WebGLGetInfo::WebGLGetInfo(PassRefPtr<Uint32Array> value) - : m_type(kTypeWebGLUnsignedIntArray) - , m_bool(false) - , m_float(0) - , m_int(0) - , m_unsignedInt(0) - , m_webglUnsignedIntArray(value) -{ -} - -WebGLGetInfo::WebGLGetInfo(PassRefPtr<WebGLVertexArrayObjectOES> value) - : m_type(kTypeWebGLVertexArrayObjectOES) - , m_bool(false) - , m_float(0) - , m_int(0) - , m_unsignedInt(0) - , m_webglVertexArrayObject(value) -{ -} - -WebGLGetInfo::~WebGLGetInfo() -{ -} - -WebGLGetInfo::Type WebGLGetInfo::getType() const -{ - return m_type; -} - -bool WebGLGetInfo::getBool() const -{ - ASSERT(getType() == kTypeBool); - return m_bool; -} - -const Vector<bool>& WebGLGetInfo::getBoolArray() const -{ - ASSERT(getType() == kTypeBoolArray); - return m_boolArray; -} - -float WebGLGetInfo::getFloat() const -{ - ASSERT(getType() == kTypeFloat); - return m_float; -} - -int WebGLGetInfo::getInt() const -{ - ASSERT(getType() == kTypeInt); - return m_int; -} - -const String& WebGLGetInfo::getString() const -{ - ASSERT(getType() == kTypeString); - return m_string; -} - -unsigned int WebGLGetInfo::getUnsignedInt() const -{ - ASSERT(getType() == kTypeUnsignedInt); - return m_unsignedInt; -} - -PassRefPtr<WebGLBuffer> WebGLGetInfo::getWebGLBuffer() const -{ - ASSERT(getType() == kTypeWebGLBuffer); - return m_webglBuffer; -} - -PassRefPtr<Float32Array> WebGLGetInfo::getWebGLFloatArray() const -{ - ASSERT(getType() == kTypeWebGLFloatArray); - return m_webglFloatArray; -} - -PassRefPtr<WebGLFramebuffer> WebGLGetInfo::getWebGLFramebuffer() const -{ - ASSERT(getType() == kTypeWebGLFramebuffer); - return m_webglFramebuffer; -} - -PassRefPtr<Int32Array> WebGLGetInfo::getWebGLIntArray() const -{ - ASSERT(getType() == kTypeWebGLIntArray); - return m_webglIntArray; -} - -PassRefPtr<WebGLProgram> WebGLGetInfo::getWebGLProgram() const -{ - ASSERT(getType() == kTypeWebGLProgram); - return m_webglProgram; -} - -PassRefPtr<WebGLRenderbuffer> WebGLGetInfo::getWebGLRenderbuffer() const -{ - ASSERT(getType() == kTypeWebGLRenderbuffer); - return m_webglRenderbuffer; -} - -PassRefPtr<WebGLTexture> WebGLGetInfo::getWebGLTexture() const -{ - ASSERT(getType() == kTypeWebGLTexture); - return m_webglTexture; -} - -PassRefPtr<Uint8Array> WebGLGetInfo::getWebGLUnsignedByteArray() const -{ - ASSERT(getType() == kTypeWebGLUnsignedByteArray); - return m_webglUnsignedByteArray; -} - -PassRefPtr<Uint32Array> WebGLGetInfo::getWebGLUnsignedIntArray() const -{ - ASSERT(getType() == kTypeWebGLUnsignedIntArray); - return m_webglUnsignedIntArray; -} - -PassRefPtr<WebGLVertexArrayObjectOES> WebGLGetInfo::getWebGLVertexArrayObjectOES() const -{ - ASSERT(getType() == kTypeWebGLVertexArrayObjectOES); - return m_webglVertexArrayObject; -} - -} // namespace WebCore - -#endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/WebGLGetInfo.h b/Source/WebCore/html/canvas/WebGLGetInfo.h deleted file mode 100644 index 082612ac9..000000000 --- a/Source/WebCore/html/canvas/WebGLGetInfo.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2009 Apple Inc. All Rights Reserved. - * Copyright (C) 2009 Google Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WebGLGetInfo_h -#define WebGLGetInfo_h - -#include "WebGLBuffer.h" -#include "WebGLFramebuffer.h" -#include "WebGLProgram.h" -#include "WebGLRenderbuffer.h" -#include "WebGLTexture.h" -#include "WebGLVertexArrayObjectOES.h" -#include <runtime/Float32Array.h> -#include <runtime/Int32Array.h> -#include <runtime/Uint32Array.h> -#include <runtime/Uint8Array.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> -#include <wtf/text/WTFString.h> - -namespace WebCore { - -// A tagged union representing the result of get queries like -// getParameter (encompassing getBooleanv, getIntegerv, getFloatv) and -// similar variants. For reference counted types, increments and -// decrements the reference count of the target object. - -class WebGLGetInfo { -public: - enum Type { - kTypeBool, - kTypeBoolArray, - kTypeFloat, - kTypeInt, - kTypeNull, - kTypeString, - kTypeUnsignedInt, - kTypeWebGLBuffer, - kTypeWebGLFloatArray, - kTypeWebGLFramebuffer, - kTypeWebGLIntArray, - kTypeWebGLObjectArray, - kTypeWebGLProgram, - kTypeWebGLRenderbuffer, - kTypeWebGLTexture, - kTypeWebGLUnsignedByteArray, - kTypeWebGLUnsignedIntArray, - kTypeWebGLVertexArrayObjectOES, - }; - - explicit WebGLGetInfo(bool value); - WebGLGetInfo(const bool* value, int size); - explicit WebGLGetInfo(float value); - explicit WebGLGetInfo(int value); - // Represents the null value and type. - WebGLGetInfo(); - explicit WebGLGetInfo(const String& value); - explicit WebGLGetInfo(unsigned int value); - explicit WebGLGetInfo(PassRefPtr<WebGLBuffer> value); - explicit WebGLGetInfo(PassRefPtr<Float32Array> value); - explicit WebGLGetInfo(PassRefPtr<WebGLFramebuffer> value); - explicit WebGLGetInfo(PassRefPtr<Int32Array> value); - // FIXME: implement WebGLObjectArray - // WebGLGetInfo(PassRefPtr<WebGLObjectArray> value); - explicit WebGLGetInfo(PassRefPtr<WebGLProgram> value); - explicit WebGLGetInfo(PassRefPtr<WebGLRenderbuffer> value); - explicit WebGLGetInfo(PassRefPtr<WebGLTexture> value); - explicit WebGLGetInfo(PassRefPtr<Uint8Array> value); - explicit WebGLGetInfo(PassRefPtr<Uint32Array> value); - explicit WebGLGetInfo(PassRefPtr<WebGLVertexArrayObjectOES> value); - - virtual ~WebGLGetInfo(); - - Type getType() const; - - bool getBool() const; - const Vector<bool>& getBoolArray() const; - float getFloat() const; - int getInt() const; - const String& getString() const; - unsigned int getUnsignedInt() const; - PassRefPtr<WebGLBuffer> getWebGLBuffer() const; - PassRefPtr<Float32Array> getWebGLFloatArray() const; - PassRefPtr<WebGLFramebuffer> getWebGLFramebuffer() const; - PassRefPtr<Int32Array> getWebGLIntArray() const; - // FIXME: implement WebGLObjectArray - // PassRefPtr<WebGLObjectArray> getWebGLObjectArray() const; - PassRefPtr<WebGLProgram> getWebGLProgram() const; - PassRefPtr<WebGLRenderbuffer> getWebGLRenderbuffer() const; - PassRefPtr<WebGLTexture> getWebGLTexture() const; - PassRefPtr<Uint8Array> getWebGLUnsignedByteArray() const; - PassRefPtr<Uint32Array> getWebGLUnsignedIntArray() const; - PassRefPtr<WebGLVertexArrayObjectOES> getWebGLVertexArrayObjectOES() const; - -private: - Type m_type; - bool m_bool; - Vector<bool> m_boolArray; - float m_float; - int m_int; - String m_string; - unsigned int m_unsignedInt; - RefPtr<WebGLBuffer> m_webglBuffer; - RefPtr<Float32Array> m_webglFloatArray; - RefPtr<WebGLFramebuffer> m_webglFramebuffer; - RefPtr<Int32Array> m_webglIntArray; - // FIXME: implement WebGLObjectArray - // RefPtr<WebGLObjectArray> m_webglObjectArray; - RefPtr<WebGLProgram> m_webglProgram; - RefPtr<WebGLRenderbuffer> m_webglRenderbuffer; - RefPtr<WebGLTexture> m_webglTexture; - RefPtr<Uint8Array> m_webglUnsignedByteArray; - RefPtr<Uint32Array> m_webglUnsignedIntArray; - RefPtr<WebGLVertexArrayObjectOES> m_webglVertexArrayObject; -}; - -} // namespace WebCore - -#endif // WebGLGetInfo_h diff --git a/Source/WebCore/html/canvas/WebGLLoseContext.cpp b/Source/WebCore/html/canvas/WebGLLoseContext.cpp index 9f4e0b01e..9bcb049b4 100644 --- a/Source/WebCore/html/canvas/WebGLLoseContext.cpp +++ b/Source/WebCore/html/canvas/WebGLLoseContext.cpp @@ -29,11 +29,11 @@ #include "WebGLLoseContext.h" -#include "WebGLRenderingContext.h" +#include "WebGLRenderingContextBase.h" namespace WebCore { -WebGLLoseContext::WebGLLoseContext(WebGLRenderingContext* context) +WebGLLoseContext::WebGLLoseContext(WebGLRenderingContextBase& context) : WebGLExtension(context) { } @@ -47,19 +47,14 @@ WebGLExtension::ExtensionName WebGLLoseContext::getName() const return WebGLLoseContextName; } -OwnPtr<WebGLLoseContext> WebGLLoseContext::create(WebGLRenderingContext* context) -{ - return adoptPtr(new WebGLLoseContext(context)); -} - void WebGLLoseContext::loseContext() { - m_context->forceLostContext(WebGLRenderingContext::SyntheticLostContext); + m_context.forceLostContext(WebGLRenderingContextBase::SyntheticLostContext); } void WebGLLoseContext::restoreContext() { - m_context->forceRestoreContext(); + m_context.forceRestoreContext(); } } // namespace WebCore diff --git a/Source/WebCore/html/canvas/WebGLLoseContext.h b/Source/WebCore/html/canvas/WebGLLoseContext.h index edba14a7c..630d2645a 100644 --- a/Source/WebCore/html/canvas/WebGLLoseContext.h +++ b/Source/WebCore/html/canvas/WebGLLoseContext.h @@ -23,30 +23,23 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLLoseContext_h -#define WebGLLoseContext_h +#pragma once #include "WebGLExtension.h" -#include <wtf/PassOwnPtr.h> namespace WebCore { -class WebGLRenderingContext; +class WebGLRenderingContextBase; -class WebGLLoseContext : public WebGLExtension { +class WebGLLoseContext final : public WebGLExtension { public: - static OwnPtr<WebGLLoseContext> create(WebGLRenderingContext*); - + explicit WebGLLoseContext(WebGLRenderingContextBase&); virtual ~WebGLLoseContext(); - virtual ExtensionName getName() const override; + + ExtensionName getName() const override; void loseContext(); void restoreContext(); - -private: - WebGLLoseContext(WebGLRenderingContext*); }; } // namespace WebCore - -#endif // WebGLLoseContext_h diff --git a/Source/WebCore/html/canvas/WebGLLoseContext.idl b/Source/WebCore/html/canvas/WebGLLoseContext.idl index a56c0d147..8560d8681 100644 --- a/Source/WebCore/html/canvas/WebGLLoseContext.idl +++ b/Source/WebCore/html/canvas/WebGLLoseContext.idl @@ -28,6 +28,6 @@ Conditional=WEBGL, GenerateIsReachable=ImplWebGLRenderingContext, ] interface WebGLLoseContext { - [StrictTypeChecking] void loseContext(); - [StrictTypeChecking] void restoreContext(); + void loseContext(); + void restoreContext(); }; diff --git a/Source/WebCore/html/canvas/WebGLObject.cpp b/Source/WebCore/html/canvas/WebGLObject.cpp index 502877a0c..48f939e0d 100644 --- a/Source/WebCore/html/canvas/WebGLObject.cpp +++ b/Source/WebCore/html/canvas/WebGLObject.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,36 +24,23 @@ */ #include "config.h" +#include "WebGLObject.h" #if ENABLE(WEBGL) -#include "WebGLObject.h" - -#include "EXTTextureFilterAnisotropic.h" #include "WebGLCompressedTextureS3TC.h" #include "WebGLContextGroup.h" #include "WebGLDebugRendererInfo.h" #include "WebGLDebugShaders.h" #include "WebGLLoseContext.h" -#include "WebGLRenderingContext.h" +#include "WebGLRenderingContextBase.h" namespace WebCore { -WebGLObject::WebGLObject(WebGLRenderingContext*) - : m_object(0) - , m_attachmentCount(0) - , m_deleted(false) -{ -} - -WebGLObject::~WebGLObject() -{ -} - void WebGLObject::setObject(Platform3DObject object) { - // object==0 && m_deleted==false indicating an uninitialized state; - ASSERT(!m_object && !m_deleted); + ASSERT(!m_object); + ASSERT(!m_deleted); m_object = object; } @@ -80,8 +67,7 @@ void WebGLObject::deleteObject(GraphicsContext3D* context3d) void WebGLObject::detach() { m_attachmentCount = 0; // Make sure OpenGL resource is deleted. - } - +} void WebGLObject::onDetached(GraphicsContext3D* context3d) { diff --git a/Source/WebCore/html/canvas/WebGLObject.h b/Source/WebCore/html/canvas/WebGLObject.h index 61af64461..69dbb5aa0 100644 --- a/Source/WebCore/html/canvas/WebGLObject.h +++ b/Source/WebCore/html/canvas/WebGLObject.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,22 +23,18 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLObject_h -#define WebGLObject_h +#pragma once #include "GraphicsContext3D.h" -#include <wtf/RefCounted.h> - namespace WebCore { -class GraphicsContext3D; class WebGLContextGroup; -class WebGLRenderingContext; +class WebGLRenderingContextBase; class WebGLObject : public RefCounted<WebGLObject> { public: - virtual ~WebGLObject(); + virtual ~WebGLObject() { } Platform3DObject object() const { return m_object; } @@ -56,10 +52,10 @@ public: bool isDeleted() { return m_deleted; } // True if this object belongs to the group or context. - virtual bool validate(const WebGLContextGroup*, const WebGLRenderingContext*) const = 0; + virtual bool validate(const WebGLContextGroup*, const WebGLRenderingContextBase&) const = 0; protected: - WebGLObject(WebGLRenderingContext*); + WebGLObject() = default; // setObject should be only called once right after creating a WebGLObject. void setObject(Platform3DObject); @@ -74,11 +70,9 @@ protected: virtual GraphicsContext3D* getAGraphicsContext3D() const = 0; private: - Platform3DObject m_object; - unsigned m_attachmentCount; - bool m_deleted; + Platform3DObject m_object { 0 }; + unsigned m_attachmentCount { 0 }; + bool m_deleted { false }; }; } // namespace WebCore - -#endif // WebGLObject_h diff --git a/Source/WebCore/html/canvas/WebGLProgram.cpp b/Source/WebCore/html/canvas/WebGLProgram.cpp index 40d35949e..c24335dc4 100644 --- a/Source/WebCore/html/canvas/WebGLProgram.cpp +++ b/Source/WebCore/html/canvas/WebGLProgram.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,28 +24,25 @@ */ #include "config.h" +#include "WebGLProgram.h" #if ENABLE(WEBGL) -#include "WebGLProgram.h" - #include "WebGLContextGroup.h" -#include "WebGLRenderingContext.h" +#include "WebGLRenderingContextBase.h" +#include "WebGLShader.h" namespace WebCore { -PassRefPtr<WebGLProgram> WebGLProgram::create(WebGLRenderingContext* ctx) +Ref<WebGLProgram> WebGLProgram::create(WebGLRenderingContextBase& ctx) { - return adoptRef(new WebGLProgram(ctx)); + return adoptRef(*new WebGLProgram(ctx)); } -WebGLProgram::WebGLProgram(WebGLRenderingContext* ctx) +WebGLProgram::WebGLProgram(WebGLRenderingContextBase& ctx) : WebGLSharedObject(ctx) - , m_linkStatus(false) - , m_linkCount(0) - , m_infoValid(true) { - setObject(ctx->graphicsContext3D()->createProgram()); + setObject(ctx.graphicsContext3D()->createProgram()); } WebGLProgram::~WebGLProgram() @@ -58,11 +55,11 @@ void WebGLProgram::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObje context3d->deleteProgram(obj); if (m_vertexShader) { m_vertexShader->onDetached(context3d); - m_vertexShader = 0; + m_vertexShader = nullptr; } if (m_fragmentShader) { m_fragmentShader->onDetached(context3d); - m_fragmentShader = 0; + m_fragmentShader = nullptr; } } @@ -148,12 +145,12 @@ bool WebGLProgram::detachShader(WebGLShader* shader) case GraphicsContext3D::VERTEX_SHADER: if (m_vertexShader != shader) return false; - m_vertexShader = 0; + m_vertexShader = nullptr; return true; case GraphicsContext3D::FRAGMENT_SHADER: if (m_fragmentShader != shader) return false; - m_fragmentShader = 0; + m_fragmentShader = nullptr; return true; default: return false; @@ -169,7 +166,7 @@ void WebGLProgram::cacheActiveAttribLocations(GraphicsContext3D* context3d) m_activeAttribLocations.resize(static_cast<size_t>(numAttribs)); for (int i = 0; i < numAttribs; ++i) { ActiveInfo info; - context3d->getActiveAttrib(object(), i, info); + context3d->getActiveAttribImpl(object(), i, info); m_activeAttribLocations[i] = context3d->getAttribLocation(object(), info.name); } } diff --git a/Source/WebCore/html/canvas/WebGLProgram.h b/Source/WebCore/html/canvas/WebGLProgram.h index 718f18498..eab76c897 100644 --- a/Source/WebCore/html/canvas/WebGLProgram.h +++ b/Source/WebCore/html/canvas/WebGLProgram.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,24 +23,19 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLProgram_h -#define WebGLProgram_h +#pragma once #include "WebGLSharedObject.h" -#include "WebGLShader.h" - -#include <wtf/PassRefPtr.h> -#include <wtf/Vector.h> - namespace WebCore { -class WebGLProgram : public WebGLSharedObject { +class WebGLShader; + +class WebGLProgram final : public WebGLSharedObject { public: + static Ref<WebGLProgram> create(WebGLRenderingContextBase&); virtual ~WebGLProgram(); - static PassRefPtr<WebGLProgram> create(WebGLRenderingContext*); - unsigned numActiveAttribLocations(); GC3Dint getActiveAttribLocation(GC3Duint index); @@ -62,30 +57,25 @@ public: bool detachShader(WebGLShader*); protected: - WebGLProgram(WebGLRenderingContext*); + WebGLProgram(WebGLRenderingContextBase&); - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override; + void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override; private: - virtual bool isProgram() const override { return true; } - void cacheActiveAttribLocations(GraphicsContext3D*); void cacheInfoIfNeeded(); Vector<GC3Dint> m_activeAttribLocations; - GC3Dint m_linkStatus; + GC3Dint m_linkStatus { 0 }; - // This is used to track whether a WebGLUniformLocation belongs to this - // program or not. - unsigned m_linkCount; + // This is used to track whether a WebGLUniformLocation belongs to this program or not. + unsigned m_linkCount { 0 }; RefPtr<WebGLShader> m_vertexShader; RefPtr<WebGLShader> m_fragmentShader; - bool m_infoValid; + bool m_infoValid { true }; }; } // namespace WebCore - -#endif // WebGLProgram_h diff --git a/Source/WebCore/html/canvas/WebGLProgram.idl b/Source/WebCore/html/canvas/WebGLProgram.idl index d404ebdb8..7c180e2b5 100644 --- a/Source/WebCore/html/canvas/WebGLProgram.idl +++ b/Source/WebCore/html/canvas/WebGLProgram.idl @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR diff --git a/Source/WebCore/html/canvas/WebGLQuery.cpp b/Source/WebCore/html/canvas/WebGLQuery.cpp new file mode 100644 index 000000000..8ca525115 --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLQuery.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2015 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(WEBGL) +#include "WebGLQuery.h" + +#include "WebGLContextGroup.h" +#include "WebGLRenderingContextBase.h" + +namespace WebCore { + +Ref<WebGLQuery> WebGLQuery::create(WebGLRenderingContextBase& ctx) +{ + return adoptRef(*new WebGLQuery(ctx)); +} + +WebGLQuery::~WebGLQuery() +{ + deleteObject(0); +} + +WebGLQuery::WebGLQuery(WebGLRenderingContextBase& ctx) + : WebGLSharedObject(ctx) +{ + // FIXME: Call createQuery from GraphicsContext3D. +} + +void WebGLQuery::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object) +{ + UNUSED_PARAM(context3d); + UNUSED_PARAM(object); + // FIXME: Call deleteQuery from GraphicsContext3D. +} + +} + +#endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/WebGLQuery.h b/Source/WebCore/html/canvas/WebGLQuery.h new file mode 100644 index 000000000..3cb761777 --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLQuery.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2015-2017 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "WebGLSharedObject.h" + +namespace WebCore { + +class WebGLQuery final : public WebGLSharedObject { +public: + static Ref<WebGLQuery> create(WebGLRenderingContextBase&); + virtual ~WebGLQuery(); + +protected: + explicit WebGLQuery(WebGLRenderingContextBase&); + void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override; +}; + +} // namespace WebCore diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext.idl b/Source/WebCore/html/canvas/WebGLQuery.idl index 6a68509cc..23d353c46 100644 --- a/Source/WebCore/html/canvas/CanvasRenderingContext.idl +++ b/Source/WebCore/html/canvas/WebGLQuery.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,11 +24,6 @@ */ [ - NoInterfaceObject, - JSCustomMarkFunction, - GenerateIsReachable, - CustomToJSObject -] interface CanvasRenderingContext { - readonly attribute HTMLCanvasElement canvas; + Conditional=WEBGL +] interface WebGLQuery { }; - diff --git a/Source/WebCore/html/canvas/WebGLRenderbuffer.cpp b/Source/WebCore/html/canvas/WebGLRenderbuffer.cpp index daaf9d4ee..6996d9b1d 100644 --- a/Source/WebCore/html/canvas/WebGLRenderbuffer.cpp +++ b/Source/WebCore/html/canvas/WebGLRenderbuffer.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -30,13 +30,13 @@ #include "WebGLRenderbuffer.h" #include "WebGLContextGroup.h" -#include "WebGLRenderingContext.h" +#include "WebGLRenderingContextBase.h" namespace WebCore { -PassRefPtr<WebGLRenderbuffer> WebGLRenderbuffer::create(WebGLRenderingContext* ctx) +Ref<WebGLRenderbuffer> WebGLRenderbuffer::create(WebGLRenderingContextBase& ctx) { - return adoptRef(new WebGLRenderbuffer(ctx)); + return adoptRef(*new WebGLRenderbuffer(ctx)); } WebGLRenderbuffer::~WebGLRenderbuffer() @@ -44,7 +44,7 @@ WebGLRenderbuffer::~WebGLRenderbuffer() deleteObject(0); } -WebGLRenderbuffer::WebGLRenderbuffer(WebGLRenderingContext* ctx) +WebGLRenderbuffer::WebGLRenderbuffer(WebGLRenderingContextBase& ctx) : WebGLSharedObject(ctx) , m_internalFormat(GraphicsContext3D::RGBA4) , m_initialized(false) @@ -53,7 +53,7 @@ WebGLRenderbuffer::WebGLRenderbuffer(WebGLRenderingContext* ctx) , m_isValid(true) , m_hasEverBeenBound(false) { - setObject(ctx->graphicsContext3D()->createRenderbuffer()); + setObject(ctx.graphicsContext3D()->createRenderbuffer()); } void WebGLRenderbuffer::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object) diff --git a/Source/WebCore/html/canvas/WebGLRenderbuffer.h b/Source/WebCore/html/canvas/WebGLRenderbuffer.h index 137953195..cf6ad6f65 100644 --- a/Source/WebCore/html/canvas/WebGLRenderbuffer.h +++ b/Source/WebCore/html/canvas/WebGLRenderbuffer.h @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,21 +23,17 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLRenderbuffer_h -#define WebGLRenderbuffer_h +#pragma once #include "WebGLSharedObject.h" -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> - namespace WebCore { -class WebGLRenderbuffer : public WebGLSharedObject { +class WebGLRenderbuffer final : public WebGLSharedObject { public: virtual ~WebGLRenderbuffer(); - static PassRefPtr<WebGLRenderbuffer> create(WebGLRenderingContext*); + static Ref<WebGLRenderbuffer> create(WebGLRenderingContextBase&); void setInternalFormat(GC3Denum internalformat) { @@ -65,12 +61,12 @@ public: void setHasEverBeenBound() { m_hasEverBeenBound = true; } protected: - WebGLRenderbuffer(WebGLRenderingContext*); + WebGLRenderbuffer(WebGLRenderingContextBase&); - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override; + void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override; private: - virtual bool isRenderbuffer() const override { return true; } + bool isRenderbuffer() const override { return true; } GC3Denum m_internalFormat; bool m_initialized; @@ -81,5 +77,3 @@ private: }; } // namespace WebCore - -#endif // WebGLRenderbuffer_h diff --git a/Source/WebCore/html/canvas/WebGLRenderbuffer.idl b/Source/WebCore/html/canvas/WebGLRenderbuffer.idl index 618f9c472..fb855a56c 100644 --- a/Source/WebCore/html/canvas/WebGLRenderbuffer.idl +++ b/Source/WebCore/html/canvas/WebGLRenderbuffer.idl @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR diff --git a/Source/WebCore/html/canvas/WebGLRenderingContext.cpp b/Source/WebCore/html/canvas/WebGLRenderingContext.cpp index 840cee14e..b56d81f83 100644 --- a/Source/WebCore/html/canvas/WebGLRenderingContext.cpp +++ b/Source/WebCore/html/canvas/WebGLRenderingContext.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2013, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2015-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,30 +24,22 @@ */ #include "config.h" +#include "WebGLRenderingContext.h" #if ENABLE(WEBGL) -#include "WebGLRenderingContext.h" - #include "ANGLEInstancedArrays.h" #include "CachedImage.h" -#include "DOMWindow.h" -#include "EXTDrawBuffers.h" +#include "EXTBlendMinMax.h" +#include "EXTFragDepth.h" +#include "EXTShaderTextureLOD.h" #include "EXTTextureFilterAnisotropic.h" -#include "ExceptionCode.h" +#include "EXTsRGB.h" #include "Extensions3D.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "FrameLoaderClient.h" -#include "FrameView.h" #include "HTMLCanvasElement.h" #include "HTMLImageElement.h" #include "HTMLVideoElement.h" -#include "ImageBuffer.h" #include "ImageData.h" -#include "IntSize.h" -#include "Logging.h" -#include "NotImplemented.h" #include "OESElementIndexUint.h" #include "OESStandardDerivatives.h" #include "OESTextureFloat.h" @@ -55,2572 +47,437 @@ #include "OESTextureHalfFloat.h" #include "OESTextureHalfFloatLinear.h" #include "OESVertexArrayObject.h" -#include "Page.h" #include "RenderBox.h" -#include "Settings.h" -#include "WebGLActiveInfo.h" -#include "WebGLBuffer.h" #include "WebGLCompressedTextureATC.h" #include "WebGLCompressedTexturePVRTC.h" #include "WebGLCompressedTextureS3TC.h" -#include "WebGLContextAttributes.h" -#include "WebGLContextEvent.h" -#include "WebGLContextGroup.h" #include "WebGLDebugRendererInfo.h" #include "WebGLDebugShaders.h" #include "WebGLDepthTexture.h" -#include "WebGLFramebuffer.h" +#include "WebGLDrawBuffers.h" #include "WebGLLoseContext.h" -#include "WebGLProgram.h" -#include "WebGLRenderbuffer.h" -#include "WebGLShader.h" -#include "WebGLShaderPrecisionFormat.h" -#include "WebGLTexture.h" -#include "WebGLUniformLocation.h" - -#include <runtime/Operations.h> -#include <runtime/TypedArrayInlines.h> -#include <runtime/Uint32Array.h> -#include <wtf/StdLibExtras.h> -#include <wtf/text/CString.h> -#include <wtf/text/StringBuilder.h> - -#if PLATFORM(WIN) || (PLATFORM(GTK) && OS(WINDOWS)) -#undef NO_ERROR -#endif - -#if PLATFORM(GTK) -#undef VERSION -#endif +#include "WebGLVertexArrayObjectOES.h" +#include <JavaScriptCore/GenericTypedArrayViewInlines.h> +#include <JavaScriptCore/JSCJSValueInlines.h> +#include <JavaScriptCore/JSCellInlines.h> +#include <JavaScriptCore/JSGenericTypedArrayViewInlines.h> +#include <heap/HeapInlines.h> namespace WebCore { -const double secondsBetweenRestoreAttempts = 1.0; -const int maxGLErrorsAllowedToConsole = 256; - -namespace { - - class ScopedDrawingBufferBinder { - public: - ScopedDrawingBufferBinder(DrawingBuffer* drawingBuffer, WebGLFramebuffer* framebufferBinding) - : m_drawingBuffer(drawingBuffer) - , m_framebufferBinding(framebufferBinding) - { - // Commit DrawingBuffer if needed (e.g., for multisampling) - if (!m_framebufferBinding && m_drawingBuffer) - m_drawingBuffer->commit(); - } - - ~ScopedDrawingBufferBinder() - { - // Restore DrawingBuffer if needed - if (!m_framebufferBinding && m_drawingBuffer) - m_drawingBuffer->bind(); - } - - private: - DrawingBuffer* m_drawingBuffer; - WebGLFramebuffer* m_framebufferBinding; - }; - - Platform3DObject objectOrZero(WebGLObject* object) - { - return object ? object->object() : 0; - } - - void clip1D(GC3Dint start, GC3Dsizei range, GC3Dsizei sourceRange, GC3Dint* clippedStart, GC3Dsizei* clippedRange) - { - ASSERT(clippedStart && clippedRange); - if (start < 0) { - range += start; - start = 0; - } - GC3Dint end = start + range; - if (end > sourceRange) - range -= end - sourceRange; - *clippedStart = start; - *clippedRange = range; - } - - // Returns false if no clipping is necessary, i.e., x, y, width, height stay the same. - bool clip2D(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, - GC3Dsizei sourceWidth, GC3Dsizei sourceHeight, - GC3Dint* clippedX, GC3Dint* clippedY, GC3Dsizei* clippedWidth, GC3Dsizei*clippedHeight) - { - ASSERT(clippedX && clippedY && clippedWidth && clippedHeight); - clip1D(x, width, sourceWidth, clippedX, clippedWidth); - clip1D(y, height, sourceHeight, clippedY, clippedHeight); - return (*clippedX != x || *clippedY != y || *clippedWidth != width || *clippedHeight != height); - } - - GC3Dint clamp(GC3Dint value, GC3Dint min, GC3Dint max) - { - if (value < min) - value = min; - if (value > max) - value = max; - return value; - } - - // Return true if a character belongs to the ASCII subset as defined in - // GLSL ES 1.0 spec section 3.1. - bool validateCharacter(unsigned char c) - { - // Printing characters are valid except " $ ` @ \ ' DEL. - if (c >= 32 && c <= 126 - && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' && c != '\'') - return true; - // Horizontal tab, line feed, vertical tab, form feed, carriage return - // are also valid. - if (c >= 9 && c <= 13) - return true; - return false; - } - - bool isPrefixReserved(const String& name) - { - if (name.startsWith("gl_") || name.startsWith("webgl_") || name.startsWith("_webgl_")) - return true; - return false; - } - - // Strips comments from shader text. This allows non-ASCII characters - // to be used in comments without potentially breaking OpenGL - // implementations not expecting characters outside the GLSL ES set. - class StripComments { - public: - StripComments(const String& str) - : m_parseState(BeginningOfLine) - , m_sourceString(str) - , m_length(str.length()) - , m_position(0) - { - parse(); - } - - String result() - { - return m_builder.toString(); - } - - private: - bool hasMoreCharacters() const - { - return (m_position < m_length); - } - - void parse() - { - while (hasMoreCharacters()) { - process(current()); - // process() might advance the position. - if (hasMoreCharacters()) - advance(); - } - } - - void process(UChar); - - bool peek(UChar& character) const - { - if (m_position + 1 >= m_length) - return false; - character = m_sourceString[m_position + 1]; - return true; - } - - UChar current() const - { - ASSERT_WITH_SECURITY_IMPLICATION(m_position < m_length); - return m_sourceString[m_position]; - } - - void advance() - { - ++m_position; - } - - bool isNewline(UChar character) const - { - // Don't attempt to canonicalize newline related characters. - return (character == '\n' || character == '\r'); - } - - void emit(UChar character) - { - m_builder.append(character); - } - - enum ParseState { - // Have not seen an ASCII non-whitespace character yet on - // this line. Possible that we might see a preprocessor - // directive. - BeginningOfLine, - - // Have seen at least one ASCII non-whitespace character - // on this line. - MiddleOfLine, - - // Handling a preprocessor directive. Passes through all - // characters up to the end of the line. Disables comment - // processing. - InPreprocessorDirective, - - // Handling a single-line comment. The comment text is - // replaced with a single space. - InSingleLineComment, - - // Handling a multi-line comment. Newlines are passed - // through to preserve line numbers. - InMultiLineComment - }; - - ParseState m_parseState; - String m_sourceString; - unsigned m_length; - unsigned m_position; - StringBuilder m_builder; - }; - - void StripComments::process(UChar c) - { - if (isNewline(c)) { - // No matter what state we are in, pass through newlines - // so we preserve line numbers. - emit(c); - - if (m_parseState != InMultiLineComment) - m_parseState = BeginningOfLine; - - return; - } - - UChar temp = 0; - switch (m_parseState) { - case BeginningOfLine: - if (WTF::isASCIISpace(c)) { - emit(c); - break; - } - - if (c == '#') { - m_parseState = InPreprocessorDirective; - emit(c); - break; - } - - // Transition to normal state and re-handle character. - m_parseState = MiddleOfLine; - process(c); - break; - - case MiddleOfLine: - if (c == '/' && peek(temp)) { - if (temp == '/') { - m_parseState = InSingleLineComment; - emit(' '); - advance(); - break; - } - - if (temp == '*') { - m_parseState = InMultiLineComment; - // Emit the comment start in case the user has - // an unclosed comment and we want to later - // signal an error. - emit('/'); - emit('*'); - advance(); - break; - } - } - - emit(c); - break; - - case InPreprocessorDirective: - // No matter what the character is, just pass it - // through. Do not parse comments in this state. This - // might not be the right thing to do long term, but it - // should handle the #error preprocessor directive. - emit(c); - break; - - case InSingleLineComment: - // The newline code at the top of this function takes care - // of resetting our state when we get out of the - // single-line comment. Swallow all other characters. - break; - - case InMultiLineComment: - if (c == '*' && peek(temp) && temp == '/') { - emit('*'); - emit('/'); - m_parseState = MiddleOfLine; - advance(); - break; - } - - // Swallow all other characters. Unclear whether we may - // want or need to just emit a space per character to try - // to preserve column numbers for debugging purposes. - break; - } - } -} // namespace anonymous - -class WebGLStateRestorer { -public: - WebGLStateRestorer(WebGLRenderingContext* context, - bool changed) - : m_context(context) - , m_changed(changed) - { - } - - ~WebGLStateRestorer() - { - m_context->cleanupAfterGraphicsCall(m_changed); - } - -private: - WebGLRenderingContext* m_context; - bool m_changed; -}; - -class WebGLRenderingContextLostCallback : public GraphicsContext3D::ContextLostCallback { - WTF_MAKE_FAST_ALLOCATED; -public: - explicit WebGLRenderingContextLostCallback(WebGLRenderingContext* cb) : m_context(cb) { } - virtual void onContextLost() override { m_context->forceLostContext(WebGLRenderingContext::RealLostContext); } - virtual ~WebGLRenderingContextLostCallback() {} -private: - WebGLRenderingContext* m_context; -}; - -class WebGLRenderingContextErrorMessageCallback : public GraphicsContext3D::ErrorMessageCallback { - WTF_MAKE_FAST_ALLOCATED; -public: - explicit WebGLRenderingContextErrorMessageCallback(WebGLRenderingContext* cb) : m_context(cb) { } - virtual void onErrorMessage(const String& message, GC3Dint) override - { - if (m_context->m_synthesizedErrorsToConsole) - m_context->printGLErrorToConsole(message); - } - virtual ~WebGLRenderingContextErrorMessageCallback() { } -private: - WebGLRenderingContext* m_context; -}; - -OwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElement* canvas, WebGLContextAttributes* attrs) +WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement& passedCanvas, GraphicsContext3DAttributes attributes) + : WebGLRenderingContextBase(passedCanvas, attributes) { - Document& document = canvas->document(); - Frame* frame = document.frame(); - if (!frame) - return nullptr; - - // The FrameLoaderClient might creation of a new WebGL context despite the page settings; in - // particular, if WebGL contexts were lost one or more times via the GL_ARB_robustness extension. - if (!frame->loader().client().allowWebGL(frame->settings().webGLEnabled())) { - canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextcreationerrorEvent, false, true, "Web page was not allowed to create a WebGL context.")); - return nullptr; - } - - HostWindow* hostWindow = document.view()->root()->hostWindow(); - GraphicsContext3D::Attributes attributes = attrs ? attrs->attributes() : GraphicsContext3D::Attributes(); - - if (attributes.antialias) { - if (!frame->settings().openGLMultisamplingEnabled()) - attributes.antialias = false; - } - - attributes.noExtensions = true; - attributes.shareResources = false; - attributes.preferDiscreteGPU = true; - - if (frame->settings().multithreadedWebGLEnabled()) - attributes.multithreaded = true; - - if (frame->settings().forceSoftwareWebGLRendering()) - attributes.forceSoftwareRenderer = true; - - RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(attributes, hostWindow)); - - if (!context || !context->makeContextCurrent()) { - canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextcreationerrorEvent, false, true, "Could not create a WebGL context.")); - return nullptr; - } - - Extensions3D* extensions = context->getExtensions(); - if (extensions->supports("GL_EXT_debug_marker")) - extensions->pushGroupMarkerEXT("WebGLRenderingContext"); - - OwnPtr<WebGLRenderingContext> renderingContext = adoptPtr(new WebGLRenderingContext(canvas, context, attributes)); - renderingContext->suspendIfNeeded(); - - return renderingContext.release(); } -WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassRefPtr<GraphicsContext3D> context, - GraphicsContext3D::Attributes attributes) - : CanvasRenderingContext(passedCanvas) - , ActiveDOMObject(&passedCanvas->document()) - , m_context(context) - , m_drawingBuffer(0) - , m_dispatchContextLostEventTimer(this, &WebGLRenderingContext::dispatchContextLostEvent) - , m_restoreAllowed(false) - , m_restoreTimer(this, &WebGLRenderingContext::maybeRestoreContext) - , m_generatedImageCache(4) - , m_contextLost(false) - , m_contextLostMode(SyntheticLostContext) - , m_attributes(attributes) - , m_synthesizedErrorsToConsole(true) - , m_numGLErrorsToConsoleAllowed(maxGLErrorsAllowedToConsole) +WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement& passedCanvas, Ref<GraphicsContext3D>&& context, GraphicsContext3DAttributes attributes) + : WebGLRenderingContextBase(passedCanvas, WTFMove(context), attributes) { - ASSERT(m_context); - m_contextGroup = WebGLContextGroup::create(); - m_contextGroup->addContext(this); - - m_maxViewportDims[0] = m_maxViewportDims[1] = 0; - m_context->getIntegerv(GraphicsContext3D::MAX_VIEWPORT_DIMS, m_maxViewportDims); - - if (m_drawingBuffer) - m_drawingBuffer->bind(); - - setupFlags(); - initializeNewContext(); + initializeVertexArrayObjects(); } -void WebGLRenderingContext::initializeNewContext() +void WebGLRenderingContext::initializeVertexArrayObjects() { - ASSERT(!m_contextLost); - m_needsUpdate = true; - m_markedCanvasDirty = false; - m_activeTextureUnit = 0; - m_packAlignment = 4; - m_unpackAlignment = 4; - m_unpackFlipY = false; - m_unpackPremultiplyAlpha = false; - m_unpackColorspaceConversion = GraphicsContext3D::BROWSER_DEFAULT_WEBGL; - m_boundArrayBuffer = 0; - m_currentProgram = 0; - m_framebufferBinding = 0; - m_renderbufferBinding = 0; - m_depthMask = true; - m_stencilEnabled = false; - m_stencilMask = 0xFFFFFFFF; - m_stencilMaskBack = 0xFFFFFFFF; - m_stencilFuncRef = 0; - m_stencilFuncRefBack = 0; - m_stencilFuncMask = 0xFFFFFFFF; - m_stencilFuncMaskBack = 0xFFFFFFFF; - m_layerCleared = false; - m_numGLErrorsToConsoleAllowed = maxGLErrorsAllowedToConsole; - - m_clearColor[0] = m_clearColor[1] = m_clearColor[2] = m_clearColor[3] = 0; - m_scissorEnabled = false; - m_clearDepth = 1; - m_clearStencil = 0; - m_colorMask[0] = m_colorMask[1] = m_colorMask[2] = m_colorMask[3] = true; - - GC3Dint numCombinedTextureImageUnits = 0; - m_context->getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numCombinedTextureImageUnits); - m_textureUnits.clear(); - m_textureUnits.resize(numCombinedTextureImageUnits); - - GC3Dint numVertexAttribs = 0; - m_context->getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &numVertexAttribs); - m_maxVertexAttribs = numVertexAttribs; - - m_maxTextureSize = 0; - m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize); - m_maxTextureLevel = WebGLTexture::computeLevelCount(m_maxTextureSize, m_maxTextureSize); - m_maxCubeMapTextureSize = 0; - m_context->getIntegerv(GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE, &m_maxCubeMapTextureSize); - m_maxCubeMapTextureLevel = WebGLTexture::computeLevelCount(m_maxCubeMapTextureSize, m_maxCubeMapTextureSize); - m_maxRenderbufferSize = 0; - m_context->getIntegerv(GraphicsContext3D::MAX_RENDERBUFFER_SIZE, &m_maxRenderbufferSize); - - // These two values from EXT_draw_buffers are lazily queried. - m_maxDrawBuffers = 0; - m_maxColorAttachments = 0; - - m_backDrawBuffer = GraphicsContext3D::BACK; - m_drawBuffersWebGLRequirementsChecked = false; - m_drawBuffersSupported = false; - - m_defaultVertexArrayObject = WebGLVertexArrayObjectOES::create(this, WebGLVertexArrayObjectOES::VaoTypeDefault); - addContextObject(m_defaultVertexArrayObject.get()); + m_defaultVertexArrayObject = WebGLVertexArrayObjectOES::create(*this, WebGLVertexArrayObjectOES::Type::Default); + addContextObject(*m_defaultVertexArrayObject); m_boundVertexArrayObject = m_defaultVertexArrayObject; - - m_vertexAttribValue.resize(m_maxVertexAttribs); - - if (!isGLES2NPOTStrict()) - createFallbackBlackTextures1x1(); if (!isGLES2Compliant()) initVertexAttrib0(); - - IntSize canvasSize = clampedCanvasSize(); - if (m_drawingBuffer) - m_drawingBuffer->reset(canvasSize); - - m_context->reshape(canvasSize.width(), canvasSize.height()); - m_context->viewport(0, 0, canvasSize.width(), canvasSize.height()); - m_context->scissor(0, 0, canvasSize.width(), canvasSize.height()); - - m_context->setContextLostCallback(adoptPtr(new WebGLRenderingContextLostCallback(this))); - m_context->setErrorMessageCallback(adoptPtr(new WebGLRenderingContextErrorMessageCallback(this))); -} - -void WebGLRenderingContext::setupFlags() -{ - ASSERT(m_context); - - if (Page* page = canvas()->document().page()) - m_synthesizedErrorsToConsole = page->settings().webGLErrorsToConsoleEnabled(); - - m_isGLES2Compliant = m_context->isGLES2Compliant(); - m_isErrorGeneratedOnOutOfBoundsAccesses = m_context->getExtensions()->isEnabled("GL_CHROMIUM_strict_attribs"); - m_isResourceSafe = m_context->getExtensions()->isEnabled("GL_CHROMIUM_resource_safe"); - if (m_isGLES2Compliant) { - m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_OES_texture_npot"); - m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_OES_packed_depth_stencil"); - } else { - m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_ARB_texture_non_power_of_two"); - m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_EXT_packed_depth_stencil"); - } - m_isRobustnessEXTSupported = m_context->getExtensions()->isEnabled("GL_EXT_robustness"); -} - -bool WebGLRenderingContext::allowPrivilegedExtensions() const -{ - if (Page* page = canvas()->document().page()) - return page->settings().privilegedWebGLExtensionsEnabled(); - return false; -} - -void WebGLRenderingContext::addCompressedTextureFormat(GC3Denum format) -{ - if (!m_compressedTextureFormats.contains(format)) - m_compressedTextureFormats.append(format); -} - -WebGLRenderingContext::~WebGLRenderingContext() -{ - // Remove all references to WebGLObjects so if they are the last reference - // they will be freed before the last context is removed from the context group. - m_boundArrayBuffer = nullptr; - m_defaultVertexArrayObject = nullptr; - m_boundVertexArrayObject = nullptr; - m_vertexAttrib0Buffer = nullptr; - m_currentProgram = nullptr; - m_framebufferBinding = nullptr; - m_renderbufferBinding = nullptr; - - for (size_t i = 0; i < m_textureUnits.size(); ++i) { - m_textureUnits[i].texture2DBinding = nullptr; - m_textureUnits[i].textureCubeMapBinding = nullptr; - } - - m_blackTexture2D = nullptr; - m_blackTextureCubeMap = nullptr; - - detachAndRemoveAllObjects(); - destroyGraphicsContext3D(); - m_contextGroup->removeContext(this); -} - -void WebGLRenderingContext::destroyGraphicsContext3D() -{ - // The drawing buffer holds a context reference. It must also be destroyed - // in order for the context to be released. - if (m_drawingBuffer) - m_drawingBuffer.clear(); - - if (m_context) { - m_context->setContextLostCallback(nullptr); - m_context->setErrorMessageCallback(nullptr); - m_context.clear(); - } -} - -void WebGLRenderingContext::markContextChanged() -{ - if (m_framebufferBinding) - return; - - m_context->markContextChanged(); - - if (m_drawingBuffer) - m_drawingBuffer->markContentsChanged(); - - m_layerCleared = false; -#if USE(ACCELERATED_COMPOSITING) - RenderBox* renderBox = canvas()->renderBox(); - if (renderBox && renderBox->hasAcceleratedCompositing()) { - m_markedCanvasDirty = true; - canvas()->clearCopiedImage(); - renderBox->contentChanged(CanvasChanged); - } else { -#endif - if (!m_markedCanvasDirty) { - m_markedCanvasDirty = true; - canvas()->didDraw(FloatRect(FloatPoint(0, 0), clampedCanvasSize())); - } -#if USE(ACCELERATED_COMPOSITING) - } -#endif -} - -bool WebGLRenderingContext::clearIfComposited(GC3Dbitfield mask) -{ - if (isContextLost()) - return false; - - if (!m_context->layerComposited() || m_layerCleared - || m_attributes.preserveDrawingBuffer || (mask && m_framebufferBinding)) - return false; - - RefPtr<WebGLContextAttributes> contextAttributes = getContextAttributes(); - - // Determine if it's possible to combine the clear the user asked for and this clear. - bool combinedClear = mask && !m_scissorEnabled; - - m_context->disable(GraphicsContext3D::SCISSOR_TEST); - if (combinedClear && (mask & GraphicsContext3D::COLOR_BUFFER_BIT)) - m_context->clearColor(m_colorMask[0] ? m_clearColor[0] : 0, - m_colorMask[1] ? m_clearColor[1] : 0, - m_colorMask[2] ? m_clearColor[2] : 0, - m_colorMask[3] ? m_clearColor[3] : 0); - else - m_context->clearColor(0, 0, 0, 0); - m_context->colorMask(true, true, true, true); - GC3Dbitfield clearMask = GraphicsContext3D::COLOR_BUFFER_BIT; - if (contextAttributes->depth()) { - if (!combinedClear || !m_depthMask || !(mask & GraphicsContext3D::DEPTH_BUFFER_BIT)) - m_context->clearDepth(1.0f); - clearMask |= GraphicsContext3D::DEPTH_BUFFER_BIT; - m_context->depthMask(true); - } - if (contextAttributes->stencil()) { - if (combinedClear && (mask & GraphicsContext3D::STENCIL_BUFFER_BIT)) - m_context->clearStencil(m_clearStencil & m_stencilMask); - else - m_context->clearStencil(0); - clearMask |= GraphicsContext3D::STENCIL_BUFFER_BIT; - m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, 0xFFFFFFFF); - } - if (m_drawingBuffer) - m_drawingBuffer->clearFramebuffers(clearMask); - else { - if (m_framebufferBinding) - m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0); - m_context->clear(clearMask); - } - - restoreStateAfterClear(); - if (m_framebufferBinding) - m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get())); - m_layerCleared = true; - - return combinedClear; -} - -void WebGLRenderingContext::restoreStateAfterClear() -{ - // Restore the state that the context set. - if (m_scissorEnabled) - m_context->enable(GraphicsContext3D::SCISSOR_TEST); - m_context->clearColor(m_clearColor[0], m_clearColor[1], - m_clearColor[2], m_clearColor[3]); - m_context->colorMask(m_colorMask[0], m_colorMask[1], - m_colorMask[2], m_colorMask[3]); - m_context->clearDepth(m_clearDepth); - m_context->clearStencil(m_clearStencil); - m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, m_stencilMask); - m_context->depthMask(m_depthMask); -} - -void WebGLRenderingContext::markLayerComposited() -{ - m_context->markLayerComposited(); -} - -void WebGLRenderingContext::paintRenderingResultsToCanvas() -{ - if (canvas()->document().printing()) - canvas()->clearPresentationCopy(); - - // Until the canvas is written to by the application, the clear that - // happened after it was composited should be ignored by the compositor. - if (m_context->layerComposited() && !m_attributes.preserveDrawingBuffer) { - m_context->paintCompositedResultsToCanvas(canvas()->buffer()); - - canvas()->makePresentationCopy(); - } else - canvas()->clearPresentationCopy(); - clearIfComposited(); - - if (!m_markedCanvasDirty && !m_layerCleared) - return; - - canvas()->clearCopiedImage(); - m_markedCanvasDirty = false; - - if (m_drawingBuffer) - m_drawingBuffer->commit(); - m_context->paintRenderingResultsToCanvas(canvas()->buffer(), m_drawingBuffer.get()); - - if (m_drawingBuffer) { - if (m_framebufferBinding) - m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get())); - else - m_drawingBuffer->bind(); - } -} - -PassRefPtr<ImageData> WebGLRenderingContext::paintRenderingResultsToImageData() -{ - clearIfComposited(); - if (m_drawingBuffer) - m_drawingBuffer->commit(); - RefPtr<ImageData> imageData = m_context->paintRenderingResultsToImageData(m_drawingBuffer.get()); - - if (m_drawingBuffer) { - if (m_framebufferBinding) - m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get())); - else - m_drawingBuffer->bind(); - } - - return imageData; -} - -void WebGLRenderingContext::reshape(int width, int height) -{ - // This is an approximation because at WebGLRenderingContext level we don't - // know if the underlying FBO uses textures or renderbuffers. - GC3Dint maxSize = std::min(m_maxTextureSize, m_maxRenderbufferSize); - // Limit drawing buffer size to 4k to avoid memory exhaustion. - const int sizeUpperLimit = 4096; - maxSize = std::min(maxSize, sizeUpperLimit); - GC3Dint maxWidth = std::min(maxSize, m_maxViewportDims[0]); - GC3Dint maxHeight = std::min(maxSize, m_maxViewportDims[1]); - width = clamp(width, 1, maxWidth); - height = clamp(height, 1, maxHeight); - - if (m_needsUpdate) { -#if USE(ACCELERATED_COMPOSITING) - RenderBox* renderBox = canvas()->renderBox(); - if (renderBox && renderBox->hasAcceleratedCompositing()) - renderBox->contentChanged(CanvasChanged); -#endif - m_needsUpdate = false; - } - - // We don't have to mark the canvas as dirty, since the newly created image buffer will also start off - // clear (and this matches what reshape will do). - if (m_drawingBuffer) { - m_drawingBuffer->reset(IntSize(width, height)); - restoreStateAfterClear(); - } else - m_context->reshape(width, height); - - m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZero(m_textureUnits[m_activeTextureUnit].texture2DBinding.get())); - m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, objectOrZero(m_renderbufferBinding.get())); - if (m_framebufferBinding) - m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get())); -} - -int WebGLRenderingContext::drawingBufferWidth() const -{ - if (m_drawingBuffer) - return m_drawingBuffer->size().width(); - - return m_context->getInternalFramebufferSize().width(); -} - -int WebGLRenderingContext::drawingBufferHeight() const -{ - if (m_drawingBuffer) - return m_drawingBuffer->size().height(); - - return m_context->getInternalFramebufferSize().height(); -} - -unsigned int WebGLRenderingContext::sizeInBytes(GC3Denum type) -{ - switch (type) { - case GraphicsContext3D::BYTE: - return sizeof(GC3Dbyte); - case GraphicsContext3D::UNSIGNED_BYTE: - return sizeof(GC3Dubyte); - case GraphicsContext3D::SHORT: - return sizeof(GC3Dshort); - case GraphicsContext3D::UNSIGNED_SHORT: - return sizeof(GC3Dushort); - case GraphicsContext3D::INT: - return sizeof(GC3Dint); - case GraphicsContext3D::UNSIGNED_INT: - return sizeof(GC3Duint); - case GraphicsContext3D::FLOAT: - return sizeof(GC3Dfloat); - } - ASSERT_NOT_REACHED(); - return 0; -} - -void WebGLRenderingContext::activeTexture(GC3Denum texture, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost()) - return; - if (texture - GraphicsContext3D::TEXTURE0 >= m_textureUnits.size()) { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "activeTexture", "texture unit out of range"); - return; - } - m_activeTextureUnit = texture - GraphicsContext3D::TEXTURE0; - m_context->activeTexture(texture); - - if (m_drawingBuffer) - m_drawingBuffer->setActiveTextureUnit(texture); - - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::attachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateWebGLObject("attachShader", program) || !validateWebGLObject("attachShader", shader)) - return; - if (!program->attachShader(shader)) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "attachShader", "shader attachment already has shader"); - return; - } - m_context->attachShader(objectOrZero(program), objectOrZero(shader)); - shader->onAttached(); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::bindAttribLocation(WebGLProgram* program, GC3Duint index, const String& name, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateWebGLObject("bindAttribLocation", program)) - return; - if (!validateLocationLength("bindAttribLocation", name)) - return; - if (!validateString("bindAttribLocation", name)) - return; - if (isPrefixReserved(name)) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindAttribLocation", "reserved prefix"); - return; - } - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bindAttribLocation", "index out of range"); - return; - } - m_context->bindAttribLocation(objectOrZero(program), index, name); - cleanupAfterGraphicsCall(false); -} - -bool WebGLRenderingContext::checkObjectToBeBound(const char* functionName, WebGLObject* object, bool& deleted) -{ - deleted = false; - if (isContextLost()) - return false; - if (object) { - if (!object->validate(contextGroup(), this)) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "object not from this context"); - return false; - } - deleted = !object->object(); - } - return true; -} - -void WebGLRenderingContext::bindBuffer(GC3Denum target, WebGLBuffer* buffer, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - bool deleted; - if (!checkObjectToBeBound("bindBuffer", buffer, deleted)) - return; - if (deleted) - buffer = 0; - if (buffer && buffer->getTarget() && buffer->getTarget() != target) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindBuffer", "buffers can not be used with multiple targets"); - return; - } - if (target == GraphicsContext3D::ARRAY_BUFFER) - m_boundArrayBuffer = buffer; - else if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER) - m_boundVertexArrayObject->setElementArrayBuffer(buffer); - else { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindBuffer", "invalid target"); - return; - } - - m_context->bindBuffer(target, objectOrZero(buffer)); - if (buffer) - buffer->setTarget(target); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::bindFramebuffer(GC3Denum target, WebGLFramebuffer* buffer, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - bool deleted; - if (!checkObjectToBeBound("bindFramebuffer", buffer, deleted)) - return; - if (deleted) - buffer = 0; - if (target != GraphicsContext3D::FRAMEBUFFER) { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindFramebuffer", "invalid target"); - return; - } - m_framebufferBinding = buffer; - if (m_drawingBuffer) - m_drawingBuffer->setFramebufferBinding(objectOrZero(m_framebufferBinding.get())); - if (!m_framebufferBinding && m_drawingBuffer) { - // Instead of binding fb 0, bind the drawing buffer. - m_drawingBuffer->bind(); - } else - m_context->bindFramebuffer(target, objectOrZero(buffer)); - if (buffer) - buffer->setHasEverBeenBound(); - applyStencilTest(); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::bindRenderbuffer(GC3Denum target, WebGLRenderbuffer* renderBuffer, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - bool deleted; - if (!checkObjectToBeBound("bindRenderbuffer", renderBuffer, deleted)) - return; - if (deleted) - renderBuffer = 0; - if (target != GraphicsContext3D::RENDERBUFFER) { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindRenderbuffer", "invalid target"); - return; - } - m_renderbufferBinding = renderBuffer; - m_context->bindRenderbuffer(target, objectOrZero(renderBuffer)); - if (renderBuffer) - renderBuffer->setHasEverBeenBound(); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::bindTexture(GC3Denum target, WebGLTexture* texture, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - bool deleted; - if (!checkObjectToBeBound("bindTexture", texture, deleted)) - return; - if (deleted) - texture = 0; - if (texture && texture->getTarget() && texture->getTarget() != target) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindTexture", "textures can not be used with multiple targets"); - return; - } - GC3Dint maxLevel = 0; - if (target == GraphicsContext3D::TEXTURE_2D) { - m_textureUnits[m_activeTextureUnit].texture2DBinding = texture; - maxLevel = m_maxTextureLevel; - - if (m_drawingBuffer && !m_activeTextureUnit) - m_drawingBuffer->setTexture2DBinding(objectOrZero(texture)); - - } else if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) { - m_textureUnits[m_activeTextureUnit].textureCubeMapBinding = texture; - maxLevel = m_maxCubeMapTextureLevel; - } else { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindTexture", "invalid target"); - return; - } - m_context->bindTexture(target, objectOrZero(texture)); - if (texture) - texture->setTarget(target, maxLevel); - - // Note: previously we used to automatically set the TEXTURE_WRAP_R - // repeat mode to CLAMP_TO_EDGE for cube map textures, because OpenGL - // ES 2.0 doesn't expose this flag (a bug in the specification) and - // otherwise the application has no control over the seams in this - // dimension. However, it appears that supporting this properly on all - // platforms is fairly involved (will require a HashMap from texture ID - // in all ports), and we have not had any complaints, so the logic has - // been removed. - - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha) -{ - if (isContextLost()) - return; - m_context->blendColor(red, green, blue, alpha); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::blendEquation(GC3Denum mode) -{ - if (isContextLost() || !validateBlendEquation("blendEquation", mode)) - return; - m_context->blendEquation(mode); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha) -{ - if (isContextLost() || !validateBlendEquation("blendEquation", modeRGB) || !validateBlendEquation("blendEquation", modeAlpha)) - return; - m_context->blendEquationSeparate(modeRGB, modeAlpha); - cleanupAfterGraphicsCall(false); -} - - -void WebGLRenderingContext::blendFunc(GC3Denum sfactor, GC3Denum dfactor) -{ - if (isContextLost() || !validateBlendFuncFactors("blendFunc", sfactor, dfactor)) - return; - m_context->blendFunc(sfactor, dfactor); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha) -{ - // Note: Alpha does not have the same restrictions as RGB. - if (isContextLost() || !validateBlendFuncFactors("blendFunc", srcRGB, dstRGB)) - return; - m_context->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::bufferData(GC3Denum target, long long size, GC3Denum usage, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost()) - return; - WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage); - if (!buffer) - return; - if (size < 0) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "size < 0"); - return; - } - if (!size) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "size == 0"); - return; - } - if (!isErrorGeneratedOnOutOfBoundsAccesses()) { - if (!buffer->associateBufferData(static_cast<GC3Dsizeiptr>(size))) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer"); - return; - } - } - - m_context->bufferData(target, static_cast<GC3Dsizeiptr>(size), usage); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBuffer* data, GC3Denum usage, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost()) - return; - WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage); - if (!buffer) - return; - if (!data) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "no data"); - return; - } - if (!isErrorGeneratedOnOutOfBoundsAccesses()) { - if (!buffer->associateBufferData(data)) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer"); - return; - } - } - - m_context->bufferData(target, data->byteLength(), data->data(), usage); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBufferView* data, GC3Denum usage, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost()) - return; - WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage); - if (!buffer) - return; - if (!data) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "no data"); - return; - } - if (!isErrorGeneratedOnOutOfBoundsAccesses()) { - if (!buffer->associateBufferData(data)) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer"); - return; - } - } - - m_context->bufferData(target, data->byteLength(), data->baseAddress(), usage); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::bufferSubData(GC3Denum target, long long offset, ArrayBuffer* data, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost()) - return; - WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GraphicsContext3D::STATIC_DRAW); - if (!buffer) - return; - if (offset < 0) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset < 0"); - return; - } - if (!data) - return; - if (!isErrorGeneratedOnOutOfBoundsAccesses()) { - if (!buffer->associateBufferSubData(static_cast<GC3Dintptr>(offset), data)) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset out of range"); - return; - } - } - - m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byteLength(), data->data()); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::bufferSubData(GC3Denum target, long long offset, ArrayBufferView* data, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost()) - return; - WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GraphicsContext3D::STATIC_DRAW); - if (!buffer) - return; - if (offset < 0) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset < 0"); - return; - } - if (!data) - return; - if (!isErrorGeneratedOnOutOfBoundsAccesses()) { - if (!buffer->associateBufferSubData(static_cast<GC3Dintptr>(offset), data)) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset out of range"); - return; - } - } - - m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byteLength(), data->baseAddress()); - cleanupAfterGraphicsCall(false); -} - -GC3Denum WebGLRenderingContext::checkFramebufferStatus(GC3Denum target) -{ - if (isContextLost()) - return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED; - if (target != GraphicsContext3D::FRAMEBUFFER) { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "checkFramebufferStatus", "invalid target"); - return 0; - } - if (!m_framebufferBinding || !m_framebufferBinding->object()) - return GraphicsContext3D::FRAMEBUFFER_COMPLETE; - const char* reason = "framebuffer incomplete"; - GC3Denum result = m_framebufferBinding->checkStatus(&reason); - if (result != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { - printGLWarningToConsole("checkFramebufferStatus", reason); - return result; - } - result = m_context->checkFramebufferStatus(target); - cleanupAfterGraphicsCall(false); - return result; -} - -void WebGLRenderingContext::clear(GC3Dbitfield mask) -{ - if (isContextLost()) - return; - if (mask & ~(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clear", "invalid mask"); - return; - } - const char* reason = "framebuffer incomplete"; - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) { - synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "clear", reason); - return; - } - if (!clearIfComposited(mask)) - m_context->clear(mask); - cleanupAfterGraphicsCall(true); -} - -void WebGLRenderingContext::clearColor(GC3Dfloat r, GC3Dfloat g, GC3Dfloat b, GC3Dfloat a) -{ - if (isContextLost()) - return; - if (std::isnan(r)) - r = 0; - if (std::isnan(g)) - g = 0; - if (std::isnan(b)) - b = 0; - if (std::isnan(a)) - a = 1; - m_clearColor[0] = r; - m_clearColor[1] = g; - m_clearColor[2] = b; - m_clearColor[3] = a; - m_context->clearColor(r, g, b, a); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::clearDepth(GC3Dfloat depth) -{ - if (isContextLost()) - return; - m_clearDepth = depth; - m_context->clearDepth(depth); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::clearStencil(GC3Dint s) -{ - if (isContextLost()) - return; - m_clearStencil = s; - m_context->clearStencil(s); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha) -{ - if (isContextLost()) - return; - m_colorMask[0] = red; - m_colorMask[1] = green; - m_colorMask[2] = blue; - m_colorMask[3] = alpha; - m_context->colorMask(red, green, blue, alpha); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::compileShader(WebGLShader* shader, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateWebGLObject("compileShader", shader)) - return; - m_context->compileShader(objectOrZero(shader)); - GC3Dint value; - m_context->getShaderiv(objectOrZero(shader), GraphicsContext3D::COMPILE_STATUS, &value); - shader->setValid(value); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, - GC3Dsizei height, GC3Dint border, ArrayBufferView* data) -{ - if (isContextLost()) - return; - if (!validateTexFuncLevel("compressedTexImage2D", target, level)) - return; - - if (!validateCompressedTexFormat(internalformat)) { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "compressedTexImage2D", "invalid internalformat"); - return; - } - if (border) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "compressedTexImage2D", "border not 0"); - return; - } - if (!validateCompressedTexDimensions("compressedTexImage2D", target, level, width, height, internalformat)) - return; - if (!validateCompressedTexFuncData("compressedTexImage2D", width, height, internalformat, data)) - return; - - WebGLTexture* tex = validateTextureBinding("compressedTexImage2D", target, true); - if (!tex) - return; - if (!isGLES2NPOTStrict()) { - if (level && WebGLTexture::isNPOT(width, height)) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "compressedTexImage2D", "level > 0 not power of 2"); - return; - } - } - graphicsContext3D()->compressedTexImage2D(target, level, internalformat, width, height, - border, data->byteLength(), data->baseAddress()); - tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE); - tex->setCompressed(); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView* data) -{ - if (isContextLost()) - return; - if (!validateTexFuncLevel("compressedTexSubImage2D", target, level)) - return; - if (!validateCompressedTexFormat(format)) { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "compressedTexSubImage2D", "invalid format"); - return; - } - if (!validateCompressedTexFuncData("compressedTexSubImage2D", width, height, format, data)) - return; - - WebGLTexture* tex = validateTextureBinding("compressedTexSubImage2D", target, true); - if (!tex) - return; - - if (format != tex->getInternalFormat(target, level)) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "compressedTexSubImage2D", "format does not match texture format"); - return; - } - - if (!validateCompressedTexSubDimensions("compressedTexSubImage2D", target, level, xoffset, yoffset, width, height, format, tex)) - return; - - graphicsContext3D()->compressedTexSubImage2D(target, level, xoffset, yoffset, - width, height, format, data->byteLength(), data->baseAddress()); - tex->setCompressed(); - cleanupAfterGraphicsCall(false); -} - -bool WebGLRenderingContext::validateSettableTexFormat(const char* functionName, GC3Denum format) -{ - if (GraphicsContext3D::getClearBitsByFormat(format) & (GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format can not be set, only rendered to"); - return false; - } - return true; -} - -void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) -{ - if (isContextLost()) - return; - if (!validateTexFuncParameters("copyTexImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, internalformat, GraphicsContext3D::UNSIGNED_BYTE)) - return; - if (!validateSettableTexFormat("copyTexImage2D", internalformat)) - return; - WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true); - if (!tex) - return; - if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexImage2D", "framebuffer is incompatible format"); - return; - } - if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexImage2D", "level > 0 not power of 2"); - return; - } - const char* reason = "framebuffer incomplete"; - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) { - synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason); - return; - } - clearIfComposited(); - if (isResourceSafe()) { - ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get()); - m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border); - } else { - ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get()); - GC3Dint clippedX, clippedY; - GC3Dsizei clippedWidth, clippedHeight; - if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) { - m_context->texImage2DResourceSafe(target, level, internalformat, width, height, border, - internalformat, GraphicsContext3D::UNSIGNED_BYTE, m_unpackAlignment); - if (clippedWidth > 0 && clippedHeight > 0) { - m_context->copyTexSubImage2D(target, level, clippedX - x, clippedY - y, - clippedX, clippedY, clippedWidth, clippedHeight); - } - } else - m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border); - } - // FIXME: if the framebuffer is not complete, none of the below should be executed. - tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) -{ - if (isContextLost()) - return; - if (!validateTexFuncLevel("copyTexSubImage2D", target, level)) - return; - WebGLTexture* tex = validateTextureBinding("copyTexSubImage2D", target, true); - if (!tex) - return; - if (!validateSize("copyTexSubImage2D", xoffset, yoffset) || !validateSize("copyTexSubImage2D", width, height)) - return; - // Before checking if it is in the range, check if overflow happens first. - if (xoffset + width < 0 || yoffset + height < 0) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "bad dimensions"); - return; - } - if (xoffset + width > tex->getWidth(target, level) || yoffset + height > tex->getHeight(target, level)) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "rectangle out of range"); - return; - } - GC3Denum internalformat = tex->getInternalFormat(target, level); - if (!validateSettableTexFormat("copyTexSubImage2D", internalformat)) - return; - if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexSubImage2D", "framebuffer is incompatible format"); - return; - } - const char* reason = "framebuffer incomplete"; - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) { - synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexSubImage2D", reason); - return; - } - clearIfComposited(); - if (isResourceSafe()) { - ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get()); - m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); - } else { - GC3Dint clippedX, clippedY; - GC3Dsizei clippedWidth, clippedHeight; - if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) { - GC3Denum format = tex->getInternalFormat(target, level); - GC3Denum type = tex->getType(target, level); - std::unique_ptr<unsigned char[]> zero; - if (width && height) { - unsigned int size; - GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &size, 0); - if (error != GraphicsContext3D::NO_ERROR) { - synthesizeGLError(error, "copyTexSubImage2D", "bad dimensions"); - return; - } - zero = std::make_unique<unsigned char[]>(size); - if (!zero) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "out of memory"); - return; - } - memset(zero.get(), 0, size); - } - m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, zero.get()); - if (clippedWidth > 0 && clippedHeight > 0) { - ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get()); - m_context->copyTexSubImage2D(target, level, xoffset + clippedX - x, yoffset + clippedY - y, - clippedX, clippedY, clippedWidth, clippedHeight); - } - } else { - ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get()); - m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); - } - } - cleanupAfterGraphicsCall(false); -} - -PassRefPtr<WebGLBuffer> WebGLRenderingContext::createBuffer() -{ - if (isContextLost()) - return 0; - RefPtr<WebGLBuffer> o = WebGLBuffer::create(this); - addSharedObject(o.get()); - return o; -} - -PassRefPtr<WebGLFramebuffer> WebGLRenderingContext::createFramebuffer() -{ - if (isContextLost()) - return 0; - RefPtr<WebGLFramebuffer> o = WebGLFramebuffer::create(this); - addContextObject(o.get()); - return o; -} - -PassRefPtr<WebGLTexture> WebGLRenderingContext::createTexture() -{ - if (isContextLost()) - return 0; - RefPtr<WebGLTexture> o = WebGLTexture::create(this); - addSharedObject(o.get()); - return o; -} - -PassRefPtr<WebGLProgram> WebGLRenderingContext::createProgram() -{ - if (isContextLost()) - return 0; - RefPtr<WebGLProgram> o = WebGLProgram::create(this); - addSharedObject(o.get()); - return o; -} - -PassRefPtr<WebGLRenderbuffer> WebGLRenderingContext::createRenderbuffer() -{ - if (isContextLost()) - return 0; - RefPtr<WebGLRenderbuffer> o = WebGLRenderbuffer::create(this); - addSharedObject(o.get()); - return o; -} - -PassRefPtr<WebGLShader> WebGLRenderingContext::createShader(GC3Denum type, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost()) - return 0; - if (type != GraphicsContext3D::VERTEX_SHADER && type != GraphicsContext3D::FRAGMENT_SHADER) { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "createShader", "invalid shader type"); - return 0; - } - - RefPtr<WebGLShader> o = WebGLShader::create(this, type); - addSharedObject(o.get()); - return o; -} - -void WebGLRenderingContext::cullFace(GC3Denum mode) -{ - if (isContextLost()) - return; - m_context->cullFace(mode); - cleanupAfterGraphicsCall(false); -} - -bool WebGLRenderingContext::deleteObject(WebGLObject* object) -{ - if (isContextLost() || !object) - return false; - if (!object->validate(contextGroup(), this)) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "delete", "object does not belong to this context"); - return false; - } - if (object->object()) - // We need to pass in context here because we want - // things in this context unbound. - object->deleteObject(graphicsContext3D()); - return true; -} - -void WebGLRenderingContext::deleteBuffer(WebGLBuffer* buffer) -{ - if (!deleteObject(buffer)) - return; - if (m_boundArrayBuffer == buffer) - m_boundArrayBuffer = 0; - - m_boundVertexArrayObject->unbindBuffer(buffer); -} - -void WebGLRenderingContext::deleteFramebuffer(WebGLFramebuffer* framebuffer) -{ - if (!deleteObject(framebuffer)) - return; - if (framebuffer == m_framebufferBinding) { - m_framebufferBinding = 0; - if (m_drawingBuffer) { - m_drawingBuffer->setFramebufferBinding(0); - // Have to call bindFramebuffer here to bind back to internal fbo. - m_drawingBuffer->bind(); - } else - m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0); - } -} - -void WebGLRenderingContext::deleteProgram(WebGLProgram* program) -{ - deleteObject(program); - // We don't reset m_currentProgram to 0 here because the deletion of the - // current program is delayed. -} - -void WebGLRenderingContext::deleteRenderbuffer(WebGLRenderbuffer* renderbuffer) -{ - if (!deleteObject(renderbuffer)) - return; - if (renderbuffer == m_renderbufferBinding) - m_renderbufferBinding = 0; - if (m_framebufferBinding) - m_framebufferBinding->removeAttachmentFromBoundFramebuffer(renderbuffer); -} - -void WebGLRenderingContext::deleteShader(WebGLShader* shader) -{ - deleteObject(shader); -} - -void WebGLRenderingContext::deleteTexture(WebGLTexture* texture) -{ - if (!deleteObject(texture)) - return; - for (size_t i = 0; i < m_textureUnits.size(); ++i) { - if (texture == m_textureUnits[i].texture2DBinding) - m_textureUnits[i].texture2DBinding = nullptr; - if (texture == m_textureUnits[i].textureCubeMapBinding) - m_textureUnits[i].textureCubeMapBinding = nullptr; - } - if (m_framebufferBinding) - m_framebufferBinding->removeAttachmentFromBoundFramebuffer(texture); -} - -void WebGLRenderingContext::depthFunc(GC3Denum func) -{ - if (isContextLost()) - return; - m_context->depthFunc(func); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::depthMask(GC3Dboolean flag) -{ - if (isContextLost()) - return; - m_depthMask = flag; - m_context->depthMask(flag); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::depthRange(GC3Dfloat zNear, GC3Dfloat zFar) -{ - if (isContextLost()) - return; - if (zNear > zFar) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "depthRange", "zNear > zFar"); - return; - } - m_context->depthRange(zNear, zFar); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::detachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateWebGLObject("detachShader", program) || !validateWebGLObject("detachShader", shader)) - return; - if (!program->detachShader(shader)) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "detachShader", "shader not attached"); - return; - } - m_context->detachShader(objectOrZero(program), objectOrZero(shader)); - shader->onDetached(graphicsContext3D()); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::disable(GC3Denum cap) -{ - if (isContextLost() || !validateCapability("disable", cap)) - return; - if (cap == GraphicsContext3D::STENCIL_TEST) { - m_stencilEnabled = false; - applyStencilTest(); - cleanupAfterGraphicsCall(false); - return; - } - if (cap == GraphicsContext3D::SCISSOR_TEST) { - m_scissorEnabled = false; - if (m_drawingBuffer) - m_drawingBuffer->setScissorEnabled(m_scissorEnabled); - } - m_context->disable(cap); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::disableVertexAttribArray(GC3Duint index, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost()) - return; - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "disableVertexAttribArray", "index out of range"); - return; - } - - WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index); - state.enabled = false; - - if (index > 0 || isGLES2Compliant()) { - m_context->disableVertexAttribArray(index); - cleanupAfterGraphicsCall(false); - } -} - -bool WebGLRenderingContext::validateElementArraySize(GC3Dsizei count, GC3Denum type, GC3Dintptr offset) -{ - RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer(); - - if (!elementArrayBuffer) - return false; - - if (offset < 0) - return false; - - if (type == GraphicsContext3D::UNSIGNED_INT) { - // For an unsigned int array, offset must be divisible by 4 for alignment reasons. - if (offset % 4) - return false; - - // Make uoffset an element offset. - offset /= 4; - - GC3Dsizeiptr n = elementArrayBuffer->byteLength() / 4; - if (offset > n || count > n - offset) - return false; - } else if (type == GraphicsContext3D::UNSIGNED_SHORT) { - // For an unsigned short array, offset must be divisible by 2 for alignment reasons. - if (offset % 2) - return false; - - // Make uoffset an element offset. - offset /= 2; - - GC3Dsizeiptr n = elementArrayBuffer->byteLength() / 2; - if (offset > n || count > n - offset) - return false; - } else if (type == GraphicsContext3D::UNSIGNED_BYTE) { - GC3Dsizeiptr n = elementArrayBuffer->byteLength(); - if (offset > n || count > n - offset) - return false; - } - return true; } -bool WebGLRenderingContext::validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired) -{ - // Performs conservative validation by caching a maximum index of - // the given type per element array buffer. If all of the bound - // array buffers have enough elements to satisfy that maximum - // index, skips the expensive per-draw-call iteration in - // validateIndexArrayPrecise. - - RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer(); - - if (!elementArrayBuffer) - return false; - - GC3Dsizeiptr numElements = elementArrayBuffer->byteLength(); - // The case count==0 is already dealt with in drawElements before validateIndexArrayConservative. - if (!numElements) - return false; - const ArrayBuffer* buffer = elementArrayBuffer->elementArrayBuffer(); - ASSERT(buffer); - - int maxIndex = elementArrayBuffer->getCachedMaxIndex(type); - if (maxIndex < 0) { - // Compute the maximum index in the entire buffer for the given type of index. - switch (type) { - case GraphicsContext3D::UNSIGNED_BYTE: { - const GC3Dubyte* p = static_cast<const GC3Dubyte*>(buffer->data()); - for (GC3Dsizeiptr i = 0; i < numElements; i++) - maxIndex = std::max(maxIndex, static_cast<int>(p[i])); - break; - } - case GraphicsContext3D::UNSIGNED_SHORT: { - numElements /= sizeof(GC3Dushort); - const GC3Dushort* p = static_cast<const GC3Dushort*>(buffer->data()); - for (GC3Dsizeiptr i = 0; i < numElements; i++) - maxIndex = std::max(maxIndex, static_cast<int>(p[i])); - break; - } - case GraphicsContext3D::UNSIGNED_INT: { - if (!m_oesElementIndexUint) - return false; - numElements /= sizeof(GC3Duint); - const GC3Duint* p = static_cast<const GC3Duint*>(buffer->data()); - for (GC3Dsizeiptr i = 0; i < numElements; i++) - maxIndex = std::max(maxIndex, static_cast<int>(p[i])); - break; - } - default: - return false; - } - elementArrayBuffer->setCachedMaxIndex(type, maxIndex); - } - - if (maxIndex >= 0) { - // The number of required elements is one more than the maximum - // index that will be accessed. - numElementsRequired = maxIndex + 1; - return true; - } - - return false; -} - -bool WebGLRenderingContext::validateIndexArrayPrecise(GC3Dsizei count, GC3Denum type, GC3Dintptr offset, unsigned& numElementsRequired) +WebGLExtension* WebGLRenderingContext::getExtension(const String& name) { - ASSERT(count >= 0 && offset >= 0); - unsigned lastIndex = 0; + if (isContextLostOrPending()) + return nullptr; - RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer(); - - if (!elementArrayBuffer) - return false; - - if (!count) { - numElementsRequired = 0; - return true; - } - - if (!elementArrayBuffer->elementArrayBuffer()) - return false; - - unsigned long uoffset = offset; - unsigned long n = count; - - if (type == GraphicsContext3D::UNSIGNED_INT) { - // Make uoffset an element offset. - uoffset /= sizeof(GC3Duint); - const GC3Duint* p = static_cast<const GC3Duint*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset; - while (n-- > 0) { - if (*p > lastIndex) - lastIndex = *p; - ++p; - } - } else if (type == GraphicsContext3D::UNSIGNED_SHORT) { - // Make uoffset an element offset. - uoffset /= sizeof(GC3Dushort); - const GC3Dushort* p = static_cast<const GC3Dushort*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset; - while (n-- > 0) { - if (*p > lastIndex) - lastIndex = *p; - ++p; - } - } else if (type == GraphicsContext3D::UNSIGNED_BYTE) { - const GC3Dubyte* p = static_cast<const GC3Dubyte*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset; - while (n-- > 0) { - if (*p > lastIndex) - lastIndex = *p; - ++p; - } - } - - // Then set the last index in the index array and make sure it is valid. - numElementsRequired = lastIndex + 1; - return numElementsRequired > 0; -} - -bool WebGLRenderingContext::validateVertexAttributes(unsigned elementCount, unsigned primitiveCount) -{ - if (!m_currentProgram) - return false; - - // Look in each enabled vertex attrib and check if they've been bound to a buffer. - for (unsigned i = 0; i < m_maxVertexAttribs; ++i) { - if (!m_boundVertexArrayObject->getVertexAttribState(i).validateBinding()) - return false; - } - - if (elementCount <= 0) - return true; - - - // Look in each consumed vertex attrib (by the current program). - bool sawNonInstancedAttrib = false; - bool sawEnabledAttrib = false; - int numActiveAttribLocations = m_currentProgram->numActiveAttribLocations(); - for (int i = 0; i < numActiveAttribLocations; ++i) { - int loc = m_currentProgram->getActiveAttribLocation(i); - if (loc >= 0 && loc < static_cast<int>(m_maxVertexAttribs)) { - const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(loc); - if (state.enabled) { - sawEnabledAttrib = true; - // Avoid off-by-one errors in numElements computation. - // For the last element, we will only touch the data for the - // element and nothing beyond it. - int bytesRemaining = static_cast<int>(state.bufferBinding->byteLength() - state.offset); - unsigned numElements = 0; - ASSERT(state.stride > 0); - if (bytesRemaining >= state.bytesPerElement) - numElements = 1 + (bytesRemaining - state.bytesPerElement) / state.stride; - unsigned instancesRequired = 0; - if (state.divisor) { - instancesRequired = ceil(static_cast<float>(primitiveCount) / state.divisor); - if (instancesRequired > numElements) - return false; - } else { - sawNonInstancedAttrib = true; - if (elementCount > numElements) - return false; - } - } - } - } - - if (!sawNonInstancedAttrib && sawEnabledAttrib) - return false; - - return true; -} - -bool WebGLRenderingContext::validateWebGLObject(const char* functionName, WebGLObject* object) -{ - if (!object || !object->object()) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no object or object deleted"); - return false; - } - if (!object->validate(contextGroup(), this)) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "object does not belong to this context"); - return false; - } - return true; -} - -bool WebGLRenderingContext::validateDrawArrays(const char* functionName, GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primitiveCount) -{ - if (isContextLost() || !validateDrawMode(functionName, mode)) - return false; - - if (!validateStencilSettings(functionName)) - return false; - - if (first < 0 || count < 0) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "first or count < 0"); - return false; - } - - if (!count) { - cleanupAfterGraphicsCall(true); - return false; - } - - if (primitiveCount < 0) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "primcount < 0"); - return false; - } - - if (!isErrorGeneratedOnOutOfBoundsAccesses()) { - // Ensure we have a valid rendering state - Checked<GC3Dint, RecordOverflow> checkedFirst(first); - Checked<GC3Dint, RecordOverflow> checkedCount(count); - Checked<GC3Dint, RecordOverflow> checkedSum = checkedFirst + checkedCount; - Checked<GC3Dint, RecordOverflow> checkedPrimitiveCount(primitiveCount); - if (checkedSum.hasOverflowed() || checkedPrimitiveCount.hasOverflowed() || !validateVertexAttributes(checkedSum.unsafeGet(), checkedPrimitiveCount.unsafeGet())) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attempt to access out of bounds arrays"); - return false; - } - } else { - if (!validateVertexAttributes(0)) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attribs not setup correctly"); - return false; - } - } - - const char* reason = "framebuffer incomplete"; - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) { - synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, functionName, reason); - return false; - } - - return true; -} - -void WebGLRenderingContext::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - - if (!validateDrawArrays("drawArrays", mode, first, count, 0)) - return; - - clearIfComposited(); - - bool vertexAttrib0Simulated = false; - if (!isGLES2Compliant()) - vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1); - if (!isGLES2NPOTStrict()) - checkTextureCompleteness("drawArrays", true); - - m_context->drawArrays(mode, first, count); - - if (!isGLES2Compliant() && vertexAttrib0Simulated) - restoreStatesAfterVertexAttrib0Simulation(); - if (!isGLES2NPOTStrict()) - checkTextureCompleteness("drawArrays", false); - cleanupAfterGraphicsCall(true); -} - -bool WebGLRenderingContext::validateDrawElements(const char* functionName, GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, unsigned& numElements, GC3Dsizei primitiveCount) -{ - if (isContextLost() || !validateDrawMode(functionName, mode)) - return false; - - if (!validateStencilSettings(functionName)) - return false; - - switch (type) { - case GraphicsContext3D::UNSIGNED_BYTE: - case GraphicsContext3D::UNSIGNED_SHORT: - break; - case GraphicsContext3D::UNSIGNED_INT: - if (m_oesElementIndexUint) - break; - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid type"); - return false; - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid type"); - return false; - } - - if (count < 0 || offset < 0) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "count or offset < 0"); - return false; - } - - if (!count) { - cleanupAfterGraphicsCall(true); - return false; - } - - if (primitiveCount < 0) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "primcount < 0"); - return false; - } - - if (!m_boundVertexArrayObject->getElementArrayBuffer()) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no ELEMENT_ARRAY_BUFFER bound"); - return false; - } - - if (!isErrorGeneratedOnOutOfBoundsAccesses()) { - // Ensure we have a valid rendering state - if (!validateElementArraySize(count, type, static_cast<GC3Dintptr>(offset))) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "request out of bounds for current ELEMENT_ARRAY_BUFFER"); - return false; - } - if (!count) - return false; - - Checked<GC3Dint, RecordOverflow> checkedCount(count); - Checked<GC3Dint, RecordOverflow> checkedPrimitiveCount(primitiveCount); - if (checkedCount.hasOverflowed() || checkedPrimitiveCount.hasOverflowed()) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attempt to access out of bounds arrays"); - return false; - } - - if (!validateIndexArrayConservative(type, numElements) || !validateVertexAttributes(numElements, checkedPrimitiveCount.unsafeGet())) { - if (!validateIndexArrayPrecise(checkedCount.unsafeGet(), type, static_cast<GC3Dintptr>(offset), numElements) || !validateVertexAttributes(numElements, checkedPrimitiveCount.unsafeGet())) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attempt to access out of bounds arrays"); - return false; + if (equalIgnoringASCIICase(name, "EXT_blend_minmax")) { + if (!m_extBlendMinMax) { + m_extBlendMinMax = enableSupportedExtension("GL_EXT_blend_minmax") + ? std::make_unique<EXTBlendMinMax>(*this) : nullptr; + } + return m_extBlendMinMax.get(); + } + if (equalIgnoringASCIICase(name, "EXT_sRGB")) { + if (!m_extsRGB) { + m_extsRGB = enableSupportedExtension("GL_EXT_sRGB") + ? std::make_unique<EXTsRGB>(*this) : nullptr; + } + return m_extsRGB.get(); + } + if (equalIgnoringASCIICase(name, "EXT_frag_depth")) { + if (!m_extFragDepth) { + m_extFragDepth = enableSupportedExtension("GL_EXT_frag_depth") + ? std::make_unique<EXTFragDepth>(*this) : nullptr; + } + return m_extFragDepth.get(); + } + if (equalIgnoringASCIICase(name, "EXT_shader_texture_lod")) { + if (!m_extShaderTextureLOD) { + if (!(m_context->getExtensions().supports(ASCIILiteral { "GL_EXT_shader_texture_lod" }) || m_context->getExtensions().supports(ASCIILiteral { "GL_ARB_shader_texture_lod" }))) + m_extShaderTextureLOD = nullptr; + else { + m_context->getExtensions().ensureEnabled(ASCIILiteral { "GL_EXT_shader_texture_lod" }); + m_extShaderTextureLOD = std::make_unique<EXTShaderTextureLOD>(*this); } } - } else { - if (!validateVertexAttributes(0)) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attribs not setup correctly"); - return false; - } - } - - const char* reason = "framebuffer incomplete"; - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) { - synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, functionName, reason); - return false; - } - - return true; -} - -void WebGLRenderingContext::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - - unsigned numElements = 0; - if (!validateDrawElements("drawElements", mode, count, type, offset, numElements, 0)) - return; - - clearIfComposited(); - - bool vertexAttrib0Simulated = false; - if (!isGLES2Compliant()) { - if (!numElements) - validateIndexArrayPrecise(count, type, static_cast<GC3Dintptr>(offset), numElements); - vertexAttrib0Simulated = simulateVertexAttrib0(numElements); - } - if (!isGLES2NPOTStrict()) - checkTextureCompleteness("drawElements", true); - - m_context->drawElements(mode, count, type, static_cast<GC3Dintptr>(offset)); - - if (!isGLES2Compliant() && vertexAttrib0Simulated) - restoreStatesAfterVertexAttrib0Simulation(); - if (!isGLES2NPOTStrict()) - checkTextureCompleteness("drawElements", false); - cleanupAfterGraphicsCall(true); -} - -void WebGLRenderingContext::enable(GC3Denum cap) -{ - if (isContextLost() || !validateCapability("enable", cap)) - return; - if (cap == GraphicsContext3D::STENCIL_TEST) { - m_stencilEnabled = true; - applyStencilTest(); - cleanupAfterGraphicsCall(false); - return; - } - if (cap == GraphicsContext3D::SCISSOR_TEST) { - m_scissorEnabled = true; - if (m_drawingBuffer) - m_drawingBuffer->setScissorEnabled(m_scissorEnabled); - } - m_context->enable(cap); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::enableVertexAttribArray(GC3Duint index, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost()) - return; - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "enableVertexAttribArray", "index out of range"); - return; - } - - WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index); - state.enabled = true; - - m_context->enableVertexAttribArray(index); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::finish() -{ - if (isContextLost()) - return; - m_context->finish(); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::flush() -{ - if (isContextLost()) - return; - m_context->flush(); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer* buffer, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateFramebufferFuncParameters("framebufferRenderbuffer", target, attachment)) - return; - if (renderbuffertarget != GraphicsContext3D::RENDERBUFFER) { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "framebufferRenderbuffer", "invalid target"); - return; - } - if (buffer && !buffer->validate(contextGroup(), this)) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferRenderbuffer", "no buffer or buffer not from this context"); - return; - } - // Don't allow the default framebuffer to be mutated; all current - // implementations use an FBO internally in place of the default - // FBO. - if (!m_framebufferBinding || !m_framebufferBinding->object()) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferRenderbuffer", "no framebuffer bound"); - return; - } - Platform3DObject bufferObject = objectOrZero(buffer); - switch (attachment) { - case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT: - m_context->framebufferRenderbuffer(target, GraphicsContext3D::DEPTH_ATTACHMENT, renderbuffertarget, bufferObject); - m_context->framebufferRenderbuffer(target, GraphicsContext3D::STENCIL_ATTACHMENT, renderbuffertarget, bufferObject); - break; - default: - m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, bufferObject); - } - m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, buffer); - applyStencilTest(); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture* texture, GC3Dint level, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateFramebufferFuncParameters("framebufferTexture2D", target, attachment)) - return; - if (level) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "framebufferTexture2D", "level not 0"); - return; - } - if (texture && !texture->validate(contextGroup(), this)) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferTexture2D", "no texture or texture not from this context"); - return; - } - // Don't allow the default framebuffer to be mutated; all current - // implementations use an FBO internally in place of the default - // FBO. - if (!m_framebufferBinding || !m_framebufferBinding->object()) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferTexture2D", "no framebuffer bound"); - return; - } - Platform3DObject textureObject = objectOrZero(texture); - switch (attachment) { - case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT: - m_context->framebufferTexture2D(target, GraphicsContext3D::DEPTH_ATTACHMENT, textarget, textureObject, level); - m_context->framebufferTexture2D(target, GraphicsContext3D::STENCIL_ATTACHMENT, textarget, textureObject, level); - break; - case GraphicsContext3D::DEPTH_ATTACHMENT: - m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level); - break; - case GraphicsContext3D::STENCIL_ATTACHMENT: - m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level); - break; - default: - m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level); - } - m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, textarget, texture, level); - applyStencilTest(); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::frontFace(GC3Denum mode) -{ - if (isContextLost()) - return; - m_context->frontFace(mode); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::generateMipmap(GC3Denum target) -{ - if (isContextLost()) - return; - WebGLTexture* tex = validateTextureBinding("generateMipmap", target, false); - if (!tex) - return; - if (!tex->canGenerateMipmaps()) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "generateMipmap", "level 0 not power of 2 or not all the same size"); - return; - } - // FIXME: https://bugs.webkit.org/show_bug.cgi?id=123916. Compressed textures should be allowed in WebGL 2: - if (tex->isCompressed()) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "generateMipmap", "trying to generate mipmaps from compressed texture"); - return; - } - if (!validateSettableTexFormat("generateMipmap", tex->getInternalFormat(target, 0))) - return; - - // generateMipmap won't work properly if minFilter is not NEAREST_MIPMAP_LINEAR - // on Mac. Remove the hack once this driver bug is fixed. -#if OS(DARWIN) - bool needToResetMinFilter = false; - if (tex->getMinFilter() != GraphicsContext3D::NEAREST_MIPMAP_LINEAR) { - m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST_MIPMAP_LINEAR); - needToResetMinFilter = true; - } -#endif - m_context->generateMipmap(target); -#if OS(DARWIN) - if (needToResetMinFilter) - m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, tex->getMinFilter()); -#endif - tex->generateMipmapLevelInfo(); - cleanupAfterGraphicsCall(false); -} - -PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveAttrib(WebGLProgram* program, GC3Duint index, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateWebGLObject("getActiveAttrib", program)) - return 0; - ActiveInfo info; - if (!m_context->getActiveAttrib(objectOrZero(program), index, info)) - return 0; - - LOG(WebGL, "Returning active attribute %d: %s", index, info.name.utf8().data()); - - return WebGLActiveInfo::create(info.name, info.type, info.size); -} - -PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveUniform(WebGLProgram* program, GC3Duint index, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateWebGLObject("getActiveUniform", program)) - return 0; - ActiveInfo info; - if (!m_context->getActiveUniform(objectOrZero(program), index, info)) - return 0; - if (!isGLES2Compliant()) - if (info.size > 1 && !info.name.endsWith("[0]")) - info.name.append("[0]"); - - LOG(WebGL, "Returning active uniform %d: %s", index, info.name.utf8().data()); - - return WebGLActiveInfo::create(info.name, info.type, info.size); -} - -bool WebGLRenderingContext::getAttachedShaders(WebGLProgram* program, Vector<RefPtr<WebGLShader>>& shaderObjects, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - shaderObjects.clear(); - if (isContextLost() || !validateWebGLObject("getAttachedShaders", program)) - return false; - - const GC3Denum shaderType[] = { - GraphicsContext3D::VERTEX_SHADER, - GraphicsContext3D::FRAGMENT_SHADER - }; - for (unsigned i = 0; i < sizeof(shaderType) / sizeof(GC3Denum); ++i) { - WebGLShader* shader = program->getAttachedShader(shaderType[i]); - if (shader) - shaderObjects.append(shader); - } - return true; -} - -GC3Dint WebGLRenderingContext::getAttribLocation(WebGLProgram* program, const String& name) -{ - if (isContextLost() || !validateWebGLObject("getAttribLocation", program)) - return -1; - if (!validateLocationLength("getAttribLocation", name)) - return -1; - if (!validateString("getAttribLocation", name)) - return -1; - if (isPrefixReserved(name)) - return -1; - if (!program->getLinkStatus()) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getAttribLocation", "program not linked"); - return -1; - } - return m_context->getAttribLocation(objectOrZero(program), name); -} - -WebGLGetInfo WebGLRenderingContext::getBufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost()) - return WebGLGetInfo(); - if (target != GraphicsContext3D::ARRAY_BUFFER && target != GraphicsContext3D::ELEMENT_ARRAY_BUFFER) { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getBufferParameter", "invalid target"); - return WebGLGetInfo(); - } - - if (pname != GraphicsContext3D::BUFFER_SIZE && pname != GraphicsContext3D::BUFFER_USAGE) { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getBufferParameter", "invalid parameter name"); - return WebGLGetInfo(); + return m_extShaderTextureLOD.get(); } - - WebGLStateRestorer(this, false); - GC3Dint value = 0; - m_context->getBufferParameteriv(target, pname, &value); - if (pname == GraphicsContext3D::BUFFER_SIZE) - return WebGLGetInfo(value); - return WebGLGetInfo(static_cast<unsigned int>(value)); -} - -PassRefPtr<WebGLContextAttributes> WebGLRenderingContext::getContextAttributes() -{ - if (isContextLost()) - return 0; - // We always need to return a new WebGLContextAttributes object to - // prevent the user from mutating any cached version. - - // Also, we need to enforce requested values of "false" for depth - // and stencil, regardless of the properties of the underlying - // GraphicsContext3D or DrawingBuffer. - RefPtr<WebGLContextAttributes> attributes = WebGLContextAttributes::create(m_context->getContextAttributes()); - if (!m_attributes.depth) - attributes->setDepth(false); - if (!m_attributes.stencil) - attributes->setStencil(false); - if (m_drawingBuffer) { - // The DrawingBuffer obtains its parameters from GraphicsContext3D::getContextAttributes(), - // but it makes its own determination of whether multisampling is supported. - attributes->setAntialias(m_drawingBuffer->multisample()); - } - return attributes.release(); -} - -GC3Denum WebGLRenderingContext::getError() -{ - return m_context->getError(); -} - -WebGLExtension* WebGLRenderingContext::getExtension(const String& name) -{ - if (isContextLost()) - return 0; - - if (equalIgnoringCase(name, "WEBKIT_EXT_texture_filter_anisotropic") - && m_context->getExtensions()->supports("GL_EXT_texture_filter_anisotropic")) { + if (equalIgnoringASCIICase(name, "EXT_texture_filter_anisotropic") || equalIgnoringASCIICase(name, "WEBKIT_EXT_texture_filter_anisotropic")) { if (!m_extTextureFilterAnisotropic) { - m_context->getExtensions()->ensureEnabled("GL_EXT_texture_filter_anisotropic"); - m_extTextureFilterAnisotropic = EXTTextureFilterAnisotropic::create(this); + m_extTextureFilterAnisotropic = enableSupportedExtension("GL_EXT_texture_filter_anisotropic") + ? std::make_unique<EXTTextureFilterAnisotropic>(*this) : nullptr; } return m_extTextureFilterAnisotropic.get(); } - if (equalIgnoringCase(name, "OES_standard_derivatives") - && m_context->getExtensions()->supports("GL_OES_standard_derivatives")) { + if (equalIgnoringASCIICase(name, "OES_standard_derivatives")) { if (!m_oesStandardDerivatives) { - m_context->getExtensions()->ensureEnabled("GL_OES_standard_derivatives"); - m_oesStandardDerivatives = OESStandardDerivatives::create(this); + m_oesStandardDerivatives = enableSupportedExtension("GL_OES_standard_derivatives") + ? std::make_unique<OESStandardDerivatives>(*this) : nullptr; } return m_oesStandardDerivatives.get(); } - if (equalIgnoringCase(name, "OES_texture_float") - && m_context->getExtensions()->supports("GL_OES_texture_float")) { + if (equalIgnoringASCIICase(name, "OES_texture_float")) { if (!m_oesTextureFloat) { - m_context->getExtensions()->ensureEnabled("GL_OES_texture_float"); - m_oesTextureFloat = OESTextureFloat::create(this); + m_oesTextureFloat = enableSupportedExtension("GL_OES_texture_float") + ? std::make_unique<OESTextureFloat>(*this) : nullptr; } return m_oesTextureFloat.get(); } - if (equalIgnoringCase(name, "OES_texture_float_linear") - && m_context->getExtensions()->supports("GL_OES_texture_float_linear")) { + if (equalIgnoringASCIICase(name, "OES_texture_float_linear")) { if (!m_oesTextureFloatLinear) { - m_context->getExtensions()->ensureEnabled("GL_OES_texture_float_linear"); - m_oesTextureFloatLinear = OESTextureFloatLinear::create(this); + m_oesTextureFloatLinear = enableSupportedExtension("GL_OES_texture_float_linear") + ? std::make_unique<OESTextureFloatLinear>(*this) : nullptr; } return m_oesTextureFloatLinear.get(); } - if (equalIgnoringCase(name, "OES_texture_half_float") - && m_context->getExtensions()->supports("GL_OES_texture_half_float")) { + if (equalIgnoringASCIICase(name, "OES_texture_half_float")) { if (!m_oesTextureHalfFloat) { - m_context->getExtensions()->ensureEnabled("GL_OES_texture_half_float"); - m_oesTextureHalfFloat = OESTextureHalfFloat::create(this); + m_oesTextureHalfFloat = enableSupportedExtension("GL_OES_texture_half_float") + ? std::make_unique<OESTextureHalfFloat>(*this) : nullptr; } return m_oesTextureHalfFloat.get(); } - if (equalIgnoringCase(name, "OES_texture_half_float_linear") - && m_context->getExtensions()->supports("GL_OES_texture_half_float_linear")) { + if (equalIgnoringASCIICase(name, "OES_texture_half_float_linear")) { if (!m_oesTextureHalfFloatLinear) { - m_context->getExtensions()->ensureEnabled("GL_OES_texture_half_float_linear"); - m_oesTextureHalfFloatLinear = OESTextureHalfFloatLinear::create(this); + m_oesTextureHalfFloatLinear = enableSupportedExtension("GL_OES_texture_half_float_linear") + ? std::make_unique<OESTextureHalfFloatLinear>(*this) : nullptr; } return m_oesTextureHalfFloatLinear.get(); } - if (equalIgnoringCase(name, "OES_vertex_array_object") - && m_context->getExtensions()->supports("GL_OES_vertex_array_object")) { + if (equalIgnoringASCIICase(name, "OES_vertex_array_object")) { if (!m_oesVertexArrayObject) { - m_context->getExtensions()->ensureEnabled("GL_OES_vertex_array_object"); - m_oesVertexArrayObject = OESVertexArrayObject::create(this); + m_oesVertexArrayObject = enableSupportedExtension("GL_OES_vertex_array_object") + ? std::make_unique<OESVertexArrayObject>(*this) : nullptr; } return m_oesVertexArrayObject.get(); } - if (equalIgnoringCase(name, "OES_element_index_uint") - && m_context->getExtensions()->supports("GL_OES_element_index_uint")) { + if (equalIgnoringASCIICase(name, "OES_element_index_uint")) { if (!m_oesElementIndexUint) { - m_context->getExtensions()->ensureEnabled("GL_OES_element_index_uint"); - m_oesElementIndexUint = OESElementIndexUint::create(this); + m_oesElementIndexUint = enableSupportedExtension("GL_OES_element_index_uint") + ? std::make_unique<OESElementIndexUint>(*this) : nullptr; } return m_oesElementIndexUint.get(); } - if (equalIgnoringCase(name, "WEBGL_lose_context")) { + if (equalIgnoringASCIICase(name, "WEBGL_lose_context")) { if (!m_webglLoseContext) - m_webglLoseContext = WebGLLoseContext::create(this); + m_webglLoseContext = std::make_unique<WebGLLoseContext>(*this); return m_webglLoseContext.get(); } - if ((equalIgnoringCase(name, "WEBKIT_WEBGL_compressed_texture_atc")) - && WebGLCompressedTextureATC::supported(this)) { - if (!m_webglCompressedTextureATC) - m_webglCompressedTextureATC = WebGLCompressedTextureATC::create(this); + if (equalIgnoringASCIICase(name, "WEBKIT_WEBGL_compressed_texture_atc")) { + if (!m_webglCompressedTextureATC) { + m_webglCompressedTextureATC = WebGLCompressedTextureATC::supported(*this) + ? std::make_unique<WebGLCompressedTextureATC>(*this) : nullptr; + } return m_webglCompressedTextureATC.get(); } - if ((equalIgnoringCase(name, "WEBKIT_WEBGL_compressed_texture_pvrtc")) - && WebGLCompressedTexturePVRTC::supported(this)) { - if (!m_webglCompressedTexturePVRTC) - m_webglCompressedTexturePVRTC = WebGLCompressedTexturePVRTC::create(this); + if (equalIgnoringASCIICase(name, "WEBKIT_WEBGL_compressed_texture_pvrtc")) { + if (!m_webglCompressedTexturePVRTC) { + m_webglCompressedTexturePVRTC = WebGLCompressedTexturePVRTC::supported(*this) + ? std::make_unique<WebGLCompressedTexturePVRTC>(*this) : nullptr; + } + return m_webglCompressedTexturePVRTC.get(); } - if (equalIgnoringCase(name, "WEBGL_compressed_texture_s3tc") - && WebGLCompressedTextureS3TC::supported(this)) { - if (!m_webglCompressedTextureS3TC) - m_webglCompressedTextureS3TC = WebGLCompressedTextureS3TC::create(this); + if (equalIgnoringASCIICase(name, "WEBGL_compressed_texture_s3tc")) { + if (!m_webglCompressedTextureS3TC) { + m_webglCompressedTextureS3TC = WebGLCompressedTextureS3TC::supported(*this) + ? std::make_unique<WebGLCompressedTextureS3TC>(*this) : nullptr; + } return m_webglCompressedTextureS3TC.get(); } - if (equalIgnoringCase(name, "WEBGL_depth_texture") - && WebGLDepthTexture::supported(graphicsContext3D())) { + if (equalIgnoringASCIICase(name, "WEBGL_depth_texture")) { if (!m_webglDepthTexture) { - m_context->getExtensions()->ensureEnabled("GL_CHROMIUM_depth_texture"); - m_webglDepthTexture = WebGLDepthTexture::create(this); + m_webglDepthTexture = WebGLDepthTexture::supported(*m_context) + ? std::make_unique<WebGLDepthTexture>(*this) : nullptr; } return m_webglDepthTexture.get(); } - if (equalIgnoringCase(name, "EXT_draw_buffers") && supportsDrawBuffers()) { - if (!m_extDrawBuffers) { - m_context->getExtensions()->ensureEnabled("GL_EXT_draw_buffers"); - m_extDrawBuffers = EXTDrawBuffers::create(this); + if (equalIgnoringASCIICase(name, "WEBGL_draw_buffers")) { + if (!m_webglDrawBuffers) { + if (!supportsDrawBuffers()) + m_webglDrawBuffers = nullptr; + else { + m_context->getExtensions().ensureEnabled(ASCIILiteral { "GL_EXT_draw_buffers" }); + m_webglDrawBuffers = std::make_unique<WebGLDrawBuffers>(*this); + } } - return m_extDrawBuffers.get(); + return m_webglDrawBuffers.get(); } - if (equalIgnoringCase(name, "ANGLE_instanced_arrays") && ANGLEInstancedArrays::supported(this)) { + if (equalIgnoringASCIICase(name, "ANGLE_instanced_arrays")) { if (!m_angleInstancedArrays) { - m_context->getExtensions()->ensureEnabled("GL_ANGLE_instanced_arrays"); - m_angleInstancedArrays = ANGLEInstancedArrays::create(this); + if (!ANGLEInstancedArrays::supported(*this)) + m_angleInstancedArrays = nullptr; + else { + m_context->getExtensions().ensureEnabled(ASCIILiteral { "GL_ANGLE_instanced_arrays" }); + m_angleInstancedArrays = std::make_unique<ANGLEInstancedArrays>(*this); + } } return m_angleInstancedArrays.get(); } - if (allowPrivilegedExtensions()) { - if (equalIgnoringCase(name, "WEBGL_debug_renderer_info")) { - if (!m_webglDebugRendererInfo) - m_webglDebugRendererInfo = WebGLDebugRendererInfo::create(this); - return m_webglDebugRendererInfo.get(); - } - if (equalIgnoringCase(name, "WEBGL_debug_shaders") - && m_context->getExtensions()->supports("GL_ANGLE_translated_shader_source")) { - if (!m_webglDebugShaders) - m_webglDebugShaders = WebGLDebugShaders::create(this); - return m_webglDebugShaders.get(); + if (equalIgnoringASCIICase(name, "WEBGL_debug_renderer_info")) { + if (!m_webglDebugRendererInfo) + m_webglDebugRendererInfo = std::make_unique<WebGLDebugRendererInfo>(*this); + return m_webglDebugRendererInfo.get(); + } + if (equalIgnoringASCIICase(name, "WEBGL_debug_shaders")) { + if (!m_webglDebugShaders) { + m_webglDebugShaders = m_context->getExtensions().supports(ASCIILiteral { "GL_ANGLE_translated_shader_source" }) + ? std::make_unique<WebGLDebugShaders>(*this) : nullptr; } + return m_webglDebugShaders.get(); } - return 0; + return nullptr; } -WebGLGetInfo WebGLRenderingContext::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname, ExceptionCode& ec) +std::optional<Vector<String>> WebGLRenderingContext::getSupportedExtensions() { - UNUSED_PARAM(ec); - if (isContextLost() || !validateFramebufferFuncParameters("getFramebufferAttachmentParameter", target, attachment)) - return WebGLGetInfo(); + if (isContextLost()) + return std::nullopt; + Vector<String> result; + + if (m_isPendingPolicyResolution) + return result; + + if (m_context->getExtensions().supports(ASCIILiteral { "GL_EXT_blend_minmax" })) + result.append(ASCIILiteral { "EXT_blend_minmax" }); + if (m_context->getExtensions().supports(ASCIILiteral { "GL_EXT_sRGB" })) + result.append(ASCIILiteral { "EXT_sRGB" }); + if (m_context->getExtensions().supports(ASCIILiteral { "GL_EXT_frag_depth" })) + result.append(ASCIILiteral { "EXT_frag_depth" }); + if (m_context->getExtensions().supports(ASCIILiteral { "GL_OES_texture_float" })) + result.append(ASCIILiteral { "OES_texture_float" }); + if (m_context->getExtensions().supports(ASCIILiteral { "GL_OES_texture_float_linear" })) + result.append(ASCIILiteral { "OES_texture_float_linear" }); + if (m_context->getExtensions().supports(ASCIILiteral { "GL_OES_texture_half_float" })) + result.append(ASCIILiteral { "OES_texture_half_float" }); + if (m_context->getExtensions().supports(ASCIILiteral { "GL_OES_texture_half_float_linear" })) + result.append(ASCIILiteral { "OES_texture_half_float_linear" }); + if (m_context->getExtensions().supports(ASCIILiteral { "GL_OES_standard_derivatives" })) + result.append(ASCIILiteral { "OES_standard_derivatives" }); + if (m_context->getExtensions().supports(ASCIILiteral { "GL_EXT_shader_texture_lod" }) || m_context->getExtensions().supports(ASCIILiteral { "GL_ARB_shader_texture_lod" })) + result.append(ASCIILiteral { "EXT_shader_texture_lod" }); + if (m_context->getExtensions().supports(ASCIILiteral { "GL_EXT_texture_filter_anisotropic" })) + result.append(ASCIILiteral { "EXT_texture_filter_anisotropic" }); + if (m_context->getExtensions().supports(ASCIILiteral { "GL_OES_vertex_array_object" })) + result.append(ASCIILiteral { "OES_vertex_array_object" }); + if (m_context->getExtensions().supports(ASCIILiteral { "GL_OES_element_index_uint" })) + result.append(ASCIILiteral { "OES_element_index_uint" }); + result.append(ASCIILiteral { "WEBGL_lose_context" }); + if (WebGLCompressedTextureATC::supported(*this)) + result.append(ASCIILiteral { "WEBKIT_WEBGL_compressed_texture_atc" }); + if (WebGLCompressedTexturePVRTC::supported(*this)) + result.append(ASCIILiteral { "WEBKIT_WEBGL_compressed_texture_pvrtc" }); + if (WebGLCompressedTextureS3TC::supported(*this)) + result.append("WEBGL_compressed_texture_s3tc"); + if (WebGLDepthTexture::supported(*m_context)) + result.append(ASCIILiteral { "WEBGL_depth_texture" }); + if (supportsDrawBuffers()) + result.append(ASCIILiteral { "WEBGL_draw_buffers" }); + if (ANGLEInstancedArrays::supported(*this)) + result.append(ASCIILiteral { "ANGLE_instanced_arrays" }); + if (m_context->getExtensions().supports(ASCIILiteral { "GL_ANGLE_translated_shader_source" })) + result.append(ASCIILiteral { "WEBGL_debug_shaders" }); + result.append(ASCIILiteral { "WEBGL_debug_renderer_info" }); + + return result; +} + +WebGLAny WebGLRenderingContext::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname) +{ + if (isContextLostOrPending() || !validateFramebufferFuncParameters("getFramebufferAttachmentParameter", target, attachment)) + return nullptr; + if (!m_framebufferBinding || !m_framebufferBinding->object()) { synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getFramebufferAttachmentParameter", "no framebuffer bound"); - return WebGLGetInfo(); + return nullptr; } - - WebGLSharedObject* object = m_framebufferBinding->getAttachmentObject(attachment); + + auto* object = m_framebufferBinding->getAttachmentObject(attachment); if (!object) { if (pname == GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) - return WebGLGetInfo(GraphicsContext3D::NONE); + return static_cast<unsigned>(GraphicsContext3D::NONE); // OpenGL ES 2.0 specifies INVALID_ENUM in this case, while desktop GL // specifies INVALID_OPERATION. synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name"); - return WebGLGetInfo(); + return nullptr; } - - ASSERT(object->isTexture() || object->isRenderbuffer()); + if (object->isTexture()) { switch (pname) { case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: - return WebGLGetInfo(GraphicsContext3D::TEXTURE); + return static_cast<unsigned>(GraphicsContext3D::TEXTURE); case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: - return WebGLGetInfo(PassRefPtr<WebGLTexture>(reinterpret_cast<WebGLTexture*>(object))); + return makeRefPtr(reinterpret_cast<WebGLTexture&>(*object)); case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: - { - WebGLStateRestorer(this, false); - GC3Dint value = 0; - m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value); - return WebGLGetInfo(value); - } + case Extensions3D::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT: { + GC3Dint value = 0; + m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value); + return value; + } default: synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for texture attachment"); - return WebGLGetInfo(); + return nullptr; } } else { + ASSERT(object->isRenderbuffer()); switch (pname) { case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: - return WebGLGetInfo(GraphicsContext3D::RENDERBUFFER); + return static_cast<unsigned>(GraphicsContext3D::RENDERBUFFER); case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: - return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(reinterpret_cast<WebGLRenderbuffer*>(object))); + return makeRefPtr(reinterpret_cast<WebGLRenderbuffer&>(*object)); + case Extensions3D::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT: { + if (!m_extsRGB) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for renderbuffer attachment"); + return nullptr; + } + WebGLRenderbuffer* renderBuffer = reinterpret_cast<WebGLRenderbuffer*>(object); + GC3Denum renderBufferFormat = renderBuffer->getInternalFormat(); + ASSERT(renderBufferFormat != Extensions3D::SRGB_EXT && renderBufferFormat != Extensions3D::SRGB_ALPHA_EXT); + if (renderBufferFormat == Extensions3D::SRGB8_ALPHA8_EXT) + return static_cast<unsigned>(Extensions3D::SRGB_EXT); + return static_cast<unsigned>(GraphicsContext3D::LINEAR); + } default: synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for renderbuffer attachment"); - return WebGLGetInfo(); + return nullptr; } } } -WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname, ExceptionCode& ec) +bool WebGLRenderingContext::validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment) { - UNUSED_PARAM(ec); - if (isContextLost()) - return WebGLGetInfo(); - const int intZero = 0; - WebGLStateRestorer(this, false); + if (target != GraphicsContext3D::FRAMEBUFFER) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target"); + return false; + } + // FIXME: Why does this return true unconditionally for COLOR_ATTACHMENT0, + // but false for other COLOR_ATTACHMENT values if m_webglDrawBuffers is false? + switch (attachment) { + case GraphicsContext3D::COLOR_ATTACHMENT0: + case GraphicsContext3D::DEPTH_ATTACHMENT: + case GraphicsContext3D::STENCIL_ATTACHMENT: + case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT: + return true; + default: + if (m_webglDrawBuffers + && attachment >= GraphicsContext3D::COLOR_ATTACHMENT0 + && attachment < static_cast<GC3Denum>(GraphicsContext3D::COLOR_ATTACHMENT0 + getMaxColorAttachments())) + return true; + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid attachment"); + return false; + } +} + +void WebGLRenderingContext::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) +{ + if (isContextLostOrPending()) + return; + if (target != GraphicsContext3D::RENDERBUFFER) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid target"); + return; + } + if (!m_renderbufferBinding || !m_renderbufferBinding->object()) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "renderbufferStorage", "no bound renderbuffer"); + return; + } + if (!validateSize("renderbufferStorage", width, height)) + return; + switch (internalformat) { + case GraphicsContext3D::DEPTH_COMPONENT16: + case GraphicsContext3D::RGBA4: + case GraphicsContext3D::RGB5_A1: + case GraphicsContext3D::RGB565: + case GraphicsContext3D::STENCIL_INDEX8: + case Extensions3D::SRGB8_ALPHA8_EXT: + if (internalformat == Extensions3D::SRGB8_ALPHA8_EXT && !m_extsRGB) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid internalformat"); + return; + } + m_context->renderbufferStorage(target, internalformat, width, height); + m_renderbufferBinding->setInternalFormat(internalformat); + m_renderbufferBinding->setIsValid(true); + m_renderbufferBinding->setSize(width, height); + break; + case GraphicsContext3D::DEPTH_STENCIL: + if (isDepthStencilSupported()) + m_context->renderbufferStorage(target, Extensions3D::DEPTH24_STENCIL8, width, height); + m_renderbufferBinding->setSize(width, height); + m_renderbufferBinding->setIsValid(isDepthStencilSupported()); + m_renderbufferBinding->setInternalFormat(internalformat); + break; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid internalformat"); + return; + } + applyStencilTest(); +} + +void WebGLRenderingContext::hint(GC3Denum target, GC3Denum mode) +{ + if (isContextLostOrPending()) + return; + bool isValid = false; + switch (target) { + case GraphicsContext3D::GENERATE_MIPMAP_HINT: + isValid = true; + break; + case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives + if (m_oesStandardDerivatives) + isValid = true; + break; + } + if (!isValid) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "hint", "invalid target"); + return; + } + m_context->hint(target, mode); +} + +void WebGLRenderingContext::clear(GC3Dbitfield mask) +{ + if (isContextLostOrPending()) + return; + if (mask & ~(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clear", "invalid mask"); + return; + } + const char* reason = "framebuffer incomplete"; + if (m_framebufferBinding && !m_framebufferBinding->onAccess(m_context.get(), &reason)) { + synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "clear", reason); + return; + } + if (!clearIfComposited(mask)) + m_context->clear(mask); + markContextChanged(); +} + +WebGLAny WebGLRenderingContext::getParameter(GC3Denum pname) +{ + if (isContextLostOrPending()) + return nullptr; + switch (pname) { case GraphicsContext3D::ACTIVE_TEXTURE: return getUnsignedIntParameter(pname); @@ -2631,7 +488,7 @@ WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname, ExceptionCode& case GraphicsContext3D::ALPHA_BITS: return getIntParameter(pname); case GraphicsContext3D::ARRAY_BUFFER_BINDING: - return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundArrayBuffer)); + return m_boundArrayBuffer; case GraphicsContext3D::BLEND: return getBooleanParameter(pname); case GraphicsContext3D::BLEND_COLOR: @@ -2655,16 +512,16 @@ WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname, ExceptionCode& case GraphicsContext3D::COLOR_WRITEMASK: return getBooleanArrayParameter(pname); case GraphicsContext3D::COMPRESSED_TEXTURE_FORMATS: - return WebGLGetInfo(Uint32Array::create(m_compressedTextureFormats.data(), m_compressedTextureFormats.size())); + return Uint32Array::create(m_compressedTextureFormats.data(), m_compressedTextureFormats.size()); case GraphicsContext3D::CULL_FACE: return getBooleanParameter(pname); case GraphicsContext3D::CULL_FACE_MODE: return getUnsignedIntParameter(pname); case GraphicsContext3D::CURRENT_PROGRAM: - return WebGLGetInfo(PassRefPtr<WebGLProgram>(m_currentProgram)); + return m_currentProgram; case GraphicsContext3D::DEPTH_BITS: if (!m_framebufferBinding && !m_attributes.depth) - return WebGLGetInfo(intZero); + return 0; return getIntParameter(pname); case GraphicsContext3D::DEPTH_CLEAR_VALUE: return getFloatParameter(pname); @@ -2679,15 +536,19 @@ WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname, ExceptionCode& case GraphicsContext3D::DITHER: return getBooleanParameter(pname); case GraphicsContext3D::ELEMENT_ARRAY_BUFFER_BINDING: - return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundVertexArrayObject->getElementArrayBuffer())); + return makeRefPtr(m_boundVertexArrayObject->getElementArrayBuffer()); case GraphicsContext3D::FRAMEBUFFER_BINDING: - return WebGLGetInfo(PassRefPtr<WebGLFramebuffer>(m_framebufferBinding)); + return m_framebufferBinding; case GraphicsContext3D::FRONT_FACE: return getUnsignedIntParameter(pname); case GraphicsContext3D::GENERATE_MIPMAP_HINT: return getUnsignedIntParameter(pname); case GraphicsContext3D::GREEN_BITS: return getIntParameter(pname); + case GraphicsContext3D::IMPLEMENTATION_COLOR_READ_FORMAT: + return getIntParameter(pname); + case GraphicsContext3D::IMPLEMENTATION_COLOR_READ_TYPE: + return getIntParameter(pname); case GraphicsContext3D::LINE_WIDTH: return getFloatParameter(pname); case GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS: @@ -2713,7 +574,6 @@ WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname, ExceptionCode& case GraphicsContext3D::MAX_VIEWPORT_DIMS: return getWebGLIntArrayParameter(pname); case GraphicsContext3D::NUM_SHADER_BINARY_FORMATS: - // FIXME: should we always return 0 for this? return getIntParameter(pname); case GraphicsContext3D::PACK_ALIGNMENT: return getIntParameter(pname); @@ -2726,9 +586,9 @@ WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname, ExceptionCode& case GraphicsContext3D::RED_BITS: return getIntParameter(pname); case GraphicsContext3D::RENDERBUFFER_BINDING: - return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(m_renderbufferBinding)); + return m_renderbufferBinding; case GraphicsContext3D::RENDERER: - return WebGLGetInfo(String("WebKit WebGL")); + return String { ASCIILiteral { "WebKit WebGL" } }; case GraphicsContext3D::SAMPLE_BUFFERS: return getIntParameter(pname); case GraphicsContext3D::SAMPLE_COVERAGE_INVERT: @@ -2742,7 +602,7 @@ WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname, ExceptionCode& case GraphicsContext3D::SCISSOR_TEST: return getBooleanParameter(pname); case GraphicsContext3D::SHADING_LANGUAGE_VERSION: - return WebGLGetInfo("WebGL GLSL ES 1.0 (" + m_context->getString(GraphicsContext3D::SHADING_LANGUAGE_VERSION) + ")"); + return "WebGL GLSL ES 1.0 (" + m_context->getString(GraphicsContext3D::SHADING_LANGUAGE_VERSION) + ")"; case GraphicsContext3D::STENCIL_BACK_FAIL: return getUnsignedIntParameter(pname); case GraphicsContext3D::STENCIL_BACK_FUNC: @@ -2759,7 +619,7 @@ WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname, ExceptionCode& return getUnsignedIntParameter(pname); case GraphicsContext3D::STENCIL_BITS: if (!m_framebufferBinding && !m_attributes.stencil) - return WebGLGetInfo(intZero); + return 0; return getIntParameter(pname); case GraphicsContext3D::STENCIL_CLEAR_VALUE: return getIntParameter(pname); @@ -2782,63 +642,63 @@ WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname, ExceptionCode& case GraphicsContext3D::SUBPIXEL_BITS: return getIntParameter(pname); case GraphicsContext3D::TEXTURE_BINDING_2D: - return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].texture2DBinding)); + return m_textureUnits[m_activeTextureUnit].texture2DBinding; case GraphicsContext3D::TEXTURE_BINDING_CUBE_MAP: - return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].textureCubeMapBinding)); + return m_textureUnits[m_activeTextureUnit].textureCubeMapBinding; case GraphicsContext3D::UNPACK_ALIGNMENT: return getIntParameter(pname); case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL: - return WebGLGetInfo(m_unpackFlipY); + return m_unpackFlipY; case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL: - return WebGLGetInfo(m_unpackPremultiplyAlpha); + return m_unpackPremultiplyAlpha; case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL: - return WebGLGetInfo(m_unpackColorspaceConversion); + return m_unpackColorspaceConversion; case GraphicsContext3D::VENDOR: - return WebGLGetInfo(String("WebKit")); + return String { ASCIILiteral { "WebKit" } }; case GraphicsContext3D::VERSION: - return WebGLGetInfo("WebGL 1.0 (" + m_context->getString(GraphicsContext3D::VERSION) + ")"); + return "WebGL 1.0 (" + m_context->getString(GraphicsContext3D::VERSION) + ")"; case GraphicsContext3D::VIEWPORT: return getWebGLIntArrayParameter(pname); case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives if (m_oesStandardDerivatives) return getUnsignedIntParameter(Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES); synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, OES_standard_derivatives not enabled"); - return WebGLGetInfo(); + return nullptr; case WebGLDebugRendererInfo::UNMASKED_RENDERER_WEBGL: if (m_webglDebugRendererInfo) - return WebGLGetInfo(m_context->getString(GraphicsContext3D::RENDERER)); + return m_context->getString(GraphicsContext3D::RENDERER); synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled"); - return WebGLGetInfo(); + return nullptr; case WebGLDebugRendererInfo::UNMASKED_VENDOR_WEBGL: if (m_webglDebugRendererInfo) - return WebGLGetInfo(m_context->getString(GraphicsContext3D::VENDOR)); + return m_context->getString(GraphicsContext3D::VENDOR); synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled"); - return WebGLGetInfo(); + return nullptr; case Extensions3D::VERTEX_ARRAY_BINDING_OES: // OES_vertex_array_object if (m_oesVertexArrayObject) { - if (!m_boundVertexArrayObject->isDefaultObject()) - return WebGLGetInfo(PassRefPtr<WebGLVertexArrayObjectOES>(m_boundVertexArrayObject)); - return WebGLGetInfo(); + if (m_boundVertexArrayObject->isDefaultObject()) + return nullptr; + return makeRefPtr(static_cast<WebGLVertexArrayObjectOES&>(*m_boundVertexArrayObject)); } synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, OES_vertex_array_object not enabled"); - return WebGLGetInfo(); + return nullptr; case Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic if (m_extTextureFilterAnisotropic) return getUnsignedIntParameter(Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT); synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled"); - return WebGLGetInfo(); + return nullptr; case Extensions3D::MAX_COLOR_ATTACHMENTS_EXT: // EXT_draw_buffers BEGIN - if (m_extDrawBuffers) - return WebGLGetInfo(getMaxColorAttachments()); - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, EXT_draw_buffers not enabled"); - return WebGLGetInfo(); + if (m_webglDrawBuffers) + return getMaxColorAttachments(); + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled"); + return nullptr; case Extensions3D::MAX_DRAW_BUFFERS_EXT: - if (m_extDrawBuffers) - return WebGLGetInfo(getMaxDrawBuffers()); - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, EXT_draw_buffers not enabled"); - return WebGLGetInfo(); + if (m_webglDrawBuffers) + return getMaxDrawBuffers(); + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled"); + return nullptr; default: - if (m_extDrawBuffers + if (m_webglDrawBuffers && pname >= Extensions3D::DRAW_BUFFER0_EXT && pname < static_cast<GC3Denum>(Extensions3D::DRAW_BUFFER0_EXT + getMaxDrawBuffers())) { GC3Dint value = GraphicsContext3D::NONE; @@ -2846,2751 +706,96 @@ WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname, ExceptionCode& value = m_framebufferBinding->getDrawBuffer(pname); else // emulated backbuffer value = m_backDrawBuffer; - return WebGLGetInfo(value); + return value; } synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name"); - return WebGLGetInfo(); - } -} - -WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, GC3Denum pname, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateWebGLObject("getProgramParameter", program)) - return WebGLGetInfo(); - - WebGLStateRestorer(this, false); - GC3Dint value = 0; - switch (pname) { - case GraphicsContext3D::DELETE_STATUS: - return WebGLGetInfo(program->isDeleted()); - case GraphicsContext3D::VALIDATE_STATUS: - m_context->getProgramiv(objectOrZero(program), pname, &value); - return WebGLGetInfo(static_cast<bool>(value)); - case GraphicsContext3D::LINK_STATUS: - return WebGLGetInfo(program->getLinkStatus()); - case GraphicsContext3D::ATTACHED_SHADERS: - m_context->getProgramiv(objectOrZero(program), pname, &value); - return WebGLGetInfo(value); - case GraphicsContext3D::ACTIVE_ATTRIBUTES: - case GraphicsContext3D::ACTIVE_UNIFORMS: - m_context->getNonBuiltInActiveSymbolCount(objectOrZero(program), pname, &value); - return WebGLGetInfo(value); - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getProgramParameter", "invalid parameter name"); - return WebGLGetInfo(); - } -} - -String WebGLRenderingContext::getProgramInfoLog(WebGLProgram* program, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost()) - return String(); - if (!validateWebGLObject("getProgramInfoLog", program)) - return ""; - WebGLStateRestorer(this, false); - return ensureNotNull(m_context->getProgramInfoLog(objectOrZero(program))); -} - -WebGLGetInfo WebGLRenderingContext::getRenderbufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost()) - return WebGLGetInfo(); - if (target != GraphicsContext3D::RENDERBUFFER) { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid target"); - return WebGLGetInfo(); - } - if (!m_renderbufferBinding || !m_renderbufferBinding->object()) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getRenderbufferParameter", "no renderbuffer bound"); - return WebGLGetInfo(); - } - - if (m_renderbufferBinding->getInternalFormat() == GraphicsContext3D::DEPTH_STENCIL - && !m_renderbufferBinding->isValid()) { - ASSERT(!isDepthStencilSupported()); - int value = 0; - switch (pname) { - case GraphicsContext3D::RENDERBUFFER_WIDTH: - value = m_renderbufferBinding->getWidth(); - break; - case GraphicsContext3D::RENDERBUFFER_HEIGHT: - value = m_renderbufferBinding->getHeight(); - break; - case GraphicsContext3D::RENDERBUFFER_RED_SIZE: - case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE: - case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE: - case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE: - value = 0; - break; - case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE: - value = 24; - break; - case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE: - value = 8; - break; - case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT: - return WebGLGetInfo(m_renderbufferBinding->getInternalFormat()); - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid parameter name"); - return WebGLGetInfo(); - } - return WebGLGetInfo(value); - } - - WebGLStateRestorer(this, false); - GC3Dint value = 0; - switch (pname) { - case GraphicsContext3D::RENDERBUFFER_WIDTH: - case GraphicsContext3D::RENDERBUFFER_HEIGHT: - case GraphicsContext3D::RENDERBUFFER_RED_SIZE: - case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE: - case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE: - case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE: - case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE: - case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE: - m_context->getRenderbufferParameteriv(target, pname, &value); - return WebGLGetInfo(value); - case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT: - return WebGLGetInfo(m_renderbufferBinding->getInternalFormat()); - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid parameter name"); - return WebGLGetInfo(); - } -} - -WebGLGetInfo WebGLRenderingContext::getShaderParameter(WebGLShader* shader, GC3Denum pname, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateWebGLObject("getShaderParameter", shader)) - return WebGLGetInfo(); - WebGLStateRestorer(this, false); - GC3Dint value = 0; - switch (pname) { - case GraphicsContext3D::DELETE_STATUS: - return WebGLGetInfo(shader->isDeleted()); - case GraphicsContext3D::COMPILE_STATUS: - m_context->getShaderiv(objectOrZero(shader), pname, &value); - return WebGLGetInfo(static_cast<bool>(value)); - case GraphicsContext3D::SHADER_TYPE: - m_context->getShaderiv(objectOrZero(shader), pname, &value); - return WebGLGetInfo(static_cast<unsigned int>(value)); - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderParameter", "invalid parameter name"); - return WebGLGetInfo(); - } -} - -String WebGLRenderingContext::getShaderInfoLog(WebGLShader* shader, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost()) - return String(); - if (!validateWebGLObject("getShaderInfoLog", shader)) - return ""; - WebGLStateRestorer(this, false); - return ensureNotNull(m_context->getShaderInfoLog(objectOrZero(shader))); -} - -PassRefPtr<WebGLShaderPrecisionFormat> WebGLRenderingContext::getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost()) - return 0; - switch (shaderType) { - case GraphicsContext3D::VERTEX_SHADER: - case GraphicsContext3D::FRAGMENT_SHADER: - break; - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderPrecisionFormat", "invalid shader type"); - return 0; - } - switch (precisionType) { - case GraphicsContext3D::LOW_FLOAT: - case GraphicsContext3D::MEDIUM_FLOAT: - case GraphicsContext3D::HIGH_FLOAT: - case GraphicsContext3D::LOW_INT: - case GraphicsContext3D::MEDIUM_INT: - case GraphicsContext3D::HIGH_INT: - break; - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderPrecisionFormat", "invalid precision type"); - return 0; - } - - GC3Dint range[2] = {0, 0}; - GC3Dint precision = 0; - m_context->getShaderPrecisionFormat(shaderType, precisionType, range, &precision); - return WebGLShaderPrecisionFormat::create(range[0], range[1], precision); -} - -String WebGLRenderingContext::getShaderSource(WebGLShader* shader, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost()) - return String(); - if (!validateWebGLObject("getShaderSource", shader)) - return ""; - return ensureNotNull(shader->getSource()); -} - -Vector<String> WebGLRenderingContext::getSupportedExtensions() -{ - Vector<String> result; - if (m_context->getExtensions()->supports("GL_OES_texture_float")) - result.append("OES_texture_float"); - if (m_context->getExtensions()->supports("GL_OES_texture_float_linear")) - result.append("OES_texture_float_linear"); - if (m_context->getExtensions()->supports("GL_OES_texture_half_float")) - result.append("OES_texture_half_float"); - if (m_context->getExtensions()->supports("GL_OES_texture_half_float_linear")) - result.append("OES_texture_half_float_linear"); - if (m_context->getExtensions()->supports("GL_OES_standard_derivatives")) - result.append("OES_standard_derivatives"); - if (m_context->getExtensions()->supports("GL_EXT_texture_filter_anisotropic")) - result.append("WEBKIT_EXT_texture_filter_anisotropic"); - if (m_context->getExtensions()->supports("GL_OES_vertex_array_object")) - result.append("OES_vertex_array_object"); - if (m_context->getExtensions()->supports("GL_OES_element_index_uint")) - result.append("OES_element_index_uint"); - result.append("WEBGL_lose_context"); - if (WebGLCompressedTextureATC::supported(this)) - result.append("WEBKIT_WEBGL_compressed_texture_atc"); - if (WebGLCompressedTexturePVRTC::supported(this)) - result.append("WEBKIT_WEBGL_compressed_texture_pvrtc"); - if (WebGLCompressedTextureS3TC::supported(this)) - result.append("WEBGL_compressed_texture_s3tc"); - if (WebGLDepthTexture::supported(graphicsContext3D())) - result.append("WEBGL_depth_texture"); - if (supportsDrawBuffers()) - result.append("EXT_draw_buffers"); - if (ANGLEInstancedArrays::supported(this)) - result.append("ANGLE_instanced_arrays"); - - if (allowPrivilegedExtensions()) { - if (m_context->getExtensions()->supports("GL_ANGLE_translated_shader_source")) - result.append("WEBGL_debug_shaders"); - result.append("WEBGL_debug_renderer_info"); - } - - return result; -} - -WebGLGetInfo WebGLRenderingContext::getTexParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost()) - return WebGLGetInfo(); - WebGLTexture* tex = validateTextureBinding("getTexParameter", target, false); - if (!tex) - return WebGLGetInfo(); - WebGLStateRestorer(this, false); - GC3Dint value = 0; - switch (pname) { - case GraphicsContext3D::TEXTURE_MAG_FILTER: - case GraphicsContext3D::TEXTURE_MIN_FILTER: - case GraphicsContext3D::TEXTURE_WRAP_S: - case GraphicsContext3D::TEXTURE_WRAP_T: - m_context->getTexParameteriv(target, pname, &value); - return WebGLGetInfo(static_cast<unsigned int>(value)); - case Extensions3D::TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic - if (m_extTextureFilterAnisotropic) { - m_context->getTexParameteriv(target, pname, &value); - return WebGLGetInfo(static_cast<unsigned int>(value)); - } - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getTexParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled"); - return WebGLGetInfo(); - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getTexParameter", "invalid parameter name"); - return WebGLGetInfo(); - } -} - -WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebGLUniformLocation* uniformLocation, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateWebGLObject("getUniform", program)) - return WebGLGetInfo(); - if (!uniformLocation || uniformLocation->program() != program) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getUniform", "no uniformlocation or not valid for this program"); - return WebGLGetInfo(); - } - GC3Dint location = uniformLocation->location(); - - WebGLStateRestorer(this, false); - GC3Denum baseType; - unsigned length; - switch (uniformLocation->type()) { - case GraphicsContext3D::BOOL: - baseType = GraphicsContext3D::BOOL; - length = 1; - break; - case GraphicsContext3D::BOOL_VEC2: - baseType = GraphicsContext3D::BOOL; - length = 2; - break; - case GraphicsContext3D::BOOL_VEC3: - baseType = GraphicsContext3D::BOOL; - length = 3; - break; - case GraphicsContext3D::BOOL_VEC4: - baseType = GraphicsContext3D::BOOL; - length = 4; - break; - case GraphicsContext3D::INT: - baseType = GraphicsContext3D::INT; - length = 1; - break; - case GraphicsContext3D::INT_VEC2: - baseType = GraphicsContext3D::INT; - length = 2; - break; - case GraphicsContext3D::INT_VEC3: - baseType = GraphicsContext3D::INT; - length = 3; - break; - case GraphicsContext3D::INT_VEC4: - baseType = GraphicsContext3D::INT; - length = 4; - break; - case GraphicsContext3D::FLOAT: - baseType = GraphicsContext3D::FLOAT; - length = 1; - break; - case GraphicsContext3D::FLOAT_VEC2: - baseType = GraphicsContext3D::FLOAT; - length = 2; - break; - case GraphicsContext3D::FLOAT_VEC3: - baseType = GraphicsContext3D::FLOAT; - length = 3; - break; - case GraphicsContext3D::FLOAT_VEC4: - baseType = GraphicsContext3D::FLOAT; - length = 4; - break; - case GraphicsContext3D::FLOAT_MAT2: - baseType = GraphicsContext3D::FLOAT; - length = 4; - break; - case GraphicsContext3D::FLOAT_MAT3: - baseType = GraphicsContext3D::FLOAT; - length = 9; - break; - case GraphicsContext3D::FLOAT_MAT4: - baseType = GraphicsContext3D::FLOAT; - length = 16; - break; - case GraphicsContext3D::SAMPLER_2D: - case GraphicsContext3D::SAMPLER_CUBE: - baseType = GraphicsContext3D::INT; - length = 1; - break; - default: - // Can't handle this type - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getUniform", "unhandled type"); - return WebGLGetInfo(); - } - switch (baseType) { - case GraphicsContext3D::FLOAT: { - GC3Dfloat value[16] = {0}; - if (m_isRobustnessEXTSupported) - m_context->getExtensions()->getnUniformfvEXT(objectOrZero(program), location, 16 * sizeof(GC3Dfloat), value); - else - m_context->getUniformfv(objectOrZero(program), location, value); - if (length == 1) - return WebGLGetInfo(value[0]); - return WebGLGetInfo(Float32Array::create(value, length)); - } - case GraphicsContext3D::INT: { - GC3Dint value[4] = {0}; - if (m_isRobustnessEXTSupported) - m_context->getExtensions()->getnUniformivEXT(objectOrZero(program), location, 4 * sizeof(GC3Dint), value); - else - m_context->getUniformiv(objectOrZero(program), location, value); - if (length == 1) - return WebGLGetInfo(value[0]); - return WebGLGetInfo(Int32Array::create(value, length)); - } - case GraphicsContext3D::BOOL: { - GC3Dint value[4] = {0}; - if (m_isRobustnessEXTSupported) - m_context->getExtensions()->getnUniformivEXT(objectOrZero(program), location, 4 * sizeof(GC3Dint), value); - else - m_context->getUniformiv(objectOrZero(program), location, value); - if (length > 1) { - bool boolValue[16] = {0}; - for (unsigned j = 0; j < length; j++) - boolValue[j] = static_cast<bool>(value[j]); - return WebGLGetInfo(boolValue, length); - } - return WebGLGetInfo(static_cast<bool>(value[0])); - } - default: - notImplemented(); - } - - // If we get here, something went wrong in our unfortunately complex logic above - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getUniform", "unknown error"); - return WebGLGetInfo(); -} - -PassRefPtr<WebGLUniformLocation> WebGLRenderingContext::getUniformLocation(WebGLProgram* program, const String& name, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateWebGLObject("getUniformLocation", program)) - return nullptr; - if (!validateLocationLength("getUniformLocation", name)) - return nullptr; - if (!validateString("getUniformLocation", name)) return nullptr; - if (isPrefixReserved(name)) - return nullptr; - if (!program->getLinkStatus()) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getUniformLocation", "program not linked"); - return nullptr; - } - WebGLStateRestorer(this, false); - GC3Dint uniformLocation = m_context->getUniformLocation(objectOrZero(program), name); - if (uniformLocation == -1) - return nullptr; - - GC3Dint activeUniforms = 0; - m_context->getProgramiv(objectOrZero(program), GraphicsContext3D::ACTIVE_UNIFORMS, &activeUniforms); - for (GC3Dint i = 0; i < activeUniforms; i++) { - ActiveInfo info; - if (!m_context->getActiveUniform(objectOrZero(program), i, info)) - return 0; - // Strip "[0]" from the name if it's an array. - if (info.name.endsWith("[0]")) - info.name = info.name.left(info.name.length() - 3); - // If it's an array, we need to iterate through each element, appending "[index]" to the name. - for (GC3Dint index = 0; index < info.size; ++index) { - String uniformName = info.name + "[" + String::number(index) + "]"; - - if (name == uniformName || name == info.name) - return WebGLUniformLocation::create(program, uniformLocation, info.type); - } - } - return nullptr; -} - -WebGLGetInfo WebGLRenderingContext::getVertexAttrib(GC3Duint index, GC3Denum pname, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - - if (isContextLost()) - return WebGLGetInfo(); - - WebGLStateRestorer(this, false); - - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getVertexAttrib", "index out of range"); - return WebGLGetInfo(); - } - - const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index); - - if (m_angleInstancedArrays && pname == GraphicsContext3D::VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE) - return WebGLGetInfo(state.divisor); - - switch (pname) { - case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: - if ((!isGLES2Compliant() && !index && m_boundVertexArrayObject->getVertexAttribState(0).bufferBinding == m_vertexAttrib0Buffer) - || !state.bufferBinding - || !state.bufferBinding->object()) - return WebGLGetInfo(); - return WebGLGetInfo(PassRefPtr<WebGLBuffer>(state.bufferBinding)); - case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_ENABLED: - return WebGLGetInfo(state.enabled); - case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_NORMALIZED: - return WebGLGetInfo(state.normalized); - case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_SIZE: - return WebGLGetInfo(state.size); - case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_STRIDE: - return WebGLGetInfo(state.originalStride); - case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_TYPE: - return WebGLGetInfo(state.type); - case GraphicsContext3D::CURRENT_VERTEX_ATTRIB: - return WebGLGetInfo(Float32Array::create(m_vertexAttribValue[index].value, 4)); - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getVertexAttrib", "invalid parameter name"); - return WebGLGetInfo(); } } -long long WebGLRenderingContext::getVertexAttribOffset(GC3Duint index, GC3Denum pname) -{ - if (isContextLost()) - return 0; - GC3Dsizeiptr result = m_context->getVertexAttribOffset(index, pname); - cleanupAfterGraphicsCall(false); - return static_cast<long long>(result); -} - -void WebGLRenderingContext::hint(GC3Denum target, GC3Denum mode) -{ - if (isContextLost()) - return; - bool isValid = false; - switch (target) { - case GraphicsContext3D::GENERATE_MIPMAP_HINT: - isValid = true; - break; - case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives - if (m_oesStandardDerivatives) - isValid = true; - break; - } - if (!isValid) { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "hint", "invalid target"); - return; - } - m_context->hint(target, mode); - cleanupAfterGraphicsCall(false); -} - -GC3Dboolean WebGLRenderingContext::isBuffer(WebGLBuffer* buffer) -{ - if (!buffer || isContextLost()) - return 0; - - if (!buffer->hasEverBeenBound()) - return 0; - - return m_context->isBuffer(buffer->object()); -} - -bool WebGLRenderingContext::isContextLost() const -{ - return m_contextLost; -} - -GC3Dboolean WebGLRenderingContext::isEnabled(GC3Denum cap) -{ - if (isContextLost() || !validateCapability("isEnabled", cap)) - return 0; - if (cap == GraphicsContext3D::STENCIL_TEST) - return m_stencilEnabled; - return m_context->isEnabled(cap); -} - -GC3Dboolean WebGLRenderingContext::isFramebuffer(WebGLFramebuffer* framebuffer) -{ - if (!framebuffer || isContextLost()) - return 0; - - if (!framebuffer->hasEverBeenBound()) - return 0; - - return m_context->isFramebuffer(framebuffer->object()); -} - -GC3Dboolean WebGLRenderingContext::isProgram(WebGLProgram* program) -{ - if (!program || isContextLost()) - return 0; - - return m_context->isProgram(program->object()); -} - -GC3Dboolean WebGLRenderingContext::isRenderbuffer(WebGLRenderbuffer* renderbuffer) -{ - if (!renderbuffer || isContextLost()) - return 0; - - if (!renderbuffer->hasEverBeenBound()) - return 0; - - return m_context->isRenderbuffer(renderbuffer->object()); -} - -GC3Dboolean WebGLRenderingContext::isShader(WebGLShader* shader) +GC3Dint WebGLRenderingContext::getMaxDrawBuffers() { - if (!shader || isContextLost()) + if (!supportsDrawBuffers()) return 0; - - return m_context->isShader(shader->object()); + if (!m_maxDrawBuffers) + m_context->getIntegerv(Extensions3D::MAX_DRAW_BUFFERS_EXT, &m_maxDrawBuffers); + if (!m_maxColorAttachments) + m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments); + // WEBGL_draw_buffers requires MAX_COLOR_ATTACHMENTS >= MAX_DRAW_BUFFERS. + return std::min(m_maxDrawBuffers, m_maxColorAttachments); } -GC3Dboolean WebGLRenderingContext::isTexture(WebGLTexture* texture) +GC3Dint WebGLRenderingContext::getMaxColorAttachments() { - if (!texture || isContextLost()) - return 0; - - if (!texture->hasEverBeenBound()) + if (!supportsDrawBuffers()) return 0; - - return m_context->isTexture(texture->object()); -} - -void WebGLRenderingContext::lineWidth(GC3Dfloat width) -{ - if (isContextLost()) - return; - m_context->lineWidth(width); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::linkProgram(WebGLProgram* program, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateWebGLObject("linkProgram", program)) - return; - if (!isGLES2Compliant()) { - WebGLShader* vertexShader = program->getAttachedShader(GraphicsContext3D::VERTEX_SHADER); - WebGLShader* fragmentShader = program->getAttachedShader(GraphicsContext3D::FRAGMENT_SHADER); - if (!vertexShader || !vertexShader->isValid() || !fragmentShader || !fragmentShader->isValid() || !m_context->precisionsMatch(objectOrZero(vertexShader), objectOrZero(fragmentShader))) { - program->setLinkStatus(false); - return; - } - } - - m_context->linkProgram(objectOrZero(program)); - program->increaseLinkCount(); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::pixelStorei(GC3Denum pname, GC3Dint param) -{ - if (isContextLost()) - return; - switch (pname) { - case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL: - m_unpackFlipY = param; - break; - case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL: - m_unpackPremultiplyAlpha = param; - break; - case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL: - if (param == GraphicsContext3D::BROWSER_DEFAULT_WEBGL || param == GraphicsContext3D::NONE) - m_unpackColorspaceConversion = static_cast<GC3Denum>(param); - else { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "pixelStorei", "invalid parameter for UNPACK_COLORSPACE_CONVERSION_WEBGL"); - return; - } - break; - case GraphicsContext3D::PACK_ALIGNMENT: - case GraphicsContext3D::UNPACK_ALIGNMENT: - if (param == 1 || param == 2 || param == 4 || param == 8) { - if (pname == GraphicsContext3D::PACK_ALIGNMENT) - m_packAlignment = param; - else // GraphicsContext3D::UNPACK_ALIGNMENT: - m_unpackAlignment = param; - m_context->pixelStorei(pname, param); - cleanupAfterGraphicsCall(false); - } else { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "pixelStorei", "invalid parameter for alignment"); - return; - } - break; - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "pixelStorei", "invalid parameter name"); - return; - } -} - -void WebGLRenderingContext::polygonOffset(GC3Dfloat factor, GC3Dfloat units) -{ - if (isContextLost()) - return; - m_context->polygonOffset(factor, units); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode&) -{ - if (isContextLost()) - return; - // Due to WebGL's same-origin restrictions, it is not possible to - // taint the origin using the WebGL API. - ASSERT(canvas()->originClean()); - // Validate input parameters. - if (!pixels) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "readPixels", "no destination ArrayBufferView"); - return; - } - switch (format) { - case GraphicsContext3D::ALPHA: - case GraphicsContext3D::RGB: - case GraphicsContext3D::RGBA: - break; - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "invalid format"); - return; - } - switch (type) { - case GraphicsContext3D::UNSIGNED_BYTE: - case GraphicsContext3D::UNSIGNED_SHORT_5_6_5: - case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4: - case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1: - break; - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "invalid type"); - return; - } - if (format != GraphicsContext3D::RGBA || type != GraphicsContext3D::UNSIGNED_BYTE) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "format not RGBA or type not UNSIGNED_BYTE"); - return; - } - // Validate array type against pixel type. - if (pixels->getType() != JSC::TypeUint8) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "ArrayBufferView not Uint8Array"); - return; - } - const char* reason = "framebuffer incomplete"; - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), !isResourceSafe(), &reason)) { - synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "readPixels", reason); - return; - } - // Calculate array size, taking into consideration of PACK_ALIGNMENT. - unsigned int totalBytesRequired = 0; - unsigned int padding = 0; - if (!m_isRobustnessEXTSupported) { - GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding); - if (error != GraphicsContext3D::NO_ERROR) { - synthesizeGLError(error, "readPixels", "invalid dimensions"); - return; - } - if (pixels->byteLength() < totalBytesRequired) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "ArrayBufferView not large enough for dimensions"); - return; - } - } - - clearIfComposited(); - void* data = pixels->baseAddress(); - - { - ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get()); - if (m_isRobustnessEXTSupported) - m_context->getExtensions()->readnPixelsEXT(x, y, width, height, format, type, pixels->byteLength(), data); - else - m_context->readPixels(x, y, width, height, format, type, data); - } - -#if OS(DARWIN) - if (m_isRobustnessEXTSupported) // we haven't computed padding - m_context->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding); - // FIXME: remove this section when GL driver bug on Mac AND the GLES driver bug - // on QC is fixed, i.e., when alpha is off, readPixels should - // set alpha to 255 instead of 0. - if (!m_framebufferBinding && !m_context->getContextAttributes().alpha) { - unsigned char* pixels = reinterpret_cast<unsigned char*>(data); - for (GC3Dsizei iy = 0; iy < height; ++iy) { - for (GC3Dsizei ix = 0; ix < width; ++ix) { - pixels[3] = 255; - pixels += 4; - } - pixels += padding; - } - } -#endif - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::releaseShaderCompiler() -{ - if (isContextLost()) - return; - m_context->releaseShaderCompiler(); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) -{ - if (isContextLost()) - return; - if (target != GraphicsContext3D::RENDERBUFFER) { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid target"); - return; - } - if (!m_renderbufferBinding || !m_renderbufferBinding->object()) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "renderbufferStorage", "no bound renderbuffer"); - return; - } - if (!validateSize("renderbufferStorage", width, height)) - return; - switch (internalformat) { - case GraphicsContext3D::DEPTH_COMPONENT16: - case GraphicsContext3D::RGBA4: - case GraphicsContext3D::RGB5_A1: - case GraphicsContext3D::RGB565: - case GraphicsContext3D::STENCIL_INDEX8: - m_context->renderbufferStorage(target, internalformat, width, height); - m_renderbufferBinding->setInternalFormat(internalformat); - m_renderbufferBinding->setIsValid(true); - m_renderbufferBinding->setSize(width, height); - cleanupAfterGraphicsCall(false); - break; - case GraphicsContext3D::DEPTH_STENCIL: - if (isDepthStencilSupported()) { - m_context->renderbufferStorage(target, Extensions3D::DEPTH24_STENCIL8, width, height); - cleanupAfterGraphicsCall(false); - } - m_renderbufferBinding->setSize(width, height); - m_renderbufferBinding->setIsValid(isDepthStencilSupported()); - m_renderbufferBinding->setInternalFormat(internalformat); - break; - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid internalformat"); - return; - } - applyStencilTest(); -} - -void WebGLRenderingContext::sampleCoverage(GC3Dfloat value, GC3Dboolean invert) -{ - if (isContextLost()) - return; - m_context->sampleCoverage(value, invert); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) -{ - if (isContextLost()) - return; - if (!validateSize("scissor", width, height)) - return; - m_context->scissor(x, y, width, height); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::shaderSource(WebGLShader* shader, const String& string, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateWebGLObject("shaderSource", shader)) - return; - String stringWithoutComments = StripComments(string).result(); - if (!validateString("shaderSource", stringWithoutComments)) - return; - shader->setSource(string); - m_context->shaderSource(objectOrZero(shader), stringWithoutComments); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask) -{ - if (isContextLost()) - return; - if (!validateStencilFunc("stencilFunc", func)) - return; - m_stencilFuncRef = ref; - m_stencilFuncRefBack = ref; - m_stencilFuncMask = mask; - m_stencilFuncMaskBack = mask; - m_context->stencilFunc(func, ref, mask); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask) -{ - if (isContextLost()) - return; - if (!validateStencilFunc("stencilFuncSeparate", func)) - return; - switch (face) { - case GraphicsContext3D::FRONT_AND_BACK: - m_stencilFuncRef = ref; - m_stencilFuncRefBack = ref; - m_stencilFuncMask = mask; - m_stencilFuncMaskBack = mask; - break; - case GraphicsContext3D::FRONT: - m_stencilFuncRef = ref; - m_stencilFuncMask = mask; - break; - case GraphicsContext3D::BACK: - m_stencilFuncRefBack = ref; - m_stencilFuncMaskBack = mask; - break; - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "stencilFuncSeparate", "invalid face"); - return; - } - m_context->stencilFuncSeparate(face, func, ref, mask); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::stencilMask(GC3Duint mask) -{ - if (isContextLost()) - return; - m_stencilMask = mask; - m_stencilMaskBack = mask; - m_context->stencilMask(mask); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::stencilMaskSeparate(GC3Denum face, GC3Duint mask) -{ - if (isContextLost()) - return; - switch (face) { - case GraphicsContext3D::FRONT_AND_BACK: - m_stencilMask = mask; - m_stencilMaskBack = mask; - break; - case GraphicsContext3D::FRONT: - m_stencilMask = mask; - break; - case GraphicsContext3D::BACK: - m_stencilMaskBack = mask; - break; - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "stencilMaskSeparate", "invalid face"); - return; - } - m_context->stencilMaskSeparate(face, mask); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass) -{ - if (isContextLost()) - return; - m_context->stencilOp(fail, zfail, zpass); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass) -{ - if (isContextLost()) - return; - m_context->stencilOpSeparate(face, fail, zfail, zpass); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode& ec) -{ - // FIXME: For now we ignore any errors returned - ec = 0; - WebGLTexture* tex = validateTextureBinding("texImage2D", target, true); - ASSERT(validateTexFuncParameters("texImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, format, type)); - ASSERT(tex); - ASSERT(!level || !WebGLTexture::isNPOT(width, height)); - if (!pixels) { - // Note: Chromium's OpenGL implementation clears textures and isResourceSafe() is therefore true. - // For other implementations, if they are using ANGLE_depth_texture, ANGLE depth textures - // can not be cleared with texImage2D and must be cleared by binding to an fbo and calling - // clear. - if (isResourceSafe()) - m_context->texImage2D(target, level, internalformat, width, height, border, format, type, 0); - else { - bool succeed = m_context->texImage2DResourceSafe(target, level, internalformat, width, height, - border, format, type, m_unpackAlignment); - if (!succeed) - return; - } - } else { - ASSERT(validateSettableTexFormat("texImage2D", internalformat)); - m_context->texImage2D(target, level, internalformat, width, height, - border, format, type, pixels); - } - tex->setLevelInfo(target, level, internalformat, width, height, type); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionCode& ec) -{ - ec = 0; - Vector<uint8_t> data; - GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE); - if (!imageExtractor.extractSucceeded()) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data"); - return; - } - GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat(); - GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp(); - const void* imagePixelData = imageExtractor.imagePixelData(); - - bool needConversion = true; - if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY) - needConversion = false; - else { - if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "packImage error"); - return; - } - } - - if (m_unpackAlignment != 1) - m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1); - texImage2DBase(target, level, internalformat, image->width(), image->height(), 0, format, type, needConversion ? data.data() : imagePixelData, ec); - if (m_unpackAlignment != 1) - m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment); + if (!m_maxColorAttachments) + m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments); + return m_maxColorAttachments; } - -bool WebGLRenderingContext::validateTexFunc(const char* functionName, TexFuncValidationFunctionType functionType, TexFuncValidationSourceType sourceType, GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint xoffset, GC3Dint yoffset) + +bool WebGLRenderingContext::validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired) { - if (!validateTexFuncParameters(functionName, functionType, target, level, internalformat, width, height, border, format, type)) + // Performs conservative validation by caching a maximum index of + // the given type per element array buffer. If all of the bound + // array buffers have enough elements to satisfy that maximum + // index, skips the expensive per-draw-call iteration in + // validateIndexArrayPrecise. + + RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer(); + + if (!elementArrayBuffer) return false; - - WebGLTexture* texture = validateTextureBinding(functionName, target, true); - if (!texture) + + GC3Dsizeiptr numElements = elementArrayBuffer->byteLength(); + // The case count==0 is already dealt with in drawElements before validateIndexArrayConservative. + if (!numElements) return false; - - if (functionType == NotTexSubImage2D) { - if (level && WebGLTexture::isNPOT(width, height)) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level > 0 not power of 2"); - return false; - } - // For SourceArrayBufferView, function validateTexFuncData() would handle whether to validate the SettableTexFormat - // by checking if the ArrayBufferView is null or not. - if (sourceType != SourceArrayBufferView) { - if (!validateSettableTexFormat(functionName, format)) - return false; - } - } else { - if (!validateSettableTexFormat(functionName, format)) - return false; - if (!validateSize(functionName, xoffset, yoffset)) - return false; - // Before checking if it is in the range, check if overflow happens first. - if (xoffset + width < 0 || yoffset + height < 0) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "bad dimensions"); - return false; - } - if (xoffset + width > texture->getWidth(target, level) || yoffset + height > texture->getHeight(target, level)) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "dimensions out of range"); - return false; - } - if (texture->getInternalFormat(target, level) != format || texture->getType(target, level) != type) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type and format do not match texture"); - return false; - } - } - - return true; -} - -void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Dsizei width, GC3Dsizei height, GC3Dint border, - GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec) -{ - if (isContextLost() || !validateTexFuncData("texImage2D", level, width, height, format, type, pixels, NullAllowed) - || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceArrayBufferView, target, level, internalformat, width, height, border, format, type, 0, 0)) - return; - void* data = pixels ? pixels->baseAddress() : 0; - Vector<uint8_t> tempData; - bool changeUnpackAlignment = false; - if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) { - if (!m_context->extractTextureData(width, height, format, type, - m_unpackAlignment, - m_unpackFlipY, m_unpackPremultiplyAlpha, - data, - tempData)) - return; - data = tempData.data(); - changeUnpackAlignment = true; - } - if (changeUnpackAlignment) - m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1); - texImage2DBase(target, level, internalformat, width, height, border, - format, type, data, ec); - if (changeUnpackAlignment) - m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment); -} - -void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec) -{ - ec = 0; - if (isContextLost() || !pixels || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceImageData, target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, 0, 0)) - return; - Vector<uint8_t> data; - bool needConversion = true; - // The data from ImageData is always of format RGBA8. - // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required. - if (!m_unpackFlipY && !m_unpackPremultiplyAlpha && format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE) - needConversion = false; - else { - if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data"); - return; - } - } - if (m_unpackAlignment != 1) - m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1); - texImage2DBase(target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, needConversion ? data.data() : pixels->data()->data(), ec); - if (m_unpackAlignment != 1) - m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment); -} - -PassRefPtr<Image> WebGLRenderingContext::drawImageIntoBuffer(Image* image, int width, int height, int deviceScaleFactor) -{ - IntSize size(width, height); - size.scale(deviceScaleFactor); - ImageBuffer* buf = m_generatedImageCache.imageBuffer(size); - if (!buf) { - synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY, "texImage2D", "out of memory"); - return 0; - } - - IntRect srcRect(IntPoint(), image->size()); - IntRect destRect(IntPoint(), size); - buf->context()->drawImage(image, ColorSpaceDeviceRGB, destRect, srcRect); - return buf->copyImage(ImageBuffer::fastCopyImageMode()); -} - -void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec) -{ - ec = 0; - if (isContextLost() || !validateHTMLImageElement("texImage2D", image, ec)) - return; - - RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer()); - if (imageForRender->isSVGImage()) - imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height(), canvas()->deviceScaleFactor()); - - if (!imageForRender || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLImageElement, target, level, internalformat, imageForRender->width(), imageForRender->height(), 0, format, type, 0, 0)) - return; - - texImage2DImpl(target, level, internalformat, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, ec); -} - -void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec) -{ - ec = 0; - if (isContextLost() || !validateHTMLCanvasElement("texImage2D", canvas, ec) || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLCanvasElement, target, level, internalformat, canvas->width(), canvas->height(), 0, format, type, 0, 0)) - return; - - WebGLTexture* texture = validateTextureBinding("texImage2D", target, true); - // If possible, copy from the canvas element directly to the texture - // via the GPU, without a read-back to system memory. - // - // FIXME: restriction of (RGB || RGBA)/UNSIGNED_BYTE should be lifted when - // ImageBuffer::copyToPlatformTexture implementations are fully functional. - if (GraphicsContext3D::TEXTURE_2D == target && texture && type == texture->getType(target, level) - && (format == GraphicsContext3D::RGB || format == GraphicsContext3D::RGBA) && type == GraphicsContext3D::UNSIGNED_BYTE) { - ImageBuffer* buffer = canvas->buffer(); - if (buffer && buffer->copyToPlatformTexture(*m_context.get(), texture->object(), internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) { - texture->setLevelInfo(target, level, internalformat, canvas->width(), canvas->height(), type); - cleanupAfterGraphicsCall(false); - return; - } - } - - RefPtr<ImageData> imageData = canvas->getImageData(); - if (imageData) - texImage2D(target, level, internalformat, format, type, imageData.get(), ec); - else - texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, ec); -} - -#if ENABLE(VIDEO) -PassRefPtr<Image> WebGLRenderingContext::videoFrameToImage(HTMLVideoElement* video, BackingStoreCopy backingStoreCopy, ExceptionCode&) -{ - IntSize size(video->videoWidth(), video->videoHeight()); - ImageBuffer* buf = m_generatedImageCache.imageBuffer(size); - if (!buf) { - synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY, "texImage2D", "out of memory"); - return 0; - } - IntRect destRect(0, 0, size.width(), size.height()); - // FIXME: Turn this into a GPU-GPU texture copy instead of CPU readback. - video->paintCurrentFrameInContext(buf->context(), destRect); - return buf->copyImage(backingStoreCopy); -} - -void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec) -{ - ec = 0; - if (isContextLost() || !validateHTMLVideoElement("texImage2D", video, ec) - || !validateTexFunc("texImage2D", NotTexSubImage2D, SourceHTMLVideoElement, target, level, internalformat, video->videoWidth(), video->videoHeight(), 0, format, type, 0, 0)) - return; - - // Go through the fast path doing a GPU-GPU textures copy without a readback to system memory if possible. - // Otherwise, it will fall back to the normal SW path. - // FIXME: The current restrictions require that format shoud be RGB or RGBA, - // type should be UNSIGNED_BYTE and level should be 0. It may be lifted in the future. - WebGLTexture* texture = validateTextureBinding("texImage2D", target, true); - if (GraphicsContext3D::TEXTURE_2D == target && texture - && (format == GraphicsContext3D::RGB || format == GraphicsContext3D::RGBA) - && type == GraphicsContext3D::UNSIGNED_BYTE - && (texture->getType(target, level) == GraphicsContext3D::UNSIGNED_BYTE || !texture->isValid(target, level)) - && !level) { - if (video->copyVideoTextureToPlatformTexture(m_context.get(), texture->object(), level, type, internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) { - texture->setLevelInfo(target, level, internalformat, video->videoWidth(), video->videoHeight(), type); - cleanupAfterGraphicsCall(false); - return; - } - } - - // Normal pure SW path. - RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode(), ec); - if (!image) - return; - texImage2DImpl(target, level, internalformat, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, ec); -} -#endif - -void WebGLRenderingContext::texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat paramf, GC3Dint parami, bool isFloat) -{ - if (isContextLost()) - return; - WebGLTexture* tex = validateTextureBinding("texParameter", target, false); - if (!tex) - return; - switch (pname) { - case GraphicsContext3D::TEXTURE_MIN_FILTER: - case GraphicsContext3D::TEXTURE_MAG_FILTER: - break; - case GraphicsContext3D::TEXTURE_WRAP_S: - case GraphicsContext3D::TEXTURE_WRAP_T: - if ((isFloat && paramf != GraphicsContext3D::CLAMP_TO_EDGE && paramf != GraphicsContext3D::MIRRORED_REPEAT && paramf != GraphicsContext3D::REPEAT) - || (!isFloat && parami != GraphicsContext3D::CLAMP_TO_EDGE && parami != GraphicsContext3D::MIRRORED_REPEAT && parami != GraphicsContext3D::REPEAT)) { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter"); - return; - } - break; - case Extensions3D::TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic - if (!m_extTextureFilterAnisotropic) { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter, EXT_texture_filter_anisotropic not enabled"); - return; - } - break; - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter name"); - return; - } - if (isFloat) { - tex->setParameterf(pname, paramf); - m_context->texParameterf(target, pname, paramf); - } else { - tex->setParameteri(pname, parami); - m_context->texParameteri(target, pname, parami); - } - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param) -{ - texParameter(target, pname, param, 0, true); -} - -void WebGLRenderingContext::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param) -{ - texParameter(target, pname, 0, param, false); -} - -void WebGLRenderingContext::texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode& ec) -{ - // FIXME: For now we ignore any errors returned - ec = 0; - ASSERT(!isContextLost()); - ASSERT(validateTexFuncParameters("texSubImage2D", TexSubImage2D, target, level, format, width, height, 0, format, type)); - ASSERT(validateSize("texSubImage2D", xoffset, yoffset)); - ASSERT(validateSettableTexFormat("texSubImage2D", format)); - WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true); - if (!tex) { - ASSERT_NOT_REACHED(); - return; - } - ASSERT((xoffset + width) >= 0); - ASSERT((yoffset + height) >= 0); - ASSERT(tex->getWidth(target, level) >= (xoffset + width)); - ASSERT(tex->getHeight(target, level) >= (yoffset + height)); - ASSERT(tex->getInternalFormat(target, level) == format); - ASSERT(tex->getType(target, level) == type); - m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionCode& ec) -{ - ec = 0; - Vector<uint8_t> data; - GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE); - if (!imageExtractor.extractSucceeded()) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image"); - return; - } - GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat(); - GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp(); - const void* imagePixelData = imageExtractor.imagePixelData(); - - bool needConversion = true; - if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY) - needConversion = false; - else { - if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data"); - return; - } - } - - if (m_unpackAlignment != 1) - m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1); - texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(), format, type, needConversion ? data.data() : imagePixelData, ec); - if (m_unpackAlignment != 1) - m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment); -} - -void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Dsizei width, GC3Dsizei height, - GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec) -{ - if (isContextLost() || !validateTexFuncData("texSubImage2D", level, width, height, format, type, pixels, NullNotAllowed) - || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceArrayBufferView, target, level, format, width, height, 0, format, type, xoffset, yoffset)) - return; - void* data = pixels->baseAddress(); - Vector<uint8_t> tempData; - bool changeUnpackAlignment = false; - if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) { - if (!m_context->extractTextureData(width, height, format, type, - m_unpackAlignment, - m_unpackFlipY, m_unpackPremultiplyAlpha, - data, - tempData)) - return; - data = tempData.data(); - changeUnpackAlignment = true; - } - if (changeUnpackAlignment) - m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1); - texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, type, data, ec); - if (changeUnpackAlignment) - m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment); -} - -void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec) -{ - ec = 0; - if (isContextLost() || !pixels || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceImageData, target, level, format, pixels->width(), pixels->height(), 0, format, type, xoffset, yoffset)) - return; - - Vector<uint8_t> data; - bool needConversion = true; - // The data from ImageData is always of format RGBA8. - // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required. - if (format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha) - needConversion = false; - else { - if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image data"); - return; - } - } - if (m_unpackAlignment != 1) - m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1); - texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(), format, type, needConversion ? data.data() : pixels->data()->data(), ec); - if (m_unpackAlignment != 1) - m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment); -} - -void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec) -{ - ec = 0; - if (isContextLost() || !validateHTMLImageElement("texSubImage2D", image, ec)) - return; - - RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer()); - if (imageForRender->isSVGImage()) - imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height(), canvas()->deviceScaleFactor()); - - if (!imageForRender || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLImageElement, target, level, format, imageForRender->width(), imageForRender->height(), 0, format, type, xoffset, yoffset)) - return; - - texSubImage2DImpl(target, level, xoffset, yoffset, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, ec); -} - -void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec) -{ - ec = 0; - if (isContextLost() || !validateHTMLCanvasElement("texSubImage2D", canvas, ec) - || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLCanvasElement, target, level, format, canvas->width(), canvas->height(), 0, format, type, xoffset, yoffset)) - return; - - RefPtr<ImageData> imageData = canvas->getImageData(); - if (imageData) - texSubImage2D(target, level, xoffset, yoffset, format, type, imageData.get(), ec); - else - texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, ec); -} - -#if ENABLE(VIDEO) -void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec) -{ - ec = 0; - if (isContextLost() || !validateHTMLVideoElement("texSubImage2D", video, ec) - || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLVideoElement, target, level, format, video->videoWidth(), video->videoHeight(), 0, format, type, xoffset, yoffset)) - return; - - RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode(), ec); - if (!image) - return; - texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, ec); -} -#endif - -void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, GC3Dfloat x, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform1f", "location not for current program"); - return; - } - - m_context->uniform1f(location->location(), x); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateUniformParameters("uniform1fv", location, v, 1)) - return; - - m_context->uniform1fv(location->location(), v->length(), v->data()); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateUniformParameters("uniform1fv", location, v, size, 1)) - return; - - m_context->uniform1fv(location->location(), size, v); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, GC3Dint x, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform1i", "location not for current program"); - return; - } - - if ((location->type() == GraphicsContext3D::SAMPLER_2D || location->type() == GraphicsContext3D::SAMPLER_CUBE) && x >= (int)m_textureUnits.size()) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "uniform1i", "invalid texture unit"); - return; - } - - m_context->uniform1i(location->location(), x); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateUniformParameters("uniform1iv", location, v, 1)) - return; - - if (location->type() == GraphicsContext3D::SAMPLER_2D || location->type() == GraphicsContext3D::SAMPLER_CUBE) - for (unsigned i = 0; i < v->length(); ++i) { - if (v->data()[i] >= static_cast<int>(m_textureUnits.size())) { - LOG(WebGL, "Texture unit size=%zu, v[%d]=%d. Location type = %04X.", m_textureUnits.size(), i, v->data()[i], location->type()); - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "uniform1iv", "invalid texture unit"); - return; - } - } - - m_context->uniform1iv(location->location(), v->length(), v->data()); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateUniformParameters("uniform1iv", location, v, size, 1)) - return; - - if (location->type() == GraphicsContext3D::SAMPLER_2D || location->type() == GraphicsContext3D::SAMPLER_CUBE) - for (unsigned i = 0; i < static_cast<unsigned>(size); ++i) { - if (((GC3Dint*)v)[i] >= static_cast<int>(m_textureUnits.size())) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "uniform1iv", "invalid texture unit"); - return; - } - } - - m_context->uniform1iv(location->location(), size, v); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform2f", "location not for current program"); - return; - } - - m_context->uniform2f(location->location(), x, y); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateUniformParameters("uniform2fv", location, v, 2)) - return; - - m_context->uniform2fv(location->location(), v->length() / 2, v->data()); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateUniformParameters("uniform2fv", location, v, size, 2)) - return; - - m_context->uniform2fv(location->location(), size / 2, v); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform2i", "location not for current program"); - return; - } - - m_context->uniform2i(location->location(), x, y); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateUniformParameters("uniform2iv", location, v, 2)) - return; - - m_context->uniform2iv(location->location(), v->length() / 2, v->data()); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateUniformParameters("uniform2iv", location, v, size, 2)) - return; - - m_context->uniform2iv(location->location(), size / 2, v); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform3f", "location not for current program"); - return; - } - - m_context->uniform3f(location->location(), x, y, z); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateUniformParameters("uniform3fv", location, v, 3)) - return; - - m_context->uniform3fv(location->location(), v->length() / 3, v->data()); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateUniformParameters("uniform3fv", location, v, size, 3)) - return; - - m_context->uniform3fv(location->location(), size / 3, v); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform3i", "location not for current program"); - return; - } - - m_context->uniform3i(location->location(), x, y, z); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateUniformParameters("uniform3iv", location, v, 3)) - return; - - m_context->uniform3iv(location->location(), v->length() / 3, v->data()); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateUniformParameters("uniform3iv", location, v, size, 3)) - return; - - m_context->uniform3iv(location->location(), size / 3, v); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform4f", "location not for current program"); - return; - } - - m_context->uniform4f(location->location(), x, y, z, w); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateUniformParameters("uniform4fv", location, v, 4)) - return; - - m_context->uniform4fv(location->location(), v->length() / 4, v->data()); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateUniformParameters("uniform4fv", location, v, size, 4)) - return; - - m_context->uniform4fv(location->location(), size / 4, v); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform4i", "location not for current program"); - return; - } - - m_context->uniform4i(location->location(), x, y, z, w); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateUniformParameters("uniform4iv", location, v, 4)) - return; - - m_context->uniform4iv(location->location(), v->length() / 4, v->data()); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateUniformParameters("uniform4iv", location, v, size, 4)) - return; - - m_context->uniform4iv(location->location(), size / 4, v); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, 4)) - return; - m_context->uniformMatrix2fv(location->location(), v->length() / 4, transpose, v->data()); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, size, 4)) - return; - m_context->uniformMatrix2fv(location->location(), size / 4, transpose, v); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, 9)) - return; - m_context->uniformMatrix3fv(location->location(), v->length() / 9, transpose, v->data()); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, size, 9)) - return; - m_context->uniformMatrix3fv(location->location(), size / 9, transpose, v); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, 16)) - return; - m_context->uniformMatrix4fv(location->location(), v->length() / 16, transpose, v->data()); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, size, 16)) - return; - m_context->uniformMatrix4fv(location->location(), size / 16, transpose, v); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::useProgram(WebGLProgram* program, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - bool deleted; - if (!checkObjectToBeBound("useProgram", program, deleted)) - return; - if (deleted) - program = 0; - if (program && !program->getLinkStatus()) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "useProgram", "program not valid"); - cleanupAfterGraphicsCall(false); - return; - } - if (m_currentProgram != program) { - if (m_currentProgram) - m_currentProgram->onDetached(graphicsContext3D()); - m_currentProgram = program; - m_context->useProgram(objectOrZero(program)); - if (program) - program->onAttached(); - } - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::validateProgram(WebGLProgram* program, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost() || !validateWebGLObject("validateProgram", program)) - return; - m_context->validateProgram(objectOrZero(program)); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::vertexAttrib1f(GC3Duint index, GC3Dfloat v0) -{ - vertexAttribfImpl("vertexAttrib1f", index, 1, v0, 0.0f, 0.0f, 1.0f); -} - -void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, Float32Array* v) -{ - vertexAttribfvImpl("vertexAttrib1fv", index, v, 1); -} - -void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size) -{ - vertexAttribfvImpl("vertexAttrib1fv", index, v, size, 1); -} - -void WebGLRenderingContext::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1) -{ - vertexAttribfImpl("vertexAttrib2f", index, 2, v0, v1, 0.0f, 1.0f); -} - -void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, Float32Array* v) -{ - vertexAttribfvImpl("vertexAttrib2fv", index, v, 2); -} - -void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size) -{ - vertexAttribfvImpl("vertexAttrib2fv", index, v, size, 2); -} - -void WebGLRenderingContext::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2) -{ - vertexAttribfImpl("vertexAttrib3f", index, 3, v0, v1, v2, 1.0f); -} - -void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, Float32Array* v) -{ - vertexAttribfvImpl("vertexAttrib3fv", index, v, 3); -} - -void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size) -{ - vertexAttribfvImpl("vertexAttrib3fv", index, v, size, 3); -} - -void WebGLRenderingContext::vertexAttrib4f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3) -{ - vertexAttribfImpl("vertexAttrib4f", index, 4, v0, v1, v2, v3); -} - -void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, Float32Array* v) -{ - vertexAttribfvImpl("vertexAttrib4fv", index, v, 4); -} - -void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size) -{ - vertexAttribfvImpl("vertexAttrib4fv", index, v, size, 4); -} - -void WebGLRenderingContext::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, long long offset, ExceptionCode& ec) -{ - UNUSED_PARAM(ec); - if (isContextLost()) - return; - switch (type) { - case GraphicsContext3D::BYTE: - case GraphicsContext3D::UNSIGNED_BYTE: - case GraphicsContext3D::SHORT: - case GraphicsContext3D::UNSIGNED_SHORT: - case GraphicsContext3D::FLOAT: - break; - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "vertexAttribPointer", "invalid type"); - return; - } - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribPointer", "index out of range"); - return; - } - if (size < 1 || size > 4 || stride < 0 || stride > 255 || offset < 0) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribPointer", "bad size, stride or offset"); - return; - } - if (!m_boundArrayBuffer) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "vertexAttribPointer", "no bound ARRAY_BUFFER"); - return; - } - // Determine the number of elements the bound buffer can hold, given the offset, size, type and stride - unsigned int typeSize = sizeInBytes(type); - if (!typeSize) { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "vertexAttribPointer", "invalid type"); - return; - } - if ((stride % typeSize) || (static_cast<GC3Dintptr>(offset) % typeSize)) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "vertexAttribPointer", "stride or offset not valid for type"); - return; - } - GC3Dsizei bytesPerElement = size * typeSize; - - m_boundVertexArrayObject->setVertexAttribState(index, bytesPerElement, size, type, normalized, stride, static_cast<GC3Dintptr>(offset), m_boundArrayBuffer); - m_context->vertexAttribPointer(index, size, type, normalized, stride, static_cast<GC3Dintptr>(offset)); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) -{ - if (isContextLost()) - return; - if (!validateSize("viewport", width, height)) - return; - m_context->viewport(x, y, width, height); - cleanupAfterGraphicsCall(false); -} - -void WebGLRenderingContext::forceLostContext(WebGLRenderingContext::LostContextMode mode) -{ - if (isContextLost()) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "loseContext", "context already lost"); - return; - } - - m_contextGroup->loseContextGroup(mode); -} - -void WebGLRenderingContext::loseContextImpl(WebGLRenderingContext::LostContextMode mode) -{ - if (isContextLost()) - return; - - m_contextLost = true; - m_contextLostMode = mode; - - if (mode == RealLostContext) { - // Inform the embedder that a lost context was received. In response, the embedder might - // decide to take action such as asking the user for permission to use WebGL again. - if (Frame* frame = canvas()->document().frame()) - frame->loader().client().didLoseWebGLContext(m_context->getExtensions()->getGraphicsResetStatusARB()); - } - - detachAndRemoveAllObjects(); - - if (m_drawingBuffer) { - // Make absolutely sure we do not refer to an already-deleted texture or framebuffer. - m_drawingBuffer->setTexture2DBinding(0); - m_drawingBuffer->setFramebufferBinding(0); - } - - // There is no direct way to clear errors from a GL implementation and - // looping until getError() becomes NO_ERROR might cause an infinite loop if - // the driver or context implementation had a bug. So, loop a reasonably - // large number of times to clear any existing errors. - for (int i = 0; i < 100; ++i) { - if (m_context->getError() == GraphicsContext3D::NO_ERROR) + const ArrayBuffer* buffer = elementArrayBuffer->elementArrayBuffer(); + ASSERT(buffer); + + std::optional<unsigned> maxIndex = elementArrayBuffer->getCachedMaxIndex(type); + if (!maxIndex) { + // Compute the maximum index in the entire buffer for the given type of index. + switch (type) { + case GraphicsContext3D::UNSIGNED_BYTE: { + const GC3Dubyte* p = static_cast<const GC3Dubyte*>(buffer->data()); + for (GC3Dsizeiptr i = 0; i < numElements; i++) + maxIndex = maxIndex ? std::max(maxIndex.value(), static_cast<unsigned>(p[i])) : static_cast<unsigned>(p[i]); break; - } - ConsoleDisplayPreference display = (mode == RealLostContext) ? DisplayInConsole: DontDisplayInConsole; - synthesizeGLError(GraphicsContext3D::CONTEXT_LOST_WEBGL, "loseContext", "context lost", display); - - // Don't allow restoration unless the context lost event has both been - // dispatched and its default behavior prevented. - m_restoreAllowed = false; - - // Always defer the dispatch of the context lost event, to implement - // the spec behavior of queueing a task. - m_dispatchContextLostEventTimer.startOneShot(0); -} - -void WebGLRenderingContext::forceRestoreContext() -{ - if (!isContextLost()) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "restoreContext", "context not lost"); - return; - } - - if (!m_restoreAllowed) { - if (m_contextLostMode == SyntheticLostContext) - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "restoreContext", "context restoration not allowed"); - return; - } - - if (!m_restoreTimer.isActive()) - m_restoreTimer.startOneShot(0); -} - -#if USE(ACCELERATED_COMPOSITING) -PlatformLayer* WebGLRenderingContext::platformLayer() const -{ - return (!isContextLost()) ? m_context->platformLayer() : 0; -} -#endif - -void WebGLRenderingContext::removeSharedObject(WebGLSharedObject* object) -{ - m_contextGroup->removeObject(object); -} - -void WebGLRenderingContext::addSharedObject(WebGLSharedObject* object) -{ - ASSERT(!isContextLost()); - m_contextGroup->addObject(object); -} - -void WebGLRenderingContext::removeContextObject(WebGLContextObject* object) -{ - m_contextObjects.remove(object); -} - -void WebGLRenderingContext::addContextObject(WebGLContextObject* object) -{ - ASSERT(!isContextLost()); - m_contextObjects.add(object); -} - -void WebGLRenderingContext::detachAndRemoveAllObjects() -{ - while (m_contextObjects.size() > 0) { - HashSet<WebGLContextObject*>::iterator it = m_contextObjects.begin(); - (*it)->detachContext(); - } -} - -bool WebGLRenderingContext::hasPendingActivity() const -{ - return false; -} - -void WebGLRenderingContext::stop() -{ - if (!isContextLost()) { - forceLostContext(SyntheticLostContext); - destroyGraphicsContext3D(); - } -} - -WebGLGetInfo WebGLRenderingContext::getBooleanParameter(GC3Denum pname) -{ - GC3Dboolean value = 0; - m_context->getBooleanv(pname, &value); - return WebGLGetInfo(static_cast<bool>(value)); -} - -WebGLGetInfo WebGLRenderingContext::getBooleanArrayParameter(GC3Denum pname) -{ - if (pname != GraphicsContext3D::COLOR_WRITEMASK) { - notImplemented(); - return WebGLGetInfo(0, 0); - } - GC3Dboolean value[4] = {0}; - m_context->getBooleanv(pname, value); - bool boolValue[4]; - for (int ii = 0; ii < 4; ++ii) - boolValue[ii] = static_cast<bool>(value[ii]); - return WebGLGetInfo(boolValue, 4); -} - -WebGLGetInfo WebGLRenderingContext::getFloatParameter(GC3Denum pname) -{ - GC3Dfloat value = 0; - m_context->getFloatv(pname, &value); - return WebGLGetInfo(value); -} - -WebGLGetInfo WebGLRenderingContext::getIntParameter(GC3Denum pname) -{ - GC3Dint value = 0; - m_context->getIntegerv(pname, &value); - return WebGLGetInfo(value); -} - -WebGLGetInfo WebGLRenderingContext::getUnsignedIntParameter(GC3Denum pname) -{ - GC3Dint value = 0; - m_context->getIntegerv(pname, &value); - return WebGLGetInfo(static_cast<unsigned int>(value)); -} - -WebGLGetInfo WebGLRenderingContext::getWebGLFloatArrayParameter(GC3Denum pname) -{ - GC3Dfloat value[4] = {0}; - m_context->getFloatv(pname, value); - unsigned length = 0; - switch (pname) { - case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE: - case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE: - case GraphicsContext3D::DEPTH_RANGE: - length = 2; - break; - case GraphicsContext3D::BLEND_COLOR: - case GraphicsContext3D::COLOR_CLEAR_VALUE: - length = 4; - break; - default: - notImplemented(); - } - return WebGLGetInfo(Float32Array::create(value, length)); -} - -WebGLGetInfo WebGLRenderingContext::getWebGLIntArrayParameter(GC3Denum pname) -{ - GC3Dint value[4] = {0}; - m_context->getIntegerv(pname, value); - unsigned length = 0; - switch (pname) { - case GraphicsContext3D::MAX_VIEWPORT_DIMS: - length = 2; - break; - case GraphicsContext3D::SCISSOR_BOX: - case GraphicsContext3D::VIEWPORT: - length = 4; - break; - default: - notImplemented(); - } - return WebGLGetInfo(Int32Array::create(value, length)); -} - -void WebGLRenderingContext::checkTextureCompleteness(const char* functionName, bool prepareToDraw) -{ - bool resetActiveUnit = false; - WebGLTexture::TextureExtensionFlag extensions = static_cast<WebGLTexture::TextureExtensionFlag>((m_oesTextureFloatLinear ? WebGLTexture::TextureExtensionFloatLinearEnabled : 0) | (m_oesTextureHalfFloatLinear ? WebGLTexture::TextureExtensionHalfFloatLinearEnabled : 0)); - - for (unsigned ii = 0; ii < m_textureUnits.size(); ++ii) { - if ((m_textureUnits[ii].texture2DBinding && m_textureUnits[ii].texture2DBinding->needToUseBlackTexture(extensions)) - || (m_textureUnits[ii].textureCubeMapBinding && m_textureUnits[ii].textureCubeMapBinding->needToUseBlackTexture(extensions))) { - if (ii != m_activeTextureUnit) { - m_context->activeTexture(ii); - resetActiveUnit = true; - } else if (resetActiveUnit) { - m_context->activeTexture(ii); - resetActiveUnit = false; - } - WebGLTexture* tex2D; - WebGLTexture* texCubeMap; - if (prepareToDraw) { - String msg(String("texture bound to texture unit ") + String::number(ii) - + " is not renderable. It maybe non-power-of-2 and have incompatible texture filtering or is not 'texture complete'," - + " or it is a float/half-float type with linear filtering and without the relevant float/half-float linear extension enabled."); - printGLWarningToConsole(functionName, msg.utf8().data()); - tex2D = m_blackTexture2D.get(); - texCubeMap = m_blackTextureCubeMap.get(); - } else { - tex2D = m_textureUnits[ii].texture2DBinding.get(); - texCubeMap = m_textureUnits[ii].textureCubeMapBinding.get(); - } - if (m_textureUnits[ii].texture2DBinding && m_textureUnits[ii].texture2DBinding->needToUseBlackTexture(extensions)) - m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZero(tex2D)); - if (m_textureUnits[ii].textureCubeMapBinding && m_textureUnits[ii].textureCubeMapBinding->needToUseBlackTexture(extensions)) - m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, objectOrZero(texCubeMap)); - } - } - if (resetActiveUnit) - m_context->activeTexture(m_activeTextureUnit); -} - -void WebGLRenderingContext::createFallbackBlackTextures1x1() -{ - unsigned char black[] = {0, 0, 0, 255}; - m_blackTexture2D = createTexture(); - m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_blackTexture2D->object()); - m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 1, 1, - 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black); - m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0); - m_blackTextureCubeMap = createTexture(); - m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, m_blackTextureCubeMap->object()); - m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X, 0, GraphicsContext3D::RGBA, 1, 1, - 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black); - m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GraphicsContext3D::RGBA, 1, 1, - 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black); - m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1, - 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black); - m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1, - 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black); - m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1, - 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black); - m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1, - 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black); - m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, 0); -} - -bool WebGLRenderingContext::isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat, - GC3Denum colorBufferFormat) -{ - unsigned need = GraphicsContext3D::getChannelBitsByFormat(texInternalFormat); - unsigned have = GraphicsContext3D::getChannelBitsByFormat(colorBufferFormat); - return (need & have) == need; -} - -GC3Denum WebGLRenderingContext::getBoundFramebufferColorFormat() -{ - if (m_framebufferBinding && m_framebufferBinding->object()) - return m_framebufferBinding->getColorBufferFormat(); - if (m_attributes.alpha) - return GraphicsContext3D::RGBA; - return GraphicsContext3D::RGB; -} - -int WebGLRenderingContext::getBoundFramebufferWidth() -{ - if (m_framebufferBinding && m_framebufferBinding->object()) - return m_framebufferBinding->getColorBufferWidth(); - return m_drawingBuffer ? m_drawingBuffer->size().width() : m_context->getInternalFramebufferSize().width(); -} - -int WebGLRenderingContext::getBoundFramebufferHeight() -{ - if (m_framebufferBinding && m_framebufferBinding->object()) - return m_framebufferBinding->getColorBufferHeight(); - return m_drawingBuffer ? m_drawingBuffer->size().height() : m_context->getInternalFramebufferSize().height(); -} - -WebGLTexture* WebGLRenderingContext::validateTextureBinding(const char* functionName, GC3Denum target, bool useSixEnumsForCubeMap) -{ - WebGLTexture* texture = nullptr; - switch (target) { - case GraphicsContext3D::TEXTURE_2D: - texture = m_textureUnits[m_activeTextureUnit].texture2DBinding.get(); - break; - case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X: - case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X: - case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y: - case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z: - case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z: - if (!useSixEnumsForCubeMap) { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target"); - return nullptr; - } - texture = m_textureUnits[m_activeTextureUnit].textureCubeMapBinding.get(); - break; - case GraphicsContext3D::TEXTURE_CUBE_MAP: - if (useSixEnumsForCubeMap) { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target"); - return nullptr; - } - texture = m_textureUnits[m_activeTextureUnit].textureCubeMapBinding.get(); - break; - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target"); - return nullptr; - } - if (!texture) - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no texture"); - return texture; -} - -bool WebGLRenderingContext::validateLocationLength(const char* functionName, const String& string) -{ - const unsigned maxWebGLLocationLength = 256; - if (string.length() > maxWebGLLocationLength) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "location length > 256"); - return false; - } - return true; -} - -bool WebGLRenderingContext::validateSize(const char* functionName, GC3Dint x, GC3Dint y) -{ - if (x < 0 || y < 0) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "size < 0"); - return false; - } - return true; -} - -bool WebGLRenderingContext::validateString(const char* functionName, const String& string) -{ - for (size_t i = 0; i < string.length(); ++i) { - if (!validateCharacter(string[i])) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "string not ASCII"); - return false; } - } - return true; -} - -bool WebGLRenderingContext::validateTexFuncFormatAndType(const char* functionName, GC3Denum format, GC3Denum type, GC3Dint level) -{ - switch (format) { - case GraphicsContext3D::ALPHA: - case GraphicsContext3D::LUMINANCE: - case GraphicsContext3D::LUMINANCE_ALPHA: - case GraphicsContext3D::RGB: - case GraphicsContext3D::RGBA: - break; - case GraphicsContext3D::DEPTH_STENCIL: - case GraphicsContext3D::DEPTH_COMPONENT: - if (m_webglDepthTexture) - break; - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "depth texture formats not enabled"); - return false; - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture format"); - return false; - } - - switch (type) { - case GraphicsContext3D::UNSIGNED_BYTE: - case GraphicsContext3D::UNSIGNED_SHORT_5_6_5: - case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4: - case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1: - break; - case GraphicsContext3D::FLOAT: - if (m_oesTextureFloat) - break; - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type"); - return false; - case GraphicsContext3D::HALF_FLOAT_OES: - if (m_oesTextureHalfFloat) - break; - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type"); - return false; - case GraphicsContext3D::UNSIGNED_INT: - case GraphicsContext3D::UNSIGNED_INT_24_8: - case GraphicsContext3D::UNSIGNED_SHORT: - if (m_webglDepthTexture) + case GraphicsContext3D::UNSIGNED_SHORT: { + numElements /= sizeof(GC3Dushort); + const GC3Dushort* p = static_cast<const GC3Dushort*>(buffer->data()); + for (GC3Dsizeiptr i = 0; i < numElements; i++) + maxIndex = maxIndex ? std::max(maxIndex.value(), static_cast<unsigned>(p[i])) : static_cast<unsigned>(p[i]); break; - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type"); - return false; - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type"); - return false; - } - - // Verify that the combination of format and type is supported. - switch (format) { - case GraphicsContext3D::ALPHA: - case GraphicsContext3D::LUMINANCE: - case GraphicsContext3D::LUMINANCE_ALPHA: - if (type != GraphicsContext3D::UNSIGNED_BYTE - && type != GraphicsContext3D::FLOAT - && type != GraphicsContext3D::HALF_FLOAT_OES) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for format"); - return false; - } - break; - case GraphicsContext3D::RGB: - if (type != GraphicsContext3D::UNSIGNED_BYTE - && type != GraphicsContext3D::UNSIGNED_SHORT_5_6_5 - && type != GraphicsContext3D::FLOAT - && type != GraphicsContext3D::HALF_FLOAT_OES) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGB format"); - return false; - } - break; - case GraphicsContext3D::RGBA: - if (type != GraphicsContext3D::UNSIGNED_BYTE - && type != GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4 - && type != GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1 - && type != GraphicsContext3D::FLOAT - && type != GraphicsContext3D::HALF_FLOAT_OES) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for RGBA format"); - return false; - } - break; - case GraphicsContext3D::DEPTH_COMPONENT: - if (!m_webglDepthTexture) { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_COMPONENT not enabled"); - return false; - } - if (type != GraphicsContext3D::UNSIGNED_SHORT - && type != GraphicsContext3D::UNSIGNED_INT) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_COMPONENT format"); - return false; - } - if (level > 0) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_COMPONENT format"); - return false; - } - break; - case GraphicsContext3D::DEPTH_STENCIL: - if (!m_webglDepthTexture) { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format. DEPTH_STENCIL not enabled"); - return false; - } - if (type != GraphicsContext3D::UNSIGNED_INT_24_8) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for DEPTH_STENCIL format"); - return false; - } - if (level > 0) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for DEPTH_STENCIL format"); - return false; - } - break; - default: - ASSERT_NOT_REACHED(); - } - - return true; -} - -bool WebGLRenderingContext::validateTexFuncLevel(const char* functionName, GC3Denum target, GC3Dint level) -{ - if (level < 0) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level < 0"); - return false; - } - switch (target) { - case GraphicsContext3D::TEXTURE_2D: - if (level >= m_maxTextureLevel) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level out of range"); - return false; - } - break; - case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X: - case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X: - case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y: - case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z: - case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z: - if (level >= m_maxCubeMapTextureLevel) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level out of range"); - return false; - } - break; - } - // This function only checks if level is legal, so we return true and don't - // generate INVALID_ENUM if target is illegal. - return true; -} - -bool WebGLRenderingContext::validateTexFuncParameters(const char* functionName, - TexFuncValidationFunctionType functionType, - GC3Denum target, GC3Dint level, - GC3Denum internalformat, - GC3Dsizei width, GC3Dsizei height, GC3Dint border, - GC3Denum format, GC3Denum type) -{ - // We absolutely have to validate the format and type combination. - // The texImage2D entry points taking HTMLImage, etc. will produce - // temporary data based on this combination, so it must be legal. - if (!validateTexFuncFormatAndType(functionName, format, type, level) || !validateTexFuncLevel(functionName, target, level)) - return false; - - if (width < 0 || height < 0) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0"); - return false; - } - - GC3Dint maxTextureSizeForLevel = pow(2.0, m_maxTextureLevel - 1 - level); - switch (target) { - case GraphicsContext3D::TEXTURE_2D: - if (width > maxTextureSizeForLevel || height > maxTextureSizeForLevel) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range"); - return false; - } - break; - case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X: - case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X: - case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y: - case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z: - case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z: - if (functionType != TexSubImage2D && width != height) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width != height for cube map"); - return false; - } - // No need to check height here. For texImage width == height. - // For texSubImage that will be checked when checking yoffset + height is in range. - if (width > maxTextureSizeForLevel) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range for cube map"); - return false; - } - break; - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target"); - return false; - } - - if (format != internalformat) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format != internalformat"); - return false; - } - - if (border) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "border != 0"); - return false; - } - - return true; -} - -bool WebGLRenderingContext::validateTexFuncData(const char* functionName, GC3Dint level, - GC3Dsizei width, GC3Dsizei height, - GC3Denum format, GC3Denum type, - ArrayBufferView* pixels, - NullDisposition disposition) -{ - if (!pixels) { - if (disposition == NullAllowed) - return true; - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels"); - return false; - } - - if (!validateTexFuncFormatAndType(functionName, format, type, level)) - return false; - if (!validateSettableTexFormat(functionName, format)) - return false; - - switch (type) { - case GraphicsContext3D::UNSIGNED_BYTE: - if (pixels->getType() != JSC::TypeUint8) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_BYTE but ArrayBufferView not Uint8Array"); - return false; - } - break; - case GraphicsContext3D::UNSIGNED_SHORT_5_6_5: - case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4: - case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1: - if (pixels->getType() != JSC::TypeUint16) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type UNSIGNED_SHORT but ArrayBufferView not Uint16Array"); - return false; - } - break; - case GraphicsContext3D::FLOAT: // OES_texture_float - if (pixels->getType() != JSC::TypeFloat32) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type FLOAT but ArrayBufferView not Float32Array"); - return false; - } - break; - case GraphicsContext3D::HALF_FLOAT_OES: // OES_texture_half_float - // As per the specification, ArrayBufferView should be null when - // OES_texture_half_float is enabled. - if (pixels) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type HALF_FLOAT_OES but ArrayBufferView is not NULL"); - return false; - } - break; - default: - ASSERT_NOT_REACHED(); - } - - unsigned int totalBytesRequired; - GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0); - if (error != GraphicsContext3D::NO_ERROR) { - synthesizeGLError(error, functionName, "invalid texture dimensions"); - return false; - } - if (pixels->byteLength() < totalBytesRequired) { - if (m_unpackAlignment != 1) { - error = m_context->computeImageSizeInBytes(format, type, width, height, 1, &totalBytesRequired, 0); - if (pixels->byteLength() == totalBytesRequired) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request with UNPACK_ALIGNMENT > 1"); - return false; - } - } - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request"); - return false; - } - return true; -} - -bool WebGLRenderingContext::validateCompressedTexFormat(GC3Denum format) -{ - return m_compressedTextureFormats.contains(format); -} - -bool WebGLRenderingContext::validateCompressedTexFuncData(const char* functionName, - GC3Dsizei width, GC3Dsizei height, - GC3Denum format, ArrayBufferView* pixels) -{ - if (!pixels) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels"); - return false; - } - if (width < 0 || height < 0) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0"); - return false; - } - - unsigned int bytesRequired = 0; - - switch (format) { - case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT: - case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT: - case Extensions3D::COMPRESSED_ATC_RGB_AMD: - { - const int kBlockSize = 8; - const int kBlockWidth = 4; - const int kBlockHeight = 4; - int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth; - int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight; - bytesRequired = numBlocksAcross * numBlocksDown * kBlockSize; } - break; - case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT: - case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: - case Extensions3D::COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD: - case Extensions3D::COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD: - { - const int kBlockSize = 16; - const int kBlockWidth = 4; - const int kBlockHeight = 4; - int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth; - int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight; - bytesRequired = numBlocksAcross * numBlocksDown * kBlockSize; - } - break; - case Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG: - case Extensions3D::COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: - { - const int kBlockSize = 8; - const int kBlockWidth = 8; - const int kBlockHeight = 8; - bytesRequired = (std::max(width, kBlockWidth) * std::max(height, kBlockHeight) * 4 + 7) / kBlockSize; - } - break; - case Extensions3D::COMPRESSED_RGB_PVRTC_2BPPV1_IMG: - case Extensions3D::COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: - { - const int kBlockSize = 8; - const int kBlockWidth = 16; - const int kBlockHeight = 8; - bytesRequired = (std::max(width, kBlockWidth) * std::max(height, kBlockHeight) * 2 + 7) / kBlockSize; - } - break; - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format"); - return false; - } - - if (pixels->byteLength() != bytesRequired) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "length of ArrayBufferView is not correct for dimensions"); - return false; - } - - return true; -} - -bool WebGLRenderingContext::validateCompressedTexDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum format) -{ - switch (format) { - case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT: - case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT: - case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT: - case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: { - const GC3Dsizei kBlockWidth = 4; - const GC3Dsizei kBlockHeight = 4; - const GC3Dint maxTextureSize = target ? m_maxTextureSize : m_maxCubeMapTextureSize; - const GC3Dsizei maxCompressedDimension = maxTextureSize >> level; - bool widthValid = (level && width == 1) || (level && width == 2) || (!(width % kBlockWidth) && width <= maxCompressedDimension); - bool heightValid = (level && height == 1) || (level && height == 2) || (!(height % kBlockHeight) && height <= maxCompressedDimension); - if (!widthValid || !heightValid) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "width or height invalid for level"); - return false; - } - return true; - } - default: - return false; - } -} - -bool WebGLRenderingContext::validateCompressedTexSubDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Dsizei width, GC3Dsizei height, GC3Denum format, WebGLTexture* tex) -{ - if (xoffset < 0 || yoffset < 0) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "xoffset or yoffset < 0"); - return false; - } - - switch (format) { - case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT: - case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT: - case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT: - case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: { - const int kBlockWidth = 4; - const int kBlockHeight = 4; - if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "xoffset or yoffset not multiple of 4"); - return false; + case GraphicsContext3D::UNSIGNED_INT: { + if (!m_oesElementIndexUint) + return false; + numElements /= sizeof(GC3Duint); + const GC3Duint* p = static_cast<const GC3Duint*>(buffer->data()); + for (GC3Dsizeiptr i = 0; i < numElements; i++) + maxIndex = maxIndex ? std::max(maxIndex.value(), static_cast<unsigned>(p[i])) : static_cast<unsigned>(p[i]); + break; } - if (width - xoffset > tex->getWidth(target, level) - || height - yoffset > tex->getHeight(target, level)) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "dimensions out of range"); + default: return false; } - return validateCompressedTexDimensions(functionName, target, level, width, height, format); + if (maxIndex) + elementArrayBuffer->setCachedMaxIndex(type, maxIndex.value()); } - default: - return false; - } -} - -bool WebGLRenderingContext::validateDrawMode(const char* functionName, GC3Denum mode) -{ - switch (mode) { - case GraphicsContext3D::POINTS: - case GraphicsContext3D::LINE_STRIP: - case GraphicsContext3D::LINE_LOOP: - case GraphicsContext3D::LINES: - case GraphicsContext3D::TRIANGLE_STRIP: - case GraphicsContext3D::TRIANGLE_FAN: - case GraphicsContext3D::TRIANGLES: - return true; - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid draw mode"); - return false; - } -} - -bool WebGLRenderingContext::validateStencilSettings(const char* functionName) -{ - if (m_stencilMask != m_stencilMaskBack || m_stencilFuncRef != m_stencilFuncRefBack || m_stencilFuncMask != m_stencilFuncMaskBack) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "front and back stencils settings do not match"); - return false; - } - return true; -} - -bool WebGLRenderingContext::validateStencilFunc(const char* functionName, GC3Denum func) -{ - switch (func) { - case GraphicsContext3D::NEVER: - case GraphicsContext3D::LESS: - case GraphicsContext3D::LEQUAL: - case GraphicsContext3D::GREATER: - case GraphicsContext3D::GEQUAL: - case GraphicsContext3D::EQUAL: - case GraphicsContext3D::NOTEQUAL: - case GraphicsContext3D::ALWAYS: - return true; - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid function"); + + if (!maxIndex) return false; - } -} - -void WebGLRenderingContext::printGLErrorToConsole(const String& message) -{ - if (!m_numGLErrorsToConsoleAllowed) - return; - --m_numGLErrorsToConsoleAllowed; - printWarningToConsole(message); - - if (!m_numGLErrorsToConsoleAllowed) - printWarningToConsole("WebGL: too many errors, no more errors will be reported to the console for this context."); -} - -void WebGLRenderingContext::printWarningToConsole(const String& message) -{ - if (!canvas()) - return; - canvas()->document().addConsoleMessage(RenderingMessageSource, WarningMessageLevel, message); -} + // The number of required elements is one more than the maximum + // index that will be accessed. + numElementsRequired = maxIndex.value() + 1; -bool WebGLRenderingContext::validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment) -{ - if (target != GraphicsContext3D::FRAMEBUFFER) { - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target"); - return false; - } - switch (attachment) { - case GraphicsContext3D::COLOR_ATTACHMENT0: - case GraphicsContext3D::DEPTH_ATTACHMENT: - case GraphicsContext3D::STENCIL_ATTACHMENT: - case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT: - break; - default: - if (m_extDrawBuffers - && attachment > GraphicsContext3D::COLOR_ATTACHMENT0 - && attachment < static_cast<GC3Denum>(GraphicsContext3D::COLOR_ATTACHMENT0 + getMaxColorAttachments())) - break; - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid attachment"); - return false; - } - return true; + // Check for overflow. + return numElementsRequired > 0; } bool WebGLRenderingContext::validateBlendEquation(const char* functionName, GC3Denum mode) @@ -5599,25 +804,20 @@ bool WebGLRenderingContext::validateBlendEquation(const char* functionName, GC3D case GraphicsContext3D::FUNC_ADD: case GraphicsContext3D::FUNC_SUBTRACT: case GraphicsContext3D::FUNC_REVERSE_SUBTRACT: + case Extensions3D::MIN_EXT: + case Extensions3D::MAX_EXT: + if ((mode == Extensions3D::MIN_EXT || mode == Extensions3D::MAX_EXT) && !m_extBlendMinMax) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid mode"); + return false; + } return true; + break; default: synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid mode"); return false; } } -bool WebGLRenderingContext::validateBlendFuncFactors(const char* functionName, GC3Denum src, GC3Denum dst) -{ - if (((src == GraphicsContext3D::CONSTANT_COLOR || src == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR) - && (dst == GraphicsContext3D::CONSTANT_ALPHA || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA)) - || ((dst == GraphicsContext3D::CONSTANT_COLOR || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR) - && (src == GraphicsContext3D::CONSTANT_ALPHA || src == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA))) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "incompatible src and dst"); - return false; - } - return true; -} - bool WebGLRenderingContext::validateCapability(const char* functionName, GC3Denum cap) { switch (cap) { @@ -5637,621 +837,6 @@ bool WebGLRenderingContext::validateCapability(const char* functionName, GC3Denu } } -bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Float32Array* v, GC3Dsizei requiredMinSize) -{ - if (!v) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array"); - return false; - } - return validateUniformMatrixParameters(functionName, location, false, v->data(), v->length(), requiredMinSize); -} - -bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Int32Array* v, GC3Dsizei requiredMinSize) -{ - if (!v) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array"); - return false; - } - return validateUniformMatrixParameters(functionName, location, false, v->data(), v->length(), requiredMinSize); -} - -bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize) -{ - return validateUniformMatrixParameters(functionName, location, false, v, size, requiredMinSize); -} - -bool WebGLRenderingContext::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, GC3Dsizei requiredMinSize) -{ - if (!v) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array"); - return false; - } - return validateUniformMatrixParameters(functionName, location, transpose, v->data(), v->length(), requiredMinSize); -} - -bool WebGLRenderingContext::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GC3Dboolean transpose, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize) -{ - if (!location) - return false; - if (location->program() != m_currentProgram) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "location is not from current program"); - return false; - } - if (!v) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array"); - return false; - } - if (transpose) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "transpose not FALSE"); - return false; - } - if (size < requiredMinSize || (size % requiredMinSize)) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid size"); - return false; - } - return true; -} - -WebGLBuffer* WebGLRenderingContext::validateBufferDataParameters(const char* functionName, GC3Denum target, GC3Denum usage) -{ - WebGLBuffer* buffer = 0; - switch (target) { - case GraphicsContext3D::ELEMENT_ARRAY_BUFFER: - buffer = m_boundVertexArrayObject->getElementArrayBuffer().get(); - break; - case GraphicsContext3D::ARRAY_BUFFER: - buffer = m_boundArrayBuffer.get(); - break; - default: - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target"); - return 0; - } - if (!buffer) { - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no buffer"); - return 0; - } - switch (usage) { - case GraphicsContext3D::STREAM_DRAW: - case GraphicsContext3D::STATIC_DRAW: - case GraphicsContext3D::DYNAMIC_DRAW: - return buffer; - } - synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid usage"); - return 0; -} - -bool WebGLRenderingContext::validateHTMLImageElement(const char* functionName, HTMLImageElement* image, ExceptionCode& ec) -{ - if (!image || !image->cachedImage()) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no image"); - return false; - } - const URL& url = image->cachedImage()->response().url(); - if (url.isNull() || url.isEmpty() || !url.isValid()) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid image"); - return false; - } - if (wouldTaintOrigin(image)) { - ec = SECURITY_ERR; - return false; - } - return true; -} - -bool WebGLRenderingContext::validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement* canvas, ExceptionCode& ec) -{ - if (!canvas || !canvas->buffer()) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no canvas"); - return false; - } - if (wouldTaintOrigin(canvas)) { - ec = SECURITY_ERR; - return false; - } - return true; -} - -#if ENABLE(VIDEO) -bool WebGLRenderingContext::validateHTMLVideoElement(const char* functionName, HTMLVideoElement* video, ExceptionCode& ec) -{ - if (!video || !video->videoWidth() || !video->videoHeight()) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no video"); - return false; - } - if (wouldTaintOrigin(video)) { - ec = SECURITY_ERR; - return false; - } - return true; -} -#endif - -void WebGLRenderingContext::vertexAttribfImpl(const char* functionName, GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3) -{ - if (isContextLost()) - return; - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "index out of range"); - return; - } - // In GL, we skip setting vertexAttrib0 values. - if (index || isGLES2Compliant()) { - switch (expectedSize) { - case 1: - m_context->vertexAttrib1f(index, v0); - break; - case 2: - m_context->vertexAttrib2f(index, v0, v1); - break; - case 3: - m_context->vertexAttrib3f(index, v0, v1, v2); - break; - case 4: - m_context->vertexAttrib4f(index, v0, v1, v2, v3); - break; - } - cleanupAfterGraphicsCall(false); - } - VertexAttribValue& attribValue = m_vertexAttribValue[index]; - attribValue.value[0] = v0; - attribValue.value[1] = v1; - attribValue.value[2] = v2; - attribValue.value[3] = v3; -} - -void WebGLRenderingContext::vertexAttribfvImpl(const char* functionName, GC3Duint index, Float32Array* v, GC3Dsizei expectedSize) -{ - if (isContextLost()) - return; - if (!v) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array"); - return; - } - vertexAttribfvImpl(functionName, index, v->data(), v->length(), expectedSize); -} - -void WebGLRenderingContext::vertexAttribfvImpl(const char* functionName, GC3Duint index, GC3Dfloat* v, GC3Dsizei size, GC3Dsizei expectedSize) -{ - if (isContextLost()) - return; - if (!v) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array"); - return; - } - if (size < expectedSize) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid size"); - return; - } - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "index out of range"); - return; - } - // In GL, we skip setting vertexAttrib0 values. - if (index || isGLES2Compliant()) { - switch (expectedSize) { - case 1: - m_context->vertexAttrib1fv(index, v); - break; - case 2: - m_context->vertexAttrib2fv(index, v); - break; - case 3: - m_context->vertexAttrib3fv(index, v); - break; - case 4: - m_context->vertexAttrib4fv(index, v); - break; - } - cleanupAfterGraphicsCall(false); - } - VertexAttribValue& attribValue = m_vertexAttribValue[index]; - attribValue.initValue(); - for (int ii = 0; ii < expectedSize; ++ii) - attribValue.value[ii] = v[ii]; -} - -void WebGLRenderingContext::initVertexAttrib0() -{ - WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0); - - m_vertexAttrib0Buffer = createBuffer(); - m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object()); - m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, 0, GraphicsContext3D::DYNAMIC_DRAW); - m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, false, 0, 0); - state.bufferBinding = m_vertexAttrib0Buffer; - m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0); - m_context->enableVertexAttribArray(0); - m_vertexAttrib0BufferSize = 0; - m_vertexAttrib0BufferValue[0] = 0.0f; - m_vertexAttrib0BufferValue[1] = 0.0f; - m_vertexAttrib0BufferValue[2] = 0.0f; - m_vertexAttrib0BufferValue[3] = 1.0f; - m_forceAttrib0BufferRefill = false; - m_vertexAttrib0UsedBefore = false; -} - -bool WebGLRenderingContext::simulateVertexAttrib0(GC3Dsizei numVertex) -{ - const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0); - const VertexAttribValue& attribValue = m_vertexAttribValue[0]; - if (!m_currentProgram) - return false; - bool usingVertexAttrib0 = m_currentProgram->isUsingVertexAttrib0(); - if (usingVertexAttrib0) - m_vertexAttrib0UsedBefore = true; - if (state.enabled && usingVertexAttrib0) - return false; - if (!usingVertexAttrib0 && !m_vertexAttrib0UsedBefore) - return false; - m_vertexAttrib0UsedBefore = true; - m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object()); - GC3Dsizeiptr bufferDataSize = (numVertex + 1) * 4 * sizeof(GC3Dfloat); - if (bufferDataSize > m_vertexAttrib0BufferSize) { - m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, bufferDataSize, 0, GraphicsContext3D::DYNAMIC_DRAW); - m_vertexAttrib0BufferSize = bufferDataSize; - m_forceAttrib0BufferRefill = true; - } - if (usingVertexAttrib0 - && (m_forceAttrib0BufferRefill - || attribValue.value[0] != m_vertexAttrib0BufferValue[0] - || attribValue.value[1] != m_vertexAttrib0BufferValue[1] - || attribValue.value[2] != m_vertexAttrib0BufferValue[2] - || attribValue.value[3] != m_vertexAttrib0BufferValue[3])) { - auto bufferData = std::make_unique<GC3Dfloat[]>((numVertex + 1) * 4); - for (GC3Dsizei ii = 0; ii < numVertex + 1; ++ii) { - bufferData[ii * 4] = attribValue.value[0]; - bufferData[ii * 4 + 1] = attribValue.value[1]; - bufferData[ii * 4 + 2] = attribValue.value[2]; - bufferData[ii * 4 + 3] = attribValue.value[3]; - } - m_vertexAttrib0BufferValue[0] = attribValue.value[0]; - m_vertexAttrib0BufferValue[1] = attribValue.value[1]; - m_vertexAttrib0BufferValue[2] = attribValue.value[2]; - m_vertexAttrib0BufferValue[3] = attribValue.value[3]; - m_forceAttrib0BufferRefill = false; - m_context->bufferSubData(GraphicsContext3D::ARRAY_BUFFER, 0, bufferDataSize, bufferData.get()); - } - m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, 0, 0, 0); - return true; -} - -void WebGLRenderingContext::restoreStatesAfterVertexAttrib0Simulation() -{ - const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0); - if (state.bufferBinding != m_vertexAttrib0Buffer) { - m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(state.bufferBinding.get())); - m_context->vertexAttribPointer(0, state.size, state.type, state.normalized, state.originalStride, state.offset); - } - m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(m_boundArrayBuffer.get())); -} - -void WebGLRenderingContext::dispatchContextLostEvent(Timer<WebGLRenderingContext>*) -{ - RefPtr<WebGLContextEvent> event = WebGLContextEvent::create(eventNames().webglcontextlostEvent, false, true, ""); - canvas()->dispatchEvent(event); - m_restoreAllowed = event->defaultPrevented(); - if (m_contextLostMode == RealLostContext && m_restoreAllowed) - m_restoreTimer.startOneShot(0); -} - -void WebGLRenderingContext::maybeRestoreContext(Timer<WebGLRenderingContext>*) -{ - ASSERT(m_contextLost); - if (!m_contextLost) - return; - - // The rendering context is not restored unless the default behavior of the - // webglcontextlost event was prevented earlier. - // - // Because of the way m_restoreTimer is set up for real vs. synthetic lost - // context events, we don't have to worry about this test short-circuiting - // the retry loop for real context lost events. - if (!m_restoreAllowed) - return; - - int contextLostReason = m_context->getExtensions()->getGraphicsResetStatusARB(); - - switch (contextLostReason) { - case GraphicsContext3D::NO_ERROR: - // The GraphicsContext3D implementation might not fully - // support GL_ARB_robustness semantics yet. Alternatively, the - // WEBGL_lose_context extension might have been used to force - // a lost context. - break; - case Extensions3D::GUILTY_CONTEXT_RESET_ARB: - // The rendering context is not restored if this context was - // guilty of causing the graphics reset. - printWarningToConsole("WARNING: WebGL content on the page caused the graphics card to reset; not restoring the context"); - return; - case Extensions3D::INNOCENT_CONTEXT_RESET_ARB: - // Always allow the context to be restored. - break; - case Extensions3D::UNKNOWN_CONTEXT_RESET_ARB: - // Warn. Ideally, prompt the user telling them that WebGL - // content on the page might have caused the graphics card to - // reset and ask them whether they want to continue running - // the content. Only if they say "yes" should we start - // attempting to restore the context. - printWarningToConsole("WARNING: WebGL content on the page might have caused the graphics card to reset"); - break; - } - - Frame* frame = canvas()->document().frame(); - if (!frame) - return; - - if (!frame->loader().client().allowWebGL(frame->settings().webGLEnabled())) - return; - - FrameView* view = frame->view(); - if (!view) - return; - ScrollView* root = view->root(); - if (!root) - return; - HostWindow* hostWindow = root->hostWindow(); - if (!hostWindow) - return; - - RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(m_attributes, hostWindow)); - if (!context) { - if (m_contextLostMode == RealLostContext) - m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts); - else - // This likely shouldn't happen but is the best way to report it to the WebGL app. - synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "", "error restoring context"); - return; - } - - // Construct a new drawing buffer with the new GraphicsContext3D. - if (m_drawingBuffer) { - m_drawingBuffer->discardResources(); - DrawingBuffer::PreserveDrawingBuffer preserve = m_attributes.preserveDrawingBuffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard; - DrawingBuffer::AlphaRequirement alpha = m_attributes.alpha ? DrawingBuffer::Alpha : DrawingBuffer::Opaque; - m_drawingBuffer = DrawingBuffer::create(context.get(), m_drawingBuffer->size(), preserve, alpha); - m_drawingBuffer->bind(); - } - - m_context = context; - m_contextLost = false; - setupFlags(); - initializeNewContext(); - canvas()->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextrestoredEvent, false, true, "")); -} - -String WebGLRenderingContext::ensureNotNull(const String& text) const -{ - if (text.isNull()) - return WTF::emptyString(); - return text; -} - -WebGLRenderingContext::LRUImageBufferCache::LRUImageBufferCache(int capacity) - : m_buffers(std::make_unique<std::unique_ptr<ImageBuffer>[]>(capacity)) - , m_capacity(capacity) -{ -} - -ImageBuffer* WebGLRenderingContext::LRUImageBufferCache::imageBuffer(const IntSize& size) -{ - int i; - for (i = 0; i < m_capacity; ++i) { - ImageBuffer* buf = m_buffers[i].get(); - if (!buf) - break; - if (buf->logicalSize() != size) - continue; - bubbleToFront(i); - return buf; - } - - std::unique_ptr<ImageBuffer> temp = ImageBuffer::create(size, 1); - if (!temp) - return 0; - i = std::min(m_capacity - 1, i); - m_buffers[i] = std::move(temp); - - ImageBuffer* buf = m_buffers[i].get(); - bubbleToFront(i); - return buf; -} - -void WebGLRenderingContext::LRUImageBufferCache::bubbleToFront(int idx) -{ - for (int i = idx; i > 0; --i) - m_buffers[i].swap(m_buffers[i-1]); -} - -namespace { - - String GetErrorString(GC3Denum error) - { - switch (error) { - case GraphicsContext3D::INVALID_ENUM: - return "INVALID_ENUM"; - case GraphicsContext3D::INVALID_VALUE: - return "INVALID_VALUE"; - case GraphicsContext3D::INVALID_OPERATION: - return "INVALID_OPERATION"; - case GraphicsContext3D::OUT_OF_MEMORY: - return "OUT_OF_MEMORY"; - case GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION: - return "INVALID_FRAMEBUFFER_OPERATION"; - case GraphicsContext3D::CONTEXT_LOST_WEBGL: - return "CONTEXT_LOST_WEBGL"; - default: - return String::format("WebGL ERROR(%04x)", error); - } - } - -} // namespace anonymous - -void WebGLRenderingContext::synthesizeGLError(GC3Denum error, const char* functionName, const char* description, ConsoleDisplayPreference display) -{ - if (m_synthesizedErrorsToConsole && display == DisplayInConsole) { - String str = String("WebGL: ") + GetErrorString(error) + ": " + String(functionName) + ": " + String(description); - printGLErrorToConsole(str); - } - m_context->synthesizeGLError(error); -} - - -void WebGLRenderingContext::printGLWarningToConsole(const char* functionName, const char* description) -{ - if (m_synthesizedErrorsToConsole) { - String str = String("WebGL: ") + String(functionName) + ": " + String(description); - printGLErrorToConsole(str); - } -} - -void WebGLRenderingContext::applyStencilTest() -{ - bool haveStencilBuffer = false; - - if (m_framebufferBinding) - haveStencilBuffer = m_framebufferBinding->hasStencilBuffer(); - else { - RefPtr<WebGLContextAttributes> attributes = getContextAttributes(); - haveStencilBuffer = attributes->stencil(); - } - enableOrDisable(GraphicsContext3D::STENCIL_TEST, - m_stencilEnabled && haveStencilBuffer); -} - -void WebGLRenderingContext::enableOrDisable(GC3Denum capability, bool enable) -{ - if (enable) - m_context->enable(capability); - else - m_context->disable(capability); -} - -IntSize WebGLRenderingContext::clampedCanvasSize() -{ - return IntSize(clamp(canvas()->width(), 1, m_maxViewportDims[0]), - clamp(canvas()->height(), 1, m_maxViewportDims[1])); -} - -GC3Dint WebGLRenderingContext::getMaxDrawBuffers() -{ - if (!supportsDrawBuffers()) - return 0; - if (!m_maxDrawBuffers) - m_context->getIntegerv(Extensions3D::MAX_DRAW_BUFFERS_EXT, &m_maxDrawBuffers); - if (!m_maxColorAttachments) - m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments); - // WEBGL_draw_buffers requires MAX_COLOR_ATTACHMENTS >= MAX_DRAW_BUFFERS. - return std::min(m_maxDrawBuffers, m_maxColorAttachments); -} - -GC3Dint WebGLRenderingContext::getMaxColorAttachments() -{ - if (!supportsDrawBuffers()) - return 0; - if (!m_maxColorAttachments) - m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments); - return m_maxColorAttachments; -} - -void WebGLRenderingContext::setBackDrawBuffer(GC3Denum buf) -{ - m_backDrawBuffer = buf; -} - -void WebGLRenderingContext::restoreCurrentFramebuffer() -{ - ExceptionCode ec; - bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_framebufferBinding.get(), ec); -} - -void WebGLRenderingContext::restoreCurrentTexture2D() -{ - ExceptionCode ec; - bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureUnits[m_activeTextureUnit].texture2DBinding.get(), ec); -} - -bool WebGLRenderingContext::supportsDrawBuffers() -{ - if (!m_drawBuffersWebGLRequirementsChecked) { - m_drawBuffersWebGLRequirementsChecked = true; - m_drawBuffersSupported = EXTDrawBuffers::supported(this); - } - return m_drawBuffersSupported; -} - -void WebGLRenderingContext::drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount) -{ - if (!primcount) { - cleanupAfterGraphicsCall(true); - return; - } - - if (!validateDrawArrays("drawArraysInstanced", mode, first, count, primcount)) - return; - - clearIfComposited(); - - bool vertexAttrib0Simulated = false; - if (!isGLES2Compliant()) - vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1); - if (!isGLES2NPOTStrict()) - checkTextureCompleteness("drawArraysInstanced", true); - - m_context->drawArraysInstanced(mode, first, count, primcount); - - if (!isGLES2Compliant() && vertexAttrib0Simulated) - restoreStatesAfterVertexAttrib0Simulation(); - if (!isGLES2NPOTStrict()) - checkTextureCompleteness("drawArraysInstanced", false); - cleanupAfterGraphicsCall(true); -} - -void WebGLRenderingContext::drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount) -{ - if (!primcount) { - cleanupAfterGraphicsCall(true); - return; - } - - unsigned numElements = 0; - if (!validateDrawElements("drawElementsInstanced", mode, count, type, offset, numElements, primcount)) - return; - - clearIfComposited(); - - bool vertexAttrib0Simulated = false; - if (!isGLES2Compliant()) { - if (!numElements) - validateIndexArrayPrecise(count, type, static_cast<GC3Dintptr>(offset), numElements); - vertexAttrib0Simulated = simulateVertexAttrib0(numElements); - } - if (!isGLES2NPOTStrict()) - checkTextureCompleteness("drawElementsInstanced", true); - - m_context->drawElementsInstanced(mode, count, type, static_cast<GC3Dintptr>(offset), primcount); - - if (!isGLES2Compliant() && vertexAttrib0Simulated) - restoreStatesAfterVertexAttrib0Simulation(); - if (!isGLES2NPOTStrict()) - checkTextureCompleteness("drawElementsInstanced", false); - cleanupAfterGraphicsCall(true); -} - -void WebGLRenderingContext::vertexAttribDivisor(GC3Duint index, GC3Duint divisor) -{ - if (isContextLost()) - return; - - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribDivisor", "index out of range"); - return; - } - - m_boundVertexArrayObject->setVertexAttribDivisor(index, divisor); - m_context->vertexAttribDivisor(index, divisor); -} - - } // namespace WebCore #endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/WebGLRenderingContext.h b/Source/WebCore/html/canvas/WebGLRenderingContext.h index a4a0a1b7b..5f4e5d00b 100644 --- a/Source/WebCore/html/canvas/WebGLRenderingContext.h +++ b/Source/WebCore/html/canvas/WebGLRenderingContext.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2015-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,782 +23,38 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLRenderingContext_h -#define WebGLRenderingContext_h +#pragma once -#include "ActiveDOMObject.h" -#include "CanvasRenderingContext.h" -#include "DrawingBuffer.h" -#include "GraphicsContext3D.h" -#include "ImageBuffer.h" -#include "Timer.h" -#include "WebGLGetInfo.h" - -#include <memory> -#include <runtime/Float32Array.h> -#include <runtime/Int32Array.h> -#include <wtf/text/WTFString.h> +#include "WebGLRenderingContextBase.h" namespace WebCore { -class ANGLEInstancedArrays; -class EXTDrawBuffers; -class EXTTextureFilterAnisotropic; -class HTMLImageElement; -class HTMLVideoElement; -class ImageBuffer; -class ImageData; -class IntSize; -class OESStandardDerivatives; -class OESTextureFloat; -class OESTextureFloatLinear; -class OESTextureHalfFloat; -class OESTextureHalfFloatLinear; -class OESVertexArrayObject; -class OESElementIndexUint; -class WebGLActiveInfo; -class WebGLBuffer; -class WebGLContextGroup; -class WebGLContextObject; -class WebGLCompressedTextureATC; -class WebGLCompressedTexturePVRTC; -class WebGLCompressedTextureS3TC; -class WebGLContextAttributes; -class WebGLDebugRendererInfo; -class WebGLDebugShaders; -class WebGLDepthTexture; -class WebGLExtension; -class WebGLFramebuffer; -class WebGLLoseContext; -class WebGLObject; -class WebGLProgram; -class WebGLRenderbuffer; -class WebGLShader; -class WebGLSharedObject; -class WebGLShaderPrecisionFormat; -class WebGLTexture; -class WebGLUniformLocation; -class WebGLVertexArrayObjectOES; - -typedef int ExceptionCode; - -class WebGLRenderingContext : public CanvasRenderingContext, public ActiveDOMObject { +class WebGLRenderingContext final : public WebGLRenderingContextBase { public: - static OwnPtr<WebGLRenderingContext> create(HTMLCanvasElement*, WebGLContextAttributes*); - virtual ~WebGLRenderingContext(); - - virtual bool is3d() const override { return true; } - virtual bool isAccelerated() const override { return true; } - - int drawingBufferWidth() const; - int drawingBufferHeight() const; - - void activeTexture(GC3Denum texture, ExceptionCode&); - void attachShader(WebGLProgram*, WebGLShader*, ExceptionCode&); - void bindAttribLocation(WebGLProgram*, GC3Duint index, const String& name, ExceptionCode&); - void bindBuffer(GC3Denum target, WebGLBuffer*, ExceptionCode&); - void bindFramebuffer(GC3Denum target, WebGLFramebuffer*, ExceptionCode&); - void bindRenderbuffer(GC3Denum target, WebGLRenderbuffer*, ExceptionCode&); - void bindTexture(GC3Denum target, WebGLTexture*, ExceptionCode&); - void blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha); - void blendEquation(GC3Denum mode); - void blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha); - void blendFunc(GC3Denum sfactor, GC3Denum dfactor); - void blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha); - - void bufferData(GC3Denum target, long long size, GC3Denum usage, ExceptionCode&); - void bufferData(GC3Denum target, ArrayBuffer* data, GC3Denum usage, ExceptionCode&); - void bufferData(GC3Denum target, ArrayBufferView* data, GC3Denum usage, ExceptionCode&); - void bufferSubData(GC3Denum target, long long offset, ArrayBuffer* data, ExceptionCode&); - void bufferSubData(GC3Denum target, long long offset, ArrayBufferView* data, ExceptionCode&); - - GC3Denum checkFramebufferStatus(GC3Denum target); - void clear(GC3Dbitfield mask); - void clearColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha); - void clearDepth(GC3Dfloat); - void clearStencil(GC3Dint); - void colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha); - void compileShader(WebGLShader*, ExceptionCode&); - - void compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, - GC3Dsizei height, GC3Dint border, ArrayBufferView* data); - void compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView* data); - - void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border); - void copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height); - - PassRefPtr<WebGLBuffer> createBuffer(); - PassRefPtr<WebGLFramebuffer> createFramebuffer(); - PassRefPtr<WebGLProgram> createProgram(); - PassRefPtr<WebGLRenderbuffer> createRenderbuffer(); - PassRefPtr<WebGLShader> createShader(GC3Denum type, ExceptionCode&); - PassRefPtr<WebGLTexture> createTexture(); - - void cullFace(GC3Denum mode); - - void deleteBuffer(WebGLBuffer*); - void deleteFramebuffer(WebGLFramebuffer*); - void deleteProgram(WebGLProgram*); - void deleteRenderbuffer(WebGLRenderbuffer*); - void deleteShader(WebGLShader*); - void deleteTexture(WebGLTexture*); - - void depthFunc(GC3Denum); - void depthMask(GC3Dboolean); - void depthRange(GC3Dfloat zNear, GC3Dfloat zFar); - void detachShader(WebGLProgram*, WebGLShader*, ExceptionCode&); - void disable(GC3Denum cap); - void disableVertexAttribArray(GC3Duint index, ExceptionCode&); - void drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count, ExceptionCode&); - void drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, ExceptionCode&); - - void enable(GC3Denum cap); - void enableVertexAttribArray(GC3Duint index, ExceptionCode&); - void finish(); - void flush(); - void framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer*, ExceptionCode&); - void framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture*, GC3Dint level, ExceptionCode&); - void frontFace(GC3Denum mode); - void generateMipmap(GC3Denum target); - - PassRefPtr<WebGLActiveInfo> getActiveAttrib(WebGLProgram*, GC3Duint index, ExceptionCode&); - PassRefPtr<WebGLActiveInfo> getActiveUniform(WebGLProgram*, GC3Duint index, ExceptionCode&); - bool getAttachedShaders(WebGLProgram*, Vector<RefPtr<WebGLShader>>&, ExceptionCode&); - GC3Dint getAttribLocation(WebGLProgram*, const String& name); - WebGLGetInfo getBufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode&); - PassRefPtr<WebGLContextAttributes> getContextAttributes(); - GC3Denum getError(); - WebGLExtension* getExtension(const String& name); - WebGLGetInfo getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname, ExceptionCode&); - WebGLGetInfo getParameter(GC3Denum pname, ExceptionCode&); - WebGLGetInfo getProgramParameter(WebGLProgram*, GC3Denum pname, ExceptionCode&); - String getProgramInfoLog(WebGLProgram*, ExceptionCode&); - WebGLGetInfo getRenderbufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode&); - WebGLGetInfo getShaderParameter(WebGLShader*, GC3Denum pname, ExceptionCode&); - String getShaderInfoLog(WebGLShader*, ExceptionCode&); - PassRefPtr<WebGLShaderPrecisionFormat> getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType, ExceptionCode&); - String getShaderSource(WebGLShader*, ExceptionCode&); - Vector<String> getSupportedExtensions(); - WebGLGetInfo getTexParameter(GC3Denum target, GC3Denum pname, ExceptionCode&); - WebGLGetInfo getUniform(WebGLProgram*, const WebGLUniformLocation*, ExceptionCode&); - PassRefPtr<WebGLUniformLocation> getUniformLocation(WebGLProgram*, const String&, ExceptionCode&); - WebGLGetInfo getVertexAttrib(GC3Duint index, GC3Denum pname, ExceptionCode&); - long long getVertexAttribOffset(GC3Duint index, GC3Denum pname); - - void hint(GC3Denum target, GC3Denum mode); - GC3Dboolean isBuffer(WebGLBuffer*); - bool isContextLost() const; - GC3Dboolean isEnabled(GC3Denum cap); - GC3Dboolean isFramebuffer(WebGLFramebuffer*); - GC3Dboolean isProgram(WebGLProgram*); - GC3Dboolean isRenderbuffer(WebGLRenderbuffer*); - GC3Dboolean isShader(WebGLShader*); - GC3Dboolean isTexture(WebGLTexture*); - - void lineWidth(GC3Dfloat); - void linkProgram(WebGLProgram*, ExceptionCode&); - void pixelStorei(GC3Denum pname, GC3Dint param); - void polygonOffset(GC3Dfloat factor, GC3Dfloat units); - void readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode&); - void releaseShaderCompiler(); - void renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height); - void sampleCoverage(GC3Dfloat value, GC3Dboolean invert); - void scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height); - void shaderSource(WebGLShader*, const String&, ExceptionCode&); - void stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask); - void stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask); - void stencilMask(GC3Duint); - void stencilMaskSeparate(GC3Denum face, GC3Duint mask); - void stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass); - void stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass); - - void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Dsizei width, GC3Dsizei height, GC3Dint border, - GC3Denum format, GC3Denum type, ArrayBufferView*, ExceptionCode&); - void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, ImageData*, ExceptionCode&); - void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionCode&); - void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionCode&); -#if ENABLE(VIDEO) - void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionCode&); -#endif - - void texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param); - void texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param); - - void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Dsizei width, GC3Dsizei height, - GC3Denum format, GC3Denum type, ArrayBufferView*, ExceptionCode&); - void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, ImageData*, ExceptionCode&); - void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionCode&); - void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionCode&); -#if ENABLE(VIDEO) - void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionCode&); -#endif - - void uniform1f(const WebGLUniformLocation* location, GC3Dfloat x, ExceptionCode&); - void uniform1fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&); - void uniform1fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode&); - void uniform1i(const WebGLUniformLocation* location, GC3Dint x, ExceptionCode&); - void uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&); - void uniform1iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode&); - void uniform2f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, ExceptionCode&); - void uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&); - void uniform2fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode&); - void uniform2i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, ExceptionCode&); - void uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&); - void uniform2iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode&); - void uniform3f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, ExceptionCode&); - void uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&); - void uniform3fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode&); - void uniform3i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, ExceptionCode&); - void uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&); - void uniform3iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode&); - void uniform4f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w, ExceptionCode&); - void uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode&); - void uniform4fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode&); - void uniform4i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w, ExceptionCode&); - void uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode&); - void uniform4iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode&); - void uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* value, ExceptionCode&); - void uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei size, ExceptionCode&); - void uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* value, ExceptionCode&); - void uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei size, ExceptionCode&); - void uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* value, ExceptionCode&); - void uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei size, ExceptionCode&); - - void useProgram(WebGLProgram*, ExceptionCode&); - void validateProgram(WebGLProgram*, ExceptionCode&); - - void vertexAttrib1f(GC3Duint index, GC3Dfloat x); - void vertexAttrib1fv(GC3Duint index, Float32Array* values); - void vertexAttrib1fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei size); - void vertexAttrib2f(GC3Duint index, GC3Dfloat x, GC3Dfloat y); - void vertexAttrib2fv(GC3Duint index, Float32Array* values); - void vertexAttrib2fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei size); - void vertexAttrib3f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z); - void vertexAttrib3fv(GC3Duint index, Float32Array* values); - void vertexAttrib3fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei size); - void vertexAttrib4f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w); - void vertexAttrib4fv(GC3Duint index, Float32Array* values); - void vertexAttrib4fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei size); - void vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, - GC3Dsizei stride, long long offset, ExceptionCode&); - - void viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height); - - // WEBKIT_lose_context support - enum LostContextMode { - // Lost context occurred at the graphics system level. - RealLostContext, - - // Lost context provoked by WEBKIT_lose_context. - SyntheticLostContext - }; - void forceLostContext(LostContextMode); - void forceRestoreContext(); - void loseContextImpl(LostContextMode); - - GraphicsContext3D* graphicsContext3D() const { return m_context.get(); } - WebGLContextGroup* contextGroup() const { return m_contextGroup.get(); } -#if USE(ACCELERATED_COMPOSITING) - virtual PlatformLayer* platformLayer() const override; -#endif - - void reshape(int width, int height); - - void markLayerComposited(); - virtual void paintRenderingResultsToCanvas() override; - virtual PassRefPtr<ImageData> paintRenderingResultsToImageData(); - - void removeSharedObject(WebGLSharedObject*); - void removeContextObject(WebGLContextObject*); - - unsigned getMaxVertexAttribs() const { return m_maxVertexAttribs; } - - // ANGLE_instanced_arrays extension functions. - void drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount); - void drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount); - void vertexAttribDivisor(GC3Duint index, GC3Duint divisor); + WebGLRenderingContext(HTMLCanvasElement&, GraphicsContext3DAttributes); + WebGLRenderingContext(HTMLCanvasElement&, Ref<GraphicsContext3D>&&, GraphicsContext3DAttributes); private: - friend class EXTDrawBuffers; - friend class WebGLFramebuffer; - friend class WebGLObject; - friend class OESVertexArrayObject; - friend class WebGLDebugShaders; - friend class WebGLCompressedTextureATC; - friend class WebGLCompressedTexturePVRTC; - friend class WebGLCompressedTextureS3TC; - friend class WebGLRenderingContextErrorMessageCallback; - friend class WebGLVertexArrayObjectOES; - - WebGLRenderingContext(HTMLCanvasElement*, PassRefPtr<GraphicsContext3D>, GraphicsContext3D::Attributes); - void initializeNewContext(); - void setupFlags(); - - // ActiveDOMObject - virtual bool hasPendingActivity() const override; - virtual void stop() override; - - void addSharedObject(WebGLSharedObject*); - void addContextObject(WebGLContextObject*); - void detachAndRemoveAllObjects(); - - void destroyGraphicsContext3D(); - void markContextChanged(); - void cleanupAfterGraphicsCall(bool changed) - { - if (changed) - markContextChanged(); - } - - // Query whether it is built on top of compliant GLES2 implementation. - bool isGLES2Compliant() { return m_isGLES2Compliant; } - // Query if the GL implementation is NPOT strict. - bool isGLES2NPOTStrict() { return m_isGLES2NPOTStrict; } - // Query if the GL implementation generates errors on out-of-bounds buffer accesses. - bool isErrorGeneratedOnOutOfBoundsAccesses() { return m_isErrorGeneratedOnOutOfBoundsAccesses; } - // Query if the GL implementation initializes textures/renderbuffers to 0. - bool isResourceSafe() { return m_isResourceSafe; } - // Query if depth_stencil buffer is supported. - bool isDepthStencilSupported() { return m_isDepthStencilSupported; } - - // Helper to return the size in bytes of OpenGL data types - // like GL_FLOAT, GL_INT, etc. - unsigned int sizeInBytes(GC3Denum type); - - // Basic validation of count and offset against number of elements in element array buffer - bool validateElementArraySize(GC3Dsizei count, GC3Denum type, GC3Dintptr offset); - - // Conservative but quick index validation - bool validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired); - - // Precise but slow index validation -- only done if conservative checks fail - bool validateIndexArrayPrecise(GC3Dsizei count, GC3Denum type, GC3Dintptr offset, unsigned& numElementsRequired); - bool validateVertexAttributes(unsigned elementCount, unsigned primitiveCount = 0); - - bool validateWebGLObject(const char*, WebGLObject*); - - bool validateDrawArrays(const char* functionName, GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount); - bool validateDrawElements(const char* functionName, GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, unsigned& numElements, GC3Dsizei primcount); - - // Adds a compressed texture format. - void addCompressedTextureFormat(GC3Denum); - - PassRefPtr<Image> drawImageIntoBuffer(Image*, int width, int height, int deviceScaleFactor); - -#if ENABLE(VIDEO) - PassRefPtr<Image> videoFrameToImage(HTMLVideoElement*, BackingStoreCopy, ExceptionCode&); -#endif - - RefPtr<GraphicsContext3D> m_context; - RefPtr<WebGLContextGroup> m_contextGroup; - - // Optional structure for rendering to a DrawingBuffer, instead of directly - // to the back-buffer of m_context. - RefPtr<DrawingBuffer> m_drawingBuffer; - - // Dispatches a context lost event once it is determined that one is needed. - // This is used both for synthetic and real context losses. For real ones, it's - // likely that there's no JavaScript on the stack, but that might be dependent - // on how exactly the platform discovers that the context was lost. For better - // portability we always defer the dispatch of the event. - Timer<WebGLRenderingContext> m_dispatchContextLostEventTimer; - bool m_restoreAllowed; - Timer<WebGLRenderingContext> m_restoreTimer; - - bool m_needsUpdate; - bool m_markedCanvasDirty; - HashSet<WebGLContextObject*> m_contextObjects; - - // List of bound VBO's. Used to maintain info about sizes for ARRAY_BUFFER and stored values for ELEMENT_ARRAY_BUFFER - RefPtr<WebGLBuffer> m_boundArrayBuffer; - - RefPtr<WebGLVertexArrayObjectOES> m_defaultVertexArrayObject; - RefPtr<WebGLVertexArrayObjectOES> m_boundVertexArrayObject; - void setBoundVertexArrayObject(PassRefPtr<WebGLVertexArrayObjectOES> arrayObject) - { - if (arrayObject) - m_boundVertexArrayObject = arrayObject; - else - m_boundVertexArrayObject = m_defaultVertexArrayObject; - } - - class VertexAttribValue { - public: - VertexAttribValue() - { - initValue(); - } - - void initValue() - { - value[0] = 0.0f; - value[1] = 0.0f; - value[2] = 0.0f; - value[3] = 1.0f; - } - - GC3Dfloat value[4]; - }; - Vector<VertexAttribValue> m_vertexAttribValue; - unsigned m_maxVertexAttribs; - RefPtr<WebGLBuffer> m_vertexAttrib0Buffer; - long m_vertexAttrib0BufferSize; - GC3Dfloat m_vertexAttrib0BufferValue[4]; - bool m_forceAttrib0BufferRefill; - bool m_vertexAttrib0UsedBefore; - - RefPtr<WebGLProgram> m_currentProgram; - RefPtr<WebGLFramebuffer> m_framebufferBinding; - RefPtr<WebGLRenderbuffer> m_renderbufferBinding; - struct TextureUnitState { - RefPtr<WebGLTexture> texture2DBinding; - RefPtr<WebGLTexture> textureCubeMapBinding; - }; - Vector<TextureUnitState> m_textureUnits; - unsigned long m_activeTextureUnit; - - RefPtr<WebGLTexture> m_blackTexture2D; - RefPtr<WebGLTexture> m_blackTextureCubeMap; - - Vector<GC3Denum> m_compressedTextureFormats; - - // Fixed-size cache of reusable image buffers for video texImage2D calls. - class LRUImageBufferCache { - public: - LRUImageBufferCache(int capacity); - // The pointer returned is owned by the image buffer map. - ImageBuffer* imageBuffer(const IntSize& size); - private: - void bubbleToFront(int idx); - std::unique_ptr<std::unique_ptr<ImageBuffer>[]> m_buffers; - int m_capacity; - }; - LRUImageBufferCache m_generatedImageCache; - - GC3Dint m_maxTextureSize; - GC3Dint m_maxCubeMapTextureSize; - GC3Dint m_maxRenderbufferSize; - GC3Dint m_maxViewportDims[2]; - GC3Dint m_maxTextureLevel; - GC3Dint m_maxCubeMapTextureLevel; - - GC3Dint m_maxDrawBuffers; - GC3Dint m_maxColorAttachments; - GC3Denum m_backDrawBuffer; - bool m_drawBuffersWebGLRequirementsChecked; - bool m_drawBuffersSupported; - - GC3Dint m_packAlignment; - GC3Dint m_unpackAlignment; - bool m_unpackFlipY; - bool m_unpackPremultiplyAlpha; - GC3Denum m_unpackColorspaceConversion; - bool m_contextLost; - LostContextMode m_contextLostMode; - GraphicsContext3D::Attributes m_attributes; - - bool m_layerCleared; - GC3Dfloat m_clearColor[4]; - bool m_scissorEnabled; - GC3Dfloat m_clearDepth; - GC3Dint m_clearStencil; - GC3Dboolean m_colorMask[4]; - GC3Dboolean m_depthMask; - - bool m_stencilEnabled; - GC3Duint m_stencilMask, m_stencilMaskBack; - GC3Dint m_stencilFuncRef, m_stencilFuncRefBack; // Note that these are the user specified values, not the internal clamped value. - GC3Duint m_stencilFuncMask, m_stencilFuncMaskBack; - - bool m_isGLES2Compliant; - bool m_isGLES2NPOTStrict; - bool m_isErrorGeneratedOnOutOfBoundsAccesses; - bool m_isResourceSafe; - bool m_isDepthStencilSupported; - bool m_isRobustnessEXTSupported; - - bool m_synthesizedErrorsToConsole; - int m_numGLErrorsToConsoleAllowed; - - // Enabled extension objects. - OwnPtr<EXTDrawBuffers> m_extDrawBuffers; - OwnPtr<EXTTextureFilterAnisotropic> m_extTextureFilterAnisotropic; - OwnPtr<OESTextureFloat> m_oesTextureFloat; - OwnPtr<OESTextureFloatLinear> m_oesTextureFloatLinear; - OwnPtr<OESTextureHalfFloat> m_oesTextureHalfFloat; - OwnPtr<OESTextureHalfFloatLinear> m_oesTextureHalfFloatLinear; - OwnPtr<OESStandardDerivatives> m_oesStandardDerivatives; - OwnPtr<OESVertexArrayObject> m_oesVertexArrayObject; - OwnPtr<OESElementIndexUint> m_oesElementIndexUint; - OwnPtr<WebGLLoseContext> m_webglLoseContext; - OwnPtr<WebGLDebugRendererInfo> m_webglDebugRendererInfo; - OwnPtr<WebGLDebugShaders> m_webglDebugShaders; - OwnPtr<WebGLCompressedTextureATC> m_webglCompressedTextureATC; - OwnPtr<WebGLCompressedTexturePVRTC> m_webglCompressedTexturePVRTC; - OwnPtr<WebGLCompressedTextureS3TC> m_webglCompressedTextureS3TC; - OwnPtr<WebGLDepthTexture> m_webglDepthTexture; - OwnPtr<ANGLEInstancedArrays> m_angleInstancedArrays; - - // Helpers for getParameter and others - WebGLGetInfo getBooleanParameter(GC3Denum); - WebGLGetInfo getBooleanArrayParameter(GC3Denum); - WebGLGetInfo getFloatParameter(GC3Denum); - WebGLGetInfo getIntParameter(GC3Denum); - WebGLGetInfo getUnsignedIntParameter(GC3Denum); - WebGLGetInfo getWebGLFloatArrayParameter(GC3Denum); - WebGLGetInfo getWebGLIntArrayParameter(GC3Denum); - - // Clear the backbuffer if it was composited since the last operation. - // clearMask is set to the bitfield of any clear that would happen anyway at this time - // and the function returns true if that clear is now unnecessary. - bool clearIfComposited(GC3Dbitfield clearMask = 0); - - // Helper to restore state that clearing the framebuffer may destroy. - void restoreStateAfterClear(); - - void texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode&); - void texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionCode&); - void texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels, ExceptionCode&); - void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionCode&); - - void checkTextureCompleteness(const char*, bool); - - void createFallbackBlackTextures1x1(); - - // Helper function for copyTex{Sub}Image, check whether the internalformat - // and the color buffer format of the current bound framebuffer combination - // is valid. - bool isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat, - GC3Denum colorBufferFormat); - - // Helper function to get the bound framebuffer's color buffer format. - GC3Denum getBoundFramebufferColorFormat(); - - // Helper function to get the bound framebuffer's width. - int getBoundFramebufferWidth(); - - // Helper function to get the bound framebuffer's height. - int getBoundFramebufferHeight(); - - // Helper function to verify limits on the length of uniform and attribute locations. - bool validateLocationLength(const char* functionName, const String&); - - // Helper function to check if size is non-negative. - // Generate GL error and return false for negative inputs; otherwise, return true. - bool validateSize(const char* functionName, GC3Dint x, GC3Dint y); - - // Helper function to check if all characters in the string belong to the - // ASCII subset as defined in GLSL ES 1.0 spec section 3.1. - bool validateString(const char* functionName, const String&); - - // Helper function to check target and texture bound to the target. - // Generate GL errors and return 0 if target is invalid or texture bound is - // null. Otherwise, return the texture bound to the target. - WebGLTexture* validateTextureBinding(const char* functionName, GC3Denum target, bool useSixEnumsForCubeMap); - - // Helper function to check input format/type for functions {copy}Tex{Sub}Image. - // Generates GL error and returns false if parameters are invalid. - bool validateTexFuncFormatAndType(const char* functionName, GC3Denum format, GC3Denum type, GC3Dint level); - - // Helper function to check input level for functions {copy}Tex{Sub}Image. - // Generates GL error and returns false if level is invalid. - bool validateTexFuncLevel(const char* functionName, GC3Denum target, GC3Dint level); - - enum TexFuncValidationFunctionType { - NotTexSubImage2D, - TexSubImage2D, - }; - - enum TexFuncValidationSourceType { - SourceArrayBufferView, - SourceImageData, - SourceHTMLImageElement, - SourceHTMLCanvasElement, - SourceHTMLVideoElement, - }; - - // Helper function for tex{Sub}Image2D to check if the input format/type/level/target/width/height/border/xoffset/yoffset are valid. - // Otherwise, it would return quickly without doing other work. - bool validateTexFunc(const char* functionName, TexFuncValidationFunctionType, TexFuncValidationSourceType, GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, - GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint xoffset, GC3Dint yoffset); - - // Helper function to check input parameters for functions {copy}Tex{Sub}Image. - // Generates GL error and returns false if parameters are invalid. - bool validateTexFuncParameters(const char* functionName, - TexFuncValidationFunctionType, - GC3Denum target, GC3Dint level, - GC3Denum internalformat, - GC3Dsizei width, GC3Dsizei height, GC3Dint border, - GC3Denum format, GC3Denum type); - - enum NullDisposition { - NullAllowed, - NullNotAllowed - }; - - // Helper function to validate that the given ArrayBufferView - // is of the correct type and contains enough data for the texImage call. - // Generates GL error and returns false if parameters are invalid. - bool validateTexFuncData(const char* functionName, GC3Dint level, - GC3Dsizei width, GC3Dsizei height, - GC3Denum format, GC3Denum type, - ArrayBufferView* pixels, - NullDisposition); - - // Helper function to validate a given texture format is settable as in - // you can supply data to texImage2D, or call texImage2D, copyTexImage2D and - // copyTexSubImage2D. - // Generates GL error and returns false if the format is not settable. - bool validateSettableTexFormat(const char* functionName, GC3Denum format); - - // Helper function to validate compressed texture data is correct size - // for the given format and dimensions. - bool validateCompressedTexFuncData(const char* functionName, - GC3Dsizei width, GC3Dsizei height, - GC3Denum format, ArrayBufferView* pixels); - - // Helper function for validating compressed texture formats. - bool validateCompressedTexFormat(GC3Denum format); - - // Helper function to validate compressed texture dimensions are valid for - // the given format. - bool validateCompressedTexDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum format); - - // Helper function to validate compressed texture dimensions are valid for - // the given format. - bool validateCompressedTexSubDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Dsizei width, GC3Dsizei height, GC3Denum format, WebGLTexture*); - - // Helper function to validate mode for draw{Arrays/Elements}. - bool validateDrawMode(const char* functionName, GC3Denum); - - // Helper function to validate if front/back stencilMask and stencilFunc settings are the same. - bool validateStencilSettings(const char* functionName); - - // Helper function to validate stencil func. - bool validateStencilFunc(const char* functionName, GC3Denum); - - // Helper function for texParameterf and texParameteri. - void texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat parami, GC3Dint paramf, bool isFloat); - - // Helper function to print GL errors to console. - void printGLErrorToConsole(const String&); - void printGLWarningToConsole(const char* function, const char* reason); - - // Helper function to print warnings to console. Currently - // used only to warn about use of obsolete functions. - void printWarningToConsole(const String&); - - // Helper function to validate input parameters for framebuffer functions. - // Generate GL error if parameters are illegal. - bool validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment); - - // Helper function to validate blend equation mode. - bool validateBlendEquation(const char* functionName, GC3Denum); - - // Helper function to validate blend func factors. - bool validateBlendFuncFactors(const char* functionName, GC3Denum src, GC3Denum dst); - - // Helper function to validate a GL capability. - bool validateCapability(const char* functionName, GC3Denum); - - // Helper function to validate input parameters for uniform functions. - bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, Float32Array*, GC3Dsizei mod); - bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, Int32Array*, GC3Dsizei mod); - bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, void*, GC3Dsizei, GC3Dsizei mod); - bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GC3Dboolean transpose, Float32Array*, GC3Dsizei mod); - bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GC3Dboolean transpose, void*, GC3Dsizei, GC3Dsizei mod); - - // Helper function to validate parameters for bufferData. - // Return the current bound buffer to target, or 0 if parameters are invalid. - WebGLBuffer* validateBufferDataParameters(const char* functionName, GC3Denum target, GC3Denum usage); - - // Helper function for tex{Sub}Image2D to make sure image is ready and wouldn't taint Origin. - bool validateHTMLImageElement(const char* functionName, HTMLImageElement*, ExceptionCode&); - - // Helper function for tex{Sub}Image2D to make sure canvas is ready and wouldn't taint Origin. - bool validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement*, ExceptionCode&); - -#if ENABLE(VIDEO) - // Helper function for tex{Sub}Image2D to make sure video is ready wouldn't taint Origin. - bool validateHTMLVideoElement(const char* functionName, HTMLVideoElement*, ExceptionCode&); -#endif - - // Helper functions for vertexAttribNf{v}. - void vertexAttribfImpl(const char* functionName, GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat, GC3Dfloat, GC3Dfloat, GC3Dfloat); - void vertexAttribfvImpl(const char* functionName, GC3Duint index, Float32Array*, GC3Dsizei expectedSize); - void vertexAttribfvImpl(const char* functionName, GC3Duint index, GC3Dfloat*, GC3Dsizei, GC3Dsizei expectedSize); - - // Helper function for delete* (deleteBuffer, deleteProgram, etc) functions. - // Return false if caller should return without further processing. - bool deleteObject(WebGLObject*); - - // Helper function for bind* (bindBuffer, bindTexture, etc) and useProgram. - // If the object has already been deleted, set deleted to true upon return. - // Return false if caller should return without further processing. - bool checkObjectToBeBound(const char* functionName, WebGLObject*, bool& deleted); - - // Helpers for simulating vertexAttrib0 - void initVertexAttrib0(); - bool simulateVertexAttrib0(GC3Dsizei numVertex); - void restoreStatesAfterVertexAttrib0Simulation(); - - void dispatchContextLostEvent(Timer<WebGLRenderingContext>*); - // Helper for restoration after context lost. - void maybeRestoreContext(Timer<WebGLRenderingContext>*); - - // Determine if we are running privileged code in the browser, for example, - // a Safari or Chrome extension. - bool allowPrivilegedExtensions() const; - - enum ConsoleDisplayPreference { - DisplayInConsole, - DontDisplayInConsole - }; - - // Wrapper for GraphicsContext3D::synthesizeGLError that sends a message - // to the JavaScript console. - void synthesizeGLError(GC3Denum, const char* functionName, const char* description, ConsoleDisplayPreference = DisplayInConsole); - - String ensureNotNull(const String&) const; - - // Enable or disable stencil test based on user setting and - // whether the current FBO has a stencil buffer. - void applyStencilTest(); - - // Helper for enabling or disabling a capability. - void enableOrDisable(GC3Denum capability, bool enable); - - // Clamp the width and height to GL_MAX_VIEWPORT_DIMS. - IntSize clampedCanvasSize(); - - // First time called, if EXT_draw_buffers is supported, query the value; otherwise return 0. - // Later, return the cached value. - GC3Dint getMaxDrawBuffers(); - GC3Dint getMaxColorAttachments(); - - void setBackDrawBuffer(GC3Denum); - - void restoreCurrentFramebuffer(); - void restoreCurrentTexture2D(); - - // Check if EXT_draw_buffers extension is supported and if it satisfies the WebGL requirements. - bool supportsDrawBuffers(); - - friend class WebGLStateRestorer; + bool isWebGL1() const final { return true; } + + WebGLExtension* getExtension(const String&) final; + WebGLAny getParameter(GC3Denum pname) final; + std::optional<Vector<String>> getSupportedExtensions() final; + + WebGLAny getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname) final; + void renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) final; + bool validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment) final; + void hint(GC3Denum target, GC3Denum mode) final; + void clear(GC3Dbitfield mask) final; + + GC3Dint getMaxDrawBuffers() final; + GC3Dint getMaxColorAttachments() final; + void initializeVertexArrayObjects() final; + bool validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired) final; + bool validateBlendEquation(const char* functionName, GC3Denum mode) final; + bool validateCapability(const char* functionName, GC3Denum cap) final; }; - + } // namespace WebCore -#endif +SPECIALIZE_TYPE_TRAITS_CANVASRENDERINGCONTEXT(WebCore::WebGLRenderingContext, isWebGL1()) diff --git a/Source/WebCore/html/canvas/WebGLRenderingContext.idl b/Source/WebCore/html/canvas/WebGLRenderingContext.idl index 54d9b0431..80cd98eca 100644 --- a/Source/WebCore/html/canvas/WebGLRenderingContext.idl +++ b/Source/WebCore/html/canvas/WebGLRenderingContext.idl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,647 +23,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -typedef unsigned long GLenum; -typedef boolean GLboolean; -typedef unsigned long GLbitfield; -typedef byte GLbyte; /* 'byte' should be a signed 8 bit type. */ -typedef short GLshort; -typedef long GLint; -typedef long GLsizei; -typedef long long GLintptr; -typedef long long GLsizeiptr; -typedef octet GLubyte; /* 'octet' should be an unsigned 8 bit type. */ -typedef unsigned short GLushort; -typedef unsigned long GLuint; -typedef /*unrestricted*/ float GLfloat; -typedef /*unrestricted*/ float GLclampf; - [ Conditional=WEBGL, JSCustomMarkFunction, + JSGenerateToJSObject, DoNotCheckConstants, -] interface WebGLRenderingContext : CanvasRenderingContext { - - /* ClearBufferMask */ - const GLenum DEPTH_BUFFER_BIT = 0x00000100; - const GLenum STENCIL_BUFFER_BIT = 0x00000400; - const GLenum COLOR_BUFFER_BIT = 0x00004000; - - /* BeginMode */ - const GLenum POINTS = 0x0000; - const GLenum LINES = 0x0001; - const GLenum LINE_LOOP = 0x0002; - const GLenum LINE_STRIP = 0x0003; - const GLenum TRIANGLES = 0x0004; - const GLenum TRIANGLE_STRIP = 0x0005; - const GLenum TRIANGLE_FAN = 0x0006; - - /* AlphaFunction (not supported in ES20) */ - /* NEVER */ - /* LESS */ - /* EQUAL */ - /* LEQUAL */ - /* GREATER */ - /* NOTEQUAL */ - /* GEQUAL */ - /* ALWAYS */ - - /* BlendingFactorDest */ - const GLenum ZERO = 0; - const GLenum ONE = 1; - const GLenum SRC_COLOR = 0x0300; - const GLenum ONE_MINUS_SRC_COLOR = 0x0301; - const GLenum SRC_ALPHA = 0x0302; - const GLenum ONE_MINUS_SRC_ALPHA = 0x0303; - const GLenum DST_ALPHA = 0x0304; - const GLenum ONE_MINUS_DST_ALPHA = 0x0305; - - /* BlendingFactorSrc */ - /* ZERO */ - /* ONE */ - const GLenum DST_COLOR = 0x0306; - const GLenum ONE_MINUS_DST_COLOR = 0x0307; - const GLenum SRC_ALPHA_SATURATE = 0x0308; - /* SRC_ALPHA */ - /* ONE_MINUS_SRC_ALPHA */ - /* DST_ALPHA */ - /* ONE_MINUS_DST_ALPHA */ - - /* BlendEquationSeparate */ - const GLenum FUNC_ADD = 0x8006; - const GLenum BLEND_EQUATION = 0x8009; - const GLenum BLEND_EQUATION_RGB = 0x8009; /* same as BLEND_EQUATION */ - const GLenum BLEND_EQUATION_ALPHA = 0x883D; - - /* BlendSubtract */ - const GLenum FUNC_SUBTRACT = 0x800A; - const GLenum FUNC_REVERSE_SUBTRACT = 0x800B; - - /* Separate Blend Functions */ - const GLenum BLEND_DST_RGB = 0x80C8; - const GLenum BLEND_SRC_RGB = 0x80C9; - const GLenum BLEND_DST_ALPHA = 0x80CA; - const GLenum BLEND_SRC_ALPHA = 0x80CB; - const GLenum CONSTANT_COLOR = 0x8001; - const GLenum ONE_MINUS_CONSTANT_COLOR = 0x8002; - const GLenum CONSTANT_ALPHA = 0x8003; - const GLenum ONE_MINUS_CONSTANT_ALPHA = 0x8004; - const GLenum BLEND_COLOR = 0x8005; - - /* Buffer Objects */ - const GLenum ARRAY_BUFFER = 0x8892; - const GLenum ELEMENT_ARRAY_BUFFER = 0x8893; - const GLenum ARRAY_BUFFER_BINDING = 0x8894; - const GLenum ELEMENT_ARRAY_BUFFER_BINDING = 0x8895; - - const GLenum STREAM_DRAW = 0x88E0; - const GLenum STATIC_DRAW = 0x88E4; - const GLenum DYNAMIC_DRAW = 0x88E8; - - const GLenum BUFFER_SIZE = 0x8764; - const GLenum BUFFER_USAGE = 0x8765; - - const GLenum CURRENT_VERTEX_ATTRIB = 0x8626; - - /* CullFaceMode */ - const GLenum FRONT = 0x0404; - const GLenum BACK = 0x0405; - const GLenum FRONT_AND_BACK = 0x0408; - - /* DepthFunction */ - /* NEVER */ - /* LESS */ - /* EQUAL */ - /* LEQUAL */ - /* GREATER */ - /* NOTEQUAL */ - /* GEQUAL */ - /* ALWAYS */ - - /* EnableCap */ - const GLenum TEXTURE_2D = 0x0DE1; - const GLenum CULL_FACE = 0x0B44; - const GLenum BLEND = 0x0BE2; - const GLenum DITHER = 0x0BD0; - const GLenum STENCIL_TEST = 0x0B90; - const GLenum DEPTH_TEST = 0x0B71; - const GLenum SCISSOR_TEST = 0x0C11; - const GLenum POLYGON_OFFSET_FILL = 0x8037; - const GLenum SAMPLE_ALPHA_TO_COVERAGE = 0x809E; - const GLenum SAMPLE_COVERAGE = 0x80A0; - - /* ErrorCode */ - const GLenum NO_ERROR = 0; - const GLenum INVALID_ENUM = 0x0500; - const GLenum INVALID_VALUE = 0x0501; - const GLenum INVALID_OPERATION = 0x0502; - const GLenum OUT_OF_MEMORY = 0x0505; - - /* FrontFaceDirection */ - const GLenum CW = 0x0900; - const GLenum CCW = 0x0901; - - /* GetPName */ - const GLenum LINE_WIDTH = 0x0B21; - const GLenum ALIASED_POINT_SIZE_RANGE = 0x846D; - const GLenum ALIASED_LINE_WIDTH_RANGE = 0x846E; - const GLenum CULL_FACE_MODE = 0x0B45; - const GLenum FRONT_FACE = 0x0B46; - const GLenum DEPTH_RANGE = 0x0B70; - const GLenum DEPTH_WRITEMASK = 0x0B72; - const GLenum DEPTH_CLEAR_VALUE = 0x0B73; - const GLenum DEPTH_FUNC = 0x0B74; - const GLenum STENCIL_CLEAR_VALUE = 0x0B91; - const GLenum STENCIL_FUNC = 0x0B92; - const GLenum STENCIL_FAIL = 0x0B94; - const GLenum STENCIL_PASS_DEPTH_FAIL = 0x0B95; - const GLenum STENCIL_PASS_DEPTH_PASS = 0x0B96; - const GLenum STENCIL_REF = 0x0B97; - const GLenum STENCIL_VALUE_MASK = 0x0B93; - const GLenum STENCIL_WRITEMASK = 0x0B98; - const GLenum STENCIL_BACK_FUNC = 0x8800; - const GLenum STENCIL_BACK_FAIL = 0x8801; - const GLenum STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802; - const GLenum STENCIL_BACK_PASS_DEPTH_PASS = 0x8803; - const GLenum STENCIL_BACK_REF = 0x8CA3; - const GLenum STENCIL_BACK_VALUE_MASK = 0x8CA4; - const GLenum STENCIL_BACK_WRITEMASK = 0x8CA5; - const GLenum VIEWPORT = 0x0BA2; - const GLenum SCISSOR_BOX = 0x0C10; - /* SCISSOR_TEST */ - const GLenum COLOR_CLEAR_VALUE = 0x0C22; - const GLenum COLOR_WRITEMASK = 0x0C23; - const GLenum UNPACK_ALIGNMENT = 0x0CF5; - const GLenum PACK_ALIGNMENT = 0x0D05; - const GLenum MAX_TEXTURE_SIZE = 0x0D33; - const GLenum MAX_VIEWPORT_DIMS = 0x0D3A; - const GLenum SUBPIXEL_BITS = 0x0D50; - const GLenum RED_BITS = 0x0D52; - const GLenum GREEN_BITS = 0x0D53; - const GLenum BLUE_BITS = 0x0D54; - const GLenum ALPHA_BITS = 0x0D55; - const GLenum DEPTH_BITS = 0x0D56; - const GLenum STENCIL_BITS = 0x0D57; - const GLenum POLYGON_OFFSET_UNITS = 0x2A00; - /* POLYGON_OFFSET_FILL */ - const GLenum POLYGON_OFFSET_FACTOR = 0x8038; - const GLenum TEXTURE_BINDING_2D = 0x8069; - const GLenum SAMPLE_BUFFERS = 0x80A8; - const GLenum SAMPLES = 0x80A9; - const GLenum SAMPLE_COVERAGE_VALUE = 0x80AA; - const GLenum SAMPLE_COVERAGE_INVERT = 0x80AB; - - /* GetTextureParameter */ - /* TEXTURE_MAG_FILTER */ - /* TEXTURE_MIN_FILTER */ - /* TEXTURE_WRAP_S */ - /* TEXTURE_WRAP_T */ - - const GLenum COMPRESSED_TEXTURE_FORMATS = 0x86A3; - - /* HintMode */ - const GLenum DONT_CARE = 0x1100; - const GLenum FASTEST = 0x1101; - const GLenum NICEST = 0x1102; - - /* HintTarget */ - const GLenum GENERATE_MIPMAP_HINT = 0x8192; - - /* DataType */ - const GLenum BYTE = 0x1400; - const GLenum UNSIGNED_BYTE = 0x1401; - const GLenum SHORT = 0x1402; - const GLenum UNSIGNED_SHORT = 0x1403; - const GLenum INT = 0x1404; - const GLenum UNSIGNED_INT = 0x1405; - const GLenum FLOAT = 0x1406; - - /* PixelFormat */ - const GLenum DEPTH_COMPONENT = 0x1902; - const GLenum ALPHA = 0x1906; - const GLenum RGB = 0x1907; - const GLenum RGBA = 0x1908; - const GLenum LUMINANCE = 0x1909; - const GLenum LUMINANCE_ALPHA = 0x190A; - - /* PixelType */ - /* UNSIGNED_BYTE */ - const GLenum UNSIGNED_SHORT_4_4_4_4 = 0x8033; - const GLenum UNSIGNED_SHORT_5_5_5_1 = 0x8034; - const GLenum UNSIGNED_SHORT_5_6_5 = 0x8363; - - /* Shaders */ - const GLenum FRAGMENT_SHADER = 0x8B30; - const GLenum VERTEX_SHADER = 0x8B31; - const GLenum MAX_VERTEX_ATTRIBS = 0x8869; - const GLenum MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB; - const GLenum MAX_VARYING_VECTORS = 0x8DFC; - const GLenum MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D; - const GLenum MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C; - const GLenum MAX_TEXTURE_IMAGE_UNITS = 0x8872; - const GLenum MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD; - const GLenum SHADER_TYPE = 0x8B4F; - const GLenum DELETE_STATUS = 0x8B80; - const GLenum LINK_STATUS = 0x8B82; - const GLenum VALIDATE_STATUS = 0x8B83; - const GLenum ATTACHED_SHADERS = 0x8B85; - const GLenum ACTIVE_UNIFORMS = 0x8B86; - const GLenum ACTIVE_ATTRIBUTES = 0x8B89; - const GLenum SHADING_LANGUAGE_VERSION = 0x8B8C; - const GLenum CURRENT_PROGRAM = 0x8B8D; - - /* StencilFunction */ - const GLenum NEVER = 0x0200; - const GLenum LESS = 0x0201; - const GLenum EQUAL = 0x0202; - const GLenum LEQUAL = 0x0203; - const GLenum GREATER = 0x0204; - const GLenum NOTEQUAL = 0x0205; - const GLenum GEQUAL = 0x0206; - const GLenum ALWAYS = 0x0207; - - /* StencilOp */ - /* ZERO */ - const GLenum KEEP = 0x1E00; - const GLenum REPLACE = 0x1E01; - const GLenum INCR = 0x1E02; - const GLenum DECR = 0x1E03; - const GLenum INVERT = 0x150A; - const GLenum INCR_WRAP = 0x8507; - const GLenum DECR_WRAP = 0x8508; - - /* StringName */ - const GLenum VENDOR = 0x1F00; - const GLenum RENDERER = 0x1F01; - const GLenum VERSION = 0x1F02; - - /* TextureMagFilter */ - const GLenum NEAREST = 0x2600; - const GLenum LINEAR = 0x2601; - - /* TextureMinFilter */ - /* NEAREST */ - /* LINEAR */ - const GLenum NEAREST_MIPMAP_NEAREST = 0x2700; - const GLenum LINEAR_MIPMAP_NEAREST = 0x2701; - const GLenum NEAREST_MIPMAP_LINEAR = 0x2702; - const GLenum LINEAR_MIPMAP_LINEAR = 0x2703; - - /* TextureParameterName */ - const GLenum TEXTURE_MAG_FILTER = 0x2800; - const GLenum TEXTURE_MIN_FILTER = 0x2801; - const GLenum TEXTURE_WRAP_S = 0x2802; - const GLenum TEXTURE_WRAP_T = 0x2803; - - /* TextureTarget */ - /* TEXTURE_2D */ - const GLenum TEXTURE = 0x1702; - - const GLenum TEXTURE_CUBE_MAP = 0x8513; - const GLenum TEXTURE_BINDING_CUBE_MAP = 0x8514; - const GLenum TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515; - const GLenum TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516; - const GLenum TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517; - const GLenum TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518; - const GLenum TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519; - const GLenum TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A; - const GLenum MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C; - - /* TextureUnit */ - const GLenum TEXTURE0 = 0x84C0; - const GLenum TEXTURE1 = 0x84C1; - const GLenum TEXTURE2 = 0x84C2; - const GLenum TEXTURE3 = 0x84C3; - const GLenum TEXTURE4 = 0x84C4; - const GLenum TEXTURE5 = 0x84C5; - const GLenum TEXTURE6 = 0x84C6; - const GLenum TEXTURE7 = 0x84C7; - const GLenum TEXTURE8 = 0x84C8; - const GLenum TEXTURE9 = 0x84C9; - const GLenum TEXTURE10 = 0x84CA; - const GLenum TEXTURE11 = 0x84CB; - const GLenum TEXTURE12 = 0x84CC; - const GLenum TEXTURE13 = 0x84CD; - const GLenum TEXTURE14 = 0x84CE; - const GLenum TEXTURE15 = 0x84CF; - const GLenum TEXTURE16 = 0x84D0; - const GLenum TEXTURE17 = 0x84D1; - const GLenum TEXTURE18 = 0x84D2; - const GLenum TEXTURE19 = 0x84D3; - const GLenum TEXTURE20 = 0x84D4; - const GLenum TEXTURE21 = 0x84D5; - const GLenum TEXTURE22 = 0x84D6; - const GLenum TEXTURE23 = 0x84D7; - const GLenum TEXTURE24 = 0x84D8; - const GLenum TEXTURE25 = 0x84D9; - const GLenum TEXTURE26 = 0x84DA; - const GLenum TEXTURE27 = 0x84DB; - const GLenum TEXTURE28 = 0x84DC; - const GLenum TEXTURE29 = 0x84DD; - const GLenum TEXTURE30 = 0x84DE; - const GLenum TEXTURE31 = 0x84DF; - const GLenum ACTIVE_TEXTURE = 0x84E0; - - /* TextureWrapMode */ - const GLenum REPEAT = 0x2901; - const GLenum CLAMP_TO_EDGE = 0x812F; - const GLenum MIRRORED_REPEAT = 0x8370; - - /* Uniform Types */ - const GLenum FLOAT_VEC2 = 0x8B50; - const GLenum FLOAT_VEC3 = 0x8B51; - const GLenum FLOAT_VEC4 = 0x8B52; - const GLenum INT_VEC2 = 0x8B53; - const GLenum INT_VEC3 = 0x8B54; - const GLenum INT_VEC4 = 0x8B55; - const GLenum BOOL = 0x8B56; - const GLenum BOOL_VEC2 = 0x8B57; - const GLenum BOOL_VEC3 = 0x8B58; - const GLenum BOOL_VEC4 = 0x8B59; - const GLenum FLOAT_MAT2 = 0x8B5A; - const GLenum FLOAT_MAT3 = 0x8B5B; - const GLenum FLOAT_MAT4 = 0x8B5C; - const GLenum SAMPLER_2D = 0x8B5E; - const GLenum SAMPLER_CUBE = 0x8B60; - - /* Vertex Arrays */ - const GLenum VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622; - const GLenum VERTEX_ATTRIB_ARRAY_SIZE = 0x8623; - const GLenum VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624; - const GLenum VERTEX_ATTRIB_ARRAY_TYPE = 0x8625; - const GLenum VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A; - const GLenum VERTEX_ATTRIB_ARRAY_POINTER = 0x8645; - const GLenum VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F; - - /* Shader Source */ - const GLenum COMPILE_STATUS = 0x8B81; - - /* Shader Precision-Specified Types */ - const GLenum LOW_FLOAT = 0x8DF0; - const GLenum MEDIUM_FLOAT = 0x8DF1; - const GLenum HIGH_FLOAT = 0x8DF2; - const GLenum LOW_INT = 0x8DF3; - const GLenum MEDIUM_INT = 0x8DF4; - const GLenum HIGH_INT = 0x8DF5; - - /* Framebuffer Object. */ - const GLenum FRAMEBUFFER = 0x8D40; - const GLenum RENDERBUFFER = 0x8D41; - - const GLenum RGBA4 = 0x8056; - const GLenum RGB5_A1 = 0x8057; - const GLenum RGB565 = 0x8D62; - const GLenum DEPTH_COMPONENT16 = 0x81A5; - const GLenum STENCIL_INDEX = 0x1901; - const GLenum STENCIL_INDEX8 = 0x8D48; - const GLenum DEPTH_STENCIL = 0x84F9; - - const GLenum RENDERBUFFER_WIDTH = 0x8D42; - const GLenum RENDERBUFFER_HEIGHT = 0x8D43; - const GLenum RENDERBUFFER_INTERNAL_FORMAT = 0x8D44; - const GLenum RENDERBUFFER_RED_SIZE = 0x8D50; - const GLenum RENDERBUFFER_GREEN_SIZE = 0x8D51; - const GLenum RENDERBUFFER_BLUE_SIZE = 0x8D52; - const GLenum RENDERBUFFER_ALPHA_SIZE = 0x8D53; - const GLenum RENDERBUFFER_DEPTH_SIZE = 0x8D54; - const GLenum RENDERBUFFER_STENCIL_SIZE = 0x8D55; - - const GLenum FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8CD0; - const GLenum FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1; - const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8CD2; - const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3; - - const GLenum COLOR_ATTACHMENT0 = 0x8CE0; - const GLenum DEPTH_ATTACHMENT = 0x8D00; - const GLenum STENCIL_ATTACHMENT = 0x8D20; - const GLenum DEPTH_STENCIL_ATTACHMENT = 0x821A; - - const GLenum NONE = 0; - - const GLenum FRAMEBUFFER_COMPLETE = 0x8CD5; - const GLenum FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6; - const GLenum FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7; - const GLenum FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9; - const GLenum FRAMEBUFFER_UNSUPPORTED = 0x8CDD; - - const GLenum FRAMEBUFFER_BINDING = 0x8CA6; - const GLenum RENDERBUFFER_BINDING = 0x8CA7; - const GLenum MAX_RENDERBUFFER_SIZE = 0x84E8; - - const GLenum INVALID_FRAMEBUFFER_OPERATION = 0x0506; - - /* WebGL-specific enums */ - const GLenum UNPACK_FLIP_Y_WEBGL = 0x9240; - const GLenum UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241; - const GLenum CONTEXT_LOST_WEBGL = 0x9242; - const GLenum UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243; - const GLenum BROWSER_DEFAULT_WEBGL = 0x9244; - - readonly attribute GLsizei drawingBufferWidth; - readonly attribute GLsizei drawingBufferHeight; - - [StrictTypeChecking, RaisesException] void activeTexture(GLenum texture); - [StrictTypeChecking, RaisesException] void attachShader(WebGLProgram program, WebGLShader shader); - [StrictTypeChecking, RaisesException] void bindAttribLocation(WebGLProgram program, GLuint index, DOMString name); - [StrictTypeChecking, RaisesException] void bindBuffer(GLenum target, WebGLBuffer buffer); - [StrictTypeChecking, RaisesException] void bindFramebuffer(GLenum target, WebGLFramebuffer framebuffer); - [StrictTypeChecking, RaisesException] void bindRenderbuffer(GLenum target, WebGLRenderbuffer renderbuffer); - [StrictTypeChecking, RaisesException] void bindTexture(GLenum target, WebGLTexture texture); - [StrictTypeChecking] void blendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); - [StrictTypeChecking] void blendEquation(GLenum mode); - [StrictTypeChecking] void blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha); - [StrictTypeChecking] void blendFunc(GLenum sfactor, GLenum dfactor); - [StrictTypeChecking] void blendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); - [StrictTypeChecking, RaisesException] void bufferData(GLenum target, ArrayBuffer? data, GLenum usage); - [StrictTypeChecking, RaisesException] void bufferData(GLenum target, ArrayBufferView? data, GLenum usage); - [StrictTypeChecking, RaisesException] void bufferData(GLenum target, GLsizeiptr size, GLenum usage); - [StrictTypeChecking, RaisesException] void bufferSubData(GLenum target, GLintptr offset, ArrayBuffer? data); - [StrictTypeChecking, RaisesException] void bufferSubData(GLenum target, GLintptr offset, ArrayBufferView? data); - - [StrictTypeChecking] GLenum checkFramebufferStatus(GLenum target); - [StrictTypeChecking] void clear(GLbitfield mask); - [StrictTypeChecking] void clearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); - [StrictTypeChecking] void clearDepth(GLclampf depth); - [StrictTypeChecking] void clearStencil(GLint s); - [StrictTypeChecking] void colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); - [StrictTypeChecking, RaisesException] void compileShader(WebGLShader shader); - - [StrictTypeChecking] void compressedTexImage2D(GLenum target, GLint level, GLenum internalformat, - GLsizei width, GLsizei height, GLint border, ArrayBufferView data); - [StrictTypeChecking] void compressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, GLenum format, ArrayBufferView data); - - [StrictTypeChecking] void copyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); - [StrictTypeChecking] void copyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); - - [StrictTypeChecking] WebGLBuffer createBuffer(); - [StrictTypeChecking] WebGLFramebuffer createFramebuffer(); - [StrictTypeChecking] WebGLProgram createProgram(); - [StrictTypeChecking] WebGLRenderbuffer createRenderbuffer(); - [StrictTypeChecking, RaisesException] WebGLShader createShader(GLenum type); - [StrictTypeChecking] WebGLTexture createTexture(); - - [StrictTypeChecking] void cullFace(GLenum mode); - - [StrictTypeChecking] void deleteBuffer(WebGLBuffer buffer); - [StrictTypeChecking] void deleteFramebuffer(WebGLFramebuffer framebuffer); - [StrictTypeChecking] void deleteProgram(WebGLProgram program); - [StrictTypeChecking] void deleteRenderbuffer(WebGLRenderbuffer renderbuffer); - [StrictTypeChecking] void deleteShader(WebGLShader shader); - [StrictTypeChecking] void deleteTexture(WebGLTexture texture); - - [StrictTypeChecking] void depthFunc(GLenum func); - [StrictTypeChecking] void depthMask(GLboolean flag); - [StrictTypeChecking] void depthRange(GLclampf zNear, GLclampf zFar); - [StrictTypeChecking, RaisesException] void detachShader(WebGLProgram program, WebGLShader shader); - [StrictTypeChecking] void disable(GLenum cap); - [StrictTypeChecking, RaisesException] void disableVertexAttribArray(GLuint index); - [StrictTypeChecking, RaisesException] void drawArrays(GLenum mode, GLint first, GLsizei count); - [StrictTypeChecking, RaisesException] void drawElements(GLenum mode, GLsizei count, GLenum type, GLintptr offset); - - [StrictTypeChecking] void enable(GLenum cap); - [StrictTypeChecking, RaisesException] void enableVertexAttribArray(GLuint index); - [StrictTypeChecking] void finish(); - [StrictTypeChecking] void flush(); - [StrictTypeChecking, RaisesException] void framebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, WebGLRenderbuffer renderbuffer); - [StrictTypeChecking, RaisesException] void framebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, WebGLTexture texture, GLint level); - [StrictTypeChecking] void frontFace(GLenum mode); - [StrictTypeChecking] void generateMipmap(GLenum target); - - [StrictTypeChecking, RaisesException] WebGLActiveInfo getActiveAttrib(WebGLProgram program, GLuint index); - [StrictTypeChecking, RaisesException] WebGLActiveInfo getActiveUniform(WebGLProgram program, GLuint index); - - [StrictTypeChecking, Custom, RaisesException] void getAttachedShaders(WebGLProgram program); - - [StrictTypeChecking] GLint getAttribLocation(WebGLProgram program, DOMString name); - - [StrictTypeChecking, Custom] any getBufferParameter(GLenum target, GLenum pname); - - [StrictTypeChecking] WebGLContextAttributes getContextAttributes(); - - [StrictTypeChecking] GLenum getError(); - - // object getExtension(DOMString name); - [StrictTypeChecking, Custom] any getExtension(DOMString name); - - [StrictTypeChecking, Custom, RaisesException] any getFramebufferAttachmentParameter(GLenum target, GLenum attachment, GLenum pname); - [StrictTypeChecking, Custom, RaisesException] any getParameter(GLenum pname); - [StrictTypeChecking, Custom, RaisesException] any getProgramParameter(WebGLProgram program, GLenum pname); - [StrictTypeChecking, TreatReturnedNullStringAs=Null, RaisesException] DOMString getProgramInfoLog(WebGLProgram program); - [StrictTypeChecking, Custom, RaisesException] any getRenderbufferParameter(GLenum target, GLenum pname); - [StrictTypeChecking, Custom, RaisesException] any getShaderParameter(WebGLShader shader, GLenum pname); - - [StrictTypeChecking, TreatReturnedNullStringAs=Null, RaisesException] DOMString getShaderInfoLog(WebGLShader shader); - - [StrictTypeChecking, RaisesException] WebGLShaderPrecisionFormat getShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype); - - [StrictTypeChecking, TreatReturnedNullStringAs=Null, RaisesException] DOMString getShaderSource(WebGLShader shader); - - [StrictTypeChecking, Custom] sequence<DOMString> getSupportedExtensions(); - - [StrictTypeChecking, Custom, RaisesException] any getTexParameter(GLenum target, GLenum pname); - - [StrictTypeChecking, Custom, RaisesException] any getUniform(WebGLProgram program, WebGLUniformLocation location); - - [StrictTypeChecking, RaisesException] WebGLUniformLocation getUniformLocation(WebGLProgram program, DOMString name); - - [StrictTypeChecking, Custom, RaisesException] any getVertexAttrib(GLuint index, GLenum pname); - - [StrictTypeChecking] GLsizeiptr getVertexAttribOffset(GLuint index, GLenum pname); - - [StrictTypeChecking] void hint(GLenum target, GLenum mode); - [StrictTypeChecking] GLboolean isBuffer(WebGLBuffer buffer); - [StrictTypeChecking] GLboolean isContextLost(); - [StrictTypeChecking] GLboolean isEnabled(GLenum cap); - [StrictTypeChecking] GLboolean isFramebuffer(WebGLFramebuffer framebuffer); - [StrictTypeChecking] GLboolean isProgram(WebGLProgram program); - [StrictTypeChecking] GLboolean isRenderbuffer(WebGLRenderbuffer renderbuffer); - [StrictTypeChecking] GLboolean isShader(WebGLShader shader); - [StrictTypeChecking] GLboolean isTexture(WebGLTexture texture); - [StrictTypeChecking] void lineWidth(GLfloat width); - [StrictTypeChecking, RaisesException] void linkProgram(WebGLProgram program); - [StrictTypeChecking] void pixelStorei(GLenum pname, GLint param); - [StrictTypeChecking] void polygonOffset(GLfloat factor, GLfloat units); - - [StrictTypeChecking, RaisesException] void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, ArrayBufferView pixels); - - [StrictTypeChecking] void releaseShaderCompiler(); - [StrictTypeChecking] void renderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); - [StrictTypeChecking] void sampleCoverage(GLclampf value, GLboolean invert); - [StrictTypeChecking] void scissor(GLint x, GLint y, GLsizei width, GLsizei height); - [StrictTypeChecking, RaisesException] void shaderSource(WebGLShader shader, DOMString string); - [StrictTypeChecking] void stencilFunc(GLenum func, GLint ref, GLuint mask); - [StrictTypeChecking] void stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask); - [StrictTypeChecking] void stencilMask(GLuint mask); - [StrictTypeChecking] void stencilMaskSeparate(GLenum face, GLuint mask); - [StrictTypeChecking] void stencilOp(GLenum fail, GLenum zfail, GLenum zpass); - [StrictTypeChecking] void stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass); - - [StrictTypeChecking] void texParameterf(GLenum target, GLenum pname, GLfloat param); - [StrictTypeChecking] void texParameteri(GLenum target, GLenum pname, GLint param); - - // Supported forms: - [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, - GLint border, GLenum format, GLenum type, ArrayBufferView? pixels); - [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat, - GLenum format, GLenum type, ImageData? pixels); - [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat, - GLenum format, GLenum type, HTMLImageElement? image); - [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat, - GLenum format, GLenum type, HTMLCanvasElement? canvas); -#if defined(ENABLE_VIDEO) && ENABLE_VIDEO - [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat, - GLenum format, GLenum type, HTMLVideoElement? video); -#endif - - [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, - GLenum format, GLenum type, ArrayBufferView? pixels); - [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, - GLenum format, GLenum type, ImageData? pixels); - [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, - GLenum format, GLenum type, HTMLImageElement? image); - [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, - GLenum format, GLenum type, HTMLCanvasElement? canvas); -#if defined(ENABLE_VIDEO) && ENABLE_VIDEO - [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, - GLenum format, GLenum type, HTMLVideoElement? video); -#endif - - [StrictTypeChecking, RaisesException] void uniform1f(WebGLUniformLocation location, GLfloat x); - [StrictTypeChecking, Custom, RaisesException] void uniform1fv(WebGLUniformLocation location, Float32Array v); - [StrictTypeChecking, RaisesException] void uniform1i(WebGLUniformLocation location, GLint x); - [StrictTypeChecking, Custom, RaisesException] void uniform1iv(WebGLUniformLocation location, Int32Array v); - [StrictTypeChecking, RaisesException] void uniform2f(WebGLUniformLocation location, GLfloat x, GLfloat y); - [StrictTypeChecking, Custom, RaisesException] void uniform2fv(WebGLUniformLocation location, Float32Array v); - [StrictTypeChecking, RaisesException] void uniform2i(WebGLUniformLocation location, GLint x, GLint y); - [StrictTypeChecking, Custom, RaisesException] void uniform2iv(WebGLUniformLocation location, Int32Array v); - [StrictTypeChecking, RaisesException] void uniform3f(WebGLUniformLocation location, GLfloat x, GLfloat y, GLfloat z); - [StrictTypeChecking, Custom, RaisesException] void uniform3fv(WebGLUniformLocation location, Float32Array v); - [StrictTypeChecking, RaisesException] void uniform3i(WebGLUniformLocation location, GLint x, GLint y, GLint z); - [StrictTypeChecking, Custom, RaisesException] void uniform3iv(WebGLUniformLocation location, Int32Array v); - [StrictTypeChecking, RaisesException] void uniform4f(WebGLUniformLocation location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); - [StrictTypeChecking, Custom, RaisesException] void uniform4fv(WebGLUniformLocation location, Float32Array v); - [StrictTypeChecking, RaisesException] void uniform4i(WebGLUniformLocation location, GLint x, GLint y, GLint z, GLint w); - [StrictTypeChecking, Custom, RaisesException] void uniform4iv(WebGLUniformLocation location, Int32Array v); - - [StrictTypeChecking, Custom, RaisesException] void uniformMatrix2fv(WebGLUniformLocation location, GLboolean transpose, Float32Array array); - [StrictTypeChecking, Custom, RaisesException] void uniformMatrix3fv(WebGLUniformLocation location, GLboolean transpose, Float32Array array); - [StrictTypeChecking, Custom, RaisesException] void uniformMatrix4fv(WebGLUniformLocation location, GLboolean transpose, Float32Array array); - - [StrictTypeChecking, RaisesException] void useProgram(WebGLProgram program); - [StrictTypeChecking, RaisesException] void validateProgram(WebGLProgram program); - - [StrictTypeChecking] void vertexAttrib1f(GLuint indx, GLfloat x); - [StrictTypeChecking, Custom] void vertexAttrib1fv(GLuint indx, Float32Array values); - [StrictTypeChecking] void vertexAttrib2f(GLuint indx, GLfloat x, GLfloat y); - [StrictTypeChecking, Custom] void vertexAttrib2fv(GLuint indx, Float32Array values); - [StrictTypeChecking] void vertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z); - [StrictTypeChecking, Custom] void vertexAttrib3fv(GLuint indx, Float32Array values); - [StrictTypeChecking] void vertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); - [StrictTypeChecking, Custom] void vertexAttrib4fv(GLuint indx, Float32Array values); - [StrictTypeChecking, RaisesException] void vertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, - GLsizei stride, GLintptr offset); - - [StrictTypeChecking] void viewport(GLint x, GLint y, GLsizei width, GLsizei height); +] interface WebGLRenderingContext : WebGLRenderingContextBase { }; diff --git a/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp b/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp new file mode 100644 index 000000000..f8fd63f7d --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp @@ -0,0 +1,5897 @@ +/* + * Copyright (C) 2015-2017 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebGLRenderingContextBase.h" + +#if ENABLE(WEBGL) + +#include "ANGLEInstancedArrays.h" +#include "CachedImage.h" +#include "DOMWindow.h" +#include "DiagnosticLoggingClient.h" +#include "DiagnosticLoggingKeys.h" +#include "Document.h" +#include "EXTBlendMinMax.h" +#include "EXTFragDepth.h" +#include "EXTShaderTextureLOD.h" +#include "EXTTextureFilterAnisotropic.h" +#include "EXTsRGB.h" +#include "EventNames.h" +#include "ExceptionCode.h" +#include "Extensions3D.h" +#include "Frame.h" +#include "FrameLoader.h" +#include "FrameLoaderClient.h" +#include "FrameView.h" +#include "GraphicsContext.h" +#include "HTMLCanvasElement.h" +#include "HTMLImageElement.h" +#include "HTMLVideoElement.h" +#include "ImageBuffer.h" +#include "ImageData.h" +#include "IntSize.h" +#include "Logging.h" +#include "MainFrame.h" +#include "NotImplemented.h" +#include "OESElementIndexUint.h" +#include "OESStandardDerivatives.h" +#include "OESTextureFloat.h" +#include "OESTextureFloatLinear.h" +#include "OESTextureHalfFloat.h" +#include "OESTextureHalfFloatLinear.h" +#include "OESVertexArrayObject.h" +#include "Page.h" +#include "RenderBox.h" +#include "RuntimeEnabledFeatures.h" +#include "Settings.h" +#include "WebGL2RenderingContext.h" +#include "WebGLActiveInfo.h" +#include "WebGLBuffer.h" +#include "WebGLCompressedTextureATC.h" +#include "WebGLCompressedTexturePVRTC.h" +#include "WebGLCompressedTextureS3TC.h" +#include "WebGLContextAttributes.h" +#include "WebGLContextEvent.h" +#include "WebGLContextGroup.h" +#include "WebGLDebugRendererInfo.h" +#include "WebGLDebugShaders.h" +#include "WebGLDepthTexture.h" +#include "WebGLDrawBuffers.h" +#include "WebGLFramebuffer.h" +#include "WebGLLoseContext.h" +#include "WebGLProgram.h" +#include "WebGLRenderbuffer.h" +#include "WebGLRenderingContext.h" +#include "WebGLShader.h" +#include "WebGLShaderPrecisionFormat.h" +#include "WebGLTexture.h" +#include "WebGLUniformLocation.h" + +#include <runtime/JSCInlines.h> +#include <runtime/TypedArrayInlines.h> +#include <runtime/Uint32Array.h> +#include <wtf/CheckedArithmetic.h> +#include <wtf/StdLibExtras.h> +#include <wtf/text/CString.h> +#include <wtf/text/StringBuilder.h> + +namespace WebCore { + +const double secondsBetweenRestoreAttempts = 1.0; +const int maxGLErrorsAllowedToConsole = 256; +static const std::chrono::seconds checkContextLossHandlingDelay { 3 }; + +namespace { + + Platform3DObject objectOrZero(WebGLObject* object) + { + return object ? object->object() : 0; + } + + GC3Dint clamp(GC3Dint value, GC3Dint min, GC3Dint max) + { + if (value < min) + value = min; + if (value > max) + value = max; + return value; + } + + // Return true if a character belongs to the ASCII subset as defined in + // GLSL ES 1.0 spec section 3.1. + bool validateCharacter(unsigned char c) + { + // Printing characters are valid except " $ ` @ \ ' DEL. + if (c >= 32 && c <= 126 + && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' && c != '\'') + return true; + // Horizontal tab, line feed, vertical tab, form feed, carriage return + // are also valid. + if (c >= 9 && c <= 13) + return true; + return false; + } + + bool isPrefixReserved(const String& name) + { + if (name.startsWith("gl_") || name.startsWith("webgl_") || name.startsWith("_webgl_")) + return true; + return false; + } + + // Strips comments from shader text. This allows non-ASCII characters + // to be used in comments without potentially breaking OpenGL + // implementations not expecting characters outside the GLSL ES set. + class StripComments { + public: + StripComments(const String& str) + : m_parseState(BeginningOfLine) + , m_sourceString(str) + , m_length(str.length()) + , m_position(0) + { + parse(); + } + + String result() + { + return m_builder.toString(); + } + + private: + bool hasMoreCharacters() const + { + return (m_position < m_length); + } + + void parse() + { + while (hasMoreCharacters()) { + process(current()); + // process() might advance the position. + if (hasMoreCharacters()) + advance(); + } + } + + void process(UChar); + + bool peek(UChar& character) const + { + if (m_position + 1 >= m_length) + return false; + character = m_sourceString[m_position + 1]; + return true; + } + + UChar current() const + { + ASSERT_WITH_SECURITY_IMPLICATION(m_position < m_length); + return m_sourceString[m_position]; + } + + void advance() + { + ++m_position; + } + + bool isNewline(UChar character) const + { + // Don't attempt to canonicalize newline related characters. + return (character == '\n' || character == '\r'); + } + + void emit(UChar character) + { + m_builder.append(character); + } + + enum ParseState { + // Have not seen an ASCII non-whitespace character yet on + // this line. Possible that we might see a preprocessor + // directive. + BeginningOfLine, + + // Have seen at least one ASCII non-whitespace character + // on this line. + MiddleOfLine, + + // Handling a preprocessor directive. Passes through all + // characters up to the end of the line. Disables comment + // processing. + InPreprocessorDirective, + + // Handling a single-line comment. The comment text is + // replaced with a single space. + InSingleLineComment, + + // Handling a multi-line comment. Newlines are passed + // through to preserve line numbers. + InMultiLineComment + }; + + ParseState m_parseState; + String m_sourceString; + unsigned m_length; + unsigned m_position; + StringBuilder m_builder; + }; + + void StripComments::process(UChar c) + { + if (isNewline(c)) { + // No matter what state we are in, pass through newlines + // so we preserve line numbers. + emit(c); + + if (m_parseState != InMultiLineComment) + m_parseState = BeginningOfLine; + + return; + } + + UChar temp = 0; + switch (m_parseState) { + case BeginningOfLine: + if (WTF::isASCIISpace(c)) { + emit(c); + break; + } + + if (c == '#') { + m_parseState = InPreprocessorDirective; + emit(c); + break; + } + + // Transition to normal state and re-handle character. + m_parseState = MiddleOfLine; + process(c); + break; + + case MiddleOfLine: + if (c == '/' && peek(temp)) { + if (temp == '/') { + m_parseState = InSingleLineComment; + emit(' '); + advance(); + break; + } + + if (temp == '*') { + m_parseState = InMultiLineComment; + // Emit the comment start in case the user has + // an unclosed comment and we want to later + // signal an error. + emit('/'); + emit('*'); + advance(); + break; + } + } + + emit(c); + break; + + case InPreprocessorDirective: + // No matter what the character is, just pass it + // through. Do not parse comments in this state. This + // might not be the right thing to do long term, but it + // should handle the #error preprocessor directive. + emit(c); + break; + + case InSingleLineComment: + // The newline code at the top of this function takes care + // of resetting our state when we get out of the + // single-line comment. Swallow all other characters. + break; + + case InMultiLineComment: + if (c == '*' && peek(temp) && temp == '/') { + emit('*'); + emit('/'); + m_parseState = MiddleOfLine; + advance(); + break; + } + + // Swallow all other characters. Unclear whether we may + // want or need to just emit a space per character to try + // to preserve column numbers for debugging purposes. + break; + } + } +} // namespace anonymous + +class WebGLRenderingContextLostCallback : public GraphicsContext3D::ContextLostCallback { + WTF_MAKE_FAST_ALLOCATED; +public: + explicit WebGLRenderingContextLostCallback(WebGLRenderingContextBase* cb) : m_context(cb) { } + void onContextLost() override { m_context->forceLostContext(WebGLRenderingContext::RealLostContext); } + virtual ~WebGLRenderingContextLostCallback() {} +private: + WebGLRenderingContextBase* m_context; +}; + +class WebGLRenderingContextErrorMessageCallback : public GraphicsContext3D::ErrorMessageCallback { + WTF_MAKE_FAST_ALLOCATED; +public: + explicit WebGLRenderingContextErrorMessageCallback(WebGLRenderingContextBase* cb) : m_context(cb) { } + void onErrorMessage(const String& message, GC3Dint) override + { + if (m_context->m_synthesizedErrorsToConsole) + m_context->printGLErrorToConsole(message); + } + virtual ~WebGLRenderingContextErrorMessageCallback() { } +private: + WebGLRenderingContextBase* m_context; +}; + +static bool isHighPerformanceContext(const RefPtr<GraphicsContext3D>& context) +{ + return context->powerPreferenceUsedForCreation() == WebGLPowerPreference::HighPerformance; +} + +std::unique_ptr<WebGLRenderingContextBase> WebGLRenderingContextBase::create(HTMLCanvasElement& canvas, WebGLContextAttributes& attributes, const String& type) +{ +#if ENABLE(WEBGL2) + if (type == "webgl2" && !RuntimeEnabledFeatures::sharedFeatures().webGL2Enabled()) + return nullptr; +#else + UNUSED_PARAM(type); +#endif + + Document& document = canvas.document(); + Frame* frame = document.frame(); + if (!frame) + return nullptr; + + // The FrameLoaderClient might block creation of a new WebGL context despite the page settings; in + // particular, if WebGL contexts were lost one or more times via the GL_ARB_robustness extension. + if (!frame->loader().client().allowWebGL(frame->settings().webGLEnabled())) { + canvas.dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextcreationerrorEvent, false, true, "Web page was not allowed to create a WebGL context.")); + return nullptr; + } + + bool isPendingPolicyResolution = false; + Document& topDocument = document.topDocument(); + Page* page = topDocument.page(); + bool forcingPendingPolicy = frame->settings().isForcePendingWebGLPolicy(); + + if (forcingPendingPolicy || (page && !topDocument.url().isLocalFile())) { + WebGLLoadPolicy policy = forcingPendingPolicy ? WebGLPendingCreation : page->mainFrame().loader().client().webGLPolicyForURL(topDocument.url()); + + if (policy == WebGLBlockCreation) { + LOG(WebGL, "The policy for this URL (%s) is to block WebGL.", topDocument.url().host().utf8().data()); + return nullptr; + } + + if (policy == WebGLPendingCreation) { + LOG(WebGL, "WebGL policy is pending. May need to be resolved later."); + isPendingPolicyResolution = true; + } + } + + attributes.noExtensions = true; + attributes.shareResources = false; + + if (frame->settings().forceSoftwareWebGLRendering()) + attributes.forceSoftwareRenderer = true; + + attributes.initialPowerPreference = attributes.powerPreference; + if (frame->settings().forceWebGLUsesLowPower()) { + if (attributes.powerPreference == GraphicsContext3DPowerPreference::HighPerformance) + LOG(WebGL, "Overriding powerPreference from high-performance to low-power."); + attributes.powerPreference = GraphicsContext3DPowerPreference::LowPower; + } + + if (page) + attributes.devicePixelRatio = page->deviceScaleFactor(); + +#if ENABLE(WEBGL2) + if (type == "webgl2") + attributes.useGLES3 = true; +#endif + + if (isPendingPolicyResolution) { + LOG(WebGL, "Create a WebGL context that looks real, but will require a policy resolution if used."); + std::unique_ptr<WebGLRenderingContextBase> renderingContext = nullptr; +#if ENABLE(WEBGL2) + if (type == "webgl2") + renderingContext = std::make_unique<WebGL2RenderingContext>(canvas, attributes); + else +#endif + renderingContext = std::make_unique<WebGLRenderingContext>(canvas, attributes); + renderingContext->suspendIfNeeded(); + return renderingContext; + } + + auto context = GraphicsContext3D::create(attributes, document.view()->root()->hostWindow()); + if (!context || !context->makeContextCurrent()) { + canvas.dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextcreationerrorEvent, false, true, "Could not create a WebGL context.")); + return nullptr; + } + + auto& extensions = context->getExtensions(); + if (extensions.supports(ASCIILiteral { "GL_EXT_debug_marker" })) + extensions.pushGroupMarkerEXT(ASCIILiteral { "WebGLRenderingContext" }); + +#if ENABLE(WEBGL2) && PLATFORM(MAC) + // glTexStorage() was only added to Core in OpenGL 4.2. + // However, according to https://developer.apple.com/opengl/capabilities/ all Apple GPUs support this extension. + if (attributes.useGLES3 && !extensions.supports("GL_ARB_texture_storage")) + return nullptr; +#endif + + std::unique_ptr<WebGLRenderingContextBase> renderingContext; +#if ENABLE(WEBGL2) + if (type == "webgl2") + renderingContext = std::make_unique<WebGL2RenderingContext>(canvas, context.releaseNonNull(), attributes); + else +#endif + renderingContext = std::make_unique<WebGLRenderingContext>(canvas, context.releaseNonNull(), attributes); + renderingContext->suspendIfNeeded(); + + return renderingContext; +} + +WebGLRenderingContextBase::WebGLRenderingContextBase(HTMLCanvasElement& passedCanvas, WebGLContextAttributes attributes) + : CanvasRenderingContext(passedCanvas) + , ActiveDOMObject(&passedCanvas.document()) + , m_dispatchContextLostEventTimer(*this, &WebGLRenderingContextBase::dispatchContextLostEvent) + , m_restoreTimer(*this, &WebGLRenderingContextBase::maybeRestoreContext) + , m_attributes(attributes) + , m_numGLErrorsToConsoleAllowed(maxGLErrorsAllowedToConsole) + , m_isPendingPolicyResolution(true) + , m_checkForContextLossHandlingTimer(*this, &WebGLRenderingContextBase::checkForContextLossHandling) +{ + registerWithWebGLStateTracker(); + m_checkForContextLossHandlingTimer.startOneShot(checkContextLossHandlingDelay); +} + +WebGLRenderingContextBase::WebGLRenderingContextBase(HTMLCanvasElement& passedCanvas, Ref<GraphicsContext3D>&& context, WebGLContextAttributes attributes) + : CanvasRenderingContext(passedCanvas) + , ActiveDOMObject(&passedCanvas.document()) + , m_context(WTFMove(context)) + , m_dispatchContextLostEventTimer(*this, &WebGLRenderingContextBase::dispatchContextLostEvent) + , m_restoreTimer(*this, &WebGLRenderingContextBase::maybeRestoreContext) + , m_generatedImageCache(4) + , m_attributes(attributes) + , m_numGLErrorsToConsoleAllowed(maxGLErrorsAllowedToConsole) + , m_checkForContextLossHandlingTimer(*this, &WebGLRenderingContextBase::checkForContextLossHandling) +{ + m_contextGroup = WebGLContextGroup::create(); + m_contextGroup->addContext(*this); + + m_context->setWebGLContext(this); + + m_context->getIntegerv(GraphicsContext3D::MAX_VIEWPORT_DIMS, m_maxViewportDims); + + setupFlags(); + initializeNewContext(); + registerWithWebGLStateTracker(); + m_checkForContextLossHandlingTimer.startOneShot(checkContextLossHandlingDelay); + + addActivityStateChangeObserverIfNecessary(); +} + +// We check for context loss handling after a few seconds to give the JS a chance to register the event listeners +// and to discard temporary GL contexts (e.g. feature detection). +void WebGLRenderingContextBase::checkForContextLossHandling() +{ + if (!canvas().renderer()) + return; + + auto* page = canvas().document().page(); + if (!page) + return; + + bool handlesContextLoss = canvas().hasEventListeners(eventNames().webglcontextlostEvent) && canvas().hasEventListeners(eventNames().webglcontextrestoredEvent); + page->diagnosticLoggingClient().logDiagnosticMessage(DiagnosticLoggingKeys::pageHandlesWebGLContextLossKey(), handlesContextLoss ? DiagnosticLoggingKeys::yesKey() : DiagnosticLoggingKeys::noKey(), ShouldSample::No); +} + +void WebGLRenderingContextBase::registerWithWebGLStateTracker() +{ + auto* page = canvas().document().page(); + if (!page) + return; + + auto* tracker = page->webGLStateTracker(); + if (!tracker) + return; + + m_trackerToken = tracker->token(m_attributes.initialPowerPreference); +} + +void WebGLRenderingContextBase::initializeNewContext() +{ + ASSERT(!m_contextLost); + m_needsUpdate = true; + m_markedCanvasDirty = false; + m_activeTextureUnit = 0; + m_packAlignment = 4; + m_unpackAlignment = 4; + m_unpackFlipY = false; + m_unpackPremultiplyAlpha = false; + m_unpackColorspaceConversion = GraphicsContext3D::BROWSER_DEFAULT_WEBGL; + m_boundArrayBuffer = nullptr; + m_currentProgram = nullptr; + m_framebufferBinding = nullptr; + m_renderbufferBinding = nullptr; + m_depthMask = true; + m_stencilEnabled = false; + m_stencilMask = 0xFFFFFFFF; + m_stencilMaskBack = 0xFFFFFFFF; + m_stencilFuncRef = 0; + m_stencilFuncRefBack = 0; + m_stencilFuncMask = 0xFFFFFFFF; + m_stencilFuncMaskBack = 0xFFFFFFFF; + m_layerCleared = false; + m_numGLErrorsToConsoleAllowed = maxGLErrorsAllowedToConsole; + + m_clearColor[0] = m_clearColor[1] = m_clearColor[2] = m_clearColor[3] = 0; + m_scissorEnabled = false; + m_clearDepth = 1; + m_clearStencil = 0; + m_colorMask[0] = m_colorMask[1] = m_colorMask[2] = m_colorMask[3] = true; + + GC3Dint numCombinedTextureImageUnits = 0; + m_context->getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numCombinedTextureImageUnits); + m_textureUnits.clear(); + m_textureUnits.resize(numCombinedTextureImageUnits); + for (GC3Dint i = 0; i < numCombinedTextureImageUnits; ++i) + m_unrenderableTextureUnits.add(i); + + GC3Dint numVertexAttribs = 0; + m_context->getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &numVertexAttribs); + m_maxVertexAttribs = numVertexAttribs; + + m_maxTextureSize = 0; + m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize); + m_maxTextureLevel = WebGLTexture::computeLevelCount(m_maxTextureSize, m_maxTextureSize); + m_maxCubeMapTextureSize = 0; + m_context->getIntegerv(GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE, &m_maxCubeMapTextureSize); + m_maxCubeMapTextureLevel = WebGLTexture::computeLevelCount(m_maxCubeMapTextureSize, m_maxCubeMapTextureSize); + m_maxRenderbufferSize = 0; + m_context->getIntegerv(GraphicsContext3D::MAX_RENDERBUFFER_SIZE, &m_maxRenderbufferSize); + + // These two values from EXT_draw_buffers are lazily queried. + m_maxDrawBuffers = 0; + m_maxColorAttachments = 0; + + m_backDrawBuffer = GraphicsContext3D::BACK; + m_drawBuffersWebGLRequirementsChecked = false; + m_drawBuffersSupported = false; + + m_vertexAttribValue.resize(m_maxVertexAttribs); + + if (!isGLES2NPOTStrict()) + createFallbackBlackTextures1x1(); + + IntSize canvasSize = clampedCanvasSize(); + m_context->reshape(canvasSize.width(), canvasSize.height()); + m_context->viewport(0, 0, canvasSize.width(), canvasSize.height()); + m_context->scissor(0, 0, canvasSize.width(), canvasSize.height()); + + m_context->setContextLostCallback(std::make_unique<WebGLRenderingContextLostCallback>(this)); + m_context->setErrorMessageCallback(std::make_unique<WebGLRenderingContextErrorMessageCallback>(this)); +} + +void WebGLRenderingContextBase::setupFlags() +{ + ASSERT(m_context); + + if (Page* page = canvas().document().page()) + m_synthesizedErrorsToConsole = page->settings().webGLErrorsToConsoleEnabled(); + + m_isGLES2Compliant = m_context->isGLES2Compliant(); + if (m_isGLES2Compliant) { + m_isGLES2NPOTStrict = !m_context->getExtensions().isEnabled("GL_OES_texture_npot"); + m_isDepthStencilSupported = m_context->getExtensions().isEnabled("GL_OES_packed_depth_stencil"); + } else { + m_isGLES2NPOTStrict = !m_context->getExtensions().isEnabled("GL_ARB_texture_non_power_of_two"); + m_isDepthStencilSupported = m_context->getExtensions().isEnabled("GL_EXT_packed_depth_stencil"); + } + m_isRobustnessEXTSupported = m_context->getExtensions().isEnabled("GL_EXT_robustness"); +} + +void WebGLRenderingContextBase::addCompressedTextureFormat(GC3Denum format) +{ + if (!m_compressedTextureFormats.contains(format)) + m_compressedTextureFormats.append(format); +} + +void WebGLRenderingContextBase::addActivityStateChangeObserverIfNecessary() +{ + // We are only interested in visibility changes for contexts + // that are using the high-performance GPU. + if (!isHighPerformanceContext(m_context)) + return; + + auto* page = canvas().document().page(); + if (!page) + return; + + page->addActivityStateChangeObserver(*this); + + // We won't get a state change right away, so + // make sure the context knows if it visible or not. + if (m_context) + m_context->setContextVisibility(page->isVisible()); +} + +void WebGLRenderingContextBase::removeActivityStateChangeObserver() +{ + if (auto* page = canvas().document().page()) + page->removeActivityStateChangeObserver(*this); +} + +WebGLRenderingContextBase::~WebGLRenderingContextBase() +{ + // Remove all references to WebGLObjects so if they are the last reference + // they will be freed before the last context is removed from the context group. + m_boundArrayBuffer = nullptr; + m_defaultVertexArrayObject = nullptr; + m_boundVertexArrayObject = nullptr; + m_vertexAttrib0Buffer = nullptr; + m_currentProgram = nullptr; + m_framebufferBinding = nullptr; + m_renderbufferBinding = nullptr; + + for (auto& textureUnit : m_textureUnits) { + textureUnit.texture2DBinding = nullptr; + textureUnit.textureCubeMapBinding = nullptr; + } + + m_blackTexture2D = nullptr; + m_blackTextureCubeMap = nullptr; + + if (!m_isPendingPolicyResolution) { + detachAndRemoveAllObjects(); + destroyGraphicsContext3D(); + m_contextGroup->removeContext(*this); + } +} + +void WebGLRenderingContextBase::destroyGraphicsContext3D() +{ + if (m_isPendingPolicyResolution) + return; + + removeActivityStateChangeObserver(); + + if (m_context) { + m_context->setContextLostCallback(nullptr); + m_context->setErrorMessageCallback(nullptr); + m_context = nullptr; + } +} + +void WebGLRenderingContextBase::markContextChanged() +{ + if (m_framebufferBinding) + return; + + m_context->markContextChanged(); + + m_layerCleared = false; + RenderBox* renderBox = canvas().renderBox(); + if (isAccelerated() && renderBox && renderBox->hasAcceleratedCompositing()) { + m_markedCanvasDirty = true; + canvas().clearCopiedImage(); + renderBox->contentChanged(CanvasChanged); + } else { + if (!m_markedCanvasDirty) { + m_markedCanvasDirty = true; + canvas().didDraw(FloatRect(FloatPoint(0, 0), clampedCanvasSize())); + } + } +} + +bool WebGLRenderingContextBase::clearIfComposited(GC3Dbitfield mask) +{ + if (isContextLostOrPending()) + return false; + + if (!m_context->layerComposited() || m_layerCleared + || m_attributes.preserveDrawingBuffer || (mask && m_framebufferBinding)) + return false; + + auto contextAttributes = getContextAttributes(); + ASSERT(contextAttributes); + + // Determine if it's possible to combine the clear the user asked for and this clear. + bool combinedClear = mask && !m_scissorEnabled; + + m_context->disable(GraphicsContext3D::SCISSOR_TEST); + if (combinedClear && (mask & GraphicsContext3D::COLOR_BUFFER_BIT)) + m_context->clearColor(m_colorMask[0] ? m_clearColor[0] : 0, + m_colorMask[1] ? m_clearColor[1] : 0, + m_colorMask[2] ? m_clearColor[2] : 0, + m_colorMask[3] ? m_clearColor[3] : 0); + else + m_context->clearColor(0, 0, 0, 0); + m_context->colorMask(true, true, true, true); + GC3Dbitfield clearMask = GraphicsContext3D::COLOR_BUFFER_BIT; + if (contextAttributes->depth) { + if (!combinedClear || !m_depthMask || !(mask & GraphicsContext3D::DEPTH_BUFFER_BIT)) + m_context->clearDepth(1.0f); + clearMask |= GraphicsContext3D::DEPTH_BUFFER_BIT; + m_context->depthMask(true); + } + if (contextAttributes->stencil) { + if (combinedClear && (mask & GraphicsContext3D::STENCIL_BUFFER_BIT)) + m_context->clearStencil(m_clearStencil & m_stencilMask); + else + m_context->clearStencil(0); + clearMask |= GraphicsContext3D::STENCIL_BUFFER_BIT; + m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, 0xFFFFFFFF); + } + if (m_framebufferBinding) + m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0); + m_context->clear(clearMask); + + restoreStateAfterClear(); + if (m_framebufferBinding) + m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get())); + m_layerCleared = true; + + return combinedClear; +} + +void WebGLRenderingContextBase::restoreStateAfterClear() +{ + // Restore the state that the context set. + if (m_scissorEnabled) + m_context->enable(GraphicsContext3D::SCISSOR_TEST); + m_context->clearColor(m_clearColor[0], m_clearColor[1], + m_clearColor[2], m_clearColor[3]); + m_context->colorMask(m_colorMask[0], m_colorMask[1], + m_colorMask[2], m_colorMask[3]); + m_context->clearDepth(m_clearDepth); + m_context->clearStencil(m_clearStencil); + m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, m_stencilMask); + m_context->depthMask(m_depthMask); +} + +void WebGLRenderingContextBase::markLayerComposited() +{ + if (isContextLostOrPending()) + return; + m_context->markLayerComposited(); +} + +void WebGLRenderingContextBase::paintRenderingResultsToCanvas() +{ + if (isContextLostOrPending()) + return; + + if (canvas().document().printing()) + canvas().clearPresentationCopy(); + + // Until the canvas is written to by the application, the clear that + // happened after it was composited should be ignored by the compositor. + if (m_context->layerComposited() && !m_attributes.preserveDrawingBuffer) { + m_context->paintCompositedResultsToCanvas(canvas().buffer()); + + canvas().makePresentationCopy(); + } else + canvas().clearPresentationCopy(); + clearIfComposited(); + + if (!m_markedCanvasDirty && !m_layerCleared) + return; + + canvas().clearCopiedImage(); + m_markedCanvasDirty = false; + + m_context->paintRenderingResultsToCanvas(canvas().buffer()); +} + +RefPtr<ImageData> WebGLRenderingContextBase::paintRenderingResultsToImageData() +{ + if (isContextLostOrPending()) + return nullptr; + clearIfComposited(); + return m_context->paintRenderingResultsToImageData(); +} + +WebGLTexture::TextureExtensionFlag WebGLRenderingContextBase::textureExtensionFlags() const +{ + return static_cast<WebGLTexture::TextureExtensionFlag>((m_oesTextureFloatLinear ? WebGLTexture::TextureExtensionFloatLinearEnabled : 0) | (m_oesTextureHalfFloatLinear ? WebGLTexture::TextureExtensionHalfFloatLinearEnabled : 0)); +} + +void WebGLRenderingContextBase::reshape(int width, int height) +{ + if (isContextLostOrPending()) + return; + + // This is an approximation because at WebGLRenderingContext level we don't + // know if the underlying FBO uses textures or renderbuffers. + GC3Dint maxSize = std::min(m_maxTextureSize, m_maxRenderbufferSize); + // Limit drawing buffer size to 4k to avoid memory exhaustion. + const int sizeUpperLimit = 4096; + maxSize = std::min(maxSize, sizeUpperLimit); + GC3Dint maxWidth = std::min(maxSize, m_maxViewportDims[0]); + GC3Dint maxHeight = std::min(maxSize, m_maxViewportDims[1]); + width = clamp(width, 1, maxWidth); + height = clamp(height, 1, maxHeight); + + if (m_needsUpdate) { + RenderBox* renderBox = canvas().renderBox(); + if (renderBox && renderBox->hasAcceleratedCompositing()) + renderBox->contentChanged(CanvasChanged); + m_needsUpdate = false; + } + + // We don't have to mark the canvas as dirty, since the newly created image buffer will also start off + // clear (and this matches what reshape will do). + m_context->reshape(width, height); + + auto& textureUnit = m_textureUnits[m_activeTextureUnit]; + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZero(textureUnit.texture2DBinding.get())); + if (textureUnit.texture2DBinding && textureUnit.texture2DBinding->needToUseBlackTexture(textureExtensionFlags())) + m_unrenderableTextureUnits.add(m_activeTextureUnit); + m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, objectOrZero(m_renderbufferBinding.get())); + if (m_framebufferBinding) + m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, objectOrZero(m_framebufferBinding.get())); +} + +int WebGLRenderingContextBase::drawingBufferWidth() const +{ + if (isContextLost()) + return 0; + + if (m_isPendingPolicyResolution && !m_hasRequestedPolicyResolution) + return 0; + + return m_context->getInternalFramebufferSize().width(); +} + +int WebGLRenderingContextBase::drawingBufferHeight() const +{ + if (isContextLost()) + return 0; + + if (m_isPendingPolicyResolution && !m_hasRequestedPolicyResolution) + return 0; + + return m_context->getInternalFramebufferSize().height(); +} + +unsigned WebGLRenderingContextBase::sizeInBytes(GC3Denum type) +{ + switch (type) { + case GraphicsContext3D::BYTE: + return sizeof(GC3Dbyte); + case GraphicsContext3D::UNSIGNED_BYTE: + return sizeof(GC3Dubyte); + case GraphicsContext3D::SHORT: + return sizeof(GC3Dshort); + case GraphicsContext3D::UNSIGNED_SHORT: + return sizeof(GC3Dushort); + case GraphicsContext3D::INT: + return sizeof(GC3Dint); + case GraphicsContext3D::UNSIGNED_INT: + return sizeof(GC3Duint); + case GraphicsContext3D::FLOAT: + return sizeof(GC3Dfloat); + } + ASSERT_NOT_REACHED(); + return 0; +} + +void WebGLRenderingContextBase::activeTexture(GC3Denum texture) +{ + if (isContextLostOrPending()) + return; + if (texture - GraphicsContext3D::TEXTURE0 >= m_textureUnits.size()) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "activeTexture", "texture unit out of range"); + return; + } + m_activeTextureUnit = texture - GraphicsContext3D::TEXTURE0; + m_context->activeTexture(texture); +} + +void WebGLRenderingContextBase::attachShader(WebGLProgram* program, WebGLShader* shader) +{ + if (isContextLostOrPending() || !validateWebGLObject("attachShader", program) || !validateWebGLObject("attachShader", shader)) + return; + if (!program->attachShader(shader)) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "attachShader", "shader attachment already has shader"); + return; + } + m_context->attachShader(objectOrZero(program), objectOrZero(shader)); + shader->onAttached(); +} + +void WebGLRenderingContextBase::bindAttribLocation(WebGLProgram* program, GC3Duint index, const String& name) +{ + if (isContextLostOrPending() || !validateWebGLObject("bindAttribLocation", program)) + return; + if (!validateLocationLength("bindAttribLocation", name)) + return; + if (!validateString("bindAttribLocation", name)) + return; + if (isPrefixReserved(name)) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindAttribLocation", "reserved prefix"); + return; + } + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bindAttribLocation", "index out of range"); + return; + } + m_context->bindAttribLocation(objectOrZero(program), index, name); +} + +bool WebGLRenderingContextBase::checkObjectToBeBound(const char* functionName, WebGLObject* object, bool& deleted) +{ + deleted = false; + if (isContextLostOrPending()) + return false; + if (object) { + if (!object->validate(contextGroup(), *this)) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "object not from this context"); + return false; + } + deleted = !object->object(); + } + return true; +} + +void WebGLRenderingContextBase::bindBuffer(GC3Denum target, WebGLBuffer* buffer) +{ + bool deleted; + if (!checkObjectToBeBound("bindBuffer", buffer, deleted)) + return; + if (deleted) + buffer = nullptr; + if (buffer && buffer->getTarget() && buffer->getTarget() != target) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindBuffer", "buffers can not be used with multiple targets"); + return; + } + if (target == GraphicsContext3D::ARRAY_BUFFER) + m_boundArrayBuffer = buffer; + else if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER) + m_boundVertexArrayObject->setElementArrayBuffer(buffer); + else { + bool success = false; +#if ENABLE(WEBGL2) + if (isWebGL2()) { + success = true; + switch (target) { + case GraphicsContext3D::COPY_READ_BUFFER: + m_boundCopyReadBuffer = buffer; + break; + case GraphicsContext3D::COPY_WRITE_BUFFER: + m_boundCopyWriteBuffer = buffer; + break; + case GraphicsContext3D::PIXEL_PACK_BUFFER: + m_boundPixelPackBuffer = buffer; + break; + case GraphicsContext3D::PIXEL_UNPACK_BUFFER: + m_boundPixelUnpackBuffer = buffer; + break; + case GraphicsContext3D::TRANSFORM_FEEDBACK_BUFFER: + m_boundTransformFeedbackBuffer = buffer; + break; + case GraphicsContext3D::UNIFORM_BUFFER: + m_boundUniformBuffer = buffer; + break; + default: + success = false; + break; + } + } +#endif + if (!success) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindBuffer", "invalid target"); + return; + } + } + + m_context->bindBuffer(target, objectOrZero(buffer)); + if (buffer) + buffer->setTarget(target, isWebGL2()); +} + +void WebGLRenderingContextBase::bindFramebuffer(GC3Denum target, WebGLFramebuffer* buffer) +{ + bool deleted; + if (!checkObjectToBeBound("bindFramebuffer", buffer, deleted)) + return; + if (deleted) + buffer = 0; + if (target != GraphicsContext3D::FRAMEBUFFER) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindFramebuffer", "invalid target"); + return; + } + m_framebufferBinding = buffer; + m_context->bindFramebuffer(target, objectOrZero(buffer)); + if (buffer) + buffer->setHasEverBeenBound(); + applyStencilTest(); +} + +void WebGLRenderingContextBase::bindRenderbuffer(GC3Denum target, WebGLRenderbuffer* renderBuffer) +{ + bool deleted; + if (!checkObjectToBeBound("bindRenderbuffer", renderBuffer, deleted)) + return; + if (deleted) + renderBuffer = 0; + if (target != GraphicsContext3D::RENDERBUFFER) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindRenderbuffer", "invalid target"); + return; + } + m_renderbufferBinding = renderBuffer; + m_context->bindRenderbuffer(target, objectOrZero(renderBuffer)); + if (renderBuffer) + renderBuffer->setHasEverBeenBound(); +} + +void WebGLRenderingContextBase::bindTexture(GC3Denum target, WebGLTexture* texture) +{ + bool deleted; + if (!checkObjectToBeBound("bindTexture", texture, deleted)) + return; + if (deleted) + texture = nullptr; + if (texture && texture->getTarget() && texture->getTarget() != target) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bindTexture", "textures can not be used with multiple targets"); + return; + } + GC3Dint maxLevel = 0; + auto& textureUnit = m_textureUnits[m_activeTextureUnit]; + if (target == GraphicsContext3D::TEXTURE_2D) { + textureUnit.texture2DBinding = texture; + maxLevel = m_maxTextureLevel; + if (texture && texture->needToUseBlackTexture(textureExtensionFlags())) + m_unrenderableTextureUnits.add(m_activeTextureUnit); + else + m_unrenderableTextureUnits.remove(m_activeTextureUnit); + } else if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) { + textureUnit.textureCubeMapBinding = texture; + maxLevel = m_maxCubeMapTextureLevel; + if (texture && texture->needToUseBlackTexture(textureExtensionFlags())) + m_unrenderableTextureUnits.add(m_activeTextureUnit); + else + m_unrenderableTextureUnits.remove(m_activeTextureUnit); + } else { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "bindTexture", "invalid target"); + return; + } + m_context->bindTexture(target, objectOrZero(texture)); + if (texture) + texture->setTarget(target, maxLevel); + + // Note: previously we used to automatically set the TEXTURE_WRAP_R + // repeat mode to CLAMP_TO_EDGE for cube map textures, because OpenGL + // ES 2.0 doesn't expose this flag (a bug in the specification) and + // otherwise the application has no control over the seams in this + // dimension. However, it appears that supporting this properly on all + // platforms is fairly involved (will require a HashMap from texture ID + // in all ports), and we have not had any complaints, so the logic has + // been removed. +} + +void WebGLRenderingContextBase::blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha) +{ + if (isContextLostOrPending()) + return; + m_context->blendColor(red, green, blue, alpha); +} + +void WebGLRenderingContextBase::blendEquation(GC3Denum mode) +{ + if (isContextLostOrPending() || !validateBlendEquation("blendEquation", mode)) + return; + m_context->blendEquation(mode); +} + +void WebGLRenderingContextBase::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha) +{ + if (isContextLostOrPending() || !validateBlendEquation("blendEquation", modeRGB) || !validateBlendEquation("blendEquation", modeAlpha)) + return; + m_context->blendEquationSeparate(modeRGB, modeAlpha); +} + + +void WebGLRenderingContextBase::blendFunc(GC3Denum sfactor, GC3Denum dfactor) +{ + if (isContextLostOrPending() || !validateBlendFuncFactors("blendFunc", sfactor, dfactor)) + return; + m_context->blendFunc(sfactor, dfactor); +} + +void WebGLRenderingContextBase::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha) +{ + // Note: Alpha does not have the same restrictions as RGB. + if (isContextLostOrPending() || !validateBlendFuncFactors("blendFunc", srcRGB, dstRGB)) + return; + m_context->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); +} + +void WebGLRenderingContextBase::bufferData(GC3Denum target, long long size, GC3Denum usage) +{ + if (isContextLostOrPending()) + return; + WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage); + if (!buffer) + return; + if (size < 0) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "size < 0"); + return; + } + if (!size) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "size == 0"); + return; + } + if (!buffer->associateBufferData(static_cast<GC3Dsizeiptr>(size))) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer"); + return; + } + + m_context->moveErrorsToSyntheticErrorList(); + m_context->bufferData(target, static_cast<GC3Dsizeiptr>(size), usage); + if (m_context->moveErrorsToSyntheticErrorList()) { + // The bufferData function failed. Tell the buffer it doesn't have the data it thinks it does. + buffer->disassociateBufferData(); + } +} + +void WebGLRenderingContextBase::bufferData(GC3Denum target, std::optional<BufferDataSource>&& data, GC3Denum usage) +{ + if (isContextLostOrPending()) + return; + if (!data) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "null data"); + return; + } + WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage); + if (!buffer) + return; + + WTF::visit([&](auto& data) { + if (!buffer->associateBufferData(data.get())) { + this->synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "invalid buffer"); + return; + } + + m_context->moveErrorsToSyntheticErrorList(); + m_context->bufferData(target, data->byteLength(), data->data(), usage); + if (m_context->moveErrorsToSyntheticErrorList()) { + // The bufferData function failed. Tell the buffer it doesn't have the data it thinks it does. + buffer->disassociateBufferData(); + } + }, data.value()); +} + +void WebGLRenderingContextBase::bufferSubData(GC3Denum target, long long offset, std::optional<BufferDataSource>&& data) +{ + if (isContextLostOrPending()) + return; + WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GraphicsContext3D::STATIC_DRAW); + if (!buffer) + return; + if (offset < 0) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset < 0"); + return; + } + if (!data) + return; + + WTF::visit([&](auto& data) { + if (!buffer->associateBufferSubData(static_cast<GC3Dintptr>(offset), data.get())) { + this->synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "offset out of range"); + return; + } + + m_context->moveErrorsToSyntheticErrorList(); + m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byteLength(), data->data()); + if (m_context->moveErrorsToSyntheticErrorList()) { + // The bufferSubData function failed. Tell the buffer it doesn't have the data it thinks it does. + buffer->disassociateBufferData(); + } + }, data.value()); +} + +GC3Denum WebGLRenderingContextBase::checkFramebufferStatus(GC3Denum target) +{ + if (isContextLostOrPending()) + return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED; + if (target != GraphicsContext3D::FRAMEBUFFER) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "checkFramebufferStatus", "invalid target"); + return 0; + } + if (!m_framebufferBinding || !m_framebufferBinding->object()) + return GraphicsContext3D::FRAMEBUFFER_COMPLETE; + const char* reason = "framebuffer incomplete"; + GC3Denum result = m_framebufferBinding->checkStatus(&reason); + if (result != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { + printGLWarningToConsole("checkFramebufferStatus", reason); + return result; + } + result = m_context->checkFramebufferStatus(target); + return result; +} + +void WebGLRenderingContextBase::clearColor(GC3Dfloat r, GC3Dfloat g, GC3Dfloat b, GC3Dfloat a) +{ + if (isContextLostOrPending()) + return; + if (std::isnan(r)) + r = 0; + if (std::isnan(g)) + g = 0; + if (std::isnan(b)) + b = 0; + if (std::isnan(a)) + a = 1; + m_clearColor[0] = r; + m_clearColor[1] = g; + m_clearColor[2] = b; + m_clearColor[3] = a; + m_context->clearColor(r, g, b, a); +} + +void WebGLRenderingContextBase::clearDepth(GC3Dfloat depth) +{ + if (isContextLostOrPending()) + return; + m_clearDepth = depth; + m_context->clearDepth(depth); +} + +void WebGLRenderingContextBase::clearStencil(GC3Dint s) +{ + if (isContextLostOrPending()) + return; + m_clearStencil = s; + m_context->clearStencil(s); +} + +void WebGLRenderingContextBase::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha) +{ + if (isContextLostOrPending()) + return; + m_colorMask[0] = red; + m_colorMask[1] = green; + m_colorMask[2] = blue; + m_colorMask[3] = alpha; + m_context->colorMask(red, green, blue, alpha); +} + +void WebGLRenderingContextBase::compileShader(WebGLShader* shader) +{ + if (isContextLostOrPending() || !validateWebGLObject("compileShader", shader)) + return; + m_context->compileShader(objectOrZero(shader)); + GC3Dint value; + m_context->getShaderiv(objectOrZero(shader), GraphicsContext3D::COMPILE_STATUS, &value); + shader->setValid(value); +} + +void WebGLRenderingContextBase::compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, ArrayBufferView& data) +{ + if (isContextLostOrPending()) + return; + if (!validateTexFuncLevel("compressedTexImage2D", target, level)) + return; + + if (!validateCompressedTexFormat(internalformat)) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "compressedTexImage2D", "invalid internalformat"); + return; + } + if (border) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "compressedTexImage2D", "border not 0"); + return; + } + if (!validateCompressedTexDimensions("compressedTexImage2D", target, level, width, height, internalformat)) + return; + if (!validateCompressedTexFuncData("compressedTexImage2D", width, height, internalformat, data)) + return; + + WebGLTexture* tex = validateTextureBinding("compressedTexImage2D", target, true); + if (!tex) + return; + if (!validateNPOTTextureLevel(width, height, level, "compressedTexImage2D")) + return; + m_context->moveErrorsToSyntheticErrorList(); + m_context->compressedTexImage2D(target, level, internalformat, width, height, + border, data.byteLength(), data.baseAddress()); + if (m_context->moveErrorsToSyntheticErrorList()) { + // The compressedTexImage2D function failed. Tell the WebGLTexture it doesn't have the data for this level. + tex->markInvalid(target, level); + return; + } + + tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE); + tex->setCompressed(); +} + +void WebGLRenderingContextBase::compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView& data) +{ + if (isContextLostOrPending()) + return; + if (!validateTexFuncLevel("compressedTexSubImage2D", target, level)) + return; + if (!validateCompressedTexFormat(format)) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "compressedTexSubImage2D", "invalid format"); + return; + } + if (!validateCompressedTexFuncData("compressedTexSubImage2D", width, height, format, data)) + return; + + WebGLTexture* tex = validateTextureBinding("compressedTexSubImage2D", target, true); + if (!tex) + return; + + if (format != tex->getInternalFormat(target, level)) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "compressedTexSubImage2D", "format does not match texture format"); + return; + } + + if (!validateCompressedTexSubDimensions("compressedTexSubImage2D", target, level, xoffset, yoffset, width, height, format, tex)) + return; + + graphicsContext3D()->compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, data.byteLength(), data.baseAddress()); + tex->setCompressed(); +} + +bool WebGLRenderingContextBase::validateSettableTexInternalFormat(const char* functionName, GC3Denum internalFormat) +{ + switch (internalFormat) { + case GraphicsContext3D::DEPTH_COMPONENT: + case GraphicsContext3D::DEPTH_STENCIL: + case GraphicsContext3D::DEPTH_COMPONENT16: + case GraphicsContext3D::DEPTH_COMPONENT24: + case GraphicsContext3D::DEPTH_COMPONENT32F: + case GraphicsContext3D::DEPTH24_STENCIL8: + case GraphicsContext3D::DEPTH32F_STENCIL8: + case GraphicsContext3D::STENCIL_INDEX8: + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format can not be set, only rendered to"); + return false; + default: + return true; + } +} + +void WebGLRenderingContextBase::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) +{ + if (isContextLostOrPending()) + return; + if (!validateTexFuncLevel("copyTexSubImage2D", target, level)) + return; + WebGLTexture* tex = validateTextureBinding("copyTexSubImage2D", target, true); + if (!tex) + return; + if (!validateSize("copyTexSubImage2D", xoffset, yoffset) || !validateSize("copyTexSubImage2D", width, height)) + return; + // Before checking if it is in the range, check if overflow happens first. + if (xoffset + width < 0 || yoffset + height < 0) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "bad dimensions"); + return; + } + if (xoffset + width > tex->getWidth(target, level) || yoffset + height > tex->getHeight(target, level)) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "rectangle out of range"); + return; + } + GC3Denum internalFormat = tex->getInternalFormat(target, level); + if (!validateSettableTexInternalFormat("copyTexSubImage2D", internalFormat)) + return; + if (!isTexInternalFormatColorBufferCombinationValid(internalFormat, getBoundFramebufferColorFormat())) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexSubImage2D", "framebuffer is incompatible format"); + return; + } + const char* reason = "framebuffer incomplete"; + if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { + synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexSubImage2D", reason); + return; + } + clearIfComposited(); + + GC3Dint clippedX, clippedY; + GC3Dsizei clippedWidth, clippedHeight; + if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) { + GC3Denum format; + GC3Denum type; + if (!GraphicsContext3D::possibleFormatAndTypeForInternalFormat(tex->getInternalFormat(target, level), format, type)) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "copyTexSubImage2D", "Texture has unknown internal format"); + return; + } + std::unique_ptr<unsigned char[]> zero; + if (width && height) { + unsigned size; + GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &size, nullptr); + if (error != GraphicsContext3D::NO_ERROR) { + synthesizeGLError(error, "copyTexSubImage2D", "bad dimensions"); + return; + } + zero = std::make_unique<unsigned char[]>(size); + if (!zero) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexSubImage2D", "out of memory"); + return; + } + memset(zero.get(), 0, size); + } + m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, zero.get()); + if (clippedWidth > 0 && clippedHeight > 0) + m_context->copyTexSubImage2D(target, level, xoffset + clippedX - x, yoffset + clippedY - y, clippedX, clippedY, clippedWidth, clippedHeight); + } else + m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); +} + +RefPtr<WebGLBuffer> WebGLRenderingContextBase::createBuffer() +{ + if (isContextLostOrPending()) + return nullptr; + auto buffer = WebGLBuffer::create(*this); + addSharedObject(buffer.get()); + return WTFMove(buffer); +} + +RefPtr<WebGLFramebuffer> WebGLRenderingContextBase::createFramebuffer() +{ + if (isContextLostOrPending()) + return nullptr; + auto buffer = WebGLFramebuffer::create(*this); + addContextObject(buffer.get()); + return WTFMove(buffer); +} + +RefPtr<WebGLTexture> WebGLRenderingContextBase::createTexture() +{ + if (isContextLostOrPending()) + return nullptr; + auto texture = WebGLTexture::create(*this); + addSharedObject(texture.get()); + return WTFMove(texture); +} + +RefPtr<WebGLProgram> WebGLRenderingContextBase::createProgram() +{ + if (isContextLostOrPending()) + return nullptr; + auto program = WebGLProgram::create(*this); + addSharedObject(program.get()); + return WTFMove(program); +} + +RefPtr<WebGLRenderbuffer> WebGLRenderingContextBase::createRenderbuffer() +{ + if (isContextLostOrPending()) + return nullptr; + auto buffer = WebGLRenderbuffer::create(*this); + addSharedObject(buffer.get()); + return WTFMove(buffer); +} + +RefPtr<WebGLShader> WebGLRenderingContextBase::createShader(GC3Denum type) +{ + if (isContextLostOrPending()) + return nullptr; + if (type != GraphicsContext3D::VERTEX_SHADER && type != GraphicsContext3D::FRAGMENT_SHADER) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "createShader", "invalid shader type"); + return nullptr; + } + + auto shader = WebGLShader::create(*this, type); + addSharedObject(shader.get()); + return WTFMove(shader); +} + +void WebGLRenderingContextBase::cullFace(GC3Denum mode) +{ + if (isContextLostOrPending()) + return; + m_context->cullFace(mode); +} + +bool WebGLRenderingContextBase::deleteObject(WebGLObject* object) +{ + if (isContextLostOrPending() || !object) + return false; + if (!object->validate(contextGroup(), *this)) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "delete", "object does not belong to this context"); + return false; + } + if (object->object()) + // We need to pass in context here because we want + // things in this context unbound. + object->deleteObject(graphicsContext3D()); + return true; +} + +void WebGLRenderingContextBase::deleteBuffer(WebGLBuffer* buffer) +{ + if (!deleteObject(buffer)) + return; + if (m_boundArrayBuffer == buffer) + m_boundArrayBuffer = nullptr; + + m_boundVertexArrayObject->unbindBuffer(*buffer); +} + +void WebGLRenderingContextBase::deleteFramebuffer(WebGLFramebuffer* framebuffer) +{ + if (!deleteObject(framebuffer)) + return; + if (framebuffer == m_framebufferBinding) { + m_framebufferBinding = nullptr; + m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0); + } +} + +void WebGLRenderingContextBase::deleteProgram(WebGLProgram* program) +{ + deleteObject(program); + // We don't reset m_currentProgram to 0 here because the deletion of the + // current program is delayed. +} + +void WebGLRenderingContextBase::deleteRenderbuffer(WebGLRenderbuffer* renderbuffer) +{ + if (!deleteObject(renderbuffer)) + return; + if (renderbuffer == m_renderbufferBinding) + m_renderbufferBinding = nullptr; + if (m_framebufferBinding) + m_framebufferBinding->removeAttachmentFromBoundFramebuffer(renderbuffer); +} + +void WebGLRenderingContextBase::deleteShader(WebGLShader* shader) +{ + deleteObject(shader); +} + +void WebGLRenderingContextBase::deleteTexture(WebGLTexture* texture) +{ + if (!deleteObject(texture)) + return; + + unsigned current = 0; + for (auto& textureUnit : m_textureUnits) { + if (texture == textureUnit.texture2DBinding) { + textureUnit.texture2DBinding = nullptr; + m_unrenderableTextureUnits.remove(current); + } + if (texture == textureUnit.textureCubeMapBinding) { + textureUnit.textureCubeMapBinding = nullptr; + m_unrenderableTextureUnits.remove(current); + } + ++current; + } + if (m_framebufferBinding) + m_framebufferBinding->removeAttachmentFromBoundFramebuffer(texture); +} + +void WebGLRenderingContextBase::depthFunc(GC3Denum func) +{ + if (isContextLostOrPending()) + return; + m_context->depthFunc(func); +} + +void WebGLRenderingContextBase::depthMask(GC3Dboolean flag) +{ + if (isContextLostOrPending()) + return; + m_depthMask = flag; + m_context->depthMask(flag); +} + +void WebGLRenderingContextBase::depthRange(GC3Dfloat zNear, GC3Dfloat zFar) +{ + if (isContextLostOrPending()) + return; + if (zNear > zFar) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "depthRange", "zNear > zFar"); + return; + } + m_context->depthRange(zNear, zFar); +} + +void WebGLRenderingContextBase::detachShader(WebGLProgram* program, WebGLShader* shader) +{ + if (isContextLostOrPending() || !validateWebGLObject("detachShader", program) || !validateWebGLObject("detachShader", shader)) + return; + if (!program->detachShader(shader)) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "detachShader", "shader not attached"); + return; + } + m_context->detachShader(objectOrZero(program), objectOrZero(shader)); + shader->onDetached(graphicsContext3D()); +} + +void WebGLRenderingContextBase::disable(GC3Denum cap) +{ + if (isContextLostOrPending() || !validateCapability("disable", cap)) + return; + if (cap == GraphicsContext3D::STENCIL_TEST) { + m_stencilEnabled = false; + applyStencilTest(); + return; + } + if (cap == GraphicsContext3D::SCISSOR_TEST) + m_scissorEnabled = false; + m_context->disable(cap); +} + +void WebGLRenderingContextBase::disableVertexAttribArray(GC3Duint index) +{ + if (isContextLostOrPending()) + return; + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "disableVertexAttribArray", "index out of range"); + return; + } + + WebGLVertexArrayObjectBase::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index); + state.enabled = false; + + if (index > 0 || isGLES2Compliant()) + m_context->disableVertexAttribArray(index); +} + +bool WebGLRenderingContextBase::validateNPOTTextureLevel(GC3Dsizei width, GC3Dsizei height, GC3Dint level, const char* functionName) +{ + if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level > 0 not power of 2"); + return false; + } + + return true; +} + +bool WebGLRenderingContextBase::validateElementArraySize(GC3Dsizei count, GC3Denum type, GC3Dintptr offset) +{ + RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer(); + + if (!elementArrayBuffer) + return false; + + if (offset < 0) + return false; + + if (type == GraphicsContext3D::UNSIGNED_INT) { + // For an unsigned int array, offset must be divisible by 4 for alignment reasons. + if (offset % 4) + return false; + + // Make uoffset an element offset. + offset /= 4; + + GC3Dsizeiptr n = elementArrayBuffer->byteLength() / 4; + if (offset > n || count > n - offset) + return false; + } else if (type == GraphicsContext3D::UNSIGNED_SHORT) { + // For an unsigned short array, offset must be divisible by 2 for alignment reasons. + if (offset % 2) + return false; + + // Make uoffset an element offset. + offset /= 2; + + GC3Dsizeiptr n = elementArrayBuffer->byteLength() / 2; + if (offset > n || count > n - offset) + return false; + } else if (type == GraphicsContext3D::UNSIGNED_BYTE) { + GC3Dsizeiptr n = elementArrayBuffer->byteLength(); + if (offset > n || count > n - offset) + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateIndexArrayPrecise(GC3Dsizei count, GC3Denum type, GC3Dintptr offset, unsigned& numElementsRequired) +{ + ASSERT(count >= 0 && offset >= 0); + unsigned lastIndex = 0; + + RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer(); + + if (!elementArrayBuffer) + return false; + + if (!count) { + numElementsRequired = 0; + return true; + } + + if (!elementArrayBuffer->elementArrayBuffer()) + return false; + + unsigned long uoffset = offset; + unsigned long n = count; + + if (type == GraphicsContext3D::UNSIGNED_INT) { + // Make uoffset an element offset. + uoffset /= sizeof(GC3Duint); + const GC3Duint* p = static_cast<const GC3Duint*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset; + while (n-- > 0) { + if (*p > lastIndex) + lastIndex = *p; + ++p; + } + } else if (type == GraphicsContext3D::UNSIGNED_SHORT) { + // Make uoffset an element offset. + uoffset /= sizeof(GC3Dushort); + const GC3Dushort* p = static_cast<const GC3Dushort*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset; + while (n-- > 0) { + if (*p > lastIndex) + lastIndex = *p; + ++p; + } + } else if (type == GraphicsContext3D::UNSIGNED_BYTE) { + const GC3Dubyte* p = static_cast<const GC3Dubyte*>(elementArrayBuffer->elementArrayBuffer()->data()) + uoffset; + while (n-- > 0) { + if (*p > lastIndex) + lastIndex = *p; + ++p; + } + } + + // Then set the last index in the index array and make sure it is valid. + numElementsRequired = lastIndex + 1; + return numElementsRequired > 0; +} + +bool WebGLRenderingContextBase::validateVertexAttributes(unsigned elementCount, unsigned primitiveCount) +{ + if (!m_currentProgram) + return false; + + // Look in each enabled vertex attrib and check if they've been bound to a buffer. + for (unsigned i = 0; i < m_maxVertexAttribs; ++i) { + if (!m_boundVertexArrayObject->getVertexAttribState(i).validateBinding()) + return false; + } + + if (!elementCount) + return true; + + // Look in each consumed vertex attrib (by the current program). + bool sawNonInstancedAttrib = false; + bool sawEnabledAttrib = false; + int numActiveAttribLocations = m_currentProgram->numActiveAttribLocations(); + for (int i = 0; i < numActiveAttribLocations; ++i) { + int loc = m_currentProgram->getActiveAttribLocation(i); + if (loc >= 0 && loc < static_cast<int>(m_maxVertexAttribs)) { + const WebGLVertexArrayObjectBase::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(loc); + if (state.enabled) { + sawEnabledAttrib = true; + // Avoid off-by-one errors in numElements computation. + // For the last element, we will only touch the data for the + // element and nothing beyond it. + int bytesRemaining = static_cast<int>(state.bufferBinding->byteLength() - state.offset); + unsigned numElements = 0; + ASSERT(state.stride > 0); + if (bytesRemaining >= state.bytesPerElement) + numElements = 1 + (bytesRemaining - state.bytesPerElement) / state.stride; + unsigned instancesRequired = 0; + if (state.divisor) { + instancesRequired = ceil(static_cast<float>(primitiveCount) / state.divisor); + if (instancesRequired > numElements) + return false; + } else { + sawNonInstancedAttrib = true; + if (elementCount > numElements) + return false; + } + } + } + } + + if (!sawNonInstancedAttrib && sawEnabledAttrib) + return false; + + bool usingSimulatedArrayBuffer = m_currentProgram->isUsingVertexAttrib0(); + + // Guard against access into non-existent buffers. + if (elementCount && !sawEnabledAttrib && !usingSimulatedArrayBuffer) + return false; + + if (elementCount && sawEnabledAttrib) { + if (!m_boundArrayBuffer && !m_boundVertexArrayObject->getElementArrayBuffer()) { + if (usingSimulatedArrayBuffer) { + auto& state = m_boundVertexArrayObject->getVertexAttribState(0); + if (state.enabled && state.isBound()) { + if (state.bufferBinding->getTarget() == GraphicsContext3D::ARRAY_BUFFER || state.bufferBinding->getTarget() == GraphicsContext3D::ELEMENT_ARRAY_BUFFER) + return !!state.bufferBinding->byteLength(); + } + } + return false; + } + } + + return true; +} + +bool WebGLRenderingContextBase::validateWebGLObject(const char* functionName, WebGLObject* object) +{ + if (!object || !object->object()) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no object or object deleted"); + return false; + } + if (!object->validate(contextGroup(), *this)) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "object does not belong to this context"); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateDrawArrays(const char* functionName, GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primitiveCount) +{ + if (isContextLostOrPending() || !validateDrawMode(functionName, mode)) + return false; + + if (!validateStencilSettings(functionName)) + return false; + + if (first < 0 || count < 0) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "first or count < 0"); + return false; + } + + if (!count) { + markContextChanged(); + return false; + } + + if (primitiveCount < 0) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "primcount < 0"); + return false; + } + + // Ensure we have a valid rendering state. + Checked<GC3Dint, RecordOverflow> checkedFirst(first); + Checked<GC3Dint, RecordOverflow> checkedCount(count); + Checked<GC3Dint, RecordOverflow> checkedSum = checkedFirst + checkedCount; + Checked<GC3Dint, RecordOverflow> checkedPrimitiveCount(primitiveCount); + if (checkedSum.hasOverflowed() || checkedPrimitiveCount.hasOverflowed() || !validateVertexAttributes(checkedSum.unsafeGet(), checkedPrimitiveCount.unsafeGet())) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attempt to access out of bounds arrays"); + return false; + } + if (!validateSimulatedVertexAttrib0(checkedSum.unsafeGet() - 1)) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attempt to access outside the bounds of the simulated vertexAttrib0 array"); + return false; + } + + const char* reason = "framebuffer incomplete"; + if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { + synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, functionName, reason); + return false; + } + + return true; +} + +bool WebGLRenderingContextBase::validateDrawElements(const char* functionName, GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, unsigned& numElements, GC3Dsizei primitiveCount) +{ + if (isContextLostOrPending() || !validateDrawMode(functionName, mode)) + return false; + + if (!validateStencilSettings(functionName)) + return false; + + switch (type) { + case GraphicsContext3D::UNSIGNED_BYTE: + case GraphicsContext3D::UNSIGNED_SHORT: + break; + case GraphicsContext3D::UNSIGNED_INT: + if (m_oesElementIndexUint || isWebGL2()) + break; + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid type"); + return false; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid type"); + return false; + } + + if (count < 0 || offset < 0) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "count or offset < 0"); + return false; + } + + if (!count) { + markContextChanged(); + return false; + } + + if (primitiveCount < 0) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "primcount < 0"); + return false; + } + + if (!m_boundVertexArrayObject->getElementArrayBuffer()) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no ELEMENT_ARRAY_BUFFER bound"); + return false; + } + + // Ensure we have a valid rendering state. + if (!validateElementArraySize(count, type, static_cast<GC3Dintptr>(offset))) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "request out of bounds for current ELEMENT_ARRAY_BUFFER"); + return false; + } + if (!count) + return false; + + Checked<GC3Dint, RecordOverflow> checkedCount(count); + Checked<GC3Dint, RecordOverflow> checkedPrimitiveCount(primitiveCount); + if (checkedCount.hasOverflowed() || checkedPrimitiveCount.hasOverflowed()) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attempt to access out of bounds arrays"); + return false; + } + + if (!validateIndexArrayConservative(type, numElements) || !validateVertexAttributes(numElements, checkedPrimitiveCount.unsafeGet())) { + if (!validateIndexArrayPrecise(checkedCount.unsafeGet(), type, static_cast<GC3Dintptr>(offset), numElements) || !validateVertexAttributes(numElements, checkedPrimitiveCount.unsafeGet())) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attempt to access out of bounds arrays"); + return false; + } + } + + if (!validateSimulatedVertexAttrib0(numElements)) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "attempt to access outside the bounds of the simulated vertexAttrib0 array"); + return false; + } + + const char* reason = "framebuffer incomplete"; + if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { + synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, functionName, reason); + return false; + } + + return true; +} + +void WebGLRenderingContextBase::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count) +{ + if (!validateDrawArrays("drawArrays", mode, first, count, 0)) + return; + + clearIfComposited(); + + bool vertexAttrib0Simulated = false; + if (!isGLES2Compliant()) + vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1); + bool usesFallbackTexture = false; + if (!isGLES2NPOTStrict()) + usesFallbackTexture = checkTextureCompleteness("drawArrays", true); + + m_context->drawArrays(mode, first, count); + + if (!isGLES2Compliant() && vertexAttrib0Simulated) + restoreStatesAfterVertexAttrib0Simulation(); + if (usesFallbackTexture) + checkTextureCompleteness("drawArrays", false); + markContextChanged(); +} + +void WebGLRenderingContextBase::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset) +{ + unsigned numElements = 0; + if (!validateDrawElements("drawElements", mode, count, type, offset, numElements, 0)) + return; + + clearIfComposited(); + + bool vertexAttrib0Simulated = false; + if (!isGLES2Compliant()) { + if (!numElements) + validateIndexArrayPrecise(count, type, static_cast<GC3Dintptr>(offset), numElements); + vertexAttrib0Simulated = simulateVertexAttrib0(numElements); + } + + bool usesFallbackTexture = false; + if (!isGLES2NPOTStrict()) + usesFallbackTexture = checkTextureCompleteness("drawElements", true); + + m_context->drawElements(mode, count, type, static_cast<GC3Dintptr>(offset)); + + if (!isGLES2Compliant() && vertexAttrib0Simulated) + restoreStatesAfterVertexAttrib0Simulation(); + if (usesFallbackTexture) + checkTextureCompleteness("drawElements", false); + markContextChanged(); +} + +void WebGLRenderingContextBase::enable(GC3Denum cap) +{ + if (isContextLostOrPending() || !validateCapability("enable", cap)) + return; + if (cap == GraphicsContext3D::STENCIL_TEST) { + m_stencilEnabled = true; + applyStencilTest(); + return; + } + if (cap == GraphicsContext3D::SCISSOR_TEST) + m_scissorEnabled = true; + m_context->enable(cap); +} + +void WebGLRenderingContextBase::enableVertexAttribArray(GC3Duint index) +{ + if (isContextLostOrPending()) + return; + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "enableVertexAttribArray", "index out of range"); + return; + } + + WebGLVertexArrayObjectBase::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index); + state.enabled = true; + + m_context->enableVertexAttribArray(index); +} + +void WebGLRenderingContextBase::finish() +{ + if (isContextLostOrPending()) + return; + m_context->finish(); +} + +void WebGLRenderingContextBase::flush() +{ + if (isContextLostOrPending()) + return; + m_context->flush(); +} + +void WebGLRenderingContextBase::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer* buffer) +{ + if (isContextLostOrPending() || !validateFramebufferFuncParameters("framebufferRenderbuffer", target, attachment)) + return; + if (renderbuffertarget != GraphicsContext3D::RENDERBUFFER) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "framebufferRenderbuffer", "invalid target"); + return; + } + if (buffer && !buffer->validate(contextGroup(), *this)) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferRenderbuffer", "no buffer or buffer not from this context"); + return; + } + // Don't allow the default framebuffer to be mutated; all current + // implementations use an FBO internally in place of the default + // FBO. + if (!m_framebufferBinding || !m_framebufferBinding->object()) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferRenderbuffer", "no framebuffer bound"); + return; + } + Platform3DObject bufferObject = objectOrZero(buffer); + switch (attachment) { + case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT: + m_context->framebufferRenderbuffer(target, GraphicsContext3D::DEPTH_ATTACHMENT, renderbuffertarget, bufferObject); + m_context->framebufferRenderbuffer(target, GraphicsContext3D::STENCIL_ATTACHMENT, renderbuffertarget, bufferObject); + break; + default: + m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, bufferObject); + } + m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, buffer); + applyStencilTest(); +} + +void WebGLRenderingContextBase::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture* texture, GC3Dint level) +{ + if (isContextLostOrPending() || !validateFramebufferFuncParameters("framebufferTexture2D", target, attachment)) + return; + if (level) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "framebufferTexture2D", "level not 0"); + return; + } + if (texture && !texture->validate(contextGroup(), *this)) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferTexture2D", "no texture or texture not from this context"); + return; + } + // Don't allow the default framebuffer to be mutated; all current + // implementations use an FBO internally in place of the default + // FBO. + if (!m_framebufferBinding || !m_framebufferBinding->object()) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "framebufferTexture2D", "no framebuffer bound"); + return; + } + Platform3DObject textureObject = objectOrZero(texture); + switch (attachment) { + case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT: + m_context->framebufferTexture2D(target, GraphicsContext3D::DEPTH_ATTACHMENT, textarget, textureObject, level); + m_context->framebufferTexture2D(target, GraphicsContext3D::STENCIL_ATTACHMENT, textarget, textureObject, level); + break; + case GraphicsContext3D::DEPTH_ATTACHMENT: + m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level); + break; + case GraphicsContext3D::STENCIL_ATTACHMENT: + m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level); + break; + default: + m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level); + } + m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, textarget, texture, level); + applyStencilTest(); +} + +void WebGLRenderingContextBase::frontFace(GC3Denum mode) +{ + if (isContextLostOrPending()) + return; + m_context->frontFace(mode); +} + +void WebGLRenderingContextBase::generateMipmap(GC3Denum target) +{ + if (isContextLostOrPending()) + return; + WebGLTexture* tex = validateTextureBinding("generateMipmap", target, false); + if (!tex) + return; + if (!tex->canGenerateMipmaps()) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "generateMipmap", "level 0 not power of 2 or not all the same size"); + return; + } + // FIXME: https://bugs.webkit.org/show_bug.cgi?id=123916. Compressed textures should be allowed in WebGL 2: + if (tex->isCompressed()) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "generateMipmap", "trying to generate mipmaps from compressed texture"); + return; + } + if (!validateSettableTexInternalFormat("generateMipmap", tex->getInternalFormat(target, 0))) + return; + + // generateMipmap won't work properly if minFilter is not NEAREST_MIPMAP_LINEAR + // on Mac. Remove the hack once this driver bug is fixed. +#if OS(DARWIN) + bool needToResetMinFilter = false; + if (tex->getMinFilter() != GraphicsContext3D::NEAREST_MIPMAP_LINEAR) { + m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST_MIPMAP_LINEAR); + needToResetMinFilter = true; + } +#endif + m_context->generateMipmap(target); +#if OS(DARWIN) + if (needToResetMinFilter) + m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, tex->getMinFilter()); +#endif + tex->generateMipmapLevelInfo(); +} + +RefPtr<WebGLActiveInfo> WebGLRenderingContextBase::getActiveAttrib(WebGLProgram* program, GC3Duint index) +{ + if (isContextLostOrPending() || !validateWebGLObject("getActiveAttrib", program)) + return nullptr; + ActiveInfo info; + if (!m_context->getActiveAttrib(objectOrZero(program), index, info)) + return nullptr; + + LOG(WebGL, "Returning active attribute %d: %s", index, info.name.utf8().data()); + + return WebGLActiveInfo::create(info.name, info.type, info.size); +} + +RefPtr<WebGLActiveInfo> WebGLRenderingContextBase::getActiveUniform(WebGLProgram* program, GC3Duint index) +{ + if (isContextLostOrPending() || !validateWebGLObject("getActiveUniform", program)) + return nullptr; + ActiveInfo info; + if (!m_context->getActiveUniform(objectOrZero(program), index, info)) + return nullptr; + if (!isGLES2Compliant()) + if (info.size > 1 && !info.name.endsWith("[0]")) + info.name.append("[0]"); + + LOG(WebGL, "Returning active uniform %d: %s", index, info.name.utf8().data()); + + return WebGLActiveInfo::create(info.name, info.type, info.size); +} + +std::optional<Vector<RefPtr<WebGLShader>>> WebGLRenderingContextBase::getAttachedShaders(WebGLProgram* program) +{ + if (isContextLostOrPending() || !validateWebGLObject("getAttachedShaders", program)) + return std::nullopt; + + const GC3Denum shaderTypes[] = { + GraphicsContext3D::VERTEX_SHADER, + GraphicsContext3D::FRAGMENT_SHADER + }; + Vector<RefPtr<WebGLShader>> shaderObjects; + for (auto shaderType : shaderTypes) { + WebGLShader* shader = program->getAttachedShader(shaderType); + if (shader) + shaderObjects.append(shader); + } + return shaderObjects; +} + +GC3Dint WebGLRenderingContextBase::getAttribLocation(WebGLProgram* program, const String& name) +{ + if (isContextLostOrPending() || !validateWebGLObject("getAttribLocation", program)) + return -1; + if (!validateLocationLength("getAttribLocation", name)) + return -1; + if (!validateString("getAttribLocation", name)) + return -1; + if (isPrefixReserved(name)) + return -1; + if (!program->getLinkStatus()) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getAttribLocation", "program not linked"); + return -1; + } + return m_context->getAttribLocation(objectOrZero(program), name); +} + +WebGLAny WebGLRenderingContextBase::getBufferParameter(GC3Denum target, GC3Denum pname) +{ + if (isContextLostOrPending()) + return nullptr; + + bool valid = false; + if (target == GraphicsContext3D::ARRAY_BUFFER || target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER) + valid = true; +#if ENABLE(WEBGL2) + if (isWebGL2()) { + switch (target) { + case GraphicsContext3D::COPY_READ_BUFFER: + case GraphicsContext3D::COPY_WRITE_BUFFER: + case GraphicsContext3D::PIXEL_PACK_BUFFER: + case GraphicsContext3D::PIXEL_UNPACK_BUFFER: + case GraphicsContext3D::TRANSFORM_FEEDBACK_BUFFER: + case GraphicsContext3D::UNIFORM_BUFFER: + valid = true; + } + } +#endif + if (!valid) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getBufferParameter", "invalid target"); + return nullptr; + } + + if (pname != GraphicsContext3D::BUFFER_SIZE && pname != GraphicsContext3D::BUFFER_USAGE) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getBufferParameter", "invalid parameter name"); + return nullptr; + } + + GC3Dint value = 0; + m_context->getBufferParameteriv(target, pname, &value); + if (pname == GraphicsContext3D::BUFFER_SIZE) + return value; + return static_cast<unsigned>(value); +} + +std::optional<WebGLContextAttributes> WebGLRenderingContextBase::getContextAttributes() +{ + if (isContextLostOrPending()) + return std::nullopt; + + // Also, we need to enforce requested values of "false" for depth + // and stencil, regardless of the properties of the underlying + // GraphicsContext3D. + + auto attributes = m_context->getContextAttributes(); + if (!m_attributes.depth) + attributes.depth = false; + if (!m_attributes.stencil) + attributes.stencil = false; + return WTFMove(attributes); +} + +GC3Denum WebGLRenderingContextBase::getError() +{ + if (m_isPendingPolicyResolution) + return GraphicsContext3D::NO_ERROR; + return m_context->getError(); +} + +WebGLAny WebGLRenderingContextBase::getProgramParameter(WebGLProgram* program, GC3Denum pname) +{ + if (isContextLostOrPending() || !validateWebGLObject("getProgramParameter", program)) + return nullptr; + + GC3Dint value = 0; + switch (pname) { + case GraphicsContext3D::DELETE_STATUS: + return program->isDeleted(); + case GraphicsContext3D::VALIDATE_STATUS: + m_context->getProgramiv(objectOrZero(program), pname, &value); + return static_cast<bool>(value); + case GraphicsContext3D::LINK_STATUS: + return program->getLinkStatus(); + case GraphicsContext3D::ATTACHED_SHADERS: + m_context->getProgramiv(objectOrZero(program), pname, &value); + return value; + case GraphicsContext3D::ACTIVE_ATTRIBUTES: + case GraphicsContext3D::ACTIVE_UNIFORMS: + m_context->getNonBuiltInActiveSymbolCount(objectOrZero(program), pname, &value); + return value; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getProgramParameter", "invalid parameter name"); + return nullptr; + } +} + +String WebGLRenderingContextBase::getProgramInfoLog(WebGLProgram* program) +{ + if (isContextLostOrPending() || !validateWebGLObject("getProgramInfoLog", program)) + return String(); + return ensureNotNull(m_context->getProgramInfoLog(objectOrZero(program))); +} + +WebGLAny WebGLRenderingContextBase::getRenderbufferParameter(GC3Denum target, GC3Denum pname) +{ + if (isContextLostOrPending()) + return nullptr; + if (target != GraphicsContext3D::RENDERBUFFER) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid target"); + return nullptr; + } + if (!m_renderbufferBinding || !m_renderbufferBinding->object()) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getRenderbufferParameter", "no renderbuffer bound"); + return nullptr; + } + + if (m_renderbufferBinding->getInternalFormat() == GraphicsContext3D::DEPTH_STENCIL + && !m_renderbufferBinding->isValid()) { + ASSERT(!isDepthStencilSupported()); + int value = 0; + switch (pname) { + case GraphicsContext3D::RENDERBUFFER_WIDTH: + value = m_renderbufferBinding->getWidth(); + break; + case GraphicsContext3D::RENDERBUFFER_HEIGHT: + value = m_renderbufferBinding->getHeight(); + break; + case GraphicsContext3D::RENDERBUFFER_RED_SIZE: + case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE: + case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE: + case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE: + value = 0; + break; + case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE: + value = 24; + break; + case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE: + value = 8; + break; + case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT: + return m_renderbufferBinding->getInternalFormat(); + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid parameter name"); + return nullptr; + } + return value; + } + + GC3Dint value = 0; + switch (pname) { + case GraphicsContext3D::RENDERBUFFER_WIDTH: + case GraphicsContext3D::RENDERBUFFER_HEIGHT: + case GraphicsContext3D::RENDERBUFFER_RED_SIZE: + case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE: + case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE: + case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE: + case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE: + case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE: + m_context->getRenderbufferParameteriv(target, pname, &value); + return value; + case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT: + return m_renderbufferBinding->getInternalFormat(); + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getRenderbufferParameter", "invalid parameter name"); + return nullptr; + } +} + +WebGLAny WebGLRenderingContextBase::getShaderParameter(WebGLShader* shader, GC3Denum pname) +{ + if (isContextLostOrPending() || !validateWebGLObject("getShaderParameter", shader)) + return nullptr; + GC3Dint value = 0; + switch (pname) { + case GraphicsContext3D::DELETE_STATUS: + return shader->isDeleted(); + case GraphicsContext3D::COMPILE_STATUS: + m_context->getShaderiv(objectOrZero(shader), pname, &value); + return static_cast<bool>(value); + case GraphicsContext3D::SHADER_TYPE: + m_context->getShaderiv(objectOrZero(shader), pname, &value); + return static_cast<unsigned>(value); + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderParameter", "invalid parameter name"); + return nullptr; + } +} + +String WebGLRenderingContextBase::getShaderInfoLog(WebGLShader* shader) +{ + if (isContextLostOrPending() || !validateWebGLObject("getShaderInfoLog", shader)) + return String(); + return ensureNotNull(m_context->getShaderInfoLog(objectOrZero(shader))); +} + +RefPtr<WebGLShaderPrecisionFormat> WebGLRenderingContextBase::getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType) +{ + if (isContextLostOrPending()) + return nullptr; + switch (shaderType) { + case GraphicsContext3D::VERTEX_SHADER: + case GraphicsContext3D::FRAGMENT_SHADER: + break; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderPrecisionFormat", "invalid shader type"); + return nullptr; + } + switch (precisionType) { + case GraphicsContext3D::LOW_FLOAT: + case GraphicsContext3D::MEDIUM_FLOAT: + case GraphicsContext3D::HIGH_FLOAT: + case GraphicsContext3D::LOW_INT: + case GraphicsContext3D::MEDIUM_INT: + case GraphicsContext3D::HIGH_INT: + break; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getShaderPrecisionFormat", "invalid precision type"); + return nullptr; + } + + GC3Dint range[2] = {0, 0}; + GC3Dint precision = 0; + m_context->getShaderPrecisionFormat(shaderType, precisionType, range, &precision); + return WebGLShaderPrecisionFormat::create(range[0], range[1], precision); +} + +String WebGLRenderingContextBase::getShaderSource(WebGLShader* shader) +{ + if (isContextLostOrPending() || !validateWebGLObject("getShaderSource", shader)) + return String(); + return ensureNotNull(shader->getSource()); +} + +WebGLAny WebGLRenderingContextBase::getTexParameter(GC3Denum target, GC3Denum pname) +{ + if (isContextLostOrPending()) + return nullptr; + WebGLTexture* tex = validateTextureBinding("getTexParameter", target, false); + if (!tex) + return nullptr; + GC3Dint value = 0; + switch (pname) { + case GraphicsContext3D::TEXTURE_MAG_FILTER: + case GraphicsContext3D::TEXTURE_MIN_FILTER: + case GraphicsContext3D::TEXTURE_WRAP_S: + case GraphicsContext3D::TEXTURE_WRAP_T: + m_context->getTexParameteriv(target, pname, &value); + return static_cast<unsigned>(value); + case Extensions3D::TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic + if (m_extTextureFilterAnisotropic) { + m_context->getTexParameteriv(target, pname, &value); + return static_cast<unsigned>(value); + } + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getTexParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled"); + return nullptr; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getTexParameter", "invalid parameter name"); + return nullptr; + } +} + +WebGLAny WebGLRenderingContextBase::getUniform(WebGLProgram* program, const WebGLUniformLocation* uniformLocation) +{ + if (isContextLostOrPending() || !validateWebGLObject("getUniform", program)) + return nullptr; + if (!uniformLocation || uniformLocation->program() != program) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getUniform", "no uniformlocation or not valid for this program"); + return nullptr; + } + GC3Dint location = uniformLocation->location(); + + GC3Denum baseType; + unsigned length; + switch (uniformLocation->type()) { + case GraphicsContext3D::BOOL: + baseType = GraphicsContext3D::BOOL; + length = 1; + break; + case GraphicsContext3D::BOOL_VEC2: + baseType = GraphicsContext3D::BOOL; + length = 2; + break; + case GraphicsContext3D::BOOL_VEC3: + baseType = GraphicsContext3D::BOOL; + length = 3; + break; + case GraphicsContext3D::BOOL_VEC4: + baseType = GraphicsContext3D::BOOL; + length = 4; + break; + case GraphicsContext3D::INT: + baseType = GraphicsContext3D::INT; + length = 1; + break; + case GraphicsContext3D::INT_VEC2: + baseType = GraphicsContext3D::INT; + length = 2; + break; + case GraphicsContext3D::INT_VEC3: + baseType = GraphicsContext3D::INT; + length = 3; + break; + case GraphicsContext3D::INT_VEC4: + baseType = GraphicsContext3D::INT; + length = 4; + break; + case GraphicsContext3D::FLOAT: + baseType = GraphicsContext3D::FLOAT; + length = 1; + break; + case GraphicsContext3D::FLOAT_VEC2: + baseType = GraphicsContext3D::FLOAT; + length = 2; + break; + case GraphicsContext3D::FLOAT_VEC3: + baseType = GraphicsContext3D::FLOAT; + length = 3; + break; + case GraphicsContext3D::FLOAT_VEC4: + baseType = GraphicsContext3D::FLOAT; + length = 4; + break; + case GraphicsContext3D::FLOAT_MAT2: + baseType = GraphicsContext3D::FLOAT; + length = 4; + break; + case GraphicsContext3D::FLOAT_MAT3: + baseType = GraphicsContext3D::FLOAT; + length = 9; + break; + case GraphicsContext3D::FLOAT_MAT4: + baseType = GraphicsContext3D::FLOAT; + length = 16; + break; + case GraphicsContext3D::SAMPLER_2D: + case GraphicsContext3D::SAMPLER_CUBE: + baseType = GraphicsContext3D::INT; + length = 1; + break; + default: + // Can't handle this type + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getUniform", "unhandled type"); + return nullptr; + } + switch (baseType) { + case GraphicsContext3D::FLOAT: { + GC3Dfloat value[16] = {0}; + if (m_isRobustnessEXTSupported) + m_context->getExtensions().getnUniformfvEXT(objectOrZero(program), location, 16 * sizeof(GC3Dfloat), value); + else + m_context->getUniformfv(objectOrZero(program), location, value); + if (length == 1) + return value[0]; + return Float32Array::create(value, length); + } + case GraphicsContext3D::INT: { + GC3Dint value[4] = {0}; + if (m_isRobustnessEXTSupported) + m_context->getExtensions().getnUniformivEXT(objectOrZero(program), location, 4 * sizeof(GC3Dint), value); + else + m_context->getUniformiv(objectOrZero(program), location, value); + if (length == 1) + return value[0]; + return Int32Array::create(value, length); + } + case GraphicsContext3D::BOOL: { + GC3Dint value[4] = {0}; + if (m_isRobustnessEXTSupported) + m_context->getExtensions().getnUniformivEXT(objectOrZero(program), location, 4 * sizeof(GC3Dint), value); + else + m_context->getUniformiv(objectOrZero(program), location, value); + if (length > 1) { + Vector<bool> vector(length); + for (unsigned j = 0; j < length; j++) + vector[j] = value[j]; + return WTFMove(vector); + } + return static_cast<bool>(value[0]); + } + default: + notImplemented(); + } + + // If we get here, something went wrong in our unfortunately complex logic above + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getUniform", "unknown error"); + return nullptr; +} + +RefPtr<WebGLUniformLocation> WebGLRenderingContextBase::getUniformLocation(WebGLProgram* program, const String& name) +{ + if (isContextLostOrPending() || !validateWebGLObject("getUniformLocation", program)) + return nullptr; + if (!validateLocationLength("getUniformLocation", name)) + return nullptr; + if (!validateString("getUniformLocation", name)) + return nullptr; + if (isPrefixReserved(name)) + return nullptr; + if (!program->getLinkStatus()) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getUniformLocation", "program not linked"); + return nullptr; + } + GC3Dint uniformLocation = m_context->getUniformLocation(objectOrZero(program), name); + if (uniformLocation == -1) + return nullptr; + + GC3Dint activeUniforms = 0; + m_context->getNonBuiltInActiveSymbolCount(objectOrZero(program), GraphicsContext3D::ACTIVE_UNIFORMS, &activeUniforms); + for (GC3Dint i = 0; i < activeUniforms; i++) { + ActiveInfo info; + if (!m_context->getActiveUniform(objectOrZero(program), i, info)) + return nullptr; + // Strip "[0]" from the name if it's an array. + if (info.name.endsWith("[0]")) + info.name = info.name.left(info.name.length() - 3); + // If it's an array, we need to iterate through each element, appending "[index]" to the name. + for (GC3Dint index = 0; index < info.size; ++index) { + String uniformName = info.name + "[" + String::number(index) + "]"; + + if (name == uniformName || name == info.name) + return WebGLUniformLocation::create(program, uniformLocation, info.type); + } + } + return nullptr; +} + +WebGLAny WebGLRenderingContextBase::getVertexAttrib(GC3Duint index, GC3Denum pname) +{ + if (isContextLostOrPending()) + return nullptr; + + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "getVertexAttrib", "index out of range"); + return nullptr; + } + + const WebGLVertexArrayObjectBase::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index); + + if ((isWebGL2() || m_angleInstancedArrays) && pname == GraphicsContext3D::VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE) + return state.divisor; + + switch (pname) { + case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: + if ((!isGLES2Compliant() && !index && m_boundVertexArrayObject->getVertexAttribState(0).bufferBinding == m_vertexAttrib0Buffer) + || !state.bufferBinding + || !state.bufferBinding->object()) + return nullptr; + return state.bufferBinding; + case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_ENABLED: + return state.enabled; + case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_NORMALIZED: + return state.normalized; + case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_SIZE: + return state.size; + case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_STRIDE: + return state.originalStride; + case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_TYPE: + return state.type; + case GraphicsContext3D::CURRENT_VERTEX_ATTRIB: + return Float32Array::create(m_vertexAttribValue[index].value, 4); + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getVertexAttrib", "invalid parameter name"); + return nullptr; + } +} + +long long WebGLRenderingContextBase::getVertexAttribOffset(GC3Duint index, GC3Denum pname) +{ + if (isContextLostOrPending()) + return 0; + return m_context->getVertexAttribOffset(index, pname); +} + +GC3Dboolean WebGLRenderingContextBase::isBuffer(WebGLBuffer* buffer) +{ + if (!buffer || isContextLostOrPending()) + return 0; + + if (!buffer->hasEverBeenBound()) + return 0; + + return m_context->isBuffer(buffer->object()); +} + +bool WebGLRenderingContextBase::isContextLost() const +{ + return m_contextLost; +} + +bool WebGLRenderingContextBase::isContextLostOrPending() +{ + if (m_isPendingPolicyResolution && !m_hasRequestedPolicyResolution) { + LOG(WebGL, "Context is being used. Attempt to resolve the policy."); + Document& document = canvas().document().topDocument(); + Page* page = document.page(); + if (page && !document.url().isLocalFile()) + page->mainFrame().loader().client().resolveWebGLPolicyForURL(document.url()); + // FIXME: We don't currently do anything with the result from resolution. A more + // complete implementation might try to construct a real context, etc and proceed + // with normal operation. + // https://bugs.webkit.org/show_bug.cgi?id=129122 + m_hasRequestedPolicyResolution = true; + } + + return m_contextLost || m_isPendingPolicyResolution; +} + +GC3Dboolean WebGLRenderingContextBase::isEnabled(GC3Denum cap) +{ + if (isContextLostOrPending() || !validateCapability("isEnabled", cap)) + return 0; + if (cap == GraphicsContext3D::STENCIL_TEST) + return m_stencilEnabled; + return m_context->isEnabled(cap); +} + +GC3Dboolean WebGLRenderingContextBase::isFramebuffer(WebGLFramebuffer* framebuffer) +{ + if (!framebuffer || isContextLostOrPending()) + return 0; + + if (!framebuffer->hasEverBeenBound()) + return 0; + + return m_context->isFramebuffer(framebuffer->object()); +} + +GC3Dboolean WebGLRenderingContextBase::isProgram(WebGLProgram* program) +{ + if (!program || isContextLostOrPending()) + return 0; + + return m_context->isProgram(program->object()); +} + +GC3Dboolean WebGLRenderingContextBase::isRenderbuffer(WebGLRenderbuffer* renderbuffer) +{ + if (!renderbuffer || isContextLostOrPending()) + return 0; + + if (!renderbuffer->hasEverBeenBound()) + return 0; + + return m_context->isRenderbuffer(renderbuffer->object()); +} + +GC3Dboolean WebGLRenderingContextBase::isShader(WebGLShader* shader) +{ + if (!shader || isContextLostOrPending()) + return 0; + + return m_context->isShader(shader->object()); +} + +GC3Dboolean WebGLRenderingContextBase::isTexture(WebGLTexture* texture) +{ + if (!texture || isContextLostOrPending()) + return 0; + + if (!texture->hasEverBeenBound()) + return 0; + + return m_context->isTexture(texture->object()); +} + +void WebGLRenderingContextBase::lineWidth(GC3Dfloat width) +{ + if (isContextLostOrPending()) + return; + m_context->lineWidth(width); +} + +void WebGLRenderingContextBase::linkProgram(WebGLProgram* program) +{ + if (isContextLostOrPending() || !validateWebGLObject("linkProgram", program)) + return; + WebGLShader* vertexShader = program->getAttachedShader(GraphicsContext3D::VERTEX_SHADER); + WebGLShader* fragmentShader = program->getAttachedShader(GraphicsContext3D::FRAGMENT_SHADER); + if (!vertexShader || !vertexShader->isValid() || !fragmentShader || !fragmentShader->isValid() || !m_context->precisionsMatch(objectOrZero(vertexShader), objectOrZero(fragmentShader)) || !m_context->checkVaryingsPacking(objectOrZero(vertexShader), objectOrZero(fragmentShader))) { + program->setLinkStatus(false); + return; + } + + m_context->linkProgram(objectOrZero(program)); + program->increaseLinkCount(); +} + +void WebGLRenderingContextBase::pixelStorei(GC3Denum pname, GC3Dint param) +{ + if (isContextLostOrPending()) + return; + switch (pname) { + case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL: + m_unpackFlipY = param; + break; + case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL: + m_unpackPremultiplyAlpha = param; + break; + case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL: + if (param == GraphicsContext3D::BROWSER_DEFAULT_WEBGL || param == GraphicsContext3D::NONE) + m_unpackColorspaceConversion = static_cast<GC3Denum>(param); + else { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "pixelStorei", "invalid parameter for UNPACK_COLORSPACE_CONVERSION_WEBGL"); + return; + } + break; + case GraphicsContext3D::PACK_ALIGNMENT: + case GraphicsContext3D::UNPACK_ALIGNMENT: + if (param == 1 || param == 2 || param == 4 || param == 8) { + if (pname == GraphicsContext3D::PACK_ALIGNMENT) + m_packAlignment = param; + else // GraphicsContext3D::UNPACK_ALIGNMENT: + m_unpackAlignment = param; + m_context->pixelStorei(pname, param); + } else { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "pixelStorei", "invalid parameter for alignment"); + return; + } + break; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "pixelStorei", "invalid parameter name"); + return; + } +} + +void WebGLRenderingContextBase::polygonOffset(GC3Dfloat factor, GC3Dfloat units) +{ + if (isContextLostOrPending()) + return; + m_context->polygonOffset(factor, units); +} + +enum class InternalFormatTheme { + None, + NormalizedFixedPoint, + Packed, + SignedNormalizedFixedPoint, + FloatingPoint, + SignedInteger, + UnsignedInteger +}; + +static InternalFormatTheme internalFormatTheme(GC3Denum internalFormat) +{ + switch (internalFormat) { + case GraphicsContext3D::RGB: + case GraphicsContext3D::RGBA: + case GraphicsContext3D::LUMINANCE_ALPHA: + case GraphicsContext3D::LUMINANCE: + case GraphicsContext3D::ALPHA: + case GraphicsContext3D::R8: + case GraphicsContext3D::RG8: + case GraphicsContext3D::RGB8: + case GraphicsContext3D::SRGB8: + case GraphicsContext3D::RGBA8: + case GraphicsContext3D::SRGB8_ALPHA8: + case GraphicsContext3D::SRGB_ALPHA: + return InternalFormatTheme::NormalizedFixedPoint; + case GraphicsContext3D::RGB565: + case GraphicsContext3D::RGB5_A1: + case GraphicsContext3D::RGBA4: + case GraphicsContext3D::RGB9_E5: + case GraphicsContext3D::RGB10_A2: + case GraphicsContext3D::R11F_G11F_B10F: + case GraphicsContext3D::RGB10_A2UI: + return InternalFormatTheme::Packed; + case GraphicsContext3D::R8_SNORM: + case GraphicsContext3D::RG8_SNORM: + case GraphicsContext3D::RGB8_SNORM: + case GraphicsContext3D::RGBA8_SNORM: + return InternalFormatTheme::SignedNormalizedFixedPoint; + case GraphicsContext3D::R16F: + case GraphicsContext3D::R32F: + case GraphicsContext3D::RG16F: + case GraphicsContext3D::RG32F: + case GraphicsContext3D::RGB16F: + case GraphicsContext3D::RGB32F: + case GraphicsContext3D::RGBA16F: + case GraphicsContext3D::RGBA32F: + return InternalFormatTheme::FloatingPoint; + case GraphicsContext3D::R8I: + case GraphicsContext3D::R16I: + case GraphicsContext3D::R32I: + case GraphicsContext3D::RG8I: + case GraphicsContext3D::RG16I: + case GraphicsContext3D::RG32I: + case GraphicsContext3D::RGB8I: + case GraphicsContext3D::RGB16I: + case GraphicsContext3D::RGB32I: + case GraphicsContext3D::RGBA8I: + case GraphicsContext3D::RGBA16I: + case GraphicsContext3D::RGBA32I: + return InternalFormatTheme::SignedInteger; + case GraphicsContext3D::R8UI: + case GraphicsContext3D::R16UI: + case GraphicsContext3D::R32UI: + case GraphicsContext3D::RG8UI: + case GraphicsContext3D::RG16UI: + case GraphicsContext3D::RG32UI: + case GraphicsContext3D::RGB8UI: + case GraphicsContext3D::RGB16UI: + case GraphicsContext3D::RGB32UI: + case GraphicsContext3D::RGBA8UI: + case GraphicsContext3D::RGBA16UI: + case GraphicsContext3D::RGBA32UI: + return InternalFormatTheme::UnsignedInteger; + default: + return InternalFormatTheme::None; + } +} + +static int numberOfComponentsForFormat(GC3Denum format) +{ + switch (format) { + case GraphicsContext3D::RED: + case GraphicsContext3D::RED_INTEGER: + return 1; + case GraphicsContext3D::RG: + case GraphicsContext3D::RG_INTEGER: + return 2; + case GraphicsContext3D::RGB: + case GraphicsContext3D::RGB_INTEGER: + return 3; + case GraphicsContext3D::RGBA: + case GraphicsContext3D::RGBA_INTEGER: + return 4; + default: + return 0; + } +} + +static int numberOfComponentsForInternalFormat(GC3Denum internalFormat) +{ + switch (internalFormat) { + case GraphicsContext3D::LUMINANCE: + case GraphicsContext3D::ALPHA: + case GraphicsContext3D::R8: + case GraphicsContext3D::R8_SNORM: + case GraphicsContext3D::R16F: + case GraphicsContext3D::R32F: + case GraphicsContext3D::R8UI: + case GraphicsContext3D::R8I: + case GraphicsContext3D::R16UI: + case GraphicsContext3D::R16I: + case GraphicsContext3D::R32UI: + case GraphicsContext3D::R32I: + case GraphicsContext3D::DEPTH_COMPONENT16: + case GraphicsContext3D::DEPTH_COMPONENT24: + case GraphicsContext3D::DEPTH_COMPONENT32F: + return 1; + case GraphicsContext3D::RG8: + case GraphicsContext3D::LUMINANCE_ALPHA: + case GraphicsContext3D::RG8_SNORM: + case GraphicsContext3D::RG16F: + case GraphicsContext3D::RG32F: + case GraphicsContext3D::RG8UI: + case GraphicsContext3D::RG8I: + case GraphicsContext3D::RG16UI: + case GraphicsContext3D::RG16I: + case GraphicsContext3D::RG32UI: + case GraphicsContext3D::RG32I: + case GraphicsContext3D::DEPTH24_STENCIL8: + case GraphicsContext3D::DEPTH32F_STENCIL8: + return 2; + case GraphicsContext3D::RGB: + case GraphicsContext3D::RGB8: + case GraphicsContext3D::SRGB8: + case GraphicsContext3D::RGB565: + case GraphicsContext3D::RGB8_SNORM: + case GraphicsContext3D::R11F_G11F_B10F: + case GraphicsContext3D::RGB9_E5: + case GraphicsContext3D::RGB16F: + case GraphicsContext3D::RGB32F: + case GraphicsContext3D::RGB8UI: + case GraphicsContext3D::RGB8I: + case GraphicsContext3D::RGB16UI: + case GraphicsContext3D::RGB16I: + case GraphicsContext3D::RGB32UI: + case GraphicsContext3D::RGB32I: + return 3; + case GraphicsContext3D::RGBA: + case GraphicsContext3D::RGBA8: + case GraphicsContext3D::SRGB_ALPHA: + case GraphicsContext3D::SRGB8_ALPHA8: + case GraphicsContext3D::RGBA8_SNORM: + case GraphicsContext3D::RGB5_A1: + case GraphicsContext3D::RGBA4: + case GraphicsContext3D::RGB10_A2: + case GraphicsContext3D::RGBA16F: + case GraphicsContext3D::RGBA32F: + case GraphicsContext3D::RGBA8UI: + case GraphicsContext3D::RGBA8I: + case GraphicsContext3D::RGB10_A2UI: + case GraphicsContext3D::RGBA16UI: + case GraphicsContext3D::RGBA16I: + case GraphicsContext3D::RGBA32UI: + case GraphicsContext3D::RGBA32I: + return 4; + default: + return 0; + } +} + +void WebGLRenderingContextBase::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView& pixels) +{ + if (isContextLostOrPending()) + return; + // Due to WebGL's same-origin restrictions, it is not possible to + // taint the origin using the WebGL API. + ASSERT(canvas().originClean()); + + GC3Denum internalFormat = 0; + if (m_framebufferBinding) { + const char* reason = "framebuffer incomplete"; + if (!m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { + synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "readPixels", reason); + return; + } + // FIXME: readBuffer() should affect this + internalFormat = m_framebufferBinding->getColorBufferFormat(); + } else { + if (m_attributes.alpha) + internalFormat = GraphicsContext3D::RGB8; + else + internalFormat = GraphicsContext3D::RGBA8; + } + + if (!internalFormat) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "Incorrect internal format"); + return; + } + + if (isWebGL1()) { + switch (format) { + case GraphicsContext3D::ALPHA: + case GraphicsContext3D::RGB: + case GraphicsContext3D::RGBA: + break; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "invalid format"); + return; + } + switch (type) { + case GraphicsContext3D::UNSIGNED_BYTE: + case GraphicsContext3D::UNSIGNED_SHORT_5_6_5: + case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4: + case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1: + break; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "invalid type"); + return; + } + if (format != GraphicsContext3D::RGBA || type != GraphicsContext3D::UNSIGNED_BYTE) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "format not RGBA or type not UNSIGNED_BYTE"); + return; + } + } + + InternalFormatTheme internalFormatTheme = WebCore::internalFormatTheme(internalFormat); + int internalFormatComponentCount = numberOfComponentsForInternalFormat(internalFormat); + if (internalFormatTheme == InternalFormatTheme::None || !internalFormatComponentCount) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "Incorrect internal format"); + return; + } + +#define INTERNAL_FORMAT_CHECK(themeMacro, typeMacro, pixelTypeMacro) case InternalFormatTheme::themeMacro: \ + if (type != GraphicsContext3D::typeMacro || pixels.getType() != JSC::pixelTypeMacro) { \ + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "type does not match internal format"); \ + return; \ + } \ + if (format != GraphicsContext3D::RED && format != GraphicsContext3D::RG && format != GraphicsContext3D::RGB && format != GraphicsContext3D::RGBA) { \ + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "Unknown format"); \ + return; \ + } \ + if (numberOfComponentsForFormat(format) < internalFormatComponentCount) { \ + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "Not enough components in format"); \ + return; \ + } \ + break; + +#define INTERNAL_FORMAT_INTEGER_CHECK(themeMacro, typeMacro, pixelTypeMacro) case InternalFormatTheme::themeMacro: \ + if (type != GraphicsContext3D::typeMacro || pixels.getType() != JSC::pixelTypeMacro) { \ + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "type does not match internal format"); \ + return; \ + } \ + if (format != GraphicsContext3D::RED_INTEGER && format != GraphicsContext3D::RG_INTEGER && format != GraphicsContext3D::RGB_INTEGER && format != GraphicsContext3D::RGBA_INTEGER) { \ + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "Unknown format"); \ + return; \ + } \ + if (numberOfComponentsForFormat(format) < internalFormatComponentCount) { \ + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "Not enough components in format"); \ + return; \ + } \ + break; + +#define PACKED_INTERNAL_FORMAT_CHECK(internalFormatMacro, formatMacro, type0Macro, pixelType0Macro, type1Macro, pixelType1Macro) case GraphicsContext3D::internalFormatMacro: \ + if (!(type == GraphicsContext3D::type0Macro && pixels.getType() == JSC::pixelType0Macro) \ + && !(type == GraphicsContext3D::type1Macro && pixels.getType() == JSC::pixelType1Macro)) { \ + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "type does not match internal format"); \ + return; \ + } \ + if (format != GraphicsContext3D::formatMacro) { \ + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "readPixels", "Invalid format"); \ + return; \ + } \ + break; + + switch (internalFormatTheme) { + INTERNAL_FORMAT_CHECK (NormalizedFixedPoint , UNSIGNED_BYTE, TypeUint8 ); + INTERNAL_FORMAT_CHECK (SignedNormalizedFixedPoint, BYTE , TypeInt8 ); + INTERNAL_FORMAT_CHECK (FloatingPoint , FLOAT , TypeFloat32); + INTERNAL_FORMAT_INTEGER_CHECK(SignedInteger , INT , TypeInt32 ); + INTERNAL_FORMAT_INTEGER_CHECK(UnsignedInteger , UNSIGNED_INT , TypeUint32 ); + case InternalFormatTheme::Packed: + switch (internalFormat) { + PACKED_INTERNAL_FORMAT_CHECK(RGB565 , RGB , UNSIGNED_SHORT_5_6_5 , TypeUint16, UNSIGNED_BYTE , TypeUint8 ); + PACKED_INTERNAL_FORMAT_CHECK(RGB5_A1 , RGBA , UNSIGNED_SHORT_5_5_5_1 , TypeUint16, UNSIGNED_BYTE , TypeUint8 ); + PACKED_INTERNAL_FORMAT_CHECK(RGBA4 , RGBA , UNSIGNED_SHORT_4_4_4_4 , TypeUint16, UNSIGNED_BYTE , TypeUint8 ); + PACKED_INTERNAL_FORMAT_CHECK(RGB9_E5 , RGB , UNSIGNED_INT_5_9_9_9_REV , TypeUint32, UNSIGNED_INT_5_9_9_9_REV , TypeUint32 ); + PACKED_INTERNAL_FORMAT_CHECK(RGB10_A2 , RGBA , UNSIGNED_INT_2_10_10_10_REV , TypeUint32, UNSIGNED_INT_2_10_10_10_REV, TypeUint32 ); + PACKED_INTERNAL_FORMAT_CHECK(R11F_G11F_B10F, RGB , UNSIGNED_INT_10F_11F_11F_REV, TypeUint32, FLOAT , TypeFloat32); + PACKED_INTERNAL_FORMAT_CHECK(RGB10_A2UI , RGBA_INTEGER, UNSIGNED_INT_2_10_10_10_REV , TypeUint32, UNSIGNED_INT_2_10_10_10_REV, TypeUint32 ); + } + break; + case InternalFormatTheme::None: + ASSERT_NOT_REACHED(); + } +#undef INTERNAL_FORMAT_CHECK +#undef INTERNAL_FORMAT_INTEGER_CHECK +#undef PACKED_INTERNAL_FORMAT_CHECK + + // Calculate array size, taking into consideration of PACK_ALIGNMENT. + unsigned totalBytesRequired = 0; + unsigned padding = 0; + if (!m_isRobustnessEXTSupported) { + GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding); + if (error != GraphicsContext3D::NO_ERROR) { + synthesizeGLError(error, "readPixels", "invalid dimensions"); + return; + } + if (pixels.byteLength() < totalBytesRequired) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "readPixels", "ArrayBufferView not large enough for dimensions"); + return; + } + } + + clearIfComposited(); + void* data = pixels.baseAddress(); + + if (m_isRobustnessEXTSupported) + m_context->getExtensions().readnPixelsEXT(x, y, width, height, format, type, pixels.byteLength(), data); + else + m_context->readPixels(x, y, width, height, format, type, data); +} + +void WebGLRenderingContextBase::releaseShaderCompiler() +{ + if (isContextLostOrPending()) + return; + m_context->releaseShaderCompiler(); +} + +void WebGLRenderingContextBase::sampleCoverage(GC3Dfloat value, GC3Dboolean invert) +{ + if (isContextLostOrPending()) + return; + m_context->sampleCoverage(value, invert); +} + +void WebGLRenderingContextBase::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) +{ + if (isContextLostOrPending()) + return; + if (!validateSize("scissor", width, height)) + return; + m_context->scissor(x, y, width, height); +} + +void WebGLRenderingContextBase::shaderSource(WebGLShader* shader, const String& string) +{ + if (isContextLostOrPending() || !validateWebGLObject("shaderSource", shader)) + return; + String stringWithoutComments = StripComments(string).result(); + if (!validateString("shaderSource", stringWithoutComments)) + return; + shader->setSource(string); + m_context->shaderSource(objectOrZero(shader), stringWithoutComments); +} + +void WebGLRenderingContextBase::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask) +{ + if (isContextLostOrPending()) + return; + if (!validateStencilFunc("stencilFunc", func)) + return; + m_stencilFuncRef = ref; + m_stencilFuncRefBack = ref; + m_stencilFuncMask = mask; + m_stencilFuncMaskBack = mask; + m_context->stencilFunc(func, ref, mask); +} + +void WebGLRenderingContextBase::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask) +{ + if (isContextLostOrPending()) + return; + if (!validateStencilFunc("stencilFuncSeparate", func)) + return; + switch (face) { + case GraphicsContext3D::FRONT_AND_BACK: + m_stencilFuncRef = ref; + m_stencilFuncRefBack = ref; + m_stencilFuncMask = mask; + m_stencilFuncMaskBack = mask; + break; + case GraphicsContext3D::FRONT: + m_stencilFuncRef = ref; + m_stencilFuncMask = mask; + break; + case GraphicsContext3D::BACK: + m_stencilFuncRefBack = ref; + m_stencilFuncMaskBack = mask; + break; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "stencilFuncSeparate", "invalid face"); + return; + } + m_context->stencilFuncSeparate(face, func, ref, mask); +} + +void WebGLRenderingContextBase::stencilMask(GC3Duint mask) +{ + if (isContextLostOrPending()) + return; + m_stencilMask = mask; + m_stencilMaskBack = mask; + m_context->stencilMask(mask); +} + +void WebGLRenderingContextBase::stencilMaskSeparate(GC3Denum face, GC3Duint mask) +{ + if (isContextLostOrPending()) + return; + switch (face) { + case GraphicsContext3D::FRONT_AND_BACK: + m_stencilMask = mask; + m_stencilMaskBack = mask; + break; + case GraphicsContext3D::FRONT: + m_stencilMask = mask; + break; + case GraphicsContext3D::BACK: + m_stencilMaskBack = mask; + break; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "stencilMaskSeparate", "invalid face"); + return; + } + m_context->stencilMaskSeparate(face, mask); +} + +void WebGLRenderingContextBase::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass) +{ + if (isContextLostOrPending()) + return; + m_context->stencilOp(fail, zfail, zpass); +} + +void WebGLRenderingContextBase::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass) +{ + if (isContextLostOrPending()) + return; + m_context->stencilOpSeparate(face, fail, zfail, zpass); +} + +void WebGLRenderingContextBase::texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels) +{ + // FIXME: For now we ignore any errors returned. + WebGLTexture* tex = validateTextureBinding("texImage2D", target, true); + ASSERT(validateTexFuncParameters("texImage2D", TexImage, target, level, internalFormat, width, height, border, format, type)); + ASSERT(tex); + ASSERT(validateNPOTTextureLevel(width, height, level, "texImage2D")); + if (!pixels) { + if (!m_context->texImage2DResourceSafe(target, level, internalFormat, width, height, border, format, type, m_unpackAlignment)) + return; + } else { + ASSERT(validateSettableTexInternalFormat("texImage2D", internalFormat)); + m_context->moveErrorsToSyntheticErrorList(); + m_context->texImage2D(target, level, internalFormat, width, height, + border, format, type, pixels); + if (m_context->moveErrorsToSyntheticErrorList()) { + // The texImage2D function failed. Tell the WebGLTexture it doesn't have the data for this level. + tex->markInvalid(target, level); + return; + } + } + tex->setLevelInfo(target, level, internalFormat, width, height, type); +} + +void WebGLRenderingContextBase::texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha) +{ + Vector<uint8_t> data; + GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE); + if (!imageExtractor.extractSucceeded()) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data"); + return; + } + GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat(); + GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp(); + const void* imagePixelData = imageExtractor.imagePixelData(); + + bool needConversion = true; + if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY) + needConversion = false; + else { + if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "packImage error"); + return; + } + } + + if (m_unpackAlignment != 1) + m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1); + texImage2DBase(target, level, internalformat, image->width(), image->height(), 0, format, type, needConversion ? data.data() : imagePixelData); + if (m_unpackAlignment != 1) + m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment); +} + +bool WebGLRenderingContextBase::validateTexFunc(const char* functionName, TexFuncValidationFunctionType functionType, TexFuncValidationSourceType sourceType, GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint xoffset, GC3Dint yoffset) +{ + if (!validateTexFuncParameters(functionName, functionType, target, level, internalFormat, width, height, border, format, type)) + return false; + + WebGLTexture* texture = validateTextureBinding(functionName, target, true); + if (!texture) + return false; + + if (functionType != TexSubImage) { + if (functionType == TexImage && texture->immutable()) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "texStorage() called on this texture previously"); + return false; + } + if (!validateNPOTTextureLevel(width, height, level, functionName)) + return false; + // For SourceArrayBufferView, function validateTexFuncData() would handle whether to validate the SettableTexFormat + // by checking if the ArrayBufferView is null or not. + if (sourceType != SourceArrayBufferView) { + if (!validateSettableTexInternalFormat(functionName, internalFormat)) + return false; + } + } else { + if (!validateSettableTexInternalFormat(functionName, internalFormat)) + return false; + if (!validateSize(functionName, xoffset, yoffset)) + return false; + // Before checking if it is in the range, check if overflow happens first. + if (xoffset + width < 0 || yoffset + height < 0) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "bad dimensions"); + return false; + } + if (xoffset + width > texture->getWidth(target, level) || yoffset + height > texture->getHeight(target, level)) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "dimensions out of range"); + return false; + } + if (texture->getInternalFormat(target, level) != internalFormat || (isWebGL1() && texture->getType(target, level) != type)) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type and format do not match texture"); + return false; + } + } + + return true; +} + +void WebGLRenderingContextBase::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&& pixels) +{ + if (isContextLostOrPending() || !validateTexFuncData("texImage2D", level, width, height, internalFormat, format, type, pixels.get(), NullAllowed) + || !validateTexFunc("texImage2D", TexImage, SourceArrayBufferView, target, level, internalFormat, width, height, border, format, type, 0, 0)) + return; + void* data = pixels ? pixels->baseAddress() : 0; + Vector<uint8_t> tempData; + bool changeUnpackAlignment = false; + if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) { + if (!m_context->extractTextureData(width, height, format, type, + m_unpackAlignment, + m_unpackFlipY, m_unpackPremultiplyAlpha, + data, + tempData)) + return; + data = tempData.data(); + changeUnpackAlignment = true; + } + if (changeUnpackAlignment) + m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1); + texImage2DBase(target, level, internalFormat, width, height, border, format, type, data); + if (changeUnpackAlignment) + m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment); +} + +void WebGLRenderingContextBase::texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha) +{ + Vector<uint8_t> data; + GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE); + if (!imageExtractor.extractSucceeded()) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image"); + return; + } + GraphicsContext3D::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat(); + GraphicsContext3D::AlphaOp alphaOp = imageExtractor.imageAlphaOp(); + const void* imagePixelData = imageExtractor.imagePixelData(); + + bool needConversion = true; + if (type == GraphicsContext3D::UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GraphicsContext3D::RGBA && alphaOp == GraphicsContext3D::AlphaDoNothing && !flipY) + needConversion = false; + else { + if (!m_context->packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data"); + return; + } + } + + if (m_unpackAlignment != 1) + m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1); + + texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(), format, format, type, needConversion ? data.data() : imagePixelData); + + if (m_unpackAlignment != 1) + m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment); +} + +void WebGLRenderingContextBase::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&& pixels) +{ + if (isContextLostOrPending()) + return; + + WebGLTexture* texture = validateTextureBinding("texSubImage2D", target, true); + if (!texture) + return; + + GC3Denum internalFormat = texture->getInternalFormat(target, level); + if (!internalFormat) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "invalid texture target or level"); + return; + } + + if (!validateTexFuncData("texSubImage2D", level, width, height, internalFormat, format, type, pixels.get(), NullNotAllowed)) + return; + + if (!validateTexFunc("texSubImage2D", TexSubImage, SourceArrayBufferView, target, level, internalFormat, width, height, 0, format, type, xoffset, yoffset)) + return; + + void* data = pixels->baseAddress(); + Vector<uint8_t> tempData; + bool changeUnpackAlignment = false; + if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) { + if (!m_context->extractTextureData(width, height, format, type, m_unpackAlignment, m_unpackFlipY, m_unpackPremultiplyAlpha, data, tempData)) + return; + data = tempData.data(); + changeUnpackAlignment = true; + } + if (changeUnpackAlignment) + m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1); + + texSubImage2DBase(target, level, xoffset, yoffset, width, height, internalFormat, format, type, data); + + if (changeUnpackAlignment) + m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment); +} + +ExceptionOr<void> WebGLRenderingContextBase::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, std::optional<TexImageSource>&& source) +{ + if (!source) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "source is null"); + return { }; + } + + if (isContextLostOrPending()) + return { }; + + auto visitor = WTF::makeVisitor([&](const RefPtr<ImageData>& pixels) -> ExceptionOr<void> { + WebGLTexture* texture = validateTextureBinding("texSubImage2D", target, true); + if (!texture) + return { }; + + GC3Denum internalFormat = texture->getInternalFormat(target, level); + if (!internalFormat) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "invalid texture target or level"); + return { }; + } + + if (!validateTexFunc("texSubImage2D", TexSubImage, SourceImageData, target, level, internalFormat, pixels->width(), pixels->height(), 0, format, type, xoffset, yoffset)) + return { }; + + Vector<uint8_t> data; + bool needConversion = true; + // The data from ImageData is always of format RGBA8. + // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required. + if (format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha) + needConversion = false; + else { + if (!m_context->extractImageData(pixels.get(), format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "bad image data"); + return { }; + } + } + if (m_unpackAlignment != 1) + m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1); + + texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(), format, format, type, needConversion ? data.data() : pixels->data()->data()); + + if (m_unpackAlignment != 1) + m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment); + + return { }; + } , [&](const RefPtr<HTMLImageElement>& image) -> ExceptionOr<void> { + ExceptionCode ec = 0; + if (isContextLostOrPending() || !validateHTMLImageElement("texSubImage2D", image.get(), ec)) + return ec ? Exception { ec } : ExceptionOr<void> { }; + + RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer()); + if (!imageForRender) + return { }; + + if (imageForRender->isSVGImage()) + imageForRender = drawImageIntoBuffer(*imageForRender, image->width(), image->height(), 1); + + WebGLTexture* texture = validateTextureBinding("texSubImage2D", target, true); + if (!texture) + return { }; + + GC3Denum internalFormat = texture->getInternalFormat(target, level); + if (!internalFormat) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "invalid texture target or level"); + return { }; + } + + if (!imageForRender || !validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLImageElement, target, level, internalFormat, imageForRender->width(), imageForRender->height(), 0, format, type, xoffset, yoffset)) + return { }; + + texSubImage2DImpl(target, level, xoffset, yoffset, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha); + return { }; + }, [&](const RefPtr<HTMLCanvasElement>& canvas) -> ExceptionOr<void> { + ExceptionCode ec = 0; + if (isContextLostOrPending() || !validateHTMLCanvasElement("texSubImage2D", canvas.get(), ec)) + return ec ? Exception { ec } : ExceptionOr<void> { }; + + WebGLTexture* texture = validateTextureBinding("texSubImage2D", target, true); + if (!texture) + return { }; + + GC3Denum internalFormat = texture->getInternalFormat(target, level); + if (!internalFormat) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "invalid texture target or level"); + return { }; + } + + if (!validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLCanvasElement, target, level, internalFormat, canvas->width(), canvas->height(), 0, format, type, xoffset, yoffset)) + return { }; + + RefPtr<ImageData> imageData = canvas->getImageData(); + if (imageData) + texSubImage2D(target, level, xoffset, yoffset, format, type, TexImageSource(imageData.get())); + else + texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha); + return { }; + }, [&](const RefPtr<HTMLVideoElement>& video) -> ExceptionOr<void> { + ExceptionCode ec = 0; + if (isContextLostOrPending() || !validateHTMLVideoElement("texSubImage2D", video.get(), ec)) + return ec ? Exception { ec } : ExceptionOr<void> { }; + + WebGLTexture* texture = validateTextureBinding("texSubImage2D", target, true); + if (!texture) + return { }; + + GC3Denum internalFormat = texture->getInternalFormat(target, level); + if (!internalFormat) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texSubImage2D", "invalid texture target or level"); + return { }; + } + + if (!validateTexFunc("texSubImage2D", TexSubImage, SourceHTMLVideoElement, target, level, internalFormat, video->videoWidth(), video->videoHeight(), 0, format, type, xoffset, yoffset)) + return { }; + + RefPtr<Image> image = videoFrameToImage(video.get(), ImageBuffer::fastCopyImageMode()); + if (!image) + return { }; + texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha); + return { }; + }); + + return WTF::visit(visitor, source.value()); +} + +bool WebGLRenderingContextBase::validateArrayBufferType(const char* functionName, GC3Denum type, std::optional<JSC::TypedArrayType> arrayType) +{ +#define TYPE_VALIDATION_CASE(arrayTypeMacro) if (arrayType && arrayType.value() != JSC::arrayTypeMacro) { \ + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not " #arrayTypeMacro); \ + return false; \ + } \ + break; + + switch (type) { + case GraphicsContext3D::UNSIGNED_BYTE: + TYPE_VALIDATION_CASE(TypeUint8); + case GraphicsContext3D::BYTE: + TYPE_VALIDATION_CASE(TypeInt8); + case GraphicsContext3D::UNSIGNED_SHORT: + case GraphicsContext3D::UNSIGNED_SHORT_5_6_5: + case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4: + case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1: + TYPE_VALIDATION_CASE(TypeUint16); + case GraphicsContext3D::SHORT: + TYPE_VALIDATION_CASE(TypeInt16); + case GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV: + case GraphicsContext3D::UNSIGNED_INT_10F_11F_11F_REV: + case GraphicsContext3D::UNSIGNED_INT_5_9_9_9_REV: + case GraphicsContext3D::UNSIGNED_INT_24_8: + case GraphicsContext3D::UNSIGNED_INT: + TYPE_VALIDATION_CASE(TypeUint32); + case GraphicsContext3D::INT: + TYPE_VALIDATION_CASE(TypeInt32); + case GraphicsContext3D::FLOAT: // OES_texture_float + TYPE_VALIDATION_CASE(TypeFloat32); + case GraphicsContext3D::HALF_FLOAT_OES: // OES_texture_half_float + case GraphicsContext3D::HALF_FLOAT: + case GraphicsContext3D::FLOAT_32_UNSIGNED_INT_24_8_REV: + // As per the specification, ArrayBufferView should be null when + // OES_texture_half_float is enabled. + if (arrayType) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "type HALF_FLOAT_OES but ArrayBufferView is not NULL"); + return false; + } + break; + default: + ASSERT_NOT_REACHED(); + return false; + } +#undef TYPE_VALIDATION_CASE + return true; +} + +bool WebGLRenderingContextBase::validateTexFuncData(const char* functionName, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum internalFormat, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, NullDisposition disposition) +{ + if (!pixels) { + if (disposition == NullAllowed) + return true; + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no pixels"); + return false; + } + + if (!validateTexFuncFormatAndType(functionName, internalFormat, format, type, level)) + return false; + if (!validateSettableTexInternalFormat(functionName, internalFormat)) + return false; + if (!validateArrayBufferType(functionName, type, pixels ? std::optional<JSC::TypedArrayType>(pixels->getType()) : std::nullopt)) + return false; + + unsigned totalBytesRequired; + GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, nullptr); + if (error != GraphicsContext3D::NO_ERROR) { + synthesizeGLError(error, functionName, "invalid texture dimensions"); + return false; + } + if (pixels->byteLength() < totalBytesRequired) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request"); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateTexFuncParameters(const char* functionName, + TexFuncValidationFunctionType functionType, + GC3Denum target, GC3Dint level, + GC3Denum internalformat, + GC3Dsizei width, GC3Dsizei height, GC3Dint border, + GC3Denum format, GC3Denum type) +{ + // We absolutely have to validate the format and type combination. + // The texImage2D entry points taking HTMLImage, etc. will produce + // temporary data based on this combination, so it must be legal. + if (!validateTexFuncFormatAndType(functionName, internalformat, format, type, level) || !validateTexFuncLevel(functionName, target, level)) + return false; + + if (width < 0 || height < 0) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0"); + return false; + } + + GC3Dint maxTextureSizeForLevel = pow(2.0, m_maxTextureLevel - 1 - level); + switch (target) { + case GraphicsContext3D::TEXTURE_2D: + if (width > maxTextureSizeForLevel || height > maxTextureSizeForLevel) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range"); + return false; + } + break; + case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X: + case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X: + case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y: + case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z: + case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z: + if (functionType != TexSubImage && width != height) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width != height for cube map"); + return false; + } + // No need to check height here. For texImage width == height. + // For texSubImage that will be checked when checking yoffset + height is in range. + if (width > maxTextureSizeForLevel) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height out of range for cube map"); + return false; + } + break; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target"); + return false; + } + + if (border) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "border != 0"); + return false; + } + + return true; +} + +bool WebGLRenderingContextBase::validateTexFuncFormatAndType(const char* functionName, GC3Denum internalFormat, GC3Denum format, GC3Denum type, GC3Dint level) +{ + switch (format) { + case GraphicsContext3D::ALPHA: + case GraphicsContext3D::LUMINANCE: + case GraphicsContext3D::LUMINANCE_ALPHA: + case GraphicsContext3D::RGB: + case GraphicsContext3D::RGBA: + break; + case GraphicsContext3D::DEPTH_STENCIL: + case GraphicsContext3D::DEPTH_COMPONENT: + if (!m_webglDepthTexture && isWebGL1()) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "depth texture formats not enabled"); + return false; + } + if (level > 0) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "level must be 0 for depth formats"); + return false; + } + break; + case Extensions3D::SRGB_EXT: + case Extensions3D::SRGB_ALPHA_EXT: + if (!m_extsRGB) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "sRGB texture formats not enabled"); + return false; + } + break; + default: +#if ENABLE(WEBGL2) + if (!isWebGL1()) { + switch (format) { + case GraphicsContext3D::RED: + case GraphicsContext3D::RED_INTEGER: + case GraphicsContext3D::RG: + case GraphicsContext3D::RG_INTEGER: + case GraphicsContext3D::RGB_INTEGER: + case GraphicsContext3D::RGBA_INTEGER: + break; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture format"); + return false; + } + } else +#endif + { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture format"); + return false; + } + } + + switch (type) { + case GraphicsContext3D::UNSIGNED_BYTE: + case GraphicsContext3D::UNSIGNED_SHORT_5_6_5: + case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4: + case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1: + break; + case GraphicsContext3D::FLOAT: + if (!m_oesTextureFloat && isWebGL1()) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type"); + return false; + } + break; + case GraphicsContext3D::HALF_FLOAT: + case GraphicsContext3D::HALF_FLOAT_OES: + if (!m_oesTextureHalfFloat && isWebGL1()) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type"); + return false; + } + break; + case GraphicsContext3D::UNSIGNED_INT: + case GraphicsContext3D::UNSIGNED_INT_24_8: + case GraphicsContext3D::UNSIGNED_SHORT: + if (!m_webglDepthTexture && isWebGL1()) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type"); + return false; + } + break; + default: +#if ENABLE(WEBGL2) + if (!isWebGL1()) { + switch (type) { + case GraphicsContext3D::BYTE: + case GraphicsContext3D::SHORT: + case GraphicsContext3D::INT: + case GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV: + case GraphicsContext3D::UNSIGNED_INT_10F_11F_11F_REV: + case GraphicsContext3D::UNSIGNED_INT_5_9_9_9_REV: + case GraphicsContext3D::FLOAT_32_UNSIGNED_INT_24_8_REV: + break; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type"); + return false; + } + } else +#endif + { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture type"); + return false; + } + } + + // Verify that the combination of internalformat, format, and type is supported. +#define INTERNAL_FORMAT_CASE(internalFormatMacro, formatMacro, type0, type1, type2, type3, type4) case GraphicsContext3D::internalFormatMacro: \ + if (format != GraphicsContext3D::formatMacro) { \ + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid format for internalformat"); \ + return false; \ + } \ + if (type != type0 && type != type1 && type != type2 && type != type3 && type != type4) { \ + if (type != GraphicsContext3D::HALF_FLOAT_OES || (type0 != GraphicsContext3D::HALF_FLOAT && type1 != GraphicsContext3D::HALF_FLOAT && type2 != GraphicsContext3D::HALF_FLOAT && type3 != GraphicsContext3D::HALF_FLOAT)) { \ + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for internalformat"); \ + return false; \ + } \ + } \ + break; + switch (internalFormat) { + INTERNAL_FORMAT_CASE(RGB , RGB , GraphicsContext3D::UNSIGNED_BYTE , GraphicsContext3D::UNSIGNED_SHORT_5_6_5 , GraphicsContext3D::HALF_FLOAT , GraphicsContext3D::FLOAT , 0 ); + INTERNAL_FORMAT_CASE(RGBA , RGBA , GraphicsContext3D::UNSIGNED_BYTE , GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4, GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1 , GraphicsContext3D::HALF_FLOAT, GraphicsContext3D::FLOAT); + INTERNAL_FORMAT_CASE(LUMINANCE_ALPHA , LUMINANCE_ALPHA, GraphicsContext3D::UNSIGNED_BYTE , GraphicsContext3D::HALF_FLOAT , GraphicsContext3D::FLOAT , 0 , 0 ); + INTERNAL_FORMAT_CASE(LUMINANCE , LUMINANCE , GraphicsContext3D::UNSIGNED_BYTE , GraphicsContext3D::HALF_FLOAT , GraphicsContext3D::FLOAT , 0 , 0 ); + INTERNAL_FORMAT_CASE(ALPHA , ALPHA , GraphicsContext3D::UNSIGNED_BYTE , GraphicsContext3D::HALF_FLOAT , GraphicsContext3D::FLOAT , 0 , 0 ); + INTERNAL_FORMAT_CASE(R8 , RED , GraphicsContext3D::UNSIGNED_BYTE , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(R8_SNORM , RED , GraphicsContext3D::BYTE , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(R16F , RED , GraphicsContext3D::HALF_FLOAT , GraphicsContext3D::FLOAT , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(R32F , RED , GraphicsContext3D::FLOAT , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(R8UI , RED_INTEGER , GraphicsContext3D::UNSIGNED_BYTE , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(R8I , RED_INTEGER , GraphicsContext3D::BYTE , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(R16UI , RED_INTEGER , GraphicsContext3D::UNSIGNED_SHORT , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(R16I , RED_INTEGER , GraphicsContext3D::SHORT , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(R32UI , RED_INTEGER , GraphicsContext3D::UNSIGNED_INT , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(R32I , RED_INTEGER , GraphicsContext3D::INT , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RG8 , RG , GraphicsContext3D::UNSIGNED_BYTE , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RG8_SNORM , RG , GraphicsContext3D::BYTE , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RG16F , RG , GraphicsContext3D::HALF_FLOAT , GraphicsContext3D::FLOAT , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RG32F , RG , GraphicsContext3D::FLOAT , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RG8UI , RG_INTEGER , GraphicsContext3D::UNSIGNED_BYTE , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RG8I , RG_INTEGER , GraphicsContext3D::BYTE , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RG16UI , RG_INTEGER , GraphicsContext3D::UNSIGNED_SHORT , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RG16I , RG_INTEGER , GraphicsContext3D::SHORT , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RG32UI , RG_INTEGER , GraphicsContext3D::UNSIGNED_INT , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RG32I , RG_INTEGER , GraphicsContext3D::INT , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGB8 , RGB , GraphicsContext3D::UNSIGNED_BYTE , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(SRGB8 , RGB , GraphicsContext3D::UNSIGNED_BYTE , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGB565 , RGB , GraphicsContext3D::UNSIGNED_BYTE , GraphicsContext3D::UNSIGNED_SHORT_5_6_5 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGB8_SNORM , RGB , GraphicsContext3D::BYTE , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(R11F_G11F_B10F , RGB , GraphicsContext3D::UNSIGNED_INT_10F_11F_11F_REV , GraphicsContext3D::HALF_FLOAT , GraphicsContext3D::FLOAT , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGB9_E5 , RGB , GraphicsContext3D::UNSIGNED_INT_5_9_9_9_REV , GraphicsContext3D::HALF_FLOAT , GraphicsContext3D::FLOAT , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGB16F , RGB , GraphicsContext3D::HALF_FLOAT , GraphicsContext3D::FLOAT , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGB32F , RGB , GraphicsContext3D::FLOAT , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGB8UI , RGB_INTEGER , GraphicsContext3D::UNSIGNED_BYTE , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGB8I , RGB_INTEGER , GraphicsContext3D::BYTE , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGB16UI , RGB_INTEGER , GraphicsContext3D::UNSIGNED_SHORT , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGB16I , RGB_INTEGER , GraphicsContext3D::SHORT , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGB32UI , RGB_INTEGER , GraphicsContext3D::UNSIGNED_INT , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGB32I , RGB_INTEGER , GraphicsContext3D::INT , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGBA8 , RGBA , GraphicsContext3D::UNSIGNED_BYTE , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(SRGB8_ALPHA8 , RGBA , GraphicsContext3D::UNSIGNED_BYTE , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGBA8_SNORM , RGBA , GraphicsContext3D::BYTE , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGB5_A1 , RGBA , GraphicsContext3D::UNSIGNED_BYTE , GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1, GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGBA4 , RGBA , GraphicsContext3D::UNSIGNED_BYTE , GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4, 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGB10_A2 , RGBA , GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGBA16F , RGBA , GraphicsContext3D::HALF_FLOAT , GraphicsContext3D::FLOAT , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGBA32F , RGBA , GraphicsContext3D::FLOAT , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGBA8UI , RGBA_INTEGER , GraphicsContext3D::UNSIGNED_BYTE , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGBA8I , RGBA_INTEGER , GraphicsContext3D::BYTE , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGB10_A2UI , RGBA_INTEGER , GraphicsContext3D::UNSIGNED_INT_2_10_10_10_REV , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGBA16UI , RGBA_INTEGER , GraphicsContext3D::UNSIGNED_SHORT , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGBA16I , RGBA_INTEGER , GraphicsContext3D::SHORT , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGBA32I , RGBA_INTEGER , GraphicsContext3D::INT , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(RGBA32UI , RGBA_INTEGER , GraphicsContext3D::UNSIGNED_INT , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(DEPTH_COMPONENT , DEPTH_COMPONENT, GraphicsContext3D::UNSIGNED_SHORT , GraphicsContext3D::UNSIGNED_INT , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(DEPTH_COMPONENT16 , DEPTH_COMPONENT, GraphicsContext3D::UNSIGNED_SHORT , GraphicsContext3D::UNSIGNED_INT , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(DEPTH_COMPONENT24 , DEPTH_COMPONENT, GraphicsContext3D::UNSIGNED_INT , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(DEPTH_COMPONENT32F, DEPTH_COMPONENT, GraphicsContext3D::FLOAT , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(DEPTH_STENCIL , DEPTH_STENCIL , GraphicsContext3D::UNSIGNED_INT_24_8 , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(DEPTH24_STENCIL8 , DEPTH_STENCIL , GraphicsContext3D::UNSIGNED_INT_24_8 , 0 , 0 , 0 , 0 ); + INTERNAL_FORMAT_CASE(DEPTH32F_STENCIL8 , DEPTH_STENCIL , GraphicsContext3D::FLOAT_32_UNSIGNED_INT_24_8_REV, 0 , 0 , 0 , 0 ); + case Extensions3D::SRGB_EXT: + if (format != internalFormat) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format and internalformat must match"); + return false; + } + if (type != GraphicsContext3D::UNSIGNED_BYTE && type != GraphicsContext3D::UNSIGNED_SHORT_5_6_5 && type != GraphicsContext3D::FLOAT && type != GraphicsContext3D::HALF_FLOAT_OES && type != GraphicsContext3D::HALF_FLOAT) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for internal format"); + return false; + } + break; + case Extensions3D::SRGB_ALPHA_EXT: + if (format != internalFormat) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "format and internalformat must match"); + return false; + } + if (type != GraphicsContext3D::UNSIGNED_BYTE && type != GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4 && type != GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1 && type != GraphicsContext3D::FLOAT && type != GraphicsContext3D::HALF_FLOAT_OES && type != GraphicsContext3D::HALF_FLOAT) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "invalid type for internal format"); + return false; + } + break; + default: + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "Unknown internal format"); + return false; + } +#undef INTERNAL_FORMAT_CASE + + return true; +} + +void WebGLRenderingContextBase::texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum internalFormat, GC3Denum format, GC3Denum type, const void* pixels) +{ + ASSERT(!isContextLost()); + ASSERT(validateTexFuncParameters("texSubImage2D", TexSubImage, target, level, internalFormat, width, height, 0, format, type)); + ASSERT(validateSize("texSubImage2D", xoffset, yoffset)); + ASSERT(validateSettableTexInternalFormat("texSubImage2D", internalFormat)); + WebGLTexture* tex = validateTextureBinding("texSubImage2D", target, true); + if (!tex) { + ASSERT_NOT_REACHED(); + return; + } + ASSERT((xoffset + width) >= 0); + ASSERT((yoffset + height) >= 0); + ASSERT(tex->getWidth(target, level) >= (xoffset + width)); + ASSERT(tex->getHeight(target, level) >= (yoffset + height)); + ASSERT_UNUSED(internalFormat, tex->getInternalFormat(target, level) == internalFormat); + m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); +} + +void WebGLRenderingContextBase::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) +{ + if (isContextLostOrPending()) + return; + if (!validateTexFuncParameters("copyTexImage2D", CopyTexImage, target, level, internalFormat, width, height, border, internalFormat, GraphicsContext3D::UNSIGNED_BYTE)) + return; + if (!validateSettableTexInternalFormat("copyTexImage2D", internalFormat)) + return; + WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true); + if (!tex) + return; + if (!isTexInternalFormatColorBufferCombinationValid(internalFormat, getBoundFramebufferColorFormat())) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyTexImage2D", "framebuffer is incompatible format"); + return; + } + if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyTexImage2D", "level > 0 not power of 2"); + return; + } + const char* reason = "framebuffer incomplete"; + if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { + synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason); + return; + } + clearIfComposited(); + + GC3Dint clippedX, clippedY; + GC3Dsizei clippedWidth, clippedHeight; + if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) { + m_context->texImage2DResourceSafe(target, level, internalFormat, width, height, border, + internalFormat, GraphicsContext3D::UNSIGNED_BYTE, m_unpackAlignment); + if (clippedWidth > 0 && clippedHeight > 0) { + m_context->copyTexSubImage2D(target, level, clippedX - x, clippedY - y, + clippedX, clippedY, clippedWidth, clippedHeight); + } + } else + m_context->copyTexImage2D(target, level, internalFormat, x, y, width, height, border); + + // FIXME: if the framebuffer is not complete, none of the below should be executed. + tex->setLevelInfo(target, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE); +} + +static bool isRGBFormat(GC3Denum internalFormat) +{ + return internalFormat == GraphicsContext3D::RGB + || internalFormat == GraphicsContext3D::RGBA + || internalFormat == GraphicsContext3D::RGB8 + || internalFormat == GraphicsContext3D::RGBA8; +} + +ExceptionOr<void> WebGLRenderingContextBase::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, std::optional<TexImageSource> source) +{ + if (!source) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "source is null"); + return { }; + } + + auto visitor = WTF::makeVisitor([&](const RefPtr<ImageData>& pixels) -> ExceptionOr<void> { + if (isContextLostOrPending() || !validateTexFunc("texImage2D", TexImage, SourceImageData, target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, 0, 0)) + return { }; + Vector<uint8_t> data; + bool needConversion = true; + // The data from ImageData is always of format RGBA8. + // No conversion is needed if destination format is RGBA and type is USIGNED_BYTE and no Flip or Premultiply operation is required. + if (!m_unpackFlipY && !m_unpackPremultiplyAlpha && format == GraphicsContext3D::RGBA && type == GraphicsContext3D::UNSIGNED_BYTE) + needConversion = false; + else { + if (!m_context->extractImageData(pixels.get(), format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "texImage2D", "bad image data"); + return { }; + } + } + if (m_unpackAlignment != 1) + m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1); + texImage2DBase(target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, needConversion ? data.data() : pixels->data()->data()); + if (m_unpackAlignment != 1) + m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment); + return { }; + }, [&](const RefPtr<HTMLImageElement>& image) -> ExceptionOr<void> { + ExceptionCode ec = 0; + if (isContextLostOrPending() || !validateHTMLImageElement("texImage2D", image.get(), ec)) + return ec ? Exception { ec } : ExceptionOr<void> { }; + + RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer()); + if (!imageForRender) + return { }; + + if (imageForRender->isSVGImage()) + imageForRender = drawImageIntoBuffer(*imageForRender, image->width(), image->height(), 1); + + if (!imageForRender || !validateTexFunc("texImage2D", TexImage, SourceHTMLImageElement, target, level, internalformat, imageForRender->width(), imageForRender->height(), 0, format, type, 0, 0)) + return { }; + + texImage2DImpl(target, level, internalformat, format, type, imageForRender.get(), GraphicsContext3D::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha); + return { }; + }, [&](const RefPtr<HTMLCanvasElement>& canvas) -> ExceptionOr<void> { + ExceptionCode ec = 0; + if (isContextLostOrPending() || !validateHTMLCanvasElement("texImage2D", canvas.get(), ec) || !validateTexFunc("texImage2D", TexImage, SourceHTMLCanvasElement, target, level, internalformat, canvas->width(), canvas->height(), 0, format, type, 0, 0)) + return ec ? Exception { ec } : ExceptionOr<void> { }; + + WebGLTexture* texture = validateTextureBinding("texImage2D", target, true); + // If possible, copy from the canvas element directly to the texture + // via the GPU, without a read-back to system memory. + // + // FIXME: restriction of (RGB || RGBA)/UNSIGNED_BYTE should be lifted when + // ImageBuffer::copyToPlatformTexture implementations are fully functional. + if (texture + && (format == GraphicsContext3D::RGB || format == GraphicsContext3D::RGBA) + && type == GraphicsContext3D::UNSIGNED_BYTE) { + auto textureInternalFormat = texture->getInternalFormat(target, level); + if (isRGBFormat(textureInternalFormat) || !texture->isValid(target, level)) { + ImageBuffer* buffer = canvas->buffer(); + if (buffer && buffer->copyToPlatformTexture(*m_context.get(), target, texture->object(), internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) { + texture->setLevelInfo(target, level, internalformat, canvas->width(), canvas->height(), type); + return { }; + } + } + } + + RefPtr<ImageData> imageData = canvas->getImageData(); + if (imageData) + texImage2D(target, level, internalformat, format, type, TexImageSource(imageData.get())); + else + texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha); + return { }; + }, [&](const RefPtr<HTMLVideoElement>& video) -> ExceptionOr<void> { + ExceptionCode ec = 0; + if (isContextLostOrPending() || !validateHTMLVideoElement("texImage2D", video.get(), ec) + || !validateTexFunc("texImage2D", TexImage, SourceHTMLVideoElement, target, level, internalformat, video->videoWidth(), video->videoHeight(), 0, format, type, 0, 0)) + return ec ? Exception { ec } : ExceptionOr<void> { }; + + // Go through the fast path doing a GPU-GPU textures copy without a readback to system memory if possible. + // Otherwise, it will fall back to the normal SW path. + // FIXME: The current restrictions require that format shoud be RGB or RGBA, + // type should be UNSIGNED_BYTE and level should be 0. It may be lifted in the future. + WebGLTexture* texture = validateTextureBinding("texImage2D", target, true); + if (GraphicsContext3D::TEXTURE_2D == target && texture + && (format == GraphicsContext3D::RGB || format == GraphicsContext3D::RGBA) + && type == GraphicsContext3D::UNSIGNED_BYTE + && !level) { + auto textureInternalFormat = texture->getInternalFormat(target, level); + if (isRGBFormat(textureInternalFormat) || !texture->isValid(target, level)) { + if (video->copyVideoTextureToPlatformTexture(m_context.get(), texture->object(), target, level, internalformat, format, type, m_unpackPremultiplyAlpha, m_unpackFlipY)) { + texture->setLevelInfo(target, level, internalformat, video->videoWidth(), video->videoHeight(), type); + return { }; + } + } + } + + // Normal pure SW path. + RefPtr<Image> image = videoFrameToImage(video.get(), ImageBuffer::fastCopyImageMode()); + if (!image) + return { }; + texImage2DImpl(target, level, internalformat, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha); + return { }; + }); + + return WTF::visit(visitor, source.value()); +} + +RefPtr<Image> WebGLRenderingContextBase::drawImageIntoBuffer(Image& image, int width, int height, int deviceScaleFactor) +{ + IntSize size(width, height); + size.scale(deviceScaleFactor); + ImageBuffer* buf = m_generatedImageCache.imageBuffer(size); + if (!buf) { + synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY, "texImage2D", "out of memory"); + return nullptr; + } + + FloatRect srcRect(FloatPoint(), image.size()); + FloatRect destRect(FloatPoint(), size); + buf->context().drawImage(image, destRect, srcRect); + return buf->copyImage(ImageBuffer::fastCopyImageMode()); +} + +#if ENABLE(VIDEO) + +RefPtr<Image> WebGLRenderingContextBase::videoFrameToImage(HTMLVideoElement* video, BackingStoreCopy backingStoreCopy) +{ + IntSize size(video->videoWidth(), video->videoHeight()); + ImageBuffer* buf = m_generatedImageCache.imageBuffer(size); + if (!buf) { + synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY, "texImage2D", "out of memory"); + return nullptr; + } + FloatRect destRect(0, 0, size.width(), size.height()); + // FIXME: Turn this into a GPU-GPU texture copy instead of CPU readback. + video->paintCurrentFrameInContext(buf->context(), destRect); + return buf->copyImage(backingStoreCopy); +} + +#endif + +void WebGLRenderingContextBase::texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat paramf, GC3Dint parami, bool isFloat) +{ + if (isContextLostOrPending()) + return; + WebGLTexture* tex = validateTextureBinding("texParameter", target, false); + if (!tex) + return; + switch (pname) { + case GraphicsContext3D::TEXTURE_MIN_FILTER: + case GraphicsContext3D::TEXTURE_MAG_FILTER: + break; + case GraphicsContext3D::TEXTURE_WRAP_S: + case GraphicsContext3D::TEXTURE_WRAP_T: + if ((isFloat && paramf != GraphicsContext3D::CLAMP_TO_EDGE && paramf != GraphicsContext3D::MIRRORED_REPEAT && paramf != GraphicsContext3D::REPEAT) + || (!isFloat && parami != GraphicsContext3D::CLAMP_TO_EDGE && parami != GraphicsContext3D::MIRRORED_REPEAT && parami != GraphicsContext3D::REPEAT)) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter"); + return; + } + break; + case Extensions3D::TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic + if (!m_extTextureFilterAnisotropic) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter, EXT_texture_filter_anisotropic not enabled"); + return; + } + break; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texParameter", "invalid parameter name"); + return; + } + if (isFloat) { + tex->setParameterf(pname, paramf); + m_context->texParameterf(target, pname, paramf); + } else { + tex->setParameteri(pname, parami); + m_context->texParameteri(target, pname, parami); + } +} + +void WebGLRenderingContextBase::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param) +{ + texParameter(target, pname, param, 0, true); +} + +void WebGLRenderingContextBase::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param) +{ + texParameter(target, pname, 0, param, false); +} + +void WebGLRenderingContextBase::uniform1f(const WebGLUniformLocation* location, GC3Dfloat x) +{ + if (isContextLostOrPending() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform1f", "location not for current program"); + return; + } + + m_context->uniform1f(location->location(), x); +} + +void WebGLRenderingContextBase::uniform2f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y) +{ + if (isContextLostOrPending() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform2f", "location not for current program"); + return; + } + + m_context->uniform2f(location->location(), x, y); +} + +void WebGLRenderingContextBase::uniform3f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z) +{ + if (isContextLostOrPending() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform3f", "location not for current program"); + return; + } + + m_context->uniform3f(location->location(), x, y, z); +} + +void WebGLRenderingContextBase::uniform4f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w) +{ + if (isContextLostOrPending() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform4f", "location not for current program"); + return; + } + + m_context->uniform4f(location->location(), x, y, z, w); +} + +void WebGLRenderingContextBase::uniform1i(const WebGLUniformLocation* location, GC3Dint x) +{ + if (isContextLostOrPending() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform1i", "location not for current program"); + return; + } + + if ((location->type() == GraphicsContext3D::SAMPLER_2D || location->type() == GraphicsContext3D::SAMPLER_CUBE) && x >= (int)m_textureUnits.size()) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "uniform1i", "invalid texture unit"); + return; + } + + m_context->uniform1i(location->location(), x); +} + +void WebGLRenderingContextBase::uniform2i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y) +{ + if (isContextLostOrPending() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform2i", "location not for current program"); + return; + } + + m_context->uniform2i(location->location(), x, y); +} + +void WebGLRenderingContextBase::uniform3i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z) +{ + if (isContextLostOrPending() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform3i", "location not for current program"); + return; + } + + m_context->uniform3i(location->location(), x, y, z); +} + +void WebGLRenderingContextBase::uniform4i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w) +{ + if (isContextLostOrPending() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "uniform4i", "location not for current program"); + return; + } + + m_context->uniform4i(location->location(), x, y, z, w); +} + +void WebGLRenderingContextBase::uniform1fv(const WebGLUniformLocation* location, Float32List&& v) +{ + if (isContextLostOrPending() || !validateUniformParameters("uniform1fv", location, v, 1)) + return; + + m_context->uniform1fv(location->location(), v.length(), v.data()); +} + +void WebGLRenderingContextBase::uniform2fv(const WebGLUniformLocation* location, Float32List&& v) +{ + if (isContextLostOrPending() || !validateUniformParameters("uniform2fv", location, v, 2)) + return; + + m_context->uniform2fv(location->location(), v.length() / 2, v.data()); +} + +void WebGLRenderingContextBase::uniform3fv(const WebGLUniformLocation* location, Float32List&& v) +{ + if (isContextLostOrPending() || !validateUniformParameters("uniform3fv", location, v, 3)) + return; + + m_context->uniform3fv(location->location(), v.length() / 3, v.data()); +} + +void WebGLRenderingContextBase::uniform4fv(const WebGLUniformLocation* location, Float32List&& v) +{ + if (isContextLostOrPending() || !validateUniformParameters("uniform4fv", location, v, 4)) + return; + + m_context->uniform4fv(location->location(), v.length() / 4, v.data()); +} + +void WebGLRenderingContextBase::uniform1iv(const WebGLUniformLocation* location, Int32List&& v) +{ + if (isContextLostOrPending() || !validateUniformParameters("uniform1iv", location, v, 1)) + return; + + auto data = v.data(); + auto length = v.length(); + + if (location->type() == GraphicsContext3D::SAMPLER_2D || location->type() == GraphicsContext3D::SAMPLER_CUBE) { + for (auto i = 0; i < length; ++i) { + if (data[i] >= static_cast<int>(m_textureUnits.size())) { + LOG(WebGL, "Texture unit size=%zu, v[%d]=%d. Location type = %04X.", m_textureUnits.size(), i, data[i], location->type()); + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "uniform1iv", "invalid texture unit"); + return; + } + } + } + + m_context->uniform1iv(location->location(), length, data); +} + +void WebGLRenderingContextBase::uniform2iv(const WebGLUniformLocation* location, Int32List&& v) +{ + if (isContextLostOrPending() || !validateUniformParameters("uniform2iv", location, v, 2)) + return; + + m_context->uniform2iv(location->location(), v.length() / 2, v.data()); +} + +void WebGLRenderingContextBase::uniform3iv(const WebGLUniformLocation* location, Int32List&& v) +{ + if (isContextLostOrPending() || !validateUniformParameters("uniform3iv", location, v, 3)) + return; + + m_context->uniform3iv(location->location(), v.length() / 3, v.data()); +} + +void WebGLRenderingContextBase::uniform4iv(const WebGLUniformLocation* location, Int32List&& v) +{ + if (isContextLostOrPending() || !validateUniformParameters("uniform4iv", location, v, 4)) + return; + + m_context->uniform4iv(location->location(), v.length() / 4, v.data()); +} + +void WebGLRenderingContextBase::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32List&& v) +{ + if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, 4)) + return; + m_context->uniformMatrix2fv(location->location(), v.length() / 4, transpose, v.data()); +} + +void WebGLRenderingContextBase::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32List&& v) +{ + if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, 9)) + return; + m_context->uniformMatrix3fv(location->location(), v.length() / 9, transpose, v.data()); +} + +void WebGLRenderingContextBase::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32List&& v) +{ + if (isContextLostOrPending() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, 16)) + return; + m_context->uniformMatrix4fv(location->location(), v.length() / 16, transpose, v.data()); +} + +void WebGLRenderingContextBase::useProgram(WebGLProgram* program) +{ + bool deleted; + if (!checkObjectToBeBound("useProgram", program, deleted)) + return; + if (deleted) + program = 0; + if (program && !program->getLinkStatus()) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "useProgram", "program not valid"); + return; + } + if (m_currentProgram != program) { + if (m_currentProgram) + m_currentProgram->onDetached(graphicsContext3D()); + m_currentProgram = program; + m_context->useProgram(objectOrZero(program)); + if (program) + program->onAttached(); + } +} + +void WebGLRenderingContextBase::validateProgram(WebGLProgram* program) +{ + if (isContextLostOrPending() || !validateWebGLObject("validateProgram", program)) + return; + m_context->validateProgram(objectOrZero(program)); +} + +void WebGLRenderingContextBase::vertexAttrib1f(GC3Duint index, GC3Dfloat v0) +{ + vertexAttribfImpl("vertexAttrib1f", index, 1, v0, 0.0f, 0.0f, 1.0f); +} + +void WebGLRenderingContextBase::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1) +{ + vertexAttribfImpl("vertexAttrib2f", index, 2, v0, v1, 0.0f, 1.0f); +} + +void WebGLRenderingContextBase::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2) +{ + vertexAttribfImpl("vertexAttrib3f", index, 3, v0, v1, v2, 1.0f); +} + +void WebGLRenderingContextBase::vertexAttrib4f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3) +{ + vertexAttribfImpl("vertexAttrib4f", index, 4, v0, v1, v2, v3); +} + +void WebGLRenderingContextBase::vertexAttrib1fv(GC3Duint index, Float32List&& v) +{ + vertexAttribfvImpl("vertexAttrib1fv", index, WTFMove(v), 1); +} + +void WebGLRenderingContextBase::vertexAttrib2fv(GC3Duint index, Float32List&& v) +{ + vertexAttribfvImpl("vertexAttrib2fv", index, WTFMove(v), 2); +} + +void WebGLRenderingContextBase::vertexAttrib3fv(GC3Duint index, Float32List&& v) +{ + vertexAttribfvImpl("vertexAttrib3fv", index, WTFMove(v), 3); +} + +void WebGLRenderingContextBase::vertexAttrib4fv(GC3Duint index, Float32List&& v) +{ + vertexAttribfvImpl("vertexAttrib4fv", index, WTFMove(v), 4); +} + +void WebGLRenderingContextBase::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, long long offset) +{ + if (isContextLostOrPending()) + return; + switch (type) { + case GraphicsContext3D::BYTE: + case GraphicsContext3D::UNSIGNED_BYTE: + case GraphicsContext3D::SHORT: + case GraphicsContext3D::UNSIGNED_SHORT: + case GraphicsContext3D::FLOAT: + break; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "vertexAttribPointer", "invalid type"); + return; + } + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribPointer", "index out of range"); + return; + } + if (size < 1 || size > 4 || stride < 0 || stride > 255 || offset < 0) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribPointer", "bad size, stride or offset"); + return; + } + if (!m_boundArrayBuffer) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "vertexAttribPointer", "no bound ARRAY_BUFFER"); + return; + } + // Determine the number of elements the bound buffer can hold, given the offset, size, type and stride + auto typeSize = sizeInBytes(type); + if (!typeSize) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "vertexAttribPointer", "invalid type"); + return; + } + if ((stride % typeSize) || (static_cast<GC3Dintptr>(offset) % typeSize)) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "vertexAttribPointer", "stride or offset not valid for type"); + return; + } + GC3Dsizei bytesPerElement = size * typeSize; + + m_boundVertexArrayObject->setVertexAttribState(index, bytesPerElement, size, type, normalized, stride, static_cast<GC3Dintptr>(offset), *m_boundArrayBuffer); + m_context->vertexAttribPointer(index, size, type, normalized, stride, static_cast<GC3Dintptr>(offset)); +} + +void WebGLRenderingContextBase::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) +{ + if (isContextLostOrPending()) + return; + if (!validateSize("viewport", width, height)) + return; + m_context->viewport(x, y, width, height); +} + +void WebGLRenderingContextBase::forceLostContext(WebGLRenderingContextBase::LostContextMode mode) +{ + if (isContextLostOrPending()) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "loseContext", "context already lost"); + return; + } + + m_contextGroup->loseContextGroup(mode); +} + +void WebGLRenderingContextBase::recycleContext() +{ + printWarningToConsole("There are too many active WebGL contexts on this page, the oldest context will be lost."); + // Using SyntheticLostContext means the developer won't be able to force the restoration + // of the context by calling preventDefault() in a "webglcontextlost" event handler. + forceLostContext(SyntheticLostContext); + destroyGraphicsContext3D(); +} + +void WebGLRenderingContextBase::loseContextImpl(WebGLRenderingContextBase::LostContextMode mode) +{ + if (isContextLost()) + return; + + m_contextLost = true; + m_contextLostMode = mode; + + if (mode == RealLostContext) { + // Inform the embedder that a lost context was received. In response, the embedder might + // decide to take action such as asking the user for permission to use WebGL again. + if (Frame* frame = canvas().document().frame()) + frame->loader().client().didLoseWebGLContext(m_context->getExtensions().getGraphicsResetStatusARB()); + } + + detachAndRemoveAllObjects(); + + // There is no direct way to clear errors from a GL implementation and + // looping until getError() becomes NO_ERROR might cause an infinite loop if + // the driver or context implementation had a bug. So, loop a reasonably + // large number of times to clear any existing errors. + for (int i = 0; i < 100; ++i) { + if (m_context->getError() == GraphicsContext3D::NO_ERROR) + break; + } + ConsoleDisplayPreference display = (mode == RealLostContext) ? DisplayInConsole: DontDisplayInConsole; + synthesizeGLError(GraphicsContext3D::CONTEXT_LOST_WEBGL, "loseContext", "context lost", display); + + // Don't allow restoration unless the context lost event has both been + // dispatched and its default behavior prevented. + m_restoreAllowed = false; + + // Always defer the dispatch of the context lost event, to implement + // the spec behavior of queueing a task. + m_dispatchContextLostEventTimer.startOneShot(0); +} + +void WebGLRenderingContextBase::forceRestoreContext() +{ + if (!isContextLostOrPending()) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "restoreContext", "context not lost"); + return; + } + + if (!m_restoreAllowed) { + if (m_contextLostMode == SyntheticLostContext) + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "restoreContext", "context restoration not allowed"); + return; + } + + if (!m_restoreTimer.isActive()) + m_restoreTimer.startOneShot(0); +} + +PlatformLayer* WebGLRenderingContextBase::platformLayer() const +{ + return (!isContextLost() && !m_isPendingPolicyResolution) ? m_context->platformLayer() : 0; +} + +void WebGLRenderingContextBase::removeSharedObject(WebGLSharedObject& object) +{ + if (m_isPendingPolicyResolution) + return; + + m_contextGroup->removeObject(object); +} + +void WebGLRenderingContextBase::addSharedObject(WebGLSharedObject& object) +{ + if (m_isPendingPolicyResolution) + return; + + ASSERT(!isContextLost()); + m_contextGroup->addObject(object); +} + +void WebGLRenderingContextBase::removeContextObject(WebGLContextObject& object) +{ + if (m_isPendingPolicyResolution) + return; + + m_contextObjects.remove(&object); +} + +void WebGLRenderingContextBase::addContextObject(WebGLContextObject& object) +{ + if (m_isPendingPolicyResolution) + return; + + ASSERT(!isContextLost()); + m_contextObjects.add(&object); +} + +void WebGLRenderingContextBase::detachAndRemoveAllObjects() +{ + if (m_isPendingPolicyResolution) + return; + + while (m_contextObjects.size() > 0) { + HashSet<WebGLContextObject*>::iterator it = m_contextObjects.begin(); + (*it)->detachContext(); + } +} + +bool WebGLRenderingContextBase::hasPendingActivity() const +{ + return false; +} + +void WebGLRenderingContextBase::stop() +{ + if (!isContextLost() && !m_isPendingPolicyResolution) { + forceLostContext(SyntheticLostContext); + destroyGraphicsContext3D(); + } +} + +const char* WebGLRenderingContextBase::activeDOMObjectName() const +{ + return "WebGLRenderingContext"; +} + +bool WebGLRenderingContextBase::canSuspendForDocumentSuspension() const +{ + // FIXME: We should try and do better here. + return false; +} + +bool WebGLRenderingContextBase::getBooleanParameter(GC3Denum pname) +{ + GC3Dboolean value = 0; + m_context->getBooleanv(pname, &value); + return value; +} + +Vector<bool> WebGLRenderingContextBase::getBooleanArrayParameter(GC3Denum pname) +{ + if (pname != GraphicsContext3D::COLOR_WRITEMASK) { + notImplemented(); + return { }; + } + GC3Dboolean value[4] = { 0 }; + m_context->getBooleanv(pname, value); + Vector<bool> vector(4); + for (unsigned i = 0; i < 4; ++i) + vector[i] = value[i]; + return vector; +} + +float WebGLRenderingContextBase::getFloatParameter(GC3Denum pname) +{ + GC3Dfloat value = 0; + m_context->getFloatv(pname, &value); + return value; +} + +int WebGLRenderingContextBase::getIntParameter(GC3Denum pname) +{ + GC3Dint value = 0; + m_context->getIntegerv(pname, &value); + return value; +} + +unsigned WebGLRenderingContextBase::getUnsignedIntParameter(GC3Denum pname) +{ + GC3Dint value = 0; + m_context->getIntegerv(pname, &value); + return value; +} + +long long WebGLRenderingContextBase::getInt64Parameter(GC3Denum pname) +{ + GC3Dint64 value = 0; + m_context->getInteger64v(pname, &value); + return value; +} + +RefPtr<Float32Array> WebGLRenderingContextBase::getWebGLFloatArrayParameter(GC3Denum pname) +{ + GC3Dfloat value[4] = {0}; + m_context->getFloatv(pname, value); + unsigned length = 0; + switch (pname) { + case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE: + case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE: + case GraphicsContext3D::DEPTH_RANGE: + length = 2; + break; + case GraphicsContext3D::BLEND_COLOR: + case GraphicsContext3D::COLOR_CLEAR_VALUE: + length = 4; + break; + default: + notImplemented(); + } + return Float32Array::create(value, length); +} + +RefPtr<Int32Array> WebGLRenderingContextBase::getWebGLIntArrayParameter(GC3Denum pname) +{ + GC3Dint value[4] = {0}; + m_context->getIntegerv(pname, value); + unsigned length = 0; + switch (pname) { + case GraphicsContext3D::MAX_VIEWPORT_DIMS: + length = 2; + break; + case GraphicsContext3D::SCISSOR_BOX: + case GraphicsContext3D::VIEWPORT: + length = 4; + break; + default: + notImplemented(); + } + return Int32Array::create(value, length); +} + +bool WebGLRenderingContextBase::checkTextureCompleteness(const char* functionName, bool prepareToDraw) +{ + bool resetActiveUnit = false; + bool usesAtLeastOneBlackTexture = false; + WebGLTexture::TextureExtensionFlag extensions = textureExtensionFlags(); + + Vector<unsigned> noLongerUnrenderable; + for (unsigned badTexture : m_unrenderableTextureUnits) { + ASSERT(badTexture < m_textureUnits.size()); + auto& textureUnit = m_textureUnits[badTexture]; + bool needsToUseBlack2DTexture = textureUnit.texture2DBinding && textureUnit.texture2DBinding->needToUseBlackTexture(extensions); + bool needsToUseBlack3DTexture = textureUnit.textureCubeMapBinding && textureUnit.textureCubeMapBinding->needToUseBlackTexture(extensions); + + if (!needsToUseBlack2DTexture && !needsToUseBlack3DTexture) { + noLongerUnrenderable.append(badTexture); + continue; + } + + usesAtLeastOneBlackTexture = true; + + if (badTexture != m_activeTextureUnit) { + m_context->activeTexture(badTexture + GraphicsContext3D::TEXTURE0); + resetActiveUnit = true; + } else if (resetActiveUnit) { + m_context->activeTexture(badTexture + GraphicsContext3D::TEXTURE0); + resetActiveUnit = false; + } + WebGLTexture* tex2D; + WebGLTexture* texCubeMap; + if (prepareToDraw) { + String msg(String("texture bound to texture unit ") + String::number(badTexture) + + " is not renderable. It maybe non-power-of-2 and have incompatible texture filtering or is not 'texture complete'," + + " or it is a float/half-float type with linear filtering and without the relevant float/half-float linear extension enabled."); + printGLWarningToConsole(functionName, msg.utf8().data()); + tex2D = m_blackTexture2D.get(); + texCubeMap = m_blackTextureCubeMap.get(); + } else { + tex2D = textureUnit.texture2DBinding.get(); + texCubeMap = textureUnit.textureCubeMapBinding.get(); + } + if (needsToUseBlack2DTexture) + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZero(tex2D)); + if (needsToUseBlack3DTexture) + m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, objectOrZero(texCubeMap)); + } + if (resetActiveUnit) + m_context->activeTexture(m_activeTextureUnit + GraphicsContext3D::TEXTURE0); + + for (unsigned renderable : noLongerUnrenderable) + m_unrenderableTextureUnits.remove(renderable); + + return usesAtLeastOneBlackTexture; +} + +void WebGLRenderingContextBase::createFallbackBlackTextures1x1() +{ + unsigned char black[] = {0, 0, 0, 255}; + m_blackTexture2D = createTexture(); + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_blackTexture2D->object()); + m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 1, 1, + 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black); + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0); + m_blackTextureCubeMap = createTexture(); + m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, m_blackTextureCubeMap->object()); + m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X, 0, GraphicsContext3D::RGBA, 1, 1, + 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black); + m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GraphicsContext3D::RGBA, 1, 1, + 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black); + m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1, + 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black); + m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1, + 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black); + m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1, + 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black); + m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1, + 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black); + m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, 0); +} + +bool WebGLRenderingContextBase::isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat, + GC3Denum colorBufferFormat) +{ + unsigned need = GraphicsContext3D::getChannelBitsByFormat(texInternalFormat); + unsigned have = GraphicsContext3D::getChannelBitsByFormat(colorBufferFormat); + return (need & have) == need; +} + +GC3Denum WebGLRenderingContextBase::getBoundFramebufferColorFormat() +{ + if (m_framebufferBinding && m_framebufferBinding->object()) + return m_framebufferBinding->getColorBufferFormat(); + if (m_attributes.alpha) + return GraphicsContext3D::RGBA; + return GraphicsContext3D::RGB; +} + +int WebGLRenderingContextBase::getBoundFramebufferWidth() +{ + if (m_framebufferBinding && m_framebufferBinding->object()) + return m_framebufferBinding->getColorBufferWidth(); + return m_context->getInternalFramebufferSize().width(); +} + +int WebGLRenderingContextBase::getBoundFramebufferHeight() +{ + if (m_framebufferBinding && m_framebufferBinding->object()) + return m_framebufferBinding->getColorBufferHeight(); + return m_context->getInternalFramebufferSize().height(); +} + +WebGLTexture* WebGLRenderingContextBase::validateTextureBinding(const char* functionName, GC3Denum target, bool useSixEnumsForCubeMap) +{ + WebGLTexture* texture = nullptr; + switch (target) { + case GraphicsContext3D::TEXTURE_2D: + texture = m_textureUnits[m_activeTextureUnit].texture2DBinding.get(); + break; + case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X: + case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X: + case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y: + case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z: + case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z: + if (!useSixEnumsForCubeMap) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target"); + return nullptr; + } + texture = m_textureUnits[m_activeTextureUnit].textureCubeMapBinding.get(); + break; + case GraphicsContext3D::TEXTURE_CUBE_MAP: + if (useSixEnumsForCubeMap) { + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target"); + return nullptr; + } + texture = m_textureUnits[m_activeTextureUnit].textureCubeMapBinding.get(); + break; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid texture target"); + return nullptr; + } + + if (texture && texture->needToUseBlackTexture(textureExtensionFlags())) + m_unrenderableTextureUnits.add(m_activeTextureUnit); + + if (!texture) + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no texture"); + return texture; +} + +bool WebGLRenderingContextBase::validateLocationLength(const char* functionName, const String& string) +{ + const unsigned maxWebGLLocationLength = 256; + if (string.length() > maxWebGLLocationLength) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "location length > 256"); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateSize(const char* functionName, GC3Dint x, GC3Dint y) +{ + if (x < 0 || y < 0) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "size < 0"); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateString(const char* functionName, const String& string) +{ + for (size_t i = 0; i < string.length(); ++i) { + if (!validateCharacter(string[i])) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "string not ASCII"); + return false; + } + } + return true; +} + +bool WebGLRenderingContextBase::validateTexFuncLevel(const char* functionName, GC3Denum target, GC3Dint level) +{ + if (level < 0) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level < 0"); + return false; + } + switch (target) { + case GraphicsContext3D::TEXTURE_2D: + if (level >= m_maxTextureLevel) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level out of range"); + return false; + } + break; + case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X: + case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X: + case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y: + case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z: + case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z: + if (level >= m_maxCubeMapTextureLevel) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "level out of range"); + return false; + } + break; + } + // This function only checks if level is legal, so we return true and don't + // generate INVALID_ENUM if target is illegal. + return true; +} + +bool WebGLRenderingContextBase::validateCompressedTexFormat(GC3Denum format) +{ + return m_compressedTextureFormats.contains(format); +} + +bool WebGLRenderingContextBase::validateCompressedTexFuncData(const char* functionName, GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView& pixels) +{ + if (width < 0 || height < 0) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0"); + return false; + } + + unsigned bytesRequired = 0; + + switch (format) { + case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT: + case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT: + case Extensions3D::COMPRESSED_ATC_RGB_AMD: + { + const int kBlockSize = 8; + const int kBlockWidth = 4; + const int kBlockHeight = 4; + int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth; + int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight; + bytesRequired = numBlocksAcross * numBlocksDown * kBlockSize; + } + break; + case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT: + case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: + case Extensions3D::COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD: + case Extensions3D::COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD: + { + const int kBlockSize = 16; + const int kBlockWidth = 4; + const int kBlockHeight = 4; + int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth; + int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight; + bytesRequired = numBlocksAcross * numBlocksDown * kBlockSize; + } + break; + case Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG: + case Extensions3D::COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: + { + const int kBlockSize = 8; + const int kBlockWidth = 8; + const int kBlockHeight = 8; + bytesRequired = (std::max(width, kBlockWidth) * std::max(height, kBlockHeight) * 4 + 7) / kBlockSize; + } + break; + case Extensions3D::COMPRESSED_RGB_PVRTC_2BPPV1_IMG: + case Extensions3D::COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: + { + const int kBlockSize = 8; + const int kBlockWidth = 16; + const int kBlockHeight = 8; + bytesRequired = (std::max(width, kBlockWidth) * std::max(height, kBlockHeight) * 2 + 7) / kBlockSize; + } + break; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid format"); + return false; + } + + if (pixels.byteLength() != bytesRequired) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "length of ArrayBufferView is not correct for dimensions"); + return false; + } + + return true; +} + +bool WebGLRenderingContextBase::validateCompressedTexDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum format) +{ + switch (format) { + case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT: + case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT: + case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT: + case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: { + const GC3Dsizei kBlockWidth = 4; + const GC3Dsizei kBlockHeight = 4; + const GC3Dint maxTextureSize = target ? m_maxTextureSize : m_maxCubeMapTextureSize; + const GC3Dsizei maxCompressedDimension = maxTextureSize >> level; + bool widthValid = (level && width == 1) || (level && width == 2) || (!(width % kBlockWidth) && width <= maxCompressedDimension); + bool heightValid = (level && height == 1) || (level && height == 2) || (!(height % kBlockHeight) && height <= maxCompressedDimension); + if (!widthValid || !heightValid) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "width or height invalid for level"); + return false; + } + return true; + } + case Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG: + case Extensions3D::COMPRESSED_RGB_PVRTC_2BPPV1_IMG: + case Extensions3D::COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: + case Extensions3D::COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: + // Height and width must be powers of 2. + if ((width & (width - 1)) || (height & (height - 1))) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "width or height invalid for level"); + return false; + } + return true; + default: + return false; + } +} + +bool WebGLRenderingContextBase::validateCompressedTexSubDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, + GC3Dsizei width, GC3Dsizei height, GC3Denum format, WebGLTexture* tex) +{ + if (xoffset < 0 || yoffset < 0) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "xoffset or yoffset < 0"); + return false; + } + + switch (format) { + case Extensions3D::COMPRESSED_RGB_S3TC_DXT1_EXT: + case Extensions3D::COMPRESSED_RGBA_S3TC_DXT1_EXT: + case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT: + case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: { + const int kBlockWidth = 4; + const int kBlockHeight = 4; + if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "xoffset or yoffset not multiple of 4"); + return false; + } + if (width - xoffset > tex->getWidth(target, level) + || height - yoffset > tex->getHeight(target, level)) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "dimensions out of range"); + return false; + } + return validateCompressedTexDimensions(functionName, target, level, width, height, format); + } + case Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG: + case Extensions3D::COMPRESSED_RGB_PVRTC_2BPPV1_IMG: + case Extensions3D::COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: + case Extensions3D::COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: { + if (xoffset || yoffset) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "xoffset and yoffset must be zero"); + return false; + } + if (width != tex->getWidth(target, level) + || height != tex->getHeight(target, level)) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "dimensions must match existing level"); + return false; + } + return validateCompressedTexDimensions(functionName, target, level, width, height, format); + } + default: + return false; + } +} + +bool WebGLRenderingContextBase::validateDrawMode(const char* functionName, GC3Denum mode) +{ + switch (mode) { + case GraphicsContext3D::POINTS: + case GraphicsContext3D::LINE_STRIP: + case GraphicsContext3D::LINE_LOOP: + case GraphicsContext3D::LINES: + case GraphicsContext3D::TRIANGLE_STRIP: + case GraphicsContext3D::TRIANGLE_FAN: + case GraphicsContext3D::TRIANGLES: + return true; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid draw mode"); + return false; + } +} + +bool WebGLRenderingContextBase::validateStencilSettings(const char* functionName) +{ + if (m_stencilMask != m_stencilMaskBack || m_stencilFuncRef != m_stencilFuncRefBack || m_stencilFuncMask != m_stencilFuncMaskBack) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "front and back stencils settings do not match"); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateStencilFunc(const char* functionName, GC3Denum func) +{ + switch (func) { + case GraphicsContext3D::NEVER: + case GraphicsContext3D::LESS: + case GraphicsContext3D::LEQUAL: + case GraphicsContext3D::GREATER: + case GraphicsContext3D::GEQUAL: + case GraphicsContext3D::EQUAL: + case GraphicsContext3D::NOTEQUAL: + case GraphicsContext3D::ALWAYS: + return true; + default: + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid function"); + return false; + } +} + +void WebGLRenderingContextBase::printGLErrorToConsole(const String& message) +{ + if (!m_numGLErrorsToConsoleAllowed) + return; + + --m_numGLErrorsToConsoleAllowed; + printWarningToConsole(message); + + if (!m_numGLErrorsToConsoleAllowed) + printWarningToConsole("WebGL: too many errors, no more errors will be reported to the console for this context."); +} + +void WebGLRenderingContextBase::printWarningToConsole(const String& message) +{ + canvas().document().addConsoleMessage(MessageSource::Rendering, MessageLevel::Warning, message); +} + +bool WebGLRenderingContextBase::validateBlendFuncFactors(const char* functionName, GC3Denum src, GC3Denum dst) +{ + if (((src == GraphicsContext3D::CONSTANT_COLOR || src == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR) + && (dst == GraphicsContext3D::CONSTANT_ALPHA || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA)) + || ((dst == GraphicsContext3D::CONSTANT_COLOR || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR) + && (src == GraphicsContext3D::CONSTANT_ALPHA || src == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA))) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "incompatible src and dst"); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, const Float32List& v, GC3Dsizei requiredMinSize) +{ + return validateUniformMatrixParameters(functionName, location, false, v.data(), v.length(), requiredMinSize); +} + +bool WebGLRenderingContextBase::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, const Int32List& v, GC3Dsizei requiredMinSize) +{ + return validateUniformMatrixParameters(functionName, location, false, v.data(), v.length(), requiredMinSize); +} + +bool WebGLRenderingContextBase::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize) +{ + return validateUniformMatrixParameters(functionName, location, false, v, size, requiredMinSize); +} + +bool WebGLRenderingContextBase::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GC3Dboolean transpose, const Float32List& v, GC3Dsizei requiredMinSize) +{ + return validateUniformMatrixParameters(functionName, location, transpose, v.data(), v.length(), requiredMinSize); +} + +bool WebGLRenderingContextBase::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GC3Dboolean transpose, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize) +{ + if (!location) + return false; + if (location->program() != m_currentProgram) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "location is not from current program"); + return false; + } + if (!v) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array"); + return false; + } + if (transpose) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "transpose not FALSE"); + return false; + } + if (size < requiredMinSize || (size % requiredMinSize)) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid size"); + return false; + } + return true; +} + +WebGLBuffer* WebGLRenderingContextBase::validateBufferDataParameters(const char* functionName, GC3Denum target, GC3Denum usage) +{ + std::optional<WebGLBuffer*> buffer; + switch (target) { + case GraphicsContext3D::ELEMENT_ARRAY_BUFFER: + buffer = m_boundVertexArrayObject->getElementArrayBuffer(); + break; + case GraphicsContext3D::ARRAY_BUFFER: + buffer = m_boundArrayBuffer.get(); + break; + default: +#if ENABLE(WEBGL2) + if (isWebGL2()) { + switch (target) { + case GraphicsContext3D::COPY_READ_BUFFER: + buffer = m_boundCopyReadBuffer.get(); + break; + case GraphicsContext3D::COPY_WRITE_BUFFER: + buffer = m_boundCopyWriteBuffer.get(); + break; + case GraphicsContext3D::PIXEL_PACK_BUFFER: + buffer = m_boundPixelPackBuffer.get(); + break; + case GraphicsContext3D::PIXEL_UNPACK_BUFFER: + buffer = m_boundPixelUnpackBuffer.get(); + break; + case GraphicsContext3D::TRANSFORM_FEEDBACK_BUFFER: + buffer = m_boundTransformFeedbackBuffer.get(); + break; + case GraphicsContext3D::UNIFORM_BUFFER: + buffer = m_boundUniformBuffer.get(); + break; + } + if (buffer) + break; + } +#endif + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target"); + return nullptr; + } + if (!buffer || !buffer.value()) { + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, "no buffer"); + return nullptr; + } + switch (usage) { + case GraphicsContext3D::STREAM_DRAW: + case GraphicsContext3D::STATIC_DRAW: + case GraphicsContext3D::DYNAMIC_DRAW: + return buffer.value(); + } + synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid usage"); + return nullptr; +} + +bool WebGLRenderingContextBase::validateHTMLImageElement(const char* functionName, HTMLImageElement* image, ExceptionCode& ec) +{ + if (!image || !image->cachedImage()) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no image"); + return false; + } + const URL& url = image->cachedImage()->response().url(); + if (url.isNull() || url.isEmpty() || !url.isValid()) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid image"); + return false; + } + if (wouldTaintOrigin(image)) { + ec = SECURITY_ERR; + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement* canvas, ExceptionCode& ec) +{ + if (!canvas || !canvas->buffer()) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no canvas"); + return false; + } + if (wouldTaintOrigin(canvas)) { + ec = SECURITY_ERR; + return false; + } + return true; +} + +#if ENABLE(VIDEO) + +bool WebGLRenderingContextBase::validateHTMLVideoElement(const char* functionName, HTMLVideoElement* video, ExceptionCode& ec) +{ + if (!video || !video->videoWidth() || !video->videoHeight()) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no video"); + return false; + } + if (wouldTaintOrigin(video)) { + ec = SECURITY_ERR; + return false; + } + return true; +} + +#endif + +void WebGLRenderingContextBase::vertexAttribfImpl(const char* functionName, GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3) +{ + if (isContextLostOrPending()) + return; + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "index out of range"); + return; + } + // In GL, we skip setting vertexAttrib0 values. + if (index || isGLES2Compliant()) { + switch (expectedSize) { + case 1: + m_context->vertexAttrib1f(index, v0); + break; + case 2: + m_context->vertexAttrib2f(index, v0, v1); + break; + case 3: + m_context->vertexAttrib3f(index, v0, v1, v2); + break; + case 4: + m_context->vertexAttrib4f(index, v0, v1, v2, v3); + break; + } + } + VertexAttribValue& attribValue = m_vertexAttribValue[index]; + attribValue.value[0] = v0; + attribValue.value[1] = v1; + attribValue.value[2] = v2; + attribValue.value[3] = v3; +} + +void WebGLRenderingContextBase::vertexAttribfvImpl(const char* functionName, GC3Duint index, Float32List&& list, GC3Dsizei expectedSize) +{ + if (isContextLostOrPending()) + return; + + auto data = list.data(); + if (!data) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "no array"); + return; + } + + int size = list.length(); + if (size < expectedSize) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "invalid size"); + return; + } + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "index out of range"); + return; + } + // In GL, we skip setting vertexAttrib0 values. + if (index || isGLES2Compliant()) { + switch (expectedSize) { + case 1: + m_context->vertexAttrib1fv(index, data); + break; + case 2: + m_context->vertexAttrib2fv(index, data); + break; + case 3: + m_context->vertexAttrib3fv(index, data); + break; + case 4: + m_context->vertexAttrib4fv(index, data); + break; + } + } + VertexAttribValue& attribValue = m_vertexAttribValue[index]; + attribValue.initValue(); + for (int ii = 0; ii < expectedSize; ++ii) + attribValue.value[ii] = data[ii]; +} + +void WebGLRenderingContextBase::initVertexAttrib0() +{ + WebGLVertexArrayObjectBase::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0); + + m_vertexAttrib0Buffer = createBuffer(); + m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object()); + m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, 0, GraphicsContext3D::DYNAMIC_DRAW); + m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, false, 0, 0); + state.bufferBinding = m_vertexAttrib0Buffer; + m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0); + m_context->enableVertexAttribArray(0); + m_vertexAttrib0BufferSize = 0; + m_vertexAttrib0BufferValue[0] = 0.0f; + m_vertexAttrib0BufferValue[1] = 0.0f; + m_vertexAttrib0BufferValue[2] = 0.0f; + m_vertexAttrib0BufferValue[3] = 1.0f; + m_forceAttrib0BufferRefill = false; + m_vertexAttrib0UsedBefore = false; +} + +bool WebGLRenderingContextBase::validateSimulatedVertexAttrib0(GC3Dsizei numVertex) +{ + if (numVertex < 0) + return false; + + if (!m_currentProgram) + return true; + + bool usingVertexAttrib0 = m_currentProgram->isUsingVertexAttrib0(); + if (!usingVertexAttrib0) + return true; + + auto& state = m_boundVertexArrayObject->getVertexAttribState(0); + if (state.enabled) + return true; + + Checked<GC3Dsizei, RecordOverflow> bufferSize(numVertex); + bufferSize += 1; + bufferSize *= Checked<GC3Dsizei>(4); + Checked<GC3Dsizeiptr, RecordOverflow> bufferDataSize(bufferSize); + bufferDataSize *= Checked<GC3Dsizeiptr>(sizeof(GC3Dfloat)); + return !bufferDataSize.hasOverflowed(); +} + +bool WebGLRenderingContextBase::simulateVertexAttrib0(GC3Dsizei numVertex) +{ + if (!m_currentProgram) + return false; + bool usingVertexAttrib0 = m_currentProgram->isUsingVertexAttrib0(); + if (usingVertexAttrib0) + m_vertexAttrib0UsedBefore = true; + + auto& state = m_boundVertexArrayObject->getVertexAttribState(0); + if (state.enabled && usingVertexAttrib0) + return false; + if (!usingVertexAttrib0 && !m_vertexAttrib0UsedBefore) + return false; + m_vertexAttrib0UsedBefore = true; + m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object()); + + Checked<GC3Dsizei> bufferSize(numVertex); + bufferSize += 1; + bufferSize *= Checked<GC3Dsizei>(4); + + Checked<GC3Dsizeiptr> bufferDataSize(bufferSize); + bufferDataSize *= Checked<GC3Dsizeiptr>(sizeof(GC3Dfloat)); + + if (bufferDataSize.unsafeGet() > m_vertexAttrib0BufferSize) { + m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, bufferDataSize.unsafeGet(), 0, GraphicsContext3D::DYNAMIC_DRAW); + m_vertexAttrib0BufferSize = bufferDataSize.unsafeGet(); + m_forceAttrib0BufferRefill = true; + } + + auto& attribValue = m_vertexAttribValue[0]; + + if (usingVertexAttrib0 + && (m_forceAttrib0BufferRefill + || attribValue.value[0] != m_vertexAttrib0BufferValue[0] + || attribValue.value[1] != m_vertexAttrib0BufferValue[1] + || attribValue.value[2] != m_vertexAttrib0BufferValue[2] + || attribValue.value[3] != m_vertexAttrib0BufferValue[3])) { + + auto bufferData = std::make_unique<GC3Dfloat[]>(bufferSize.unsafeGet()); + for (GC3Dsizei ii = 0; ii < numVertex + 1; ++ii) { + bufferData[ii * 4] = attribValue.value[0]; + bufferData[ii * 4 + 1] = attribValue.value[1]; + bufferData[ii * 4 + 2] = attribValue.value[2]; + bufferData[ii * 4 + 3] = attribValue.value[3]; + } + m_vertexAttrib0BufferValue[0] = attribValue.value[0]; + m_vertexAttrib0BufferValue[1] = attribValue.value[1]; + m_vertexAttrib0BufferValue[2] = attribValue.value[2]; + m_vertexAttrib0BufferValue[3] = attribValue.value[3]; + m_forceAttrib0BufferRefill = false; + m_context->bufferSubData(GraphicsContext3D::ARRAY_BUFFER, 0, bufferDataSize.unsafeGet(), bufferData.get()); + } + m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, 0, 0, 0); + return true; +} + +void WebGLRenderingContextBase::restoreStatesAfterVertexAttrib0Simulation() +{ + const WebGLVertexArrayObjectBase::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0); + if (state.bufferBinding != m_vertexAttrib0Buffer) { + m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(state.bufferBinding.get())); + m_context->vertexAttribPointer(0, state.size, state.type, state.normalized, state.originalStride, state.offset); + } + m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(m_boundArrayBuffer.get())); +} + +void WebGLRenderingContextBase::dispatchContextLostEvent() +{ + Ref<WebGLContextEvent> event = WebGLContextEvent::create(eventNames().webglcontextlostEvent, false, true, emptyString()); + canvas().dispatchEvent(event); + m_restoreAllowed = event->defaultPrevented(); + if (m_contextLostMode == RealLostContext && m_restoreAllowed) + m_restoreTimer.startOneShot(0); +} + +void WebGLRenderingContextBase::maybeRestoreContext() +{ + ASSERT(m_contextLost); + if (!m_contextLost) + return; + + // The rendering context is not restored unless the default behavior of the + // webglcontextlost event was prevented earlier. + // + // Because of the way m_restoreTimer is set up for real vs. synthetic lost + // context events, we don't have to worry about this test short-circuiting + // the retry loop for real context lost events. + if (!m_restoreAllowed) + return; + + int contextLostReason = m_context->getExtensions().getGraphicsResetStatusARB(); + + switch (contextLostReason) { + case GraphicsContext3D::NO_ERROR: + // The GraphicsContext3D implementation might not fully + // support GL_ARB_robustness semantics yet. Alternatively, the + // WEBGL_lose_context extension might have been used to force + // a lost context. + break; + case Extensions3D::GUILTY_CONTEXT_RESET_ARB: + // The rendering context is not restored if this context was + // guilty of causing the graphics reset. + printWarningToConsole("WARNING: WebGL content on the page caused the graphics card to reset; not restoring the context"); + return; + case Extensions3D::INNOCENT_CONTEXT_RESET_ARB: + // Always allow the context to be restored. + break; + case Extensions3D::UNKNOWN_CONTEXT_RESET_ARB: + // Warn. Ideally, prompt the user telling them that WebGL + // content on the page might have caused the graphics card to + // reset and ask them whether they want to continue running + // the content. Only if they say "yes" should we start + // attempting to restore the context. + printWarningToConsole("WARNING: WebGL content on the page might have caused the graphics card to reset"); + break; + } + + Frame* frame = canvas().document().frame(); + if (!frame) + return; + + if (!frame->loader().client().allowWebGL(frame->settings().webGLEnabled())) + return; + + FrameView* view = frame->view(); + if (!view) + return; + ScrollView* root = view->root(); + if (!root) + return; + HostWindow* hostWindow = root->hostWindow(); + if (!hostWindow) + return; + + RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(m_attributes, hostWindow)); + if (!context) { + if (m_contextLostMode == RealLostContext) + m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts); + else + // This likely shouldn't happen but is the best way to report it to the WebGL app. + synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "", "error restoring context"); + return; + } + + m_context = context; + addActivityStateChangeObserverIfNecessary(); + m_contextLost = false; + setupFlags(); + initializeNewContext(); + initializeVertexArrayObjects(); + canvas().dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextrestoredEvent, false, true, emptyString())); +} + +String WebGLRenderingContextBase::ensureNotNull(const String& text) const +{ + if (text.isNull()) + return WTF::emptyString(); + return text; +} + +WebGLRenderingContextBase::LRUImageBufferCache::LRUImageBufferCache(int capacity) + : m_buffers(std::make_unique<std::unique_ptr<ImageBuffer>[]>(capacity)) + , m_capacity(capacity) +{ +} + +ImageBuffer* WebGLRenderingContextBase::LRUImageBufferCache::imageBuffer(const IntSize& size) +{ + int i; + for (i = 0; i < m_capacity; ++i) { + ImageBuffer* buf = m_buffers[i].get(); + if (!buf) + break; + if (buf->logicalSize() != size) + continue; + bubbleToFront(i); + return buf; + } + + // FIXME (149423): Should this ImageBuffer be unconditionally unaccelerated? + std::unique_ptr<ImageBuffer> temp = ImageBuffer::create(size, Unaccelerated); + if (!temp) + return nullptr; + i = std::min(m_capacity - 1, i); + m_buffers[i] = WTFMove(temp); + + ImageBuffer* buf = m_buffers[i].get(); + bubbleToFront(i); + return buf; +} + +void WebGLRenderingContextBase::LRUImageBufferCache::bubbleToFront(int idx) +{ + for (int i = idx; i > 0; --i) + m_buffers[i].swap(m_buffers[i-1]); +} + +namespace { + + String GetErrorString(GC3Denum error) + { + switch (error) { + case GraphicsContext3D::INVALID_ENUM: + return ASCIILiteral("INVALID_ENUM"); + case GraphicsContext3D::INVALID_VALUE: + return ASCIILiteral("INVALID_VALUE"); + case GraphicsContext3D::INVALID_OPERATION: + return ASCIILiteral("INVALID_OPERATION"); + case GraphicsContext3D::OUT_OF_MEMORY: + return ASCIILiteral("OUT_OF_MEMORY"); + case GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION: + return ASCIILiteral("INVALID_FRAMEBUFFER_OPERATION"); + case GraphicsContext3D::CONTEXT_LOST_WEBGL: + return ASCIILiteral("CONTEXT_LOST_WEBGL"); + default: + return String::format("WebGL ERROR(%04x)", error); + } + } + +} // namespace anonymous + +void WebGLRenderingContextBase::synthesizeGLError(GC3Denum error, const char* functionName, const char* description, ConsoleDisplayPreference display) +{ + if (m_synthesizedErrorsToConsole && display == DisplayInConsole) { + String str = String("WebGL: ") + GetErrorString(error) + ": " + String(functionName) + ": " + String(description); + printGLErrorToConsole(str); + } + m_context->synthesizeGLError(error); +} + + +void WebGLRenderingContextBase::printGLWarningToConsole(const char* functionName, const char* description) +{ + if (m_synthesizedErrorsToConsole) { + String str = String("WebGL: ") + String(functionName) + ": " + String(description); + printGLErrorToConsole(str); + } +} + +void WebGLRenderingContextBase::applyStencilTest() +{ + bool haveStencilBuffer = false; + + if (m_framebufferBinding) + haveStencilBuffer = m_framebufferBinding->hasStencilBuffer(); + else { + auto attributes = getContextAttributes(); + ASSERT(attributes); + haveStencilBuffer = attributes->stencil; + } + enableOrDisable(GraphicsContext3D::STENCIL_TEST, m_stencilEnabled && haveStencilBuffer); +} + +void WebGLRenderingContextBase::enableOrDisable(GC3Denum capability, bool enable) +{ + if (enable) + m_context->enable(capability); + else + m_context->disable(capability); +} + +IntSize WebGLRenderingContextBase::clampedCanvasSize() +{ + return IntSize(clamp(canvas().width(), 1, m_maxViewportDims[0]), + clamp(canvas().height(), 1, m_maxViewportDims[1])); +} + +GC3Dint WebGLRenderingContextBase::getMaxDrawBuffers() +{ + if (!supportsDrawBuffers()) + return 0; + if (!m_maxDrawBuffers) + m_context->getIntegerv(Extensions3D::MAX_DRAW_BUFFERS_EXT, &m_maxDrawBuffers); + if (!m_maxColorAttachments) + m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments); + // WEBGL_draw_buffers requires MAX_COLOR_ATTACHMENTS >= MAX_DRAW_BUFFERS. + return std::min(m_maxDrawBuffers, m_maxColorAttachments); +} + +GC3Dint WebGLRenderingContextBase::getMaxColorAttachments() +{ + if (!supportsDrawBuffers()) + return 0; + if (!m_maxColorAttachments) + m_context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments); + return m_maxColorAttachments; +} + +void WebGLRenderingContextBase::setBackDrawBuffer(GC3Denum buf) +{ + m_backDrawBuffer = buf; +} + +void WebGLRenderingContextBase::restoreCurrentFramebuffer() +{ + bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_framebufferBinding.get()); +} + +void WebGLRenderingContextBase::restoreCurrentTexture2D() +{ + auto texture = m_textureUnits[m_activeTextureUnit].texture2DBinding.get(); + bindTexture(GraphicsContext3D::TEXTURE_2D, texture); + if (texture && texture->needToUseBlackTexture(textureExtensionFlags())) + m_unrenderableTextureUnits.add(m_activeTextureUnit); +} + +bool WebGLRenderingContextBase::supportsDrawBuffers() +{ + if (!m_drawBuffersWebGLRequirementsChecked) { + m_drawBuffersWebGLRequirementsChecked = true; + m_drawBuffersSupported = WebGLDrawBuffers::supported(*this); + } + return m_drawBuffersSupported; +} + +void WebGLRenderingContextBase::drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount) +{ + if (!primcount) { + markContextChanged(); + return; + } + + if (!validateDrawArrays("drawArraysInstanced", mode, first, count, primcount)) + return; + + clearIfComposited(); + + bool vertexAttrib0Simulated = false; + if (!isGLES2Compliant()) + vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1); + if (!isGLES2NPOTStrict()) + checkTextureCompleteness("drawArraysInstanced", true); + + m_context->drawArraysInstanced(mode, first, count, primcount); + + if (!isGLES2Compliant() && vertexAttrib0Simulated) + restoreStatesAfterVertexAttrib0Simulation(); + if (!isGLES2NPOTStrict()) + checkTextureCompleteness("drawArraysInstanced", false); + markContextChanged(); +} + +void WebGLRenderingContextBase::drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount) +{ + if (!primcount) { + markContextChanged(); + return; + } + + unsigned numElements = 0; + if (!validateDrawElements("drawElementsInstanced", mode, count, type, offset, numElements, primcount)) + return; + + clearIfComposited(); + + bool vertexAttrib0Simulated = false; + if (!isGLES2Compliant()) { + if (!numElements) + validateIndexArrayPrecise(count, type, static_cast<GC3Dintptr>(offset), numElements); + vertexAttrib0Simulated = simulateVertexAttrib0(numElements); + } + if (!isGLES2NPOTStrict()) + checkTextureCompleteness("drawElementsInstanced", true); + + m_context->drawElementsInstanced(mode, count, type, static_cast<GC3Dintptr>(offset), primcount); + + if (!isGLES2Compliant() && vertexAttrib0Simulated) + restoreStatesAfterVertexAttrib0Simulation(); + if (!isGLES2NPOTStrict()) + checkTextureCompleteness("drawElementsInstanced", false); + markContextChanged(); +} + +void WebGLRenderingContextBase::vertexAttribDivisor(GC3Duint index, GC3Duint divisor) +{ + if (isContextLostOrPending()) + return; + + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "vertexAttribDivisor", "index out of range"); + return; + } + + m_boundVertexArrayObject->setVertexAttribDivisor(index, divisor); + m_context->vertexAttribDivisor(index, divisor); +} + +bool WebGLRenderingContextBase::enableSupportedExtension(const char* extensionNameLiteral) +{ + ASSERT(m_context); + auto& extensions = m_context->getExtensions(); + String extensionName { ASCIILiteral { extensionNameLiteral } }; + if (!extensions.supports(extensionName)) + return false; + extensions.ensureEnabled(extensionName); + return true; +} + +void WebGLRenderingContextBase::activityStateDidChange(ActivityState::Flags oldActivityState, ActivityState::Flags newActivityState) +{ + if (!m_context) + return; + + ActivityState::Flags changed = oldActivityState ^ newActivityState; + if (changed & ActivityState::IsVisible) + m_context->setContextVisibility(newActivityState & ActivityState::IsVisible); +} + +} // namespace WebCore + +#endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/WebGLRenderingContextBase.h b/Source/WebCore/html/canvas/WebGLRenderingContextBase.h new file mode 100644 index 000000000..31e5542e6 --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLRenderingContextBase.h @@ -0,0 +1,848 @@ +/* + * Copyright (C) 2015-2017 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(WEBGL) + +#include "ActiveDOMObject.h" +#include "ActivityStateChangeObserver.h" +#include "CanvasRenderingContext.h" +#include "GraphicsContext3D.h" +#include "ImageBuffer.h" +#include "Timer.h" +#include "WebGLAny.h" +#include "WebGLBuffer.h" +#include "WebGLContextAttributes.h" +#include "WebGLFramebuffer.h" +#include "WebGLProgram.h" +#include "WebGLRenderbuffer.h" +#include "WebGLStateTracker.h" +#include "WebGLTexture.h" +#include "WebGLVertexArrayObjectOES.h" +#include <memory> + +#if ENABLE(WEBGL2) +#include "WebGLVertexArrayObject.h" +#endif + +namespace WebCore { + +class ANGLEInstancedArrays; +class EXTBlendMinMax; +class EXTTextureFilterAnisotropic; +class EXTShaderTextureLOD; +class EXTsRGB; +class EXTFragDepth; +class HTMLImageElement; +class HTMLVideoElement; +class ImageData; +class IntSize; +class OESStandardDerivatives; +class OESTextureFloat; +class OESTextureFloatLinear; +class OESTextureHalfFloat; +class OESTextureHalfFloatLinear; +class OESVertexArrayObject; +class OESElementIndexUint; +class WebGLActiveInfo; +class WebGLContextGroup; +class WebGLContextObject; +class WebGLCompressedTextureATC; +class WebGLCompressedTexturePVRTC; +class WebGLCompressedTextureS3TC; +class WebGLDebugRendererInfo; +class WebGLDebugShaders; +class WebGLDepthTexture; +class WebGLDrawBuffers; +class WebGLExtension; +class WebGLLoseContext; +class WebGLObject; +class WebGLShader; +class WebGLSharedObject; +class WebGLShaderPrecisionFormat; +class WebGLUniformLocation; + +inline void clip1D(GC3Dint start, GC3Dsizei range, GC3Dsizei sourceRange, GC3Dint* clippedStart, GC3Dsizei* clippedRange) +{ + ASSERT(clippedStart && clippedRange); + if (start < 0) { + range += start; + start = 0; + } + GC3Dint end = start + range; + if (end > sourceRange) + range -= end - sourceRange; + *clippedStart = start; + *clippedRange = range; +} + +// Returns false if no clipping is necessary, i.e., x, y, width, height stay the same. +inline bool clip2D(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, + GC3Dsizei sourceWidth, GC3Dsizei sourceHeight, + GC3Dint* clippedX, GC3Dint* clippedY, GC3Dsizei* clippedWidth, GC3Dsizei*clippedHeight) +{ + ASSERT(clippedX && clippedY && clippedWidth && clippedHeight); + clip1D(x, width, sourceWidth, clippedX, clippedWidth); + clip1D(y, height, sourceHeight, clippedY, clippedHeight); + return (*clippedX != x || *clippedY != y || *clippedWidth != width || *clippedHeight != height); +} + +class WebGLRenderingContextBase : public CanvasRenderingContext, private ActivityStateChangeObserver, public ActiveDOMObject { +public: + static std::unique_ptr<WebGLRenderingContextBase> create(HTMLCanvasElement&, WebGLContextAttributes&, const String&); + virtual ~WebGLRenderingContextBase(); + +#if PLATFORM(WIN) + // FIXME: Implement accelerated 3d canvas on Windows. + bool isAccelerated() const override { return false; } +#else + bool isAccelerated() const override { return true; } +#endif + + int drawingBufferWidth() const; + int drawingBufferHeight() const; + + void activeTexture(GC3Denum texture); + void attachShader(WebGLProgram*, WebGLShader*); + void bindAttribLocation(WebGLProgram*, GC3Duint index, const String& name); + void bindBuffer(GC3Denum target, WebGLBuffer*); + void bindFramebuffer(GC3Denum target, WebGLFramebuffer*); + void bindRenderbuffer(GC3Denum target, WebGLRenderbuffer*); + void bindTexture(GC3Denum target, WebGLTexture*); + void blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha); + void blendEquation(GC3Denum mode); + void blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha); + void blendFunc(GC3Denum sfactor, GC3Denum dfactor); + void blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha); + + using BufferDataSource = WTF::Variant<RefPtr<ArrayBuffer>, RefPtr<ArrayBufferView>>; + void bufferData(GC3Denum target, long long size, GC3Denum usage); + void bufferData(GC3Denum target, std::optional<BufferDataSource>&&, GC3Denum usage); + void bufferSubData(GC3Denum target, long long offset, std::optional<BufferDataSource>&&); + + GC3Denum checkFramebufferStatus(GC3Denum target); + virtual void clear(GC3Dbitfield mask) = 0; + void clearColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha); + void clearDepth(GC3Dfloat); + void clearStencil(GC3Dint); + void colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha); + void compileShader(WebGLShader*); + + void compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, ArrayBufferView& data); + void compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView& data); + + void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border); + void copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height); + + RefPtr<WebGLBuffer> createBuffer(); + RefPtr<WebGLFramebuffer> createFramebuffer(); + RefPtr<WebGLProgram> createProgram(); + RefPtr<WebGLRenderbuffer> createRenderbuffer(); + RefPtr<WebGLShader> createShader(GC3Denum type); + RefPtr<WebGLTexture> createTexture(); + + void cullFace(GC3Denum mode); + + void deleteBuffer(WebGLBuffer*); + void deleteFramebuffer(WebGLFramebuffer*); + void deleteProgram(WebGLProgram*); + void deleteRenderbuffer(WebGLRenderbuffer*); + void deleteShader(WebGLShader*); + void deleteTexture(WebGLTexture*); + + void depthFunc(GC3Denum); + void depthMask(GC3Dboolean); + void depthRange(GC3Dfloat zNear, GC3Dfloat zFar); + void detachShader(WebGLProgram*, WebGLShader*); + void disable(GC3Denum cap); + void disableVertexAttribArray(GC3Duint index); + void drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count); + void drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset); + + void enable(GC3Denum cap); + void enableVertexAttribArray(GC3Duint index); + void finish(); + void flush(); + void framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer*); + void framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture*, GC3Dint level); + void frontFace(GC3Denum mode); + void generateMipmap(GC3Denum target); + + RefPtr<WebGLActiveInfo> getActiveAttrib(WebGLProgram*, GC3Duint index); + RefPtr<WebGLActiveInfo> getActiveUniform(WebGLProgram*, GC3Duint index); + std::optional<Vector<RefPtr<WebGLShader>>> getAttachedShaders(WebGLProgram*); + GC3Dint getAttribLocation(WebGLProgram*, const String& name); + WebGLAny getBufferParameter(GC3Denum target, GC3Denum pname); + std::optional<WebGLContextAttributes> getContextAttributes(); + GC3Denum getError(); + virtual WebGLExtension* getExtension(const String& name) = 0; + virtual WebGLAny getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname) = 0; + virtual WebGLAny getParameter(GC3Denum pname) = 0; + WebGLAny getProgramParameter(WebGLProgram*, GC3Denum pname); + String getProgramInfoLog(WebGLProgram*); + WebGLAny getRenderbufferParameter(GC3Denum target, GC3Denum pname); + WebGLAny getShaderParameter(WebGLShader*, GC3Denum pname); + String getShaderInfoLog(WebGLShader*); + RefPtr<WebGLShaderPrecisionFormat> getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType); + String getShaderSource(WebGLShader*); + virtual std::optional<Vector<String>> getSupportedExtensions() = 0; + WebGLAny getTexParameter(GC3Denum target, GC3Denum pname); + WebGLAny getUniform(WebGLProgram*, const WebGLUniformLocation*); + RefPtr<WebGLUniformLocation> getUniformLocation(WebGLProgram*, const String&); + WebGLAny getVertexAttrib(GC3Duint index, GC3Denum pname); + long long getVertexAttribOffset(GC3Duint index, GC3Denum pname); + + virtual void hint(GC3Denum target, GC3Denum mode) = 0; + GC3Dboolean isBuffer(WebGLBuffer*); + bool isContextLost() const; + GC3Dboolean isEnabled(GC3Denum cap); + GC3Dboolean isFramebuffer(WebGLFramebuffer*); + GC3Dboolean isProgram(WebGLProgram*); + GC3Dboolean isRenderbuffer(WebGLRenderbuffer*); + GC3Dboolean isShader(WebGLShader*); + GC3Dboolean isTexture(WebGLTexture*); + + void lineWidth(GC3Dfloat); + void linkProgram(WebGLProgram*); + void pixelStorei(GC3Denum pname, GC3Dint param); + void polygonOffset(GC3Dfloat factor, GC3Dfloat units); + void readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView& pixels); + void releaseShaderCompiler(); + virtual void renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) = 0; + void sampleCoverage(GC3Dfloat value, GC3Dboolean invert); + void scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height); + void shaderSource(WebGLShader*, const String&); + void stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask); + void stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask); + void stencilMask(GC3Duint); + void stencilMaskSeparate(GC3Denum face, GC3Duint mask); + void stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass); + void stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass); + + void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&&); + + using TexImageSource = WTF::Variant<RefPtr<ImageData>, RefPtr<HTMLImageElement>, RefPtr<HTMLCanvasElement>, RefPtr<HTMLVideoElement>>; + ExceptionOr<void> texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, std::optional<TexImageSource>); + + void texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param); + void texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param); + + void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&&); + ExceptionOr<void> texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, std::optional<TexImageSource>&&); + + template <class TypedArray, class DataType> + class TypedList { + public: + using VariantType = Variant<RefPtr<TypedArray>, Vector<DataType>>; + + TypedList(VariantType&& variant) + : m_variant(WTFMove(variant)) + { + } + + DataType* data() const + { + return WTF::switchOn(m_variant, + [] (const RefPtr<TypedArray>& typedArray) -> DataType* { return typedArray->data(); }, + [] (const Vector<DataType>& vector) -> DataType* { return const_cast<Vector<DataType>&>(vector).data(); } + ); + } + + GC3Dsizei length() const + { + return WTF::switchOn(m_variant, + [] (const RefPtr<TypedArray>& typedArray) -> GC3Dsizei { return typedArray->length(); }, + [] (const Vector<DataType>& vector) -> GC3Dsizei { return vector.size(); } + ); + } + + private: + VariantType m_variant; + }; + + using Float32List = TypedList<Float32Array, float>; + using Int32List = TypedList<Int32Array, int>; + + void uniform1f(const WebGLUniformLocation*, GC3Dfloat x); + void uniform2f(const WebGLUniformLocation*, GC3Dfloat x, GC3Dfloat y); + void uniform3f(const WebGLUniformLocation*, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z); + void uniform4f(const WebGLUniformLocation*, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w); + + void uniform1i(const WebGLUniformLocation*, GC3Dint x); + void uniform2i(const WebGLUniformLocation*, GC3Dint x, GC3Dint y); + void uniform3i(const WebGLUniformLocation*, GC3Dint x, GC3Dint y, GC3Dint z); + void uniform4i(const WebGLUniformLocation*, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w); + + void uniform1fv(const WebGLUniformLocation*, Float32List&&); + void uniform2fv(const WebGLUniformLocation*, Float32List&&); + void uniform3fv(const WebGLUniformLocation*, Float32List&&); + void uniform4fv(const WebGLUniformLocation*, Float32List&&); + + void uniform1iv(const WebGLUniformLocation*, Int32List&&); + void uniform2iv(const WebGLUniformLocation*, Int32List&&); + void uniform3iv(const WebGLUniformLocation*, Int32List&&); + void uniform4iv(const WebGLUniformLocation*, Int32List&&); + + void uniformMatrix2fv(const WebGLUniformLocation*, GC3Dboolean transpose, Float32List&&); + void uniformMatrix3fv(const WebGLUniformLocation*, GC3Dboolean transpose, Float32List&&); + void uniformMatrix4fv(const WebGLUniformLocation*, GC3Dboolean transpose, Float32List&&); + + void useProgram(WebGLProgram*); + void validateProgram(WebGLProgram*); + + void vertexAttrib1f(GC3Duint index, GC3Dfloat x); + void vertexAttrib2f(GC3Duint index, GC3Dfloat x, GC3Dfloat y); + void vertexAttrib3f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z); + void vertexAttrib4f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w); + + void vertexAttrib1fv(GC3Duint index, Float32List&&); + void vertexAttrib2fv(GC3Duint index, Float32List&&); + void vertexAttrib3fv(GC3Duint index, Float32List&&); + void vertexAttrib4fv(GC3Duint index, Float32List&&); + + void vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, + GC3Dsizei stride, long long offset); + + void viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height); + + // WEBKIT_lose_context support + enum LostContextMode { + // Lost context occurred at the graphics system level. + RealLostContext, + + // Lost context provoked by WEBKIT_lose_context. + SyntheticLostContext + }; + void forceLostContext(LostContextMode); + void recycleContext(); + void forceRestoreContext(); + void loseContextImpl(LostContextMode); + + GraphicsContext3D* graphicsContext3D() const { return m_context.get(); } + WebGLContextGroup* contextGroup() const { return m_contextGroup.get(); } + PlatformLayer* platformLayer() const override; + + void reshape(int width, int height); + + void markLayerComposited(); + void paintRenderingResultsToCanvas() override; + RefPtr<ImageData> paintRenderingResultsToImageData(); + + void removeSharedObject(WebGLSharedObject&); + void removeContextObject(WebGLContextObject&); + + unsigned getMaxVertexAttribs() const { return m_maxVertexAttribs; } + + // Instanced Array helper functions. + void drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount); + void drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount); + void vertexAttribDivisor(GC3Duint index, GC3Duint divisor); + +protected: + WebGLRenderingContextBase(HTMLCanvasElement&, WebGLContextAttributes); + WebGLRenderingContextBase(HTMLCanvasElement&, Ref<GraphicsContext3D>&&, WebGLContextAttributes); + + friend class WebGLDrawBuffers; + friend class WebGLFramebuffer; + friend class WebGLObject; + friend class OESVertexArrayObject; + friend class WebGLDebugShaders; + friend class WebGLCompressedTextureATC; + friend class WebGLCompressedTexturePVRTC; + friend class WebGLCompressedTextureS3TC; + friend class WebGLRenderingContextErrorMessageCallback; + friend class WebGLVertexArrayObjectOES; + friend class WebGLVertexArrayObject; + friend class WebGLVertexArrayObjectBase; + + virtual void initializeNewContext(); + virtual void initializeVertexArrayObjects() = 0; + void setupFlags(); + + // ActiveDOMObject + bool hasPendingActivity() const override; + void stop() override; + const char* activeDOMObjectName() const override; + bool canSuspendForDocumentSuspension() const override; + + void addSharedObject(WebGLSharedObject&); + void addContextObject(WebGLContextObject&); + void detachAndRemoveAllObjects(); + + void destroyGraphicsContext3D(); + void markContextChanged(); + + void addActivityStateChangeObserverIfNecessary(); + void removeActivityStateChangeObserver(); + + // Query whether it is built on top of compliant GLES2 implementation. + bool isGLES2Compliant() { return m_isGLES2Compliant; } + // Query if the GL implementation is NPOT strict. + bool isGLES2NPOTStrict() { return m_isGLES2NPOTStrict; } + // Query if depth_stencil buffer is supported. + bool isDepthStencilSupported() { return m_isDepthStencilSupported; } + + // Helper to return the size in bytes of OpenGL data types + // like GL_FLOAT, GL_INT, etc. + unsigned int sizeInBytes(GC3Denum type); + + // Basic validation of count and offset against number of elements in element array buffer + bool validateElementArraySize(GC3Dsizei count, GC3Denum type, GC3Dintptr offset); + + // Conservative but quick index validation + virtual bool validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired) = 0; + + // Precise but slow index validation -- only done if conservative checks fail + bool validateIndexArrayPrecise(GC3Dsizei count, GC3Denum type, GC3Dintptr offset, unsigned& numElementsRequired); + bool validateVertexAttributes(unsigned elementCount, unsigned primitiveCount = 0); + + bool validateWebGLObject(const char*, WebGLObject*); + + bool validateDrawArrays(const char* functionName, GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount); + bool validateDrawElements(const char* functionName, GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, unsigned& numElements, GC3Dsizei primcount); + bool validateNPOTTextureLevel(GC3Dsizei width, GC3Dsizei height, GC3Dint level, const char* functionName); + + // Adds a compressed texture format. + void addCompressedTextureFormat(GC3Denum); + + RefPtr<Image> drawImageIntoBuffer(Image&, int width, int height, int deviceScaleFactor); + +#if ENABLE(VIDEO) + RefPtr<Image> videoFrameToImage(HTMLVideoElement*, BackingStoreCopy); +#endif + + WebGLTexture::TextureExtensionFlag textureExtensionFlags() const; + + bool enableSupportedExtension(const char* extensionNameLiteral); + + RefPtr<GraphicsContext3D> m_context; + RefPtr<WebGLContextGroup> m_contextGroup; + + // Dispatches a context lost event once it is determined that one is needed. + // This is used both for synthetic and real context losses. For real ones, it's + // likely that there's no JavaScript on the stack, but that might be dependent + // on how exactly the platform discovers that the context was lost. For better + // portability we always defer the dispatch of the event. + Timer m_dispatchContextLostEventTimer; + bool m_restoreAllowed { false }; + Timer m_restoreTimer; + + bool m_needsUpdate; + bool m_markedCanvasDirty; + HashSet<WebGLContextObject*> m_contextObjects; + + // List of bound VBO's. Used to maintain info about sizes for ARRAY_BUFFER and stored values for ELEMENT_ARRAY_BUFFER + RefPtr<WebGLBuffer> m_boundArrayBuffer; + RefPtr<WebGLBuffer> m_boundCopyReadBuffer; + RefPtr<WebGLBuffer> m_boundCopyWriteBuffer; + RefPtr<WebGLBuffer> m_boundPixelPackBuffer; + RefPtr<WebGLBuffer> m_boundPixelUnpackBuffer; + RefPtr<WebGLBuffer> m_boundTransformFeedbackBuffer; + RefPtr<WebGLBuffer> m_boundUniformBuffer; + + RefPtr<WebGLVertexArrayObjectBase> m_defaultVertexArrayObject; + RefPtr<WebGLVertexArrayObjectBase> m_boundVertexArrayObject; + + void setBoundVertexArrayObject(WebGLVertexArrayObjectBase* arrayObject) + { + m_boundVertexArrayObject = arrayObject ? arrayObject : m_defaultVertexArrayObject; + } + + class VertexAttribValue { + public: + VertexAttribValue() + { + initValue(); + } + + void initValue() + { + value[0] = 0.0f; + value[1] = 0.0f; + value[2] = 0.0f; + value[3] = 1.0f; + } + + GC3Dfloat value[4]; + }; + Vector<VertexAttribValue> m_vertexAttribValue; + unsigned m_maxVertexAttribs; + RefPtr<WebGLBuffer> m_vertexAttrib0Buffer; + long m_vertexAttrib0BufferSize; + GC3Dfloat m_vertexAttrib0BufferValue[4]; + bool m_forceAttrib0BufferRefill; + bool m_vertexAttrib0UsedBefore; + + RefPtr<WebGLProgram> m_currentProgram; + RefPtr<WebGLFramebuffer> m_framebufferBinding; + RefPtr<WebGLRenderbuffer> m_renderbufferBinding; + struct TextureUnitState { + RefPtr<WebGLTexture> texture2DBinding; + RefPtr<WebGLTexture> textureCubeMapBinding; + }; + Vector<TextureUnitState> m_textureUnits; + HashSet<unsigned, DefaultHash<unsigned>::Hash, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> m_unrenderableTextureUnits; + + unsigned long m_activeTextureUnit; + + RefPtr<WebGLTexture> m_blackTexture2D; + RefPtr<WebGLTexture> m_blackTextureCubeMap; + + Vector<GC3Denum> m_compressedTextureFormats; + + // Fixed-size cache of reusable image buffers for video texImage2D calls. + class LRUImageBufferCache { + public: + LRUImageBufferCache(int capacity); + // The pointer returned is owned by the image buffer map. + ImageBuffer* imageBuffer(const IntSize& size); + private: + void bubbleToFront(int idx); + std::unique_ptr<std::unique_ptr<ImageBuffer>[]> m_buffers; + int m_capacity; + }; + LRUImageBufferCache m_generatedImageCache { 0 }; + + GC3Dint m_maxTextureSize; + GC3Dint m_maxCubeMapTextureSize; + GC3Dint m_maxRenderbufferSize; + GC3Dint m_maxViewportDims[2] { 0, 0 }; + GC3Dint m_maxTextureLevel; + GC3Dint m_maxCubeMapTextureLevel; + + GC3Dint m_maxDrawBuffers; + GC3Dint m_maxColorAttachments; + GC3Denum m_backDrawBuffer; + bool m_drawBuffersWebGLRequirementsChecked; + bool m_drawBuffersSupported; + + GC3Dint m_packAlignment; + GC3Dint m_unpackAlignment; + bool m_unpackFlipY; + bool m_unpackPremultiplyAlpha; + GC3Denum m_unpackColorspaceConversion; + bool m_contextLost { false }; + LostContextMode m_contextLostMode { SyntheticLostContext }; + WebGLContextAttributes m_attributes; + + bool m_layerCleared; + GC3Dfloat m_clearColor[4]; + bool m_scissorEnabled; + GC3Dfloat m_clearDepth; + GC3Dint m_clearStencil; + GC3Dboolean m_colorMask[4]; + GC3Dboolean m_depthMask; + + bool m_stencilEnabled; + GC3Duint m_stencilMask, m_stencilMaskBack; + GC3Dint m_stencilFuncRef, m_stencilFuncRefBack; // Note that these are the user specified values, not the internal clamped value. + GC3Duint m_stencilFuncMask, m_stencilFuncMaskBack; + + bool m_isGLES2Compliant; + bool m_isGLES2NPOTStrict; + bool m_isDepthStencilSupported; + bool m_isRobustnessEXTSupported; + + bool m_synthesizedErrorsToConsole { true }; + int m_numGLErrorsToConsoleAllowed; + + // A WebGLRenderingContext can be created in a state where it appears as + // a valid and active context, but will not execute any important operations + // until its load policy is completely resolved. + bool m_isPendingPolicyResolution { false }; + bool m_hasRequestedPolicyResolution { false }; + bool isContextLostOrPending(); + + // Enabled extension objects. + // FIXME: Move some of these to WebGLRenderingContext, the ones not needed for WebGL2 + std::unique_ptr<EXTFragDepth> m_extFragDepth; + std::unique_ptr<EXTBlendMinMax> m_extBlendMinMax; + std::unique_ptr<EXTsRGB> m_extsRGB; + std::unique_ptr<EXTTextureFilterAnisotropic> m_extTextureFilterAnisotropic; + std::unique_ptr<EXTShaderTextureLOD> m_extShaderTextureLOD; + std::unique_ptr<OESTextureFloat> m_oesTextureFloat; + std::unique_ptr<OESTextureFloatLinear> m_oesTextureFloatLinear; + std::unique_ptr<OESTextureHalfFloat> m_oesTextureHalfFloat; + std::unique_ptr<OESTextureHalfFloatLinear> m_oesTextureHalfFloatLinear; + std::unique_ptr<OESStandardDerivatives> m_oesStandardDerivatives; + std::unique_ptr<OESVertexArrayObject> m_oesVertexArrayObject; + std::unique_ptr<OESElementIndexUint> m_oesElementIndexUint; + std::unique_ptr<WebGLLoseContext> m_webglLoseContext; + std::unique_ptr<WebGLDebugRendererInfo> m_webglDebugRendererInfo; + std::unique_ptr<WebGLDebugShaders> m_webglDebugShaders; + std::unique_ptr<WebGLCompressedTextureATC> m_webglCompressedTextureATC; + std::unique_ptr<WebGLCompressedTexturePVRTC> m_webglCompressedTexturePVRTC; + std::unique_ptr<WebGLCompressedTextureS3TC> m_webglCompressedTextureS3TC; + std::unique_ptr<WebGLDepthTexture> m_webglDepthTexture; + std::unique_ptr<WebGLDrawBuffers> m_webglDrawBuffers; + std::unique_ptr<ANGLEInstancedArrays> m_angleInstancedArrays; + + // Helpers for getParameter and other similar functions. + bool getBooleanParameter(GC3Denum); + Vector<bool> getBooleanArrayParameter(GC3Denum); + float getFloatParameter(GC3Denum); + int getIntParameter(GC3Denum); + unsigned getUnsignedIntParameter(GC3Denum); + long long getInt64Parameter(GC3Denum); + RefPtr<Float32Array> getWebGLFloatArrayParameter(GC3Denum); + RefPtr<Int32Array> getWebGLIntArrayParameter(GC3Denum); + + // Clear the backbuffer if it was composited since the last operation. + // clearMask is set to the bitfield of any clear that would happen anyway at this time + // and the function returns true if that clear is now unnecessary. + bool clearIfComposited(GC3Dbitfield clearMask = 0); + + // Helper to restore state that clearing the framebuffer may destroy. + void restoreStateAfterClear(); + + void texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels); + void texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha); + void texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum internalformat, GC3Denum format, GC3Denum type, const void* pixels); + void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha); + + bool checkTextureCompleteness(const char*, bool); + + void createFallbackBlackTextures1x1(); + + // Helper function for copyTex{Sub}Image, check whether the internalformat + // and the color buffer format of the current bound framebuffer combination + // is valid. + bool isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat, + GC3Denum colorBufferFormat); + + // Helper function to get the bound framebuffer's color buffer format. + GC3Denum getBoundFramebufferColorFormat(); + + // Helper function to get the bound framebuffer's width. + int getBoundFramebufferWidth(); + + // Helper function to get the bound framebuffer's height. + int getBoundFramebufferHeight(); + + // Helper function to verify limits on the length of uniform and attribute locations. + bool validateLocationLength(const char* functionName, const String&); + + // Helper function to check if size is non-negative. + // Generate GL error and return false for negative inputs; otherwise, return true. + bool validateSize(const char* functionName, GC3Dint x, GC3Dint y); + + // Helper function to check if all characters in the string belong to the + // ASCII subset as defined in GLSL ES 1.0 spec section 3.1. + bool validateString(const char* functionName, const String&); + + // Helper function to check target and texture bound to the target. + // Generate GL errors and return 0 if target is invalid or texture bound is + // null. Otherwise, return the texture bound to the target. + WebGLTexture* validateTextureBinding(const char* functionName, GC3Denum target, bool useSixEnumsForCubeMap); + + // Helper function to check input format/type for functions {copy}Tex{Sub}Image. + // Generates GL error and returns false if parameters are invalid. + bool validateTexFuncFormatAndType(const char* functionName, GC3Denum internalformat, GC3Denum format, GC3Denum type, GC3Dint level); + + // Helper function to check input level for functions {copy}Tex{Sub}Image. + // Generates GL error and returns false if level is invalid. + bool validateTexFuncLevel(const char* functionName, GC3Denum target, GC3Dint level); + + enum TexFuncValidationFunctionType { + TexImage, + TexSubImage, + CopyTexImage + }; + + enum TexFuncValidationSourceType { + SourceArrayBufferView, + SourceImageData, + SourceHTMLImageElement, + SourceHTMLCanvasElement, + SourceHTMLVideoElement, + }; + + // Helper function for tex{Sub}Image2D to check if the input format/type/level/target/width/height/border/xoffset/yoffset are valid. + // Otherwise, it would return quickly without doing other work. + bool validateTexFunc(const char* functionName, TexFuncValidationFunctionType, TexFuncValidationSourceType, GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, + GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint xoffset, GC3Dint yoffset); + + // Helper function to check input parameters for functions {copy}Tex{Sub}Image. + // Generates GL error and returns false if parameters are invalid. + bool validateTexFuncParameters(const char* functionName, + TexFuncValidationFunctionType, + GC3Denum target, GC3Dint level, + GC3Denum internalformat, + GC3Dsizei width, GC3Dsizei height, GC3Dint border, + GC3Denum format, GC3Denum type); + + enum NullDisposition { + NullAllowed, + NullNotAllowed + }; + + // Helper function to validate that the given ArrayBufferView + // is of the correct type and contains enough data for the texImage call. + // Generates GL error and returns false if parameters are invalid. + bool validateTexFuncData(const char* functionName, GC3Dint level, + GC3Dsizei width, GC3Dsizei height, + GC3Denum internalformat, GC3Denum format, GC3Denum type, + ArrayBufferView* pixels, + NullDisposition); + + // Helper function to validate a given texture format is settable as in + // you can supply data to texImage2D, or call texImage2D, copyTexImage2D and + // copyTexSubImage2D. + // Generates GL error and returns false if the format is not settable. + bool validateSettableTexInternalFormat(const char* functionName, GC3Denum format); + + // Helper function to validate compressed texture data is correct size + // for the given format and dimensions. + bool validateCompressedTexFuncData(const char* functionName, GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView& pixels); + + // Helper function for validating compressed texture formats. + bool validateCompressedTexFormat(GC3Denum format); + + // Helper function to validate compressed texture dimensions are valid for + // the given format. + bool validateCompressedTexDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum format); + + // Helper function to validate compressed texture dimensions are valid for + // the given format. + bool validateCompressedTexSubDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, + GC3Dsizei width, GC3Dsizei height, GC3Denum format, WebGLTexture*); + + // Helper function to validate mode for draw{Arrays/Elements}. + bool validateDrawMode(const char* functionName, GC3Denum); + + // Helper function to validate if front/back stencilMask and stencilFunc settings are the same. + bool validateStencilSettings(const char* functionName); + + // Helper function to validate stencil func. + bool validateStencilFunc(const char* functionName, GC3Denum); + + // Helper function for texParameterf and texParameteri. + void texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat parami, GC3Dint paramf, bool isFloat); + + // Helper function to print GL errors to console. + void printGLErrorToConsole(const String&); + void printGLWarningToConsole(const char* function, const char* reason); + + // Helper function to print warnings to console. Currently + // used only to warn about use of obsolete functions. + void printWarningToConsole(const String&); + + // Helper function to validate input parameters for framebuffer functions. + // Generate GL error if parameters are illegal. + virtual bool validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment) = 0; + + // Helper function to validate blend equation mode. + virtual bool validateBlendEquation(const char* functionName, GC3Denum) = 0; + + // Helper function to validate blend func factors. + bool validateBlendFuncFactors(const char* functionName, GC3Denum src, GC3Denum dst); + + // Helper function to validate a GL capability. + virtual bool validateCapability(const char* functionName, GC3Denum) = 0; + + // Helper function to validate input parameters for uniform functions. + bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, const Float32List&, GC3Dsizei mod); + bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, const Int32List&, GC3Dsizei mod); + bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, void*, GC3Dsizei, GC3Dsizei mod); + bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GC3Dboolean transpose, const Float32List&, GC3Dsizei mod); + bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GC3Dboolean transpose, void*, GC3Dsizei, GC3Dsizei mod); + + // Helper function to validate parameters for bufferData. + // Return the current bound buffer to target, or 0 if parameters are invalid. + WebGLBuffer* validateBufferDataParameters(const char* functionName, GC3Denum target, GC3Denum usage); + + // Helper function for tex{Sub}Image2D to make sure image is ready. + bool validateHTMLImageElement(const char* functionName, HTMLImageElement*, ExceptionCode&); + bool validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement*, ExceptionCode&); +#if ENABLE(VIDEO) + bool validateHTMLVideoElement(const char* functionName, HTMLVideoElement*, ExceptionCode&); +#endif + + // Helper functions for vertexAttribNf{v}. + void vertexAttribfImpl(const char* functionName, GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat, GC3Dfloat, GC3Dfloat, GC3Dfloat); + void vertexAttribfvImpl(const char* functionName, GC3Duint index, Float32List&&, GC3Dsizei expectedSize); + + // Helper function for delete* (deleteBuffer, deleteProgram, etc) functions. + // Return false if caller should return without further processing. + bool deleteObject(WebGLObject*); + + // Helper function for bind* (bindBuffer, bindTexture, etc) and useProgram. + // If the object has already been deleted, set deleted to true upon return. + // Return false if caller should return without further processing. + bool checkObjectToBeBound(const char* functionName, WebGLObject*, bool& deleted); + + // Helpers for simulating vertexAttrib0. + void initVertexAttrib0(); + bool simulateVertexAttrib0(GC3Dsizei numVertex); + bool validateSimulatedVertexAttrib0(GC3Dsizei numVertex); + void restoreStatesAfterVertexAttrib0Simulation(); + + void dispatchContextLostEvent(); + // Helper for restoration after context lost. + void maybeRestoreContext(); + + // Wrapper for GraphicsContext3D::synthesizeGLError that sends a message to the JavaScript console. + enum ConsoleDisplayPreference { DisplayInConsole, DontDisplayInConsole }; + void synthesizeGLError(GC3Denum, const char* functionName, const char* description, ConsoleDisplayPreference = DisplayInConsole); + + String ensureNotNull(const String&) const; + + // Enable or disable stencil test based on user setting and whether the current FBO has a stencil buffer. + void applyStencilTest(); + + // Helper for enabling or disabling a capability. + void enableOrDisable(GC3Denum capability, bool enable); + + // Clamp the width and height to GL_MAX_VIEWPORT_DIMS. + IntSize clampedCanvasSize(); + + virtual GC3Dint getMaxDrawBuffers() = 0; + virtual GC3Dint getMaxColorAttachments() = 0; + + void setBackDrawBuffer(GC3Denum); + + void restoreCurrentFramebuffer(); + void restoreCurrentTexture2D(); + + // Check if EXT_draw_buffers extension is supported and if it satisfies the WebGL requirements. + bool supportsDrawBuffers(); + +private: + bool validateArrayBufferType(const char* functionName, GC3Denum type, std::optional<JSC::TypedArrayType>); + void registerWithWebGLStateTracker(); + void checkForContextLossHandling(); + + void activityStateDidChange(ActivityState::Flags oldActivityState, ActivityState::Flags newActivityState) override; + + WebGLStateTracker::Token m_trackerToken; + Timer m_checkForContextLossHandlingTimer; +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CANVASRENDERINGCONTEXT(WebCore::WebGLRenderingContextBase, is3d()) + +#endif diff --git a/Source/WebCore/html/canvas/WebGLRenderingContextBase.idl b/Source/WebCore/html/canvas/WebGLRenderingContextBase.idl new file mode 100644 index 000000000..63b64cdeb --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLRenderingContextBase.idl @@ -0,0 +1,665 @@ +/* + * Copyright (C) 2015 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +typedef unsigned long GLenum; +typedef boolean GLboolean; +typedef unsigned long GLbitfield; +typedef byte GLbyte; /* 'byte' should be a signed 8 bit type. */ +typedef short GLshort; +typedef long GLint; +typedef long GLsizei; +typedef long long GLintptr; +typedef long long GLsizeiptr; +typedef octet GLubyte; /* 'octet' should be an unsigned 8 bit type. */ +typedef unsigned short GLushort; +typedef unsigned long GLuint; +typedef unrestricted float GLfloat; +typedef unrestricted float GLclampf; +typedef (ArrayBuffer or ArrayBufferView) BufferDataSource; +typedef (Float32Array or sequence<GLfloat>) Float32List; +typedef (Int32Array or sequence<GLint>) Int32List; + +// FIXME: Should allow ImageBitmap too. +typedef (ImageData or HTMLImageElement or HTMLCanvasElement or HTMLVideoElement) TexImageSource; + +[ + Conditional=WEBGL, + CustomIsReachable, + CustomToJSObject, + DoNotCheckConstants, + JSCustomMarkFunction, + NoInterfaceObject, +] interface WebGLRenderingContextBase { + + // back-reference to the canvas + readonly attribute HTMLCanvasElement canvas; + + /* ClearBufferMask */ + const GLenum DEPTH_BUFFER_BIT = 0x00000100; + const GLenum STENCIL_BUFFER_BIT = 0x00000400; + const GLenum COLOR_BUFFER_BIT = 0x00004000; + + /* BeginMode */ + const GLenum POINTS = 0x0000; + const GLenum LINES = 0x0001; + const GLenum LINE_LOOP = 0x0002; + const GLenum LINE_STRIP = 0x0003; + const GLenum TRIANGLES = 0x0004; + const GLenum TRIANGLE_STRIP = 0x0005; + const GLenum TRIANGLE_FAN = 0x0006; + + /* AlphaFunction (not supported in ES20) */ + /* NEVER */ + /* LESS */ + /* EQUAL */ + /* LEQUAL */ + /* GREATER */ + /* NOTEQUAL */ + /* GEQUAL */ + /* ALWAYS */ + + /* BlendingFactorDest */ + const GLenum ZERO = 0; + const GLenum ONE = 1; + const GLenum SRC_COLOR = 0x0300; + const GLenum ONE_MINUS_SRC_COLOR = 0x0301; + const GLenum SRC_ALPHA = 0x0302; + const GLenum ONE_MINUS_SRC_ALPHA = 0x0303; + const GLenum DST_ALPHA = 0x0304; + const GLenum ONE_MINUS_DST_ALPHA = 0x0305; + + /* BlendingFactorSrc */ + /* ZERO */ + /* ONE */ + const GLenum DST_COLOR = 0x0306; + const GLenum ONE_MINUS_DST_COLOR = 0x0307; + const GLenum SRC_ALPHA_SATURATE = 0x0308; + /* SRC_ALPHA */ + /* ONE_MINUS_SRC_ALPHA */ + /* DST_ALPHA */ + /* ONE_MINUS_DST_ALPHA */ + + /* BlendEquationSeparate */ + const GLenum FUNC_ADD = 0x8006; + const GLenum BLEND_EQUATION = 0x8009; + const GLenum BLEND_EQUATION_RGB = 0x8009; /* same as BLEND_EQUATION */ + const GLenum BLEND_EQUATION_ALPHA = 0x883D; + + /* BlendSubtract */ + const GLenum FUNC_SUBTRACT = 0x800A; + const GLenum FUNC_REVERSE_SUBTRACT = 0x800B; + + /* Separate Blend Functions */ + const GLenum BLEND_DST_RGB = 0x80C8; + const GLenum BLEND_SRC_RGB = 0x80C9; + const GLenum BLEND_DST_ALPHA = 0x80CA; + const GLenum BLEND_SRC_ALPHA = 0x80CB; + const GLenum CONSTANT_COLOR = 0x8001; + const GLenum ONE_MINUS_CONSTANT_COLOR = 0x8002; + const GLenum CONSTANT_ALPHA = 0x8003; + const GLenum ONE_MINUS_CONSTANT_ALPHA = 0x8004; + const GLenum BLEND_COLOR = 0x8005; + + /* Buffer Objects */ + const GLenum ARRAY_BUFFER = 0x8892; + const GLenum ELEMENT_ARRAY_BUFFER = 0x8893; + const GLenum ARRAY_BUFFER_BINDING = 0x8894; + const GLenum ELEMENT_ARRAY_BUFFER_BINDING = 0x8895; + + const GLenum STREAM_DRAW = 0x88E0; + const GLenum STATIC_DRAW = 0x88E4; + const GLenum DYNAMIC_DRAW = 0x88E8; + + const GLenum BUFFER_SIZE = 0x8764; + const GLenum BUFFER_USAGE = 0x8765; + + const GLenum CURRENT_VERTEX_ATTRIB = 0x8626; + + /* CullFaceMode */ + const GLenum FRONT = 0x0404; + const GLenum BACK = 0x0405; + const GLenum FRONT_AND_BACK = 0x0408; + + /* DepthFunction */ + /* NEVER */ + /* LESS */ + /* EQUAL */ + /* LEQUAL */ + /* GREATER */ + /* NOTEQUAL */ + /* GEQUAL */ + /* ALWAYS */ + + /* EnableCap */ + const GLenum TEXTURE_2D = 0x0DE1; + const GLenum CULL_FACE = 0x0B44; + const GLenum BLEND = 0x0BE2; + const GLenum DITHER = 0x0BD0; + const GLenum STENCIL_TEST = 0x0B90; + const GLenum DEPTH_TEST = 0x0B71; + const GLenum SCISSOR_TEST = 0x0C11; + const GLenum POLYGON_OFFSET_FILL = 0x8037; + const GLenum SAMPLE_ALPHA_TO_COVERAGE = 0x809E; + const GLenum SAMPLE_COVERAGE = 0x80A0; + + /* ErrorCode */ + const GLenum NO_ERROR = 0; + const GLenum INVALID_ENUM = 0x0500; + const GLenum INVALID_VALUE = 0x0501; + const GLenum INVALID_OPERATION = 0x0502; + const GLenum OUT_OF_MEMORY = 0x0505; + + /* FrontFaceDirection */ + const GLenum CW = 0x0900; + const GLenum CCW = 0x0901; + + /* GetPName */ + const GLenum LINE_WIDTH = 0x0B21; + const GLenum ALIASED_POINT_SIZE_RANGE = 0x846D; + const GLenum ALIASED_LINE_WIDTH_RANGE = 0x846E; + const GLenum CULL_FACE_MODE = 0x0B45; + const GLenum FRONT_FACE = 0x0B46; + const GLenum DEPTH_RANGE = 0x0B70; + const GLenum DEPTH_WRITEMASK = 0x0B72; + const GLenum DEPTH_CLEAR_VALUE = 0x0B73; + const GLenum DEPTH_FUNC = 0x0B74; + const GLenum STENCIL_CLEAR_VALUE = 0x0B91; + const GLenum STENCIL_FUNC = 0x0B92; + const GLenum STENCIL_FAIL = 0x0B94; + const GLenum STENCIL_PASS_DEPTH_FAIL = 0x0B95; + const GLenum STENCIL_PASS_DEPTH_PASS = 0x0B96; + const GLenum STENCIL_REF = 0x0B97; + const GLenum STENCIL_VALUE_MASK = 0x0B93; + const GLenum STENCIL_WRITEMASK = 0x0B98; + const GLenum STENCIL_BACK_FUNC = 0x8800; + const GLenum STENCIL_BACK_FAIL = 0x8801; + const GLenum STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802; + const GLenum STENCIL_BACK_PASS_DEPTH_PASS = 0x8803; + const GLenum STENCIL_BACK_REF = 0x8CA3; + const GLenum STENCIL_BACK_VALUE_MASK = 0x8CA4; + const GLenum STENCIL_BACK_WRITEMASK = 0x8CA5; + const GLenum VIEWPORT = 0x0BA2; + const GLenum SCISSOR_BOX = 0x0C10; + /* SCISSOR_TEST */ + const GLenum COLOR_CLEAR_VALUE = 0x0C22; + const GLenum COLOR_WRITEMASK = 0x0C23; + const GLenum UNPACK_ALIGNMENT = 0x0CF5; + const GLenum PACK_ALIGNMENT = 0x0D05; + const GLenum MAX_TEXTURE_SIZE = 0x0D33; + const GLenum MAX_VIEWPORT_DIMS = 0x0D3A; + const GLenum SUBPIXEL_BITS = 0x0D50; + const GLenum RED_BITS = 0x0D52; + const GLenum GREEN_BITS = 0x0D53; + const GLenum BLUE_BITS = 0x0D54; + const GLenum ALPHA_BITS = 0x0D55; + const GLenum DEPTH_BITS = 0x0D56; + const GLenum STENCIL_BITS = 0x0D57; + const GLenum POLYGON_OFFSET_UNITS = 0x2A00; + /* POLYGON_OFFSET_FILL */ + const GLenum POLYGON_OFFSET_FACTOR = 0x8038; + const GLenum TEXTURE_BINDING_2D = 0x8069; + const GLenum SAMPLE_BUFFERS = 0x80A8; + const GLenum SAMPLES = 0x80A9; + const GLenum SAMPLE_COVERAGE_VALUE = 0x80AA; + const GLenum SAMPLE_COVERAGE_INVERT = 0x80AB; + + /* GetTextureParameter */ + /* TEXTURE_MAG_FILTER */ + /* TEXTURE_MIN_FILTER */ + /* TEXTURE_WRAP_S */ + /* TEXTURE_WRAP_T */ + + const GLenum COMPRESSED_TEXTURE_FORMATS = 0x86A3; + + /* HintMode */ + const GLenum DONT_CARE = 0x1100; + const GLenum FASTEST = 0x1101; + const GLenum NICEST = 0x1102; + + /* HintTarget */ + const GLenum GENERATE_MIPMAP_HINT = 0x8192; + + /* DataType */ + const GLenum BYTE = 0x1400; + const GLenum UNSIGNED_BYTE = 0x1401; + const GLenum SHORT = 0x1402; + const GLenum UNSIGNED_SHORT = 0x1403; + const GLenum INT = 0x1404; + const GLenum UNSIGNED_INT = 0x1405; + const GLenum FLOAT = 0x1406; + + /* PixelFormat */ + const GLenum DEPTH_COMPONENT = 0x1902; + const GLenum ALPHA = 0x1906; + const GLenum RGB = 0x1907; + const GLenum RGBA = 0x1908; + const GLenum LUMINANCE = 0x1909; + const GLenum LUMINANCE_ALPHA = 0x190A; + + /* PixelType */ + /* UNSIGNED_BYTE */ + const GLenum UNSIGNED_SHORT_4_4_4_4 = 0x8033; + const GLenum UNSIGNED_SHORT_5_5_5_1 = 0x8034; + const GLenum UNSIGNED_SHORT_5_6_5 = 0x8363; + + /* Shaders */ + const GLenum FRAGMENT_SHADER = 0x8B30; + const GLenum VERTEX_SHADER = 0x8B31; + const GLenum MAX_VERTEX_ATTRIBS = 0x8869; + const GLenum MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB; + const GLenum MAX_VARYING_VECTORS = 0x8DFC; + const GLenum MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D; + const GLenum MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C; + const GLenum MAX_TEXTURE_IMAGE_UNITS = 0x8872; + const GLenum MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD; + const GLenum SHADER_TYPE = 0x8B4F; + const GLenum DELETE_STATUS = 0x8B80; + const GLenum LINK_STATUS = 0x8B82; + const GLenum VALIDATE_STATUS = 0x8B83; + const GLenum ATTACHED_SHADERS = 0x8B85; + const GLenum ACTIVE_UNIFORMS = 0x8B86; + const GLenum ACTIVE_ATTRIBUTES = 0x8B89; + const GLenum SHADING_LANGUAGE_VERSION = 0x8B8C; + const GLenum CURRENT_PROGRAM = 0x8B8D; + + /* StencilFunction */ + const GLenum NEVER = 0x0200; + const GLenum LESS = 0x0201; + const GLenum EQUAL = 0x0202; + const GLenum LEQUAL = 0x0203; + const GLenum GREATER = 0x0204; + const GLenum NOTEQUAL = 0x0205; + const GLenum GEQUAL = 0x0206; + const GLenum ALWAYS = 0x0207; + + /* StencilOp */ + /* ZERO */ + const GLenum KEEP = 0x1E00; + const GLenum REPLACE = 0x1E01; + const GLenum INCR = 0x1E02; + const GLenum DECR = 0x1E03; + const GLenum INVERT = 0x150A; + const GLenum INCR_WRAP = 0x8507; + const GLenum DECR_WRAP = 0x8508; + + /* StringName */ + const GLenum VENDOR = 0x1F00; + const GLenum RENDERER = 0x1F01; + const GLenum VERSION = 0x1F02; + + /* TextureMagFilter */ + const GLenum NEAREST = 0x2600; + const GLenum LINEAR = 0x2601; + + /* TextureMinFilter */ + /* NEAREST */ + /* LINEAR */ + const GLenum NEAREST_MIPMAP_NEAREST = 0x2700; + const GLenum LINEAR_MIPMAP_NEAREST = 0x2701; + const GLenum NEAREST_MIPMAP_LINEAR = 0x2702; + const GLenum LINEAR_MIPMAP_LINEAR = 0x2703; + + /* TextureParameterName */ + const GLenum TEXTURE_MAG_FILTER = 0x2800; + const GLenum TEXTURE_MIN_FILTER = 0x2801; + const GLenum TEXTURE_WRAP_S = 0x2802; + const GLenum TEXTURE_WRAP_T = 0x2803; + + /* TextureTarget */ + /* TEXTURE_2D */ + const GLenum TEXTURE = 0x1702; + + const GLenum TEXTURE_CUBE_MAP = 0x8513; + const GLenum TEXTURE_BINDING_CUBE_MAP = 0x8514; + const GLenum TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515; + const GLenum TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516; + const GLenum TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517; + const GLenum TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518; + const GLenum TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519; + const GLenum TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A; + const GLenum MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C; + + /* TextureUnit */ + const GLenum TEXTURE0 = 0x84C0; + const GLenum TEXTURE1 = 0x84C1; + const GLenum TEXTURE2 = 0x84C2; + const GLenum TEXTURE3 = 0x84C3; + const GLenum TEXTURE4 = 0x84C4; + const GLenum TEXTURE5 = 0x84C5; + const GLenum TEXTURE6 = 0x84C6; + const GLenum TEXTURE7 = 0x84C7; + const GLenum TEXTURE8 = 0x84C8; + const GLenum TEXTURE9 = 0x84C9; + const GLenum TEXTURE10 = 0x84CA; + const GLenum TEXTURE11 = 0x84CB; + const GLenum TEXTURE12 = 0x84CC; + const GLenum TEXTURE13 = 0x84CD; + const GLenum TEXTURE14 = 0x84CE; + const GLenum TEXTURE15 = 0x84CF; + const GLenum TEXTURE16 = 0x84D0; + const GLenum TEXTURE17 = 0x84D1; + const GLenum TEXTURE18 = 0x84D2; + const GLenum TEXTURE19 = 0x84D3; + const GLenum TEXTURE20 = 0x84D4; + const GLenum TEXTURE21 = 0x84D5; + const GLenum TEXTURE22 = 0x84D6; + const GLenum TEXTURE23 = 0x84D7; + const GLenum TEXTURE24 = 0x84D8; + const GLenum TEXTURE25 = 0x84D9; + const GLenum TEXTURE26 = 0x84DA; + const GLenum TEXTURE27 = 0x84DB; + const GLenum TEXTURE28 = 0x84DC; + const GLenum TEXTURE29 = 0x84DD; + const GLenum TEXTURE30 = 0x84DE; + const GLenum TEXTURE31 = 0x84DF; + const GLenum ACTIVE_TEXTURE = 0x84E0; + + /* TextureWrapMode */ + const GLenum REPEAT = 0x2901; + const GLenum CLAMP_TO_EDGE = 0x812F; + const GLenum MIRRORED_REPEAT = 0x8370; + + /* Uniform Types */ + const GLenum FLOAT_VEC2 = 0x8B50; + const GLenum FLOAT_VEC3 = 0x8B51; + const GLenum FLOAT_VEC4 = 0x8B52; + const GLenum INT_VEC2 = 0x8B53; + const GLenum INT_VEC3 = 0x8B54; + const GLenum INT_VEC4 = 0x8B55; + const GLenum BOOL = 0x8B56; + const GLenum BOOL_VEC2 = 0x8B57; + const GLenum BOOL_VEC3 = 0x8B58; + const GLenum BOOL_VEC4 = 0x8B59; + const GLenum FLOAT_MAT2 = 0x8B5A; + const GLenum FLOAT_MAT3 = 0x8B5B; + const GLenum FLOAT_MAT4 = 0x8B5C; + const GLenum SAMPLER_2D = 0x8B5E; + const GLenum SAMPLER_CUBE = 0x8B60; + + /* Vertex Arrays */ + const GLenum VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622; + const GLenum VERTEX_ATTRIB_ARRAY_SIZE = 0x8623; + const GLenum VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624; + const GLenum VERTEX_ATTRIB_ARRAY_TYPE = 0x8625; + const GLenum VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A; + const GLenum VERTEX_ATTRIB_ARRAY_POINTER = 0x8645; + const GLenum VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F; + + /* Read Format */ + const GLenum IMPLEMENTATION_COLOR_READ_TYPE = 0x8B9A; + const GLenum IMPLEMENTATION_COLOR_READ_FORMAT = 0x8B9B; + + /* Shader Source */ + const GLenum COMPILE_STATUS = 0x8B81; + + /* Shader Precision-Specified Types */ + const GLenum LOW_FLOAT = 0x8DF0; + const GLenum MEDIUM_FLOAT = 0x8DF1; + const GLenum HIGH_FLOAT = 0x8DF2; + const GLenum LOW_INT = 0x8DF3; + const GLenum MEDIUM_INT = 0x8DF4; + const GLenum HIGH_INT = 0x8DF5; + + /* Framebuffer Object. */ + const GLenum FRAMEBUFFER = 0x8D40; + const GLenum RENDERBUFFER = 0x8D41; + + const GLenum RGBA4 = 0x8056; + const GLenum RGB5_A1 = 0x8057; + const GLenum RGB565 = 0x8D62; + const GLenum DEPTH_COMPONENT16 = 0x81A5; + const GLenum STENCIL_INDEX = 0x1901; + const GLenum STENCIL_INDEX8 = 0x8D48; + const GLenum DEPTH_STENCIL = 0x84F9; + + const GLenum RENDERBUFFER_WIDTH = 0x8D42; + const GLenum RENDERBUFFER_HEIGHT = 0x8D43; + const GLenum RENDERBUFFER_INTERNAL_FORMAT = 0x8D44; + const GLenum RENDERBUFFER_RED_SIZE = 0x8D50; + const GLenum RENDERBUFFER_GREEN_SIZE = 0x8D51; + const GLenum RENDERBUFFER_BLUE_SIZE = 0x8D52; + const GLenum RENDERBUFFER_ALPHA_SIZE = 0x8D53; + const GLenum RENDERBUFFER_DEPTH_SIZE = 0x8D54; + const GLenum RENDERBUFFER_STENCIL_SIZE = 0x8D55; + + const GLenum FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8CD0; + const GLenum FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1; + const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8CD2; + const GLenum FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3; + + const GLenum COLOR_ATTACHMENT0 = 0x8CE0; + const GLenum DEPTH_ATTACHMENT = 0x8D00; + const GLenum STENCIL_ATTACHMENT = 0x8D20; + const GLenum DEPTH_STENCIL_ATTACHMENT = 0x821A; + + const GLenum NONE = 0; + + const GLenum FRAMEBUFFER_COMPLETE = 0x8CD5; + const GLenum FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6; + const GLenum FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7; + const GLenum FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9; + const GLenum FRAMEBUFFER_UNSUPPORTED = 0x8CDD; + + const GLenum FRAMEBUFFER_BINDING = 0x8CA6; + const GLenum RENDERBUFFER_BINDING = 0x8CA7; + const GLenum MAX_RENDERBUFFER_SIZE = 0x84E8; + + const GLenum INVALID_FRAMEBUFFER_OPERATION = 0x0506; + + /* WebGL-specific enums */ + const GLenum UNPACK_FLIP_Y_WEBGL = 0x9240; + const GLenum UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241; + const GLenum CONTEXT_LOST_WEBGL = 0x9242; + const GLenum UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243; + const GLenum BROWSER_DEFAULT_WEBGL = 0x9244; + + readonly attribute GLsizei drawingBufferWidth; + readonly attribute GLsizei drawingBufferHeight; + + void activeTexture(GLenum texture); + void attachShader(WebGLProgram? program, WebGLShader? shader); + void bindAttribLocation(WebGLProgram? program, GLuint index, DOMString name); + void bindBuffer(GLenum target, WebGLBuffer? buffer); + void bindFramebuffer(GLenum target, WebGLFramebuffer? framebuffer); + void bindRenderbuffer(GLenum target, WebGLRenderbuffer? renderbuffer); + void bindTexture(GLenum target, WebGLTexture? texture); + void blendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + void blendEquation(GLenum mode); + void blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha); + void blendFunc(GLenum sfactor, GLenum dfactor); + void blendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); + void bufferData(GLenum target, BufferDataSource? data, GLenum usage); + void bufferData(GLenum target, GLsizeiptr size, GLenum usage); + void bufferSubData(GLenum target, GLintptr offset, BufferDataSource? data); + + GLenum checkFramebufferStatus(GLenum target); + void clear(GLbitfield mask); + void clearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); + void clearDepth(GLclampf depth); + void clearStencil(GLint s); + void colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); + void compileShader(WebGLShader? shader); + + void compressedTexImage2D(GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, ArrayBufferView data); + void compressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, GLenum format, ArrayBufferView data); + + void copyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); + void copyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); + + WebGLBuffer createBuffer(); + WebGLFramebuffer createFramebuffer(); + WebGLProgram createProgram(); + WebGLRenderbuffer createRenderbuffer(); + WebGLShader createShader(GLenum type); + WebGLTexture createTexture(); + + void cullFace(GLenum mode); + + void deleteBuffer(WebGLBuffer? buffer); + void deleteFramebuffer(WebGLFramebuffer? framebuffer); + void deleteProgram(WebGLProgram? program); + void deleteRenderbuffer(WebGLRenderbuffer? renderbuffer); + void deleteShader(WebGLShader? shader); + void deleteTexture(WebGLTexture? texture); + + void depthFunc(GLenum func); + void depthMask(GLboolean flag); + void depthRange(GLclampf zNear, GLclampf zFar); + void detachShader(WebGLProgram? program, WebGLShader? shader); + void disable(GLenum cap); + void disableVertexAttribArray(GLuint index); + void drawArrays(GLenum mode, GLint first, GLsizei count); + void drawElements(GLenum mode, GLsizei count, GLenum type, GLintptr offset); + + void enable(GLenum cap); + void enableVertexAttribArray(GLuint index); + void finish(); + void flush(); + void framebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, WebGLRenderbuffer? renderbuffer); + void framebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, WebGLTexture? texture, GLint level); + void frontFace(GLenum mode); + void generateMipmap(GLenum target); + + WebGLActiveInfo getActiveAttrib(WebGLProgram? program, GLuint index); + WebGLActiveInfo getActiveUniform(WebGLProgram? program, GLuint index); + + // FIXME: The spec says this should not take a nullable WebGLProgram. + sequence<WebGLShader>? getAttachedShaders(WebGLProgram? program); + + GLint getAttribLocation(WebGLProgram? program, DOMString name); + + [OverrideIDLType=IDLWebGLAny] any getBufferParameter(GLenum target, GLenum pname); + + WebGLContextAttributes? getContextAttributes(); + + GLenum getError(); + + sequence<DOMString>? getSupportedExtensions(); + [Custom] object? getExtension(DOMString name); + + [OverrideIDLType=IDLWebGLAny] any getFramebufferAttachmentParameter(GLenum target, GLenum attachment, GLenum pname); + [OverrideIDLType=IDLWebGLAny] any getParameter(GLenum pname); + [OverrideIDLType=IDLWebGLAny] any getProgramParameter(WebGLProgram? program, GLenum pname); + DOMString? getProgramInfoLog(WebGLProgram? program); + [OverrideIDLType=IDLWebGLAny] any getRenderbufferParameter(GLenum target, GLenum pname); + [OverrideIDLType=IDLWebGLAny] any getShaderParameter(WebGLShader? shader, GLenum pname); + + DOMString? getShaderInfoLog(WebGLShader? shader); + + WebGLShaderPrecisionFormat getShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype); + + DOMString? getShaderSource(WebGLShader? shader); + + [OverrideIDLType=IDLWebGLAny] any getTexParameter(GLenum target, GLenum pname); + + [OverrideIDLType=IDLWebGLAny] any getUniform(WebGLProgram? program, WebGLUniformLocation? location); + + WebGLUniformLocation getUniformLocation(WebGLProgram? program, DOMString name); + + [OverrideIDLType=IDLWebGLAny] any getVertexAttrib(GLuint index, GLenum pname); + + GLsizeiptr getVertexAttribOffset(GLuint index, GLenum pname); + + void hint(GLenum target, GLenum mode); + GLboolean isBuffer(WebGLBuffer? buffer); + GLboolean isContextLost(); + GLboolean isEnabled(GLenum cap); + GLboolean isFramebuffer(WebGLFramebuffer? framebuffer); + GLboolean isProgram(WebGLProgram? program); + GLboolean isRenderbuffer(WebGLRenderbuffer? renderbuffer); + GLboolean isShader(WebGLShader? shader); + GLboolean isTexture(WebGLTexture? texture); + void lineWidth(GLfloat width); + void linkProgram(WebGLProgram? program); + void pixelStorei(GLenum pname, GLint param); + void polygonOffset(GLfloat factor, GLfloat units); + + void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, ArrayBufferView pixels); + + void releaseShaderCompiler(); + void renderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + void sampleCoverage(GLclampf value, GLboolean invert); + void scissor(GLint x, GLint y, GLsizei width, GLsizei height); + void shaderSource(WebGLShader? shader, DOMString string); + void stencilFunc(GLenum func, GLint ref, GLuint mask); + void stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask); + void stencilMask(GLuint mask); + void stencilMaskSeparate(GLenum face, GLuint mask); + void stencilOp(GLenum fail, GLenum zfail, GLenum zpass); + void stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass); + + void texParameterf(GLenum target, GLenum pname, GLfloat param); + void texParameteri(GLenum target, GLenum pname, GLint param); + + // Supported forms: + void texImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, ArrayBufferView? pixels); + [MayThrowException] void texImage2D(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, TexImageSource? source); + + void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, ArrayBufferView? pixels); + [MayThrowException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLenum format, GLenum type, TexImageSource? source); + + void uniform1f(WebGLUniformLocation? location, GLfloat x); + void uniform2f(WebGLUniformLocation? location, GLfloat x, GLfloat y); + void uniform3f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z); + void uniform4f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + + void uniform1i(WebGLUniformLocation? location, GLint x); + void uniform2i(WebGLUniformLocation? location, GLint x, GLint y); + void uniform3i(WebGLUniformLocation? location, GLint x, GLint y, GLint z); + void uniform4i(WebGLUniformLocation? location, GLint x, GLint y, GLint z, GLint w); + + void uniform1fv(WebGLUniformLocation? location, Float32List v); + void uniform2fv(WebGLUniformLocation? location, Float32List v); + void uniform3fv(WebGLUniformLocation? location, Float32List v); + void uniform4fv(WebGLUniformLocation? location, Float32List v); + + void uniform1iv(WebGLUniformLocation? location, Int32List v); + void uniform2iv(WebGLUniformLocation? location, Int32List v); + void uniform3iv(WebGLUniformLocation? location, Int32List v); + void uniform4iv(WebGLUniformLocation? location, Int32List v); + + void uniformMatrix2fv(WebGLUniformLocation? location, GLboolean transpose, Float32List array); + void uniformMatrix3fv(WebGLUniformLocation? location, GLboolean transpose, Float32List array); + void uniformMatrix4fv(WebGLUniformLocation? location, GLboolean transpose, Float32List array); + + void useProgram(WebGLProgram? program); + void validateProgram(WebGLProgram? program); + + void vertexAttrib1f(GLuint index, GLfloat x); + void vertexAttrib2f(GLuint index, GLfloat x, GLfloat y); + void vertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z); + void vertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + + void vertexAttrib1fv(GLuint index, Float32List values); + void vertexAttrib2fv(GLuint index, Float32List values); + void vertexAttrib3fv(GLuint index, Float32List values); + void vertexAttrib4fv(GLuint index, Float32List values); + + void vertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLintptr offset); + + void viewport(GLint x, GLint y, GLsizei width, GLsizei height); +}; diff --git a/Source/WebCore/html/canvas/WebGLSampler.cpp b/Source/WebCore/html/canvas/WebGLSampler.cpp new file mode 100644 index 000000000..0ca795b8b --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLSampler.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2015 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(WEBGL) +#include "WebGLSampler.h" + +#include "WebGLContextGroup.h" +#include "WebGLRenderingContextBase.h" + +namespace WebCore { + +Ref<WebGLSampler> WebGLSampler::create(WebGLRenderingContextBase& ctx) +{ + return adoptRef(*new WebGLSampler(ctx)); +} + +WebGLSampler::~WebGLSampler() +{ + deleteObject(0); +} + +WebGLSampler::WebGLSampler(WebGLRenderingContextBase& ctx) + : WebGLSharedObject(ctx) +{ + // FIXME: Call createSampler from GraphicsContext3D. +} + +void WebGLSampler::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object) +{ + UNUSED_PARAM(context3d); + UNUSED_PARAM(object); + // FIXME: Call deleteSampler from GraphicsContext3D. +} + +} + +#endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/WebGLSampler.h b/Source/WebCore/html/canvas/WebGLSampler.h new file mode 100644 index 000000000..a0531ff27 --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLSampler.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2015-2017 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "WebGLSharedObject.h" + +namespace WebCore { + +class WebGLSampler final : public WebGLSharedObject { +public: + static Ref<WebGLSampler> create(WebGLRenderingContextBase&); + virtual ~WebGLSampler(); + +protected: + explicit WebGLSampler(WebGLRenderingContextBase&); + void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) final; +}; + +} // namespace WebCore diff --git a/Source/WebCore/html/canvas/WebGLSampler.idl b/Source/WebCore/html/canvas/WebGLSampler.idl new file mode 100644 index 000000000..4e544ca6e --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLSampler.idl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2015 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +[ + Conditional=WEBGL +] interface WebGLSampler { +}; diff --git a/Source/WebCore/html/canvas/WebGLShader.cpp b/Source/WebCore/html/canvas/WebGLShader.cpp index 0f3315676..7faed2408 100644 --- a/Source/WebCore/html/canvas/WebGLShader.cpp +++ b/Source/WebCore/html/canvas/WebGLShader.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -30,22 +30,22 @@ #include "WebGLShader.h" #include "WebGLContextGroup.h" -#include "WebGLRenderingContext.h" +#include "WebGLRenderingContextBase.h" namespace WebCore { -PassRefPtr<WebGLShader> WebGLShader::create(WebGLRenderingContext* ctx, GC3Denum type) +Ref<WebGLShader> WebGLShader::create(WebGLRenderingContextBase& ctx, GC3Denum type) { - return adoptRef(new WebGLShader(ctx, type)); + return adoptRef(*new WebGLShader(ctx, type)); } -WebGLShader::WebGLShader(WebGLRenderingContext* ctx, GC3Denum type) +WebGLShader::WebGLShader(WebGLRenderingContextBase& ctx, GC3Denum type) : WebGLSharedObject(ctx) , m_type(type) - , m_source("") + , m_source(emptyString()) , m_isValid(false) { - setObject(ctx->graphicsContext3D()->createShader(type)); + setObject(ctx.graphicsContext3D()->createShader(type)); } WebGLShader::~WebGLShader() diff --git a/Source/WebCore/html/canvas/WebGLShader.h b/Source/WebCore/html/canvas/WebGLShader.h index 7ed00e321..952cdcc65 100644 --- a/Source/WebCore/html/canvas/WebGLShader.h +++ b/Source/WebCore/html/canvas/WebGLShader.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2013 Apple Inc. All rights reserved. + * Copyright (C) 2009-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,21 +23,17 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLShader_h -#define WebGLShader_h +#pragma once #include "WebGLSharedObject.h" -#include <wtf/PassRefPtr.h> - namespace WebCore { -class WebGLShader : public WebGLSharedObject { +class WebGLShader final : public WebGLSharedObject { public: + static Ref<WebGLShader> create(WebGLRenderingContextBase&, GC3Denum); virtual ~WebGLShader(); - static PassRefPtr<WebGLShader> create(WebGLRenderingContext*, GC3Denum); - GC3Denum getType() const { return m_type; } const String& getSource() const { return m_source; } @@ -47,11 +43,9 @@ public: void setValid(bool valid) { m_isValid = valid; } private: - WebGLShader(WebGLRenderingContext*, GC3Denum); + WebGLShader(WebGLRenderingContextBase&, GC3Denum); - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override; - - virtual bool isShader() const override { return true; } + void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) final; GC3Denum m_type; String m_source; @@ -59,5 +53,3 @@ private: }; } // namespace WebCore - -#endif // WebGLShader_h diff --git a/Source/WebCore/html/canvas/WebGLShader.idl b/Source/WebCore/html/canvas/WebGLShader.idl index 0ebae3829..52f962025 100644 --- a/Source/WebCore/html/canvas/WebGLShader.idl +++ b/Source/WebCore/html/canvas/WebGLShader.idl @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR diff --git a/Source/WebCore/html/canvas/WebGLShaderPrecisionFormat.cpp b/Source/WebCore/html/canvas/WebGLShaderPrecisionFormat.cpp index b9c5163a1..ed63a51cf 100644 --- a/Source/WebCore/html/canvas/WebGLShaderPrecisionFormat.cpp +++ b/Source/WebCore/html/canvas/WebGLShaderPrecisionFormat.cpp @@ -33,9 +33,9 @@ namespace WebCore { // static -PassRefPtr<WebGLShaderPrecisionFormat> WebGLShaderPrecisionFormat::create(GC3Dint rangeMin, GC3Dint rangeMax, GC3Dint precision) +Ref<WebGLShaderPrecisionFormat> WebGLShaderPrecisionFormat::create(GC3Dint rangeMin, GC3Dint rangeMax, GC3Dint precision) { - return adoptRef(new WebGLShaderPrecisionFormat(rangeMin, rangeMax, precision)); + return adoptRef(*new WebGLShaderPrecisionFormat(rangeMin, rangeMax, precision)); } GC3Dint WebGLShaderPrecisionFormat::rangeMin() const diff --git a/Source/WebCore/html/canvas/WebGLShaderPrecisionFormat.h b/Source/WebCore/html/canvas/WebGLShaderPrecisionFormat.h index c4c7b7861..6ff2dd467 100644 --- a/Source/WebCore/html/canvas/WebGLShaderPrecisionFormat.h +++ b/Source/WebCore/html/canvas/WebGLShaderPrecisionFormat.h @@ -24,18 +24,16 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLShaderPrecisionFormat_h -#define WebGLShaderPrecisionFormat_h +#pragma once #include "GraphicsContext3D.h" -#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> namespace WebCore { class WebGLShaderPrecisionFormat : public RefCounted<WebGLShaderPrecisionFormat> { public: - static PassRefPtr<WebGLShaderPrecisionFormat> create(GC3Dint rangeMin, GC3Dint rangeMax, GC3Dint precision); + static Ref<WebGLShaderPrecisionFormat> create(GC3Dint rangeMin, GC3Dint rangeMax, GC3Dint precision); GC3Dint rangeMin() const; GC3Dint rangeMax() const; @@ -49,6 +47,4 @@ private: GC3Dint m_precision; }; -} - -#endif // WebGLShaderPrecisionFormat_h +} // namespace WebCore diff --git a/Source/WebCore/html/canvas/WebGLSharedObject.cpp b/Source/WebCore/html/canvas/WebGLSharedObject.cpp index 9f76cae77..1b2236fbd 100644 --- a/Source/WebCore/html/canvas/WebGLSharedObject.cpp +++ b/Source/WebCore/html/canvas/WebGLSharedObject.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,41 +24,39 @@ */ #include "config.h" +#include "WebGLSharedObject.h" #if ENABLE(WEBGL) -#include "WebGLSharedObject.h" - #include "WebGLContextGroup.h" -#include "WebGLRenderingContext.h" +#include "WebGLRenderingContextBase.h" namespace WebCore { -WebGLSharedObject::WebGLSharedObject(WebGLRenderingContext* context) - : WebGLObject(context), - m_contextGroup(context->contextGroup()) +WebGLSharedObject::WebGLSharedObject(WebGLRenderingContextBase& context) + : m_contextGroup(context.contextGroup()) { } WebGLSharedObject::~WebGLSharedObject() { if (m_contextGroup) - m_contextGroup->removeObject(this); + m_contextGroup->removeObject(*this); } void WebGLSharedObject::detachContextGroup() { detach(); if (m_contextGroup) { - deleteObject(0); - m_contextGroup->removeObject(this); - m_contextGroup = 0; + deleteObject(nullptr); + m_contextGroup->removeObject(*this); + m_contextGroup = nullptr; } } GraphicsContext3D* WebGLSharedObject::getAGraphicsContext3D() const { - return m_contextGroup ? m_contextGroup->getAGraphicsContext3D() : 0; + return m_contextGroup ? &m_contextGroup->getAGraphicsContext3D() : nullptr; } } diff --git a/Source/WebCore/html/canvas/WebGLSharedObject.h b/Source/WebCore/html/canvas/WebGLSharedObject.h index a55f64871..972e580ee 100644 --- a/Source/WebCore/html/canvas/WebGLSharedObject.h +++ b/Source/WebCore/html/canvas/WebGLSharedObject.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011-2017 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,8 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLSharedObject_h -#define WebGLSharedObject_h +#pragma once #include "WebGLObject.h" @@ -32,24 +31,19 @@ namespace WebCore { class GraphicsContext3D; class WebGLContextGroup; -class WebGLRenderingContext; +class WebGLRenderingContextBase; -// WebGLSharedObject the base class for objects that can be shared by multiple -// WebGLRenderingContexts. +// WebGLSharedObject the base class for objects that can be shared by multiple WebGLRenderingContexts. class WebGLSharedObject : public WebGLObject { public: virtual ~WebGLSharedObject(); WebGLContextGroup* contextGroup() const { return m_contextGroup; } - virtual bool isBuffer() const { return false; } - virtual bool isFramebuffer() const { return false; } - virtual bool isProgram() const { return false; } virtual bool isRenderbuffer() const { return false; } - virtual bool isShader() const { return false; } virtual bool isTexture() const { return false; } - virtual bool validate(const WebGLContextGroup* contextGroup, const WebGLRenderingContext*) const override + bool validate(const WebGLContextGroup* contextGroup, const WebGLRenderingContextBase&) const override { return contextGroup == m_contextGroup; } @@ -57,19 +51,17 @@ public: void detachContextGroup(); protected: - WebGLSharedObject(WebGLRenderingContext*); + WebGLSharedObject(WebGLRenderingContextBase&); - virtual bool hasGroupOrContext() const override + bool hasGroupOrContext() const override { return m_contextGroup; } - virtual GraphicsContext3D* getAGraphicsContext3D() const override; + GraphicsContext3D* getAGraphicsContext3D() const override; private: WebGLContextGroup* m_contextGroup; }; } // namespace WebCore - -#endif // WebGLSharedObject_h diff --git a/Source/WebCore/html/canvas/WebGLSync.cpp b/Source/WebCore/html/canvas/WebGLSync.cpp new file mode 100644 index 000000000..6360fba4e --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLSync.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2015 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(WEBGL) +#include "WebGLSync.h" + +#include "WebGLContextGroup.h" +#include "WebGLRenderingContextBase.h" + +namespace WebCore { + +Ref<WebGLSync> WebGLSync::create(WebGLRenderingContextBase& ctx) +{ + return adoptRef(*new WebGLSync(ctx)); +} + +WebGLSync::~WebGLSync() +{ + deleteObject(0); +} + +WebGLSync::WebGLSync(WebGLRenderingContextBase& ctx) + : WebGLSharedObject(ctx) +{ + // FIXME: Call fenceSync from GraphicsContext3D. +} + +void WebGLSync::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object) +{ + UNUSED_PARAM(context3d); + UNUSED_PARAM(object); + // FIXME: Call deleteSync from GraphicsContext3D. +} + +} + +#endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/WebGLSync.h b/Source/WebCore/html/canvas/WebGLSync.h new file mode 100644 index 000000000..f9e718017 --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLSync.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2015-2017 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "WebGLSharedObject.h" + +namespace WebCore { + +class WebGLSync final : public WebGLSharedObject { +public: + virtual ~WebGLSync(); + + static Ref<WebGLSync> create(WebGLRenderingContextBase&); + +protected: + WebGLSync(WebGLRenderingContextBase&); + + void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override; +}; + +} // namespace WebCore diff --git a/Source/WebCore/html/canvas/WebGLSync.idl b/Source/WebCore/html/canvas/WebGLSync.idl new file mode 100644 index 000000000..e1a994758 --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLSync.idl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2015 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +[ + Conditional=WEBGL +] interface WebGLSync { +}; diff --git a/Source/WebCore/html/canvas/WebGLTexture.cpp b/Source/WebCore/html/canvas/WebGLTexture.cpp index 0872795ff..9eba972f5 100644 --- a/Source/WebCore/html/canvas/WebGLTexture.cpp +++ b/Source/WebCore/html/canvas/WebGLTexture.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -31,16 +31,16 @@ #include "WebGLContextGroup.h" #include "WebGLFramebuffer.h" -#include "WebGLRenderingContext.h" +#include "WebGLRenderingContextBase.h" namespace WebCore { -PassRefPtr<WebGLTexture> WebGLTexture::create(WebGLRenderingContext* ctx) +Ref<WebGLTexture> WebGLTexture::create(WebGLRenderingContextBase& ctx) { - return adoptRef(new WebGLTexture(ctx)); + return adoptRef(*new WebGLTexture(ctx)); } -WebGLTexture::WebGLTexture(WebGLRenderingContext* ctx) +WebGLTexture::WebGLTexture(WebGLRenderingContextBase& ctx) : WebGLSharedObject(ctx) , m_target(0) , m_minFilter(GraphicsContext3D::NEAREST_MIPMAP_LINEAR) @@ -53,8 +53,9 @@ WebGLTexture::WebGLTexture(WebGLRenderingContext* ctx) , m_isCompressed(false) , m_isFloatType(false) , m_isHalfFloatType(false) + , m_isForWebGL1(ctx.isWebGL1()) { - setObject(ctx->graphicsContext3D()->createTexture()); + setObject(ctx.graphicsContext3D()->createTexture()); } WebGLTexture::~WebGLTexture() @@ -188,6 +189,7 @@ GC3Denum WebGLTexture::getInternalFormat(GC3Denum target, GC3Dint level) const GC3Denum WebGLTexture::getType(GC3Denum target, GC3Dint level) const { + ASSERT(m_isForWebGL1); const LevelInfo* info = getLevelInfo(target, level); if (!info) return 0; @@ -218,6 +220,15 @@ bool WebGLTexture::isValid(GC3Denum target, GC3Dint level) const return info->valid; } +void WebGLTexture::markInvalid(GC3Denum target, GC3Dint level) +{ + int index = mapTargetToIndex(target); + if (index < 0) + return; + m_info[index][level].valid = false; + update(); +} + bool WebGLTexture::isNPOT(GC3Dsizei width, GC3Dsizei height) { ASSERT(width >= 0 && height >= 0); @@ -241,10 +252,12 @@ bool WebGLTexture::needToUseBlackTexture(TextureExtensionFlag extensions) const return false; if (m_needToUseBlackTexture) return true; - if ((m_isFloatType && !(extensions & TextureExtensionFloatLinearEnabled)) || (m_isHalfFloatType && !(extensions & TextureExtensionHalfFloatLinearEnabled))) { - if (m_magFilter != GraphicsContext3D::NEAREST || (m_minFilter != GraphicsContext3D::NEAREST && m_minFilter != GraphicsContext3D::NEAREST_MIPMAP_NEAREST)) - return true; - } + if (m_magFilter == GraphicsContext3D::NEAREST && (m_minFilter == GraphicsContext3D::NEAREST || m_minFilter == GraphicsContext3D::NEAREST_MIPMAP_NEAREST)) + return false; + if (m_isForWebGL1 && m_isHalfFloatType && !(extensions & TextureExtensionHalfFloatLinearEnabled)) + return true; + if (m_isFloatType && !(extensions & TextureExtensionFloatLinearEnabled)) + return true; return false; } @@ -299,7 +312,7 @@ bool WebGLTexture::canGenerateMipmaps() const LevelInfo& info = m_info[ii][0]; if (!info.valid || info.width != first.width || info.height != first.height - || info.internalFormat != first.internalFormat || info.type != first.type) + || info.internalFormat != first.internalFormat || (m_isForWebGL1 && info.type != first.type)) return false; } return true; @@ -325,6 +338,36 @@ GC3Dint WebGLTexture::computeLevelCount(GC3Dsizei width, GC3Dsizei height) return log + 1; } +static bool internalFormatIsFloatType(GC3Denum internalFormat) +{ + switch (internalFormat) { + case GraphicsContext3D::R32F: + case GraphicsContext3D::RG32F: + case GraphicsContext3D::RGB32F: + case GraphicsContext3D::RGBA32F: + case GraphicsContext3D::DEPTH_COMPONENT32F: + case GraphicsContext3D::DEPTH32F_STENCIL8: + return true; + default: + return false; + } +} + +static bool internalFormatIsHalfFloatType(GC3Denum internalFormat) +{ + switch (internalFormat) { + case GraphicsContext3D::R16F: + case GraphicsContext3D::RG16F: + case GraphicsContext3D::R11F_G11F_B10F: + case GraphicsContext3D::RGB9_E5: + case GraphicsContext3D::RGB16F: + case GraphicsContext3D::RGBA16F: + return true; + default: + return false; + } +} + void WebGLTexture::update() { m_isNPOT = false; @@ -344,7 +387,7 @@ void WebGLTexture::update() const LevelInfo& info0 = m_info[ii][0]; if (!info0.valid || info0.width != first.width || info0.height != first.height - || info0.internalFormat != first.internalFormat || info0.type != first.type) { + || info0.internalFormat != first.internalFormat || (m_isForWebGL1 && info0.type != first.type)) { m_isComplete = false; break; } @@ -356,7 +399,7 @@ void WebGLTexture::update() const LevelInfo& info = m_info[ii][level]; if (!info.valid || info.width != width || info.height != height - || info.internalFormat != info0.internalFormat || info.type != info0.type) { + || info.internalFormat != info0.internalFormat || (m_isForWebGL1 && info.type != info0.type)) { m_isComplete = false; break; } @@ -366,25 +409,37 @@ void WebGLTexture::update() } m_isFloatType = false; - if (m_isComplete) - m_isFloatType = m_info[0][0].type == GraphicsContext3D::FLOAT; - else { - for (size_t ii = 0; ii < m_info.size(); ++ii) { - if (m_info[ii][0].type == GraphicsContext3D::FLOAT) { - m_isFloatType = true; - break; + if (m_isForWebGL1) { + if (m_isComplete) { + if (m_isForWebGL1) + m_isFloatType = m_info[0][0].type == GraphicsContext3D::FLOAT; + else + m_isFloatType = internalFormatIsFloatType(m_info[0][0].internalFormat); + } else { + for (size_t ii = 0; ii < m_info.size(); ++ii) { + if ((m_isForWebGL1 && m_info[ii][0].type == GraphicsContext3D::FLOAT) + || (!m_isForWebGL1 && internalFormatIsFloatType(m_info[ii][0].internalFormat))) { + m_isFloatType = true; + break; + } } } } m_isHalfFloatType = false; - if (m_isComplete) - m_isHalfFloatType = m_info[0][0].type == GraphicsContext3D::HALF_FLOAT_OES; - else { - for (size_t ii = 0; ii < m_info.size(); ++ii) { - if (m_info[ii][0].type == GraphicsContext3D::HALF_FLOAT_OES) { - m_isHalfFloatType = true; - break; + if (m_isForWebGL1) { + if (m_isComplete) { + if (m_isForWebGL1) + m_isHalfFloatType = internalFormatIsHalfFloatType(m_info[0][0].internalFormat); + else + m_isHalfFloatType = m_info[0][0].type == GraphicsContext3D::HALF_FLOAT_OES; + } else { + for (size_t ii = 0; ii < m_info.size(); ++ii) { + if ((m_isForWebGL1 && m_info[ii][0].type == GraphicsContext3D::HALF_FLOAT_OES) + || (!m_isForWebGL1 && internalFormatIsHalfFloatType(m_info[ii][0].internalFormat))) { + m_isHalfFloatType = true; + break; + } } } } diff --git a/Source/WebCore/html/canvas/WebGLTexture.h b/Source/WebCore/html/canvas/WebGLTexture.h index dcc3d0b45..b266953a5 100644 --- a/Source/WebCore/html/canvas/WebGLTexture.h +++ b/Source/WebCore/html/canvas/WebGLTexture.h @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,17 +23,14 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLTexture_h -#define WebGLTexture_h +#pragma once #include "WebGLSharedObject.h" - -#include <wtf/PassRefPtr.h> #include <wtf/Vector.h> namespace WebCore { -class WebGLTexture : public WebGLSharedObject { +class WebGLTexture final : public WebGLSharedObject { public: enum TextureExtensionFlag { @@ -44,7 +41,7 @@ public: virtual ~WebGLTexture(); - static PassRefPtr<WebGLTexture> create(WebGLRenderingContext*); + static Ref<WebGLTexture> create(WebGLRenderingContextBase&); void setTarget(GC3Denum target, GC3Dint maxLevel); void setParameteri(GC3Denum pname, GC3Dint param); @@ -65,6 +62,7 @@ public: GC3Dsizei getWidth(GC3Denum target, GC3Dint level) const; GC3Dsizei getHeight(GC3Denum target, GC3Dint level) const; bool isValid(GC3Denum target, GC3Dint level) const; + void markInvalid(GC3Denum target, GC3Dint level); // Whether width/height is NotPowerOfTwo. static bool isNPOT(GC3Dsizei, GC3Dsizei); @@ -80,12 +78,14 @@ public: static GC3Dint computeLevelCount(GC3Dsizei width, GC3Dsizei height); -protected: - WebGLTexture(WebGLRenderingContext*); - - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override; + bool immutable() const { return m_immutable; } + void setImmutable() { m_immutable = true; } private: + WebGLTexture(WebGLRenderingContextBase&); + + void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override; + class LevelInfo { public: LevelInfo() @@ -113,7 +113,7 @@ private: GC3Denum type; }; - virtual bool isTexture() const override { return true; } + bool isTexture() const override { return true; } void update(); @@ -136,8 +136,8 @@ private: bool m_isCompressed; bool m_isFloatType; bool m_isHalfFloatType; + bool m_isForWebGL1; + bool m_immutable { false }; }; } // namespace WebCore - -#endif // WebGLTexture_h diff --git a/Source/WebCore/html/canvas/WebGLTexture.idl b/Source/WebCore/html/canvas/WebGLTexture.idl index 1ea2f2bca..67dfa3c4f 100644 --- a/Source/WebCore/html/canvas/WebGLTexture.idl +++ b/Source/WebCore/html/canvas/WebGLTexture.idl @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR diff --git a/Source/WebCore/html/canvas/WebGLTransformFeedback.cpp b/Source/WebCore/html/canvas/WebGLTransformFeedback.cpp new file mode 100644 index 000000000..353e4bac1 --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLTransformFeedback.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2015 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(WEBGL) +#include "WebGLTransformFeedback.h" + +#include "WebGLContextGroup.h" +#include "WebGLRenderingContextBase.h" + +namespace WebCore { + +Ref<WebGLTransformFeedback> WebGLTransformFeedback::create(WebGLRenderingContextBase& ctx) +{ + return adoptRef(*new WebGLTransformFeedback(ctx)); +} + +WebGLTransformFeedback::~WebGLTransformFeedback() +{ + deleteObject(0); +} + +WebGLTransformFeedback::WebGLTransformFeedback(WebGLRenderingContextBase& ctx) + : WebGLSharedObject(ctx) +{ + // FIXME: Call createTransformFeedback from GraphicsContext3D. +} + +void WebGLTransformFeedback::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object) +{ + UNUSED_PARAM(context3d); + UNUSED_PARAM(object); + // FIXME: Call deleteTransformFeedback from GraphicsContext3D. +} + +} + +#endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/WebGLTransformFeedback.h b/Source/WebCore/html/canvas/WebGLTransformFeedback.h new file mode 100644 index 000000000..714923384 --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLTransformFeedback.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2015-2017 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "WebGLSharedObject.h" + +namespace WebCore { + +class WebGLTransformFeedback final : public WebGLSharedObject { +public: + virtual ~WebGLTransformFeedback(); + + static Ref<WebGLTransformFeedback> create(WebGLRenderingContextBase&); + +protected: + WebGLTransformFeedback(WebGLRenderingContextBase&); + + void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override; +}; + +} // namespace WebCore diff --git a/Source/WebCore/html/canvas/WebGLTransformFeedback.idl b/Source/WebCore/html/canvas/WebGLTransformFeedback.idl new file mode 100644 index 000000000..22b8847ed --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLTransformFeedback.idl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2015 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +[ + Conditional=WEBGL +] interface WebGLTransformFeedback { +}; diff --git a/Source/WebCore/html/canvas/WebGLUniformLocation.cpp b/Source/WebCore/html/canvas/WebGLUniformLocation.cpp index b467238b4..f16cae3c1 100644 --- a/Source/WebCore/html/canvas/WebGLUniformLocation.cpp +++ b/Source/WebCore/html/canvas/WebGLUniformLocation.cpp @@ -11,10 +11,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -32,9 +32,9 @@ namespace WebCore { -PassRefPtr<WebGLUniformLocation> WebGLUniformLocation::create(WebGLProgram* program, GC3Dint location, GC3Denum type) +Ref<WebGLUniformLocation> WebGLUniformLocation::create(WebGLProgram* program, GC3Dint location, GC3Denum type) { - return adoptRef(new WebGLUniformLocation(program, location, type)); + return adoptRef(*new WebGLUniformLocation(program, location, type)); } WebGLUniformLocation::WebGLUniformLocation(WebGLProgram* program, GC3Dint location, GC3Denum type) diff --git a/Source/WebCore/html/canvas/WebGLUniformLocation.h b/Source/WebCore/html/canvas/WebGLUniformLocation.h index a268fa2fa..5130be0dd 100644 --- a/Source/WebCore/html/canvas/WebGLUniformLocation.h +++ b/Source/WebCore/html/canvas/WebGLUniformLocation.h @@ -11,10 +11,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -24,21 +24,18 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLUniformLocation_h -#define WebGLUniformLocation_h +#pragma once #include "WebGLProgram.h" - -#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> namespace WebCore { -class WebGLUniformLocation : public RefCounted<WebGLUniformLocation> { +class WebGLUniformLocation final : public RefCounted<WebGLUniformLocation> { public: - virtual ~WebGLUniformLocation() { } + ~WebGLUniformLocation() { } - static PassRefPtr<WebGLUniformLocation> create(WebGLProgram*, GC3Dint location, GC3Denum type); + static Ref<WebGLUniformLocation> create(WebGLProgram*, GC3Dint location, GC3Denum type); WebGLProgram* program() const; @@ -57,5 +54,3 @@ private: }; } // namespace WebCore - -#endif // WebGLUniformLocation_h diff --git a/Source/WebCore/html/canvas/WebGLUniformLocation.idl b/Source/WebCore/html/canvas/WebGLUniformLocation.idl index c211189de..a086f5713 100644 --- a/Source/WebCore/html/canvas/WebGLUniformLocation.idl +++ b/Source/WebCore/html/canvas/WebGLUniformLocation.idl @@ -11,10 +11,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -25,6 +25,7 @@ */ [ - Conditional=WEBGL + Conditional=WEBGL, + ImplementationLacksVTable, ] interface WebGLUniformLocation { }; diff --git a/Source/WebCore/html/canvas/WebGLVertexArrayObject.cpp b/Source/WebCore/html/canvas/WebGLVertexArrayObject.cpp new file mode 100644 index 000000000..89ae21f33 --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLVertexArrayObject.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2015-2017 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebGLVertexArrayObject.h" + +#if ENABLE(WEBGL2) + +#include "WebGL2RenderingContext.h" +#include "WebGLContextGroup.h" + +namespace WebCore { + +Ref<WebGLVertexArrayObject> WebGLVertexArrayObject::create(WebGLRenderingContextBase& context, Type type) +{ + return adoptRef(*new WebGLVertexArrayObject(context, type)); +} + +WebGLVertexArrayObject::~WebGLVertexArrayObject() +{ + deleteObject(nullptr); +} + +WebGLVertexArrayObject::WebGLVertexArrayObject(WebGLRenderingContextBase& context, Type type) + : WebGLVertexArrayObjectBase(context, type) +{ + switch (m_type) { + case Type::Default: + break; + case Type::User: + setObject(this->context()->graphicsContext3D()->createVertexArray()); + break; + } +} + +void WebGLVertexArrayObject::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object) +{ + switch (m_type) { + case Type::Default: + break; + case Type::User: + context3d->deleteVertexArray(object); + break; + } + + if (m_boundElementArrayBuffer) + m_boundElementArrayBuffer->onDetached(context3d); + + for (auto& state : m_vertexAttribState) { + if (state.bufferBinding) + state.bufferBinding->onDetached(context3d); + } +} + +} + +#endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/WebGLVertexArrayObject.h b/Source/WebCore/html/canvas/WebGLVertexArrayObject.h new file mode 100644 index 000000000..2f7ed3508 --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLVertexArrayObject.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015-2017 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(WEBGL2) + +#include "WebGLVertexArrayObjectBase.h" + +namespace WebCore { + +class WebGL2RenderingContext; + +class WebGLVertexArrayObject final : public WebGLVertexArrayObjectBase { +public: + static Ref<WebGLVertexArrayObject> create(WebGLRenderingContextBase&, Type); + virtual ~WebGLVertexArrayObject(); +private: + WebGLVertexArrayObject(WebGLRenderingContextBase&, Type); + void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) final; +}; + +} // namespace WebCore + +#endif // ENABLE(WEBGL2) diff --git a/Source/WebCore/html/canvas/WebGLVertexArrayObject.idl b/Source/WebCore/html/canvas/WebGLVertexArrayObject.idl new file mode 100644 index 000000000..67a1f9dec --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLVertexArrayObject.idl @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2015 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +[ + Conditional=WEBGL2, + EnabledAtRuntime=WebGL2 +] interface WebGLVertexArrayObject { +}; diff --git a/Source/WebCore/html/canvas/WebGLVertexArrayObjectBase.cpp b/Source/WebCore/html/canvas/WebGLVertexArrayObjectBase.cpp new file mode 100644 index 000000000..58dfa3d73 --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLVertexArrayObjectBase.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2015-2017 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebGLVertexArrayObjectBase.h" + +#if ENABLE(WEBGL) + +#include "WebGLRenderingContextBase.h" + +namespace WebCore { + +WebGLVertexArrayObjectBase::WebGLVertexArrayObjectBase(WebGLRenderingContextBase& context, Type type) + : WebGLContextObject(context) + , m_type(type) +{ + m_vertexAttribState.resize(context.getMaxVertexAttribs()); +} + +void WebGLVertexArrayObjectBase::setElementArrayBuffer(WebGLBuffer* buffer) +{ + if (buffer) + buffer->onAttached(); + if (m_boundElementArrayBuffer) + m_boundElementArrayBuffer->onDetached(context()->graphicsContext3D()); + m_boundElementArrayBuffer = buffer; + +} + +void WebGLVertexArrayObjectBase::setVertexAttribState(GC3Duint index, GC3Dsizei bytesPerElement, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, GC3Dintptr offset, WebGLBuffer& buffer) +{ + GC3Dsizei validatedStride = stride ? stride : bytesPerElement; + + auto& state = m_vertexAttribState[index]; + + buffer.onAttached(); + if (state.bufferBinding) + state.bufferBinding->onDetached(context()->graphicsContext3D()); + + state.bufferBinding = &buffer; + state.bytesPerElement = bytesPerElement; + state.size = size; + state.type = type; + state.normalized = normalized; + state.stride = validatedStride; + state.originalStride = stride; + state.offset = offset; +} + +void WebGLVertexArrayObjectBase::unbindBuffer(WebGLBuffer& buffer) +{ + if (m_boundElementArrayBuffer == &buffer) { + m_boundElementArrayBuffer->onDetached(context()->graphicsContext3D()); + m_boundElementArrayBuffer = nullptr; + } + + for (size_t i = 0; i < m_vertexAttribState.size(); ++i) { + auto& state = m_vertexAttribState[i]; + if (state.bufferBinding == &buffer) { + buffer.onDetached(context()->graphicsContext3D()); + + if (!i && !context()->isGLES2Compliant()) { + state.bufferBinding = context()->m_vertexAttrib0Buffer; + state.bufferBinding->onAttached(); + state.bytesPerElement = 0; + state.size = 4; + state.type = GraphicsContext3D::FLOAT; + state.normalized = false; + state.stride = 16; + state.originalStride = 0; + state.offset = 0; + } else + state.bufferBinding = nullptr; + } + } +} + +void WebGLVertexArrayObjectBase::setVertexAttribDivisor(GC3Duint index, GC3Duint divisor) +{ + m_vertexAttribState[index].divisor = divisor; +} + +} + +#endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/WebGLVertexArrayObjectBase.h b/Source/WebCore/html/canvas/WebGLVertexArrayObjectBase.h new file mode 100644 index 000000000..1275533d8 --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLVertexArrayObjectBase.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2015-2017 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "WebGLBuffer.h" +#include "WebGLContextObject.h" + +namespace WebCore { + +class WebGLVertexArrayObjectBase : public WebGLContextObject { +public: + enum class Type { Default, User }; + + // Cached values for vertex attrib range checks + struct VertexAttribState { + bool isBound() const { return bufferBinding && bufferBinding->object(); } + bool validateBinding() const { return !enabled || isBound(); } + + bool enabled { false }; + RefPtr<WebGLBuffer> bufferBinding; + GC3Dsizei bytesPerElement { 0 }; + GC3Dint size { 4 }; + GC3Denum type { GraphicsContext3D::FLOAT }; + bool normalized { false }; + GC3Dsizei stride { 16 }; + GC3Dsizei originalStride { 0 }; + GC3Dintptr offset { 0 }; + GC3Duint divisor { 0 }; + }; + + bool isDefaultObject() const { return m_type == Type::Default; } + + bool hasEverBeenBound() const { return object() && m_hasEverBeenBound; } + void setHasEverBeenBound() { m_hasEverBeenBound = true; } + + WebGLBuffer* getElementArrayBuffer() const { return m_boundElementArrayBuffer.get(); } + void setElementArrayBuffer(WebGLBuffer*); + + VertexAttribState& getVertexAttribState(int index) { return m_vertexAttribState[index]; } + void setVertexAttribState(GC3Duint, GC3Dsizei, GC3Dint, GC3Denum, GC3Dboolean, GC3Dsizei, GC3Dintptr, WebGLBuffer&); + void unbindBuffer(WebGLBuffer&); + + void setVertexAttribDivisor(GC3Duint index, GC3Duint divisor); + +protected: + WebGLVertexArrayObjectBase(WebGLRenderingContextBase&, Type); + void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override = 0; + + Type m_type; + bool m_hasEverBeenBound { false }; + RefPtr<WebGLBuffer> m_boundElementArrayBuffer; + Vector<VertexAttribState> m_vertexAttribState; +}; + +} // namespace WebCore diff --git a/Source/WebCore/html/canvas/WebGLVertexArrayObjectOES.cpp b/Source/WebCore/html/canvas/WebGLVertexArrayObjectOES.cpp index ce18a9f18..af5565cd9 100644 --- a/Source/WebCore/html/canvas/WebGLVertexArrayObjectOES.cpp +++ b/Source/WebCore/html/canvas/WebGLVertexArrayObjectOES.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -30,125 +30,50 @@ #include "WebGLVertexArrayObjectOES.h" #include "Extensions3D.h" -#include "WebGLRenderingContext.h" +#include "WebGLRenderingContextBase.h" namespace WebCore { -PassRefPtr<WebGLVertexArrayObjectOES> WebGLVertexArrayObjectOES::create(WebGLRenderingContext* ctx, VaoType type) +Ref<WebGLVertexArrayObjectOES> WebGLVertexArrayObjectOES::create(WebGLRenderingContextBase& context, Type type) { - return adoptRef(new WebGLVertexArrayObjectOES(ctx, type)); + return adoptRef(*new WebGLVertexArrayObjectOES(context, type)); } -WebGLVertexArrayObjectOES::WebGLVertexArrayObjectOES(WebGLRenderingContext* ctx, VaoType type) - : WebGLContextObject(ctx) - , m_type(type) - , m_hasEverBeenBound(false) - , m_boundElementArrayBuffer(0) +WebGLVertexArrayObjectOES::WebGLVertexArrayObjectOES(WebGLRenderingContextBase& context, Type type) + : WebGLVertexArrayObjectBase(context, type) { - m_vertexAttribState.resize(ctx->getMaxVertexAttribs()); - - Extensions3D* extensions = context()->graphicsContext3D()->getExtensions(); - switch (m_type) { - case VaoTypeDefault: + switch (type) { + case Type::Default: break; - default: - setObject(extensions->createVertexArrayOES()); + case Type::User: + setObject(this->context()->graphicsContext3D()->getExtensions().createVertexArrayOES()); break; } } WebGLVertexArrayObjectOES::~WebGLVertexArrayObjectOES() { - deleteObject(0); + deleteObject(nullptr); } void WebGLVertexArrayObjectOES::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object) { - Extensions3D* extensions = context3d->getExtensions(); switch (m_type) { - case VaoTypeDefault: + case Type::Default: break; - default: - extensions->deleteVertexArrayOES(object); + case Type::User: + context3d->getExtensions().deleteVertexArrayOES(object); break; } if (m_boundElementArrayBuffer) m_boundElementArrayBuffer->onDetached(context3d); - for (size_t i = 0; i < m_vertexAttribState.size(); ++i) { - VertexAttribState& state = m_vertexAttribState[i]; + for (auto& state : m_vertexAttribState) { if (state.bufferBinding) state.bufferBinding->onDetached(context3d); } } - -void WebGLVertexArrayObjectOES::setElementArrayBuffer(PassRefPtr<WebGLBuffer> buffer) -{ - if (buffer) - buffer->onAttached(); - if (m_boundElementArrayBuffer) - m_boundElementArrayBuffer->onDetached(context()->graphicsContext3D()); - m_boundElementArrayBuffer = buffer; - -} - -void WebGLVertexArrayObjectOES::setVertexAttribState( - GC3Duint index, GC3Dsizei bytesPerElement, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, GC3Dintptr offset, PassRefPtr<WebGLBuffer> buffer) -{ - GC3Dsizei validatedStride = stride ? stride : bytesPerElement; - - VertexAttribState& state = m_vertexAttribState[index]; - - if (buffer) - buffer->onAttached(); - if (state.bufferBinding) - state.bufferBinding->onDetached(context()->graphicsContext3D()); - - state.bufferBinding = buffer; - state.bytesPerElement = bytesPerElement; - state.size = size; - state.type = type; - state.normalized = normalized; - state.stride = validatedStride; - state.originalStride = stride; - state.offset = offset; -} - -void WebGLVertexArrayObjectOES::unbindBuffer(PassRefPtr<WebGLBuffer> buffer) -{ - if (m_boundElementArrayBuffer == buffer) { - m_boundElementArrayBuffer->onDetached(context()->graphicsContext3D()); - m_boundElementArrayBuffer = 0; - } - - for (size_t i = 0; i < m_vertexAttribState.size(); ++i) { - VertexAttribState& state = m_vertexAttribState[i]; - if (state.bufferBinding == buffer) { - buffer->onDetached(context()->graphicsContext3D()); - - if (!i && !context()->isGLES2Compliant()) { - state.bufferBinding = context()->m_vertexAttrib0Buffer; - state.bufferBinding->onAttached(); - state.bytesPerElement = 0; - state.size = 4; - state.type = GraphicsContext3D::FLOAT; - state.normalized = false; - state.stride = 16; - state.originalStride = 0; - state.offset = 0; - } else - state.bufferBinding = 0; - } - } -} - -void WebGLVertexArrayObjectOES::setVertexAttribDivisor(GC3Duint index, GC3Duint divisor) -{ - VertexAttribState& state = m_vertexAttribState[index]; - state.divisor = divisor; -} - } #endif // ENABLE(WEBGL) diff --git a/Source/WebCore/html/canvas/WebGLVertexArrayObjectOES.h b/Source/WebCore/html/canvas/WebGLVertexArrayObjectOES.h index 8853ff926..f9a2a58ec 100644 --- a/Source/WebCore/html/canvas/WebGLVertexArrayObjectOES.h +++ b/Source/WebCore/html/canvas/WebGLVertexArrayObjectOES.h @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -23,84 +23,19 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebGLVertexArrayObjectOES_h -#define WebGLVertexArrayObjectOES_h +#pragma once -#include "WebGLBuffer.h" -#include "WebGLContextObject.h" - -#include <wtf/PassRefPtr.h> +#include "WebGLVertexArrayObjectBase.h" namespace WebCore { -class WebGLVertexArrayObjectOES : public WebGLContextObject { +class WebGLVertexArrayObjectOES final : public WebGLVertexArrayObjectBase { public: - enum VaoType { - VaoTypeDefault, - VaoTypeUser, - }; - + static Ref<WebGLVertexArrayObjectOES> create(WebGLRenderingContextBase&, Type); virtual ~WebGLVertexArrayObjectOES(); - - static PassRefPtr<WebGLVertexArrayObjectOES> create(WebGLRenderingContext*, VaoType); - - // Cached values for vertex attrib range checks - struct VertexAttribState { - VertexAttribState() - : enabled(false) - , bytesPerElement(0) - , size(4) - , type(GraphicsContext3D::FLOAT) - , normalized(false) - , stride(16) - , originalStride(0) - , offset(0) - , divisor(0) - { - } - - bool isBound() const { return bufferBinding && bufferBinding->object(); } - bool validateBinding() const { return !enabled || isBound(); } - - bool enabled; - RefPtr<WebGLBuffer> bufferBinding; - GC3Dsizei bytesPerElement; - GC3Dint size; - GC3Denum type; - bool normalized; - GC3Dsizei stride; - GC3Dsizei originalStride; - GC3Dintptr offset; - GC3Duint divisor; - }; - - bool isDefaultObject() const { return m_type == VaoTypeDefault; } - - bool hasEverBeenBound() const { return object() && m_hasEverBeenBound; } - void setHasEverBeenBound() { m_hasEverBeenBound = true; } - - PassRefPtr<WebGLBuffer> getElementArrayBuffer() const { return m_boundElementArrayBuffer; } - void setElementArrayBuffer(PassRefPtr<WebGLBuffer>); - - VertexAttribState& getVertexAttribState(int index) { return m_vertexAttribState[index]; } - void setVertexAttribState(GC3Duint, GC3Dsizei, GC3Dint, GC3Denum, GC3Dboolean, GC3Dsizei, GC3Dintptr, PassRefPtr<WebGLBuffer>); - void unbindBuffer(PassRefPtr<WebGLBuffer>); - - void setVertexAttribDivisor(GC3Duint index, GC3Duint divisor); - private: - WebGLVertexArrayObjectOES(WebGLRenderingContext*, VaoType); - - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) override; - - virtual bool isVertexArray() const { return true; } - - VaoType m_type; - bool m_hasEverBeenBound; - RefPtr<WebGLBuffer> m_boundElementArrayBuffer; - Vector<VertexAttribState> m_vertexAttribState; + WebGLVertexArrayObjectOES(WebGLRenderingContextBase&, Type); + void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) final; }; } // namespace WebCore - -#endif // WebGLVertexArrayObjectOES_h diff --git a/Source/WebCore/html/canvas/WebGLVertexArrayObjectOES.idl b/Source/WebCore/html/canvas/WebGLVertexArrayObjectOES.idl index ce9f18d5f..f190a7e64 100644 --- a/Source/WebCore/html/canvas/WebGLVertexArrayObjectOES.idl +++ b/Source/WebCore/html/canvas/WebGLVertexArrayObjectOES.idl @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |