diff options
author | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-08 14:30:41 +0200 |
---|---|---|
committer | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-12 13:49:54 +0200 |
commit | ab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch) | |
tree | 498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/third_party/WebKit/Source/core/html/canvas | |
parent | 4ce69f7403811819800e7c5ae1318b2647e778d1 (diff) |
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca
Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/html/canvas')
115 files changed, 9626 insertions, 9037 deletions
diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.cpp index c7e5c9301b6..bc7f5932d0f 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.cpp @@ -32,36 +32,34 @@ #include "core/html/canvas/ANGLEInstancedArrays.h" -#include "core/html/canvas/WebGLRenderingContext.h" -#include "platform/graphics/Extensions3D.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -ANGLEInstancedArrays::ANGLEInstancedArrays(WebGLRenderingContext* context) +ANGLEInstancedArrays::ANGLEInstancedArrays(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_ANGLE_instanced_arrays"); + context->extensionsUtil()->ensureExtensionEnabled("GL_ANGLE_instanced_arrays"); } ANGLEInstancedArrays::~ANGLEInstancedArrays() { } -WebGLExtension::ExtensionName ANGLEInstancedArrays::name() const +WebGLExtensionName ANGLEInstancedArrays::name() const { return ANGLEInstancedArraysName; } -PassRefPtr<ANGLEInstancedArrays> ANGLEInstancedArrays::create(WebGLRenderingContext* context) +PassRefPtr<ANGLEInstancedArrays> ANGLEInstancedArrays::create(WebGLRenderingContextBase* context) { return adoptRef(new ANGLEInstancedArrays(context)); } -bool ANGLEInstancedArrays::supported(WebGLRenderingContext* context) +bool ANGLEInstancedArrays::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_ANGLE_instanced_arrays"); + return context->extensionsUtil()->supportsExtension("GL_ANGLE_instanced_arrays"); } const char* ANGLEInstancedArrays::extensionName() @@ -69,7 +67,7 @@ const char* ANGLEInstancedArrays::extensionName() return "ANGLE_instanced_arrays"; } -void ANGLEInstancedArrays::drawArraysInstancedANGLE(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount) +void ANGLEInstancedArrays::drawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount) { if (isLost()) return; @@ -77,7 +75,7 @@ void ANGLEInstancedArrays::drawArraysInstancedANGLE(GC3Denum mode, GC3Dint first m_context->drawArraysInstancedANGLE(mode, first, count, primcount); } -void ANGLEInstancedArrays::drawElementsInstancedANGLE(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset, GC3Dsizei primcount) +void ANGLEInstancedArrays::drawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, long long offset, GLsizei primcount) { if (isLost()) return; @@ -85,7 +83,7 @@ void ANGLEInstancedArrays::drawElementsInstancedANGLE(GC3Denum mode, GC3Dsizei c m_context->drawElementsInstancedANGLE(mode, count, type, offset, primcount); } -void ANGLEInstancedArrays::vertexAttribDivisorANGLE(GC3Duint index, GC3Duint divisor) +void ANGLEInstancedArrays::vertexAttribDivisorANGLE(GLuint index, GLuint divisor) { if (isLost()) return; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.h b/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.h index 0b9f53119e0..7141e82de09 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.h @@ -32,28 +32,27 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/html/canvas/WebGLExtension.h" -#include "platform/graphics/GraphicsTypes3D.h" #include "wtf/PassRefPtr.h" namespace WebCore { -class WebGLRenderingContext; +class WebGLRenderingContextBase; -class ANGLEInstancedArrays : public WebGLExtension, public ScriptWrappable { +class ANGLEInstancedArrays FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<ANGLEInstancedArrays> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<ANGLEInstancedArrays> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~ANGLEInstancedArrays(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; - void drawArraysInstancedANGLE(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount); - void drawElementsInstancedANGLE(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset, GC3Dsizei primcount); - void vertexAttribDivisorANGLE(GC3Duint index, GC3Duint divisor); + void drawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount); + void drawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, long long offset, GLsizei primcount); + void vertexAttribDivisorANGLE(GLuint index, GLuint divisor); private: - ANGLEInstancedArrays(WebGLRenderingContext*); + ANGLEInstancedArrays(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.idl b/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.idl index 2d257cce1b9..4e63430ade0 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.idl +++ b/chromium/third_party/WebKit/Source/core/html/canvas/ANGLEInstancedArrays.idl @@ -29,12 +29,13 @@ */ [ + DoNotCheckConstants, NoInterfaceObject, - DoNotCheckConstants + TypeChecking=Interface|Nullable, ] interface ANGLEInstancedArrays { const unsigned long 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, 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, long divisor); }; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.cpp index 66429f5af14..3ff9b1ac9ee 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.cpp @@ -26,12 +26,15 @@ #include "config.h" -#include "Canvas2DContextAttributes.h" +#include "core/html/canvas/Canvas2DContextAttributes.h" + +#include "wtf/text/WTFString.h" namespace WebCore { Canvas2DContextAttributes::Canvas2DContextAttributes() : m_alpha(true) + , m_storage(PersistentStorage) { ScriptWrappable::init(this); } @@ -55,4 +58,22 @@ void Canvas2DContextAttributes::setAlpha(bool alpha) m_alpha = alpha; } +String Canvas2DContextAttributes::storage() const +{ + return m_storage == PersistentStorage ? "persistent" : "discardable"; +} + +void Canvas2DContextAttributes::setStorage(const String& storage) +{ + if (storage == "persistent") + m_storage = PersistentStorage; + else if (storage == "discardable") + m_storage = DiscardableStorage; +} + +Canvas2DContextStorage Canvas2DContextAttributes::parsedStorage() const +{ + return m_storage; +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.h b/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.h index e777ef80778..dab44564297 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.h @@ -33,6 +33,11 @@ namespace WebCore { +enum Canvas2DContextStorage { + PersistentStorage, + DiscardableStorage +}; + class Canvas2DContextAttributes : public CanvasContextAttributes, public ScriptWrappable { public: virtual ~Canvas2DContextAttributes(); @@ -44,10 +49,15 @@ public: bool alpha() const; void setAlpha(bool); + String storage() const; + void setStorage(const String&); + Canvas2DContextStorage parsedStorage() const; + protected: Canvas2DContextAttributes(); bool m_alpha; + Canvas2DContextStorage m_storage; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.idl b/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.idl index 72e01914f14..f6017b3c86f 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.idl +++ b/chromium/third_party/WebKit/Source/core/html/canvas/Canvas2DContextAttributes.idl @@ -28,4 +28,5 @@ NoInterfaceObject ] interface Canvas2DContextAttributes { attribute boolean alpha; + [RuntimeEnabled=ExperimentalCanvasFeatures] attribute DOMString storage; }; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasGradient.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasGradient.cpp index 07e62a07e10..c63aa7d85b0 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasGradient.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasGradient.cpp @@ -49,13 +49,13 @@ CanvasGradient::CanvasGradient(const FloatPoint& p0, float r0, const FloatPoint& void CanvasGradient::addColorStop(float value, const String& color, ExceptionState& exceptionState) { if (!(value >= 0 && value <= 1.0f)) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + exceptionState.throwDOMException(IndexSizeError, "The provided value (" + String::number(value) + ") is outside the range (0.0, 1.0)."); return; } RGBA32 rgba = 0; if (!parseColorOrCurrentColor(rgba, color, 0 /*canvas*/)) { - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); + exceptionState.throwDOMException(SyntaxError, "The value provided ('" + color + "') could not be parsed as a color."); return; } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasGradient.idl b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasGradient.idl index 35a4e2a31d0..3da025a744c 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasGradient.idl +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasGradient.idl @@ -24,6 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ [ + TypeChecking=Unrestricted, ] interface CanvasGradient { [RaisesException] void addColorStop(float offset, DOMString color); diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasImageSource.h b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasImageSource.h new file mode 100644 index 00000000000..10e3b958b6c --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasImageSource.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2007 Alp Toker <alp@atoker.com> + * + * 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 COMPUTER, 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 + * 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 CanvasImageSource_h +#define CanvasImageSource_h + +#include "wtf/PassRefPtr.h" + +namespace WebCore { + +class Image; +class SecurityOrigin; + +enum SourceImageMode { + CopySourceImageIfVolatile, + DontCopySourceImage +}; + +enum SourceImageStatus { + NormalSourceImageStatus, + ExternalSourceImageStatus, // Shared with another GPU context + UndecodableSourceImageStatus, // Image element with a 'broken' image + ZeroSizeCanvasSourceImageStatus, // Source is a canvas with width or heigh of zero + IncompleteSourceImageStatus, // Image element with no source media + InvalidSourceImageStatus, +}; + +class CanvasImageSource { +public: + virtual PassRefPtr<Image> getSourceImageForCanvas(SourceImageMode, SourceImageStatus* = 0) const = 0; + + // IMPORTANT: Result must be independent of whether destinationContext is + // already tainted because this function may be used to determine whether + // a CanvasPattern is "origin clean", and that pattern may be used on + // another canvas, which may not be already tainted. + virtual bool wouldTaintOrigin(SecurityOrigin* destinationSecurityOrigin) const = 0; + + virtual bool isVideoElement() const { return false; } + + // Adjusts the source and destination rectangles for cases where the actual + // source image is a subregion of the image returned by getSourceImageForCanvas. + virtual void adjustDrawRects(FloatRect* srcRect, FloatRect* dstRect) const { } + + virtual FloatSize sourceSize() const = 0; + virtual FloatSize defaultDestinationSize() const { return sourceSize(); } + virtual const KURL& sourceURL() const { return blankURL(); } + +protected: + virtual ~CanvasImageSource() { } +}; + +} // namespace WebCore + +#endif diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPathMethods.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPathMethods.cpp index 66a1ac99fa4..879487b14d3 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPathMethods.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPathMethods.cpp @@ -113,7 +113,7 @@ void CanvasPathMethods::arcTo(float x1, float y1, float x2, float y2, float r, E return; if (r < 0) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + exceptionState.throwDOMException(IndexSizeError, "The radius provided (" + String::number(r) + ") is negative."); return; } @@ -135,7 +135,6 @@ namespace { float adjustEndAngle(float startAngle, float endAngle, bool anticlockwise) { - float twoPi = 2 * piFloat; float newEndAngle = endAngle; /* http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-arc * If the anticlockwise argument is false and endAngle-startAngle is equal to or greater than 2pi, or, @@ -143,10 +142,10 @@ float adjustEndAngle(float startAngle, float endAngle, bool anticlockwise) * then the arc is the whole circumference of this ellipse, and the point at startAngle along this circle's circumference, * measured in radians clockwise from the ellipse's semi-major axis, acts as both the start point and the end point. */ - if (!anticlockwise && endAngle - startAngle >= twoPi) - newEndAngle = startAngle + twoPi; - else if (anticlockwise && startAngle - endAngle >= twoPi) - newEndAngle = startAngle - twoPi; + if (!anticlockwise && endAngle - startAngle >= twoPiFloat) + newEndAngle = startAngle + twoPiFloat; + else if (anticlockwise && startAngle - endAngle >= twoPiFloat) + newEndAngle = startAngle - twoPiFloat; /* * Otherwise, the arc is the path along the circumference of this ellipse from the start point to the end point, @@ -159,9 +158,9 @@ float adjustEndAngle(float startAngle, float endAngle, bool anticlockwise) * We preserve backward-compatibility. */ else if (!anticlockwise && startAngle > endAngle) - newEndAngle = startAngle + (twoPi - fmodf(startAngle - endAngle, twoPi)); + newEndAngle = startAngle + (twoPiFloat - fmodf(startAngle - endAngle, twoPiFloat)); else if (anticlockwise && startAngle < endAngle) - newEndAngle = startAngle - (twoPi - fmodf(endAngle - startAngle, twoPi)); + newEndAngle = startAngle - (twoPiFloat - fmodf(endAngle - startAngle, twoPiFloat)); ASSERT(ellipseIsRenderable(startAngle, newEndAngle)); return newEndAngle; @@ -180,17 +179,16 @@ inline FloatPoint getPointOnEllipse(float radiusX, float radiusY, float theta) void canonicalizeAngle(float* startAngle, float* endAngle) { // Make 0 <= startAngle < 2*PI - float twoPi = 2 * piFloat; float newStartAngle = *startAngle; if (newStartAngle < 0) - newStartAngle = twoPi + fmodf(newStartAngle, -twoPi); + newStartAngle = twoPiFloat + fmodf(newStartAngle, -twoPiFloat); else - newStartAngle = fmodf(newStartAngle, twoPi); + newStartAngle = fmodf(newStartAngle, twoPiFloat); float delta = newStartAngle - *startAngle; *startAngle = newStartAngle; *endAngle = *endAngle + delta; - ASSERT(newStartAngle >= 0 && newStartAngle < twoPi); + ASSERT(newStartAngle >= 0 && newStartAngle < twoPiFloat); } /* @@ -227,25 +225,24 @@ void canonicalizeAngle(float* startAngle, float* endAngle) void degenerateEllipse(CanvasPathMethods* path, float x, float y, float radiusX, float radiusY, float rotation, float startAngle, float endAngle, bool anticlockwise) { ASSERT(ellipseIsRenderable(startAngle, endAngle)); - ASSERT(startAngle >= 0 && startAngle < 2 * piFloat); + ASSERT(startAngle >= 0 && startAngle < twoPiFloat); ASSERT((anticlockwise && (startAngle - endAngle) >= 0) || (!anticlockwise && (endAngle - startAngle) >= 0)); FloatPoint center(x, y); AffineTransform rotationMatrix; - rotationMatrix.rotate(rad2deg(rotation)); + rotationMatrix.rotateRadians(rotation); // First, if the object's path has any subpaths, then the method must add a straight line from the last point in the subpath to the start point of the arc. lineToFloatPoint(path, center + rotationMatrix.mapPoint(getPointOnEllipse(radiusX, radiusY, startAngle))); if ((!radiusX && !radiusY) || startAngle == endAngle) return; - float halfPiFloat = piFloat * 0.5; if (!anticlockwise) { - // startAngle - fmodf(startAngle, halfPiFloat) + halfPiFloat is the one of (0, 0.5Pi, Pi, 1.5Pi, 2Pi) + // startAngle - fmodf(startAngle, piOverTwoFloat) + piOverTwoFloat is the one of (0, 0.5Pi, Pi, 1.5Pi, 2Pi) // that is the closest to startAngle on the clockwise direction. - for (float angle = startAngle - fmodf(startAngle, halfPiFloat) + halfPiFloat; angle < endAngle; angle += halfPiFloat) + for (float angle = startAngle - fmodf(startAngle, piOverTwoFloat) + piOverTwoFloat; angle < endAngle; angle += piOverTwoFloat) lineToFloatPoint(path, center + rotationMatrix.mapPoint(getPointOnEllipse(radiusX, radiusY, angle))); } else { - for (float angle = startAngle - fmodf(startAngle, halfPiFloat); angle > endAngle; angle -= halfPiFloat) + for (float angle = startAngle - fmodf(startAngle, piOverTwoFloat); angle > endAngle; angle -= piOverTwoFloat) lineToFloatPoint(path, center + rotationMatrix.mapPoint(getPointOnEllipse(radiusX, radiusY, angle))); } @@ -260,7 +257,7 @@ void CanvasPathMethods::arc(float x, float y, float radius, float startAngle, fl return; if (radius < 0) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + exceptionState.throwDOMException(IndexSizeError, "The radius provided (" + String::number(radius) + ") is negative."); return; } @@ -283,8 +280,12 @@ void CanvasPathMethods::ellipse(float x, float y, float radiusX, float radiusY, 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) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + if (radiusX < 0) { + exceptionState.throwDOMException(IndexSizeError, "The major-axis radius provided (" + String::number(radiusX) + ") is negative."); + return; + } + if (radiusY < 0) { + exceptionState.throwDOMException(IndexSizeError, "The minor-axis radius provided (" + String::number(radiusY) + ") is negative."); return; } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPathMethods.h b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPathMethods.h index 100f95cf055..2f0160ea1bf 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPathMethods.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPathMethods.h @@ -54,6 +54,7 @@ public: protected: CanvasPathMethods() { } + CanvasPathMethods(const Path& path) : m_path(path) { } Path m_path; }; } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPathMethods.idl b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPathMethods.idl new file mode 100644 index 00000000000..2c37810cef7 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPathMethods.idl @@ -0,0 +1,20 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#canvaspathmethods + +[ + NoInterfaceObject, // Always used on target of 'implements' +] interface CanvasPathMethods { + // shared path API methods + void closePath(); + void moveTo(unrestricted float x, unrestricted float y); + void lineTo(unrestricted float x, unrestricted float y); + void quadraticCurveTo(unrestricted float cpx, unrestricted float cpy, unrestricted float x, unrestricted float y); + void bezierCurveTo(unrestricted float cp1x, unrestricted float cp1y, unrestricted float cp2x, unrestricted float cp2y, unrestricted float x, unrestricted float y); + [RaisesException] void arcTo(unrestricted float x1, unrestricted float y1, unrestricted float x2, unrestricted float y2, unrestricted float radius); + void rect(unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height); + [RaisesException] void arc(unrestricted float x, unrestricted float y, unrestricted float radius, unrestricted float startAngle, unrestricted float endAngle, [Default=Undefined] optional boolean anticlockwise); + [RaisesException] void ellipse(unrestricted float x, unrestricted float y, unrestricted float radiusX, unrestricted float radiusY, unrestricted float rotation, unrestricted float startAngle, unrestricted float endAngle, [Default=Undefined] optional boolean anticlockwise); +}; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPattern.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPattern.cpp index f7ee0da4388..e011ff082a3 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPattern.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasPattern.cpp @@ -54,7 +54,7 @@ void CanvasPattern::parseRepetitionType(const String& type, bool& repeatX, bool& repeatY = true; return; } - exceptionState.throwUninformativeAndGenericDOMException(SyntaxError); + exceptionState.throwDOMException(SyntaxError, "The provided type ('" + type + "') is not one of 'repeat', 'no-repeat', 'repeat-x', or 'repeat-y'."); } CanvasPattern::CanvasPattern(PassRefPtr<Image> image, bool repeatX, bool repeatY, bool originClean) diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.cpp index 47a0e616efb..9e5dd350d8f 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.cpp @@ -26,10 +26,7 @@ #include "config.h" #include "core/html/canvas/CanvasRenderingContext.h" -#include "core/fetch/ImageResource.h" -#include "core/html/HTMLImageElement.h" -#include "core/html/HTMLVideoElement.h" -#include "core/html/canvas/CanvasPattern.h" +#include "core/html/canvas/CanvasImageSource.h" #include "platform/weborigin/SecurityOrigin.h" namespace WebCore { @@ -37,72 +34,30 @@ namespace WebCore { CanvasRenderingContext::CanvasRenderingContext(HTMLCanvasElement* canvas) : m_canvas(canvas) { - ScriptWrappable::init(this); -} - -bool CanvasRenderingContext::wouldTaintOrigin(const CanvasPattern* pattern) -{ - if (canvas()->originClean() && pattern && !pattern->originClean()) - return true; - return false; -} - -bool CanvasRenderingContext::wouldTaintOrigin(const HTMLCanvasElement* sourceCanvas) -{ - if (canvas()->originClean() && sourceCanvas && !sourceCanvas->originClean()) - return true; - return false; -} - -bool CanvasRenderingContext::wouldTaintOrigin(const HTMLImageElement* image) -{ - if (!image || !canvas()->originClean()) - return false; - - ImageResource* cachedImage = image->cachedImage(); - if (!cachedImage->image()->currentFrameHasSingleSecurityOrigin()) - return true; - - return wouldTaintOrigin(cachedImage->response().url()) && !cachedImage->passesAccessControlCheck(canvas()->securityOrigin()); -} - -bool CanvasRenderingContext::wouldTaintOrigin(const HTMLVideoElement* video) -{ - // FIXME: This check is likely wrong when a redirect is involved. We need - // 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()) - return false; - - if (!video->hasSingleSecurityOrigin()) - return true; - - if (!(video->player() && video->player()->didPassCORSAccessCheck()) && wouldTaintOrigin(video->currentSrc())) - return true; - - return false; -} - -bool CanvasRenderingContext::wouldTaintOrigin(const KURL& url) -{ - if (!canvas()->originClean() || m_cleanURLs.contains(url.string())) - return false; - - if (canvas()->securityOrigin()->taintsCanvas(url)) - return true; - - if (url.protocolIsData()) - return false; - m_cleanURLs.add(url.string()); - return false; } -void CanvasRenderingContext::checkOrigin(const KURL& url) +bool CanvasRenderingContext::wouldTaintOrigin(CanvasImageSource* imageSource) { - if (wouldTaintOrigin(url)) - canvas()->setOriginTainted(); + const KURL& sourceURL = imageSource->sourceURL(); + bool hasURL = (sourceURL.isValid() && !sourceURL.isAboutBlankURL()); + + if (hasURL) { + if (sourceURL.protocolIsData() || m_cleanURLs.contains(sourceURL.string())) + return false; + if (m_dirtyURLs.contains(sourceURL.string())) + return true; + } + + bool taintOrigin = imageSource->wouldTaintOrigin(canvas()->securityOrigin()); + + if (hasURL) { + if (taintOrigin) + m_dirtyURLs.add(sourceURL.string()); + else + m_cleanURLs.add(sourceURL.string()); + } + return taintOrigin; } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.h b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.h index 2f5cd637991..0999d334bf7 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.h @@ -26,8 +26,8 @@ #ifndef CanvasRenderingContext_h #define CanvasRenderingContext_h -#include "bindings/v8/ScriptWrappable.h" #include "core/html/HTMLCanvasElement.h" +#include "platform/heap/Handle.h" #include "wtf/HashSet.h" #include "wtf/Noncopyable.h" #include "wtf/text/StringHash.h" @@ -36,20 +36,22 @@ namespace blink { class WebLayer; } namespace WebCore { -class CanvasPattern; +class CanvasImageSource; class HTMLCanvasElement; -class HTMLImageElement; -class HTMLVideoElement; class KURL; class WebGLObject; -class CanvasRenderingContext : public ScriptWrappable { - WTF_MAKE_NONCOPYABLE(CanvasRenderingContext); WTF_MAKE_FAST_ALLOCATED; +class CanvasRenderingContext : public NoBaseWillBeGarbageCollectedFinalized<CanvasRenderingContext> { + WTF_MAKE_NONCOPYABLE(CanvasRenderingContext); + WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; public: virtual ~CanvasRenderingContext() { } +#if !ENABLE(OILPAN) void ref() { m_canvas->ref(); } void deref() { m_canvas->deref(); } +#endif + HTMLCanvasElement* canvas() const { return m_canvas; } virtual bool is2d() const { return false; } @@ -61,24 +63,17 @@ public: virtual blink::WebLayer* platformLayer() const { return 0; } + virtual void trace(Visitor* visitor) { visitor->trace(m_canvas); } + + bool wouldTaintOrigin(CanvasImageSource*); + protected: CanvasRenderingContext(HTMLCanvasElement*); - bool wouldTaintOrigin(const CanvasPattern*); - bool wouldTaintOrigin(const HTMLCanvasElement*); - bool wouldTaintOrigin(const HTMLImageElement*); - bool wouldTaintOrigin(const HTMLVideoElement*); - bool wouldTaintOrigin(const KURL&); - - template<class T> void checkOrigin(const T* arg) - { - if (wouldTaintOrigin(arg)) - canvas()->setOriginTainted(); - } - void checkOrigin(const KURL&); private: - HTMLCanvasElement* m_canvas; + RawPtrWillBeMember<HTMLCanvasElement> m_canvas; HashSet<String> m_cleanURLs; + HashSet<String> m_dirtyURLs; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.idl b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.idl deleted file mode 100644 index ae89a5fcd56..00000000000 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext.idl +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2009 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 COMPUTER, 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 - * 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. - */ - -[ - Custom=Wrap, - NoInterfaceObject, -] interface CanvasRenderingContext { - readonly attribute HTMLCanvasElement canvas; -}; - diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.cpp index 68f213b18ae..ccca4ddd03f 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.cpp @@ -33,16 +33,18 @@ #include "config.h" #include "core/html/canvas/CanvasRenderingContext2D.h" -#include "CSSPropertyNames.h" +#include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ExceptionStatePlaceholder.h" +#include "core/CSSPropertyNames.h" #include "core/accessibility/AXObjectCache.h" #include "core/css/CSSFontSelector.h" -#include "core/css/CSSParser.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/StylePropertySet.h" #include "core/css/resolver/StyleResolver.h" #include "core/dom/ExceptionCode.h" #include "core/fetch/ImageResource.h" +#include "core/frame/ImageBitmap.h" #include "core/html/HTMLCanvasElement.h" #include "core/html/HTMLImageElement.h" #include "core/html/HTMLMediaElement.h" @@ -52,46 +54,52 @@ #include "core/html/canvas/CanvasGradient.h" #include "core/html/canvas/CanvasPattern.h" #include "core/html/canvas/CanvasStyle.h" -#include "core/html/canvas/DOMPath.h" -#include "core/frame/ImageBitmap.h" +#include "core/html/canvas/Path2D.h" #include "core/rendering/RenderImage.h" #include "core/rendering/RenderLayer.h" #include "core/rendering/RenderTheme.h" #include "platform/fonts/FontCache.h" #include "platform/geometry/FloatQuad.h" +#include "platform/graphics/DrawLooperBuilder.h" #include "platform/graphics/GraphicsContextStateSaver.h" -#include "platform/graphics/DrawLooper.h" #include "platform/text/TextRun.h" -#include "platform/weborigin/SecurityOrigin.h" #include "wtf/CheckedArithmetic.h" #include "wtf/MathExtras.h" #include "wtf/OwnPtr.h" #include "wtf/Uint8ClampedArray.h" #include "wtf/text/StringBuilder.h" -using namespace std; - namespace WebCore { static const int defaultFontSize = 10; static const char defaultFontFamily[] = "sans-serif"; static const char defaultFont[] = "10px sans-serif"; +static const double TryRestoreContextInterval = 0.5; +static const unsigned MaxTryRestoreContextAttempts = 4; + +static bool contextLostRestoredEventsEnabled() +{ + return RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled(); +} CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas, const Canvas2DContextAttributes* attrs, bool usesCSSCompatibilityParseMode) : CanvasRenderingContext(canvas) - , m_stateStack(1) - , m_unrealizedSaveCount(0) , m_usesCSSCompatibilityParseMode(usesCSSCompatibilityParseMode) , m_hasAlpha(!attrs || attrs->alpha()) -{ + , m_isContextLost(false) + , m_contextRestorable(true) + , m_storageMode(!attrs ? PersistentStorage : attrs->parsedStorage()) + , m_tryRestoreContextAttemptCount(0) + , m_dispatchContextLostEventTimer(this, &CanvasRenderingContext2D::dispatchContextLostEvent) + , m_dispatchContextRestoredEventTimer(this, &CanvasRenderingContext2D::dispatchContextRestoredEvent) + , m_tryRestoreContextEventTimer(this, &CanvasRenderingContext2D::tryRestoreContextEvent) +{ + m_stateStack.append(adoptPtrWillBeNoop(new State())); ScriptWrappable::init(this); } void CanvasRenderingContext2D::unwindStateStack() { - // Ensure that the state stack in the ImageBuffer's context - // is cleared before destruction, to avoid assertions in the - // GraphicsContext dtor. if (size_t stackSize = m_stateStack.size()) { if (GraphicsContext* context = canvas()->existingDrawingContext()) { while (--stackSize) @@ -102,8 +110,14 @@ void CanvasRenderingContext2D::unwindStateStack() CanvasRenderingContext2D::~CanvasRenderingContext2D() { -#if !ASSERT_DISABLED - unwindStateStack(); +} + +void CanvasRenderingContext2D::validateStateStack() +{ +#if ASSERT_ENABLED + GraphicsContext* context = canvas()->existingDrawingContext(); + if (context && !context->contextDisabled()) + ASSERT(context->saveCount() == m_stateStack.size()); #endif } @@ -115,13 +129,108 @@ bool CanvasRenderingContext2D::isAccelerated() const return context && context->isAccelerated(); } +bool CanvasRenderingContext2D::isContextLost() const +{ + return m_isContextLost; +} + +void CanvasRenderingContext2D::loseContext() +{ + if (m_isContextLost) + return; + m_isContextLost = true; + m_dispatchContextLostEventTimer.startOneShot(0, FROM_HERE); +} + +void CanvasRenderingContext2D::restoreContext() +{ + if (!m_contextRestorable) + return; + // This code path is for restoring from an eviction + // Restoring from surface failure is handled internally + ASSERT(m_isContextLost && !canvas()->hasImageBuffer()); + + if (canvas()->buffer()) { + if (contextLostRestoredEventsEnabled()) { + m_dispatchContextRestoredEventTimer.startOneShot(0, FROM_HERE); + } else { + // legacy synchronous context restoration. + reset(); + m_isContextLost = false; + } + } +} + +void CanvasRenderingContext2D::trace(Visitor* visitor) +{ +#if ENABLE(OILPAN) + visitor->trace(m_stateStack); + visitor->trace(m_fetchedFonts); +#endif + CanvasRenderingContext::trace(visitor); +} + +void CanvasRenderingContext2D::dispatchContextLostEvent(Timer<CanvasRenderingContext2D>*) +{ + if (contextLostRestoredEventsEnabled()) { + RefPtrWillBeRawPtr<Event> event = Event::createCancelable(EventTypeNames::contextlost); + canvas()->dispatchEvent(event); + if (event->defaultPrevented()) { + m_contextRestorable = false; + } + } + + // If an image buffer is present, it means the context was not lost due to + // an eviction, but rather due to a surface failure (gpu context lost?) + if (m_contextRestorable && canvas()->hasImageBuffer()) { + m_tryRestoreContextAttemptCount = 0; + m_tryRestoreContextEventTimer.startRepeating(TryRestoreContextInterval, FROM_HERE); + } +} + +void CanvasRenderingContext2D::tryRestoreContextEvent(Timer<CanvasRenderingContext2D>* timer) +{ + if (!m_isContextLost) { + // Canvas was already restored (possibly thanks to a resize), so stop trying. + m_tryRestoreContextEventTimer.stop(); + return; + } + if (canvas()->hasImageBuffer() && canvas()->buffer()->restoreSurface()) { + m_tryRestoreContextEventTimer.stop(); + dispatchContextRestoredEvent(0); + } + + if (++m_tryRestoreContextAttemptCount > MaxTryRestoreContextAttempts) + canvas()->discardImageBuffer(); + + if (!canvas()->hasImageBuffer()) { + // final attempt: allocate a brand new image buffer instead of restoring + timer->stop(); + if (canvas()->buffer()) + dispatchContextRestoredEvent(0); + } +} + +void CanvasRenderingContext2D::dispatchContextRestoredEvent(Timer<CanvasRenderingContext2D>*) +{ + if (!m_isContextLost) + return; + reset(); + m_isContextLost = false; + if (contextLostRestoredEventsEnabled()) { + RefPtrWillBeRawPtr<Event> event(Event::create(EventTypeNames::contextrestored)); + canvas()->dispatchEvent(event); + } +} + void CanvasRenderingContext2D::reset() { + validateStateStack(); unwindStateStack(); m_stateStack.resize(1); - m_stateStack.first() = State(); + m_stateStack.first() = adoptPtrWillBeNoop(new State()); m_path.clear(); - m_unrealizedSaveCount = 0; + validateStateStack(); } // Important: Several of these properties are also stored in GraphicsContext's @@ -129,7 +238,8 @@ void CanvasRenderingContext2D::reset() // that the canvas 2d spec specifies. Make sure to sync the initial state of the // GraphicsContext in HTMLCanvasElement::createImageBuffer()! CanvasRenderingContext2D::State::State() - : m_strokeStyle(CanvasStyle::createFromRGBA(Color::black)) + : m_unrealizedSaveCount(0) + , m_strokeStyle(CanvasStyle::createFromRGBA(Color::black)) , m_fillStyle(CanvasStyle::createFromRGBA(Color::black)) , m_lineWidth(1) , m_lineCap(ButtCap) @@ -151,7 +261,8 @@ CanvasRenderingContext2D::State::State() } CanvasRenderingContext2D::State::State(const State& other) - : FontSelectorClient() + : CSSFontSelectorClient() + , m_unrealizedSaveCount(other.m_unrealizedSaveCount) , m_unparsedStrokeColor(other.m_unparsedStrokeColor) , m_unparsedFillColor(other.m_unparsedFillColor) , m_strokeStyle(other.m_strokeStyle) @@ -177,7 +288,7 @@ CanvasRenderingContext2D::State::State(const State& other) , m_realizedFont(other.m_realizedFont) { if (m_realizedFont) - m_font.fontSelector()->registerForInvalidationCallbacks(this); + static_cast<CSSFontSelector*>(m_font.fontSelector())->registerForInvalidationCallbacks(this); } CanvasRenderingContext2D::State& CanvasRenderingContext2D::State::operator=(const State& other) @@ -185,9 +296,12 @@ CanvasRenderingContext2D::State& CanvasRenderingContext2D::State::operator=(cons if (this == &other) return *this; +#if !ENABLE(OILPAN) if (m_realizedFont) - m_font.fontSelector()->unregisterForInvalidationCallbacks(this); + static_cast<CSSFontSelector*>(m_font.fontSelector())->unregisterForInvalidationCallbacks(this); +#endif + m_unrealizedSaveCount = other.m_unrealizedSaveCount; m_unparsedStrokeColor = other.m_unparsedStrokeColor; m_unparsedFillColor = other.m_unparsedFillColor; m_strokeStyle = other.m_strokeStyle; @@ -212,18 +326,20 @@ CanvasRenderingContext2D::State& CanvasRenderingContext2D::State::operator=(cons m_realizedFont = other.m_realizedFont; if (m_realizedFont) - m_font.fontSelector()->registerForInvalidationCallbacks(this); + static_cast<CSSFontSelector*>(m_font.fontSelector())->registerForInvalidationCallbacks(this); return *this; } CanvasRenderingContext2D::State::~State() { +#if !ENABLE(OILPAN) if (m_realizedFont) - m_font.fontSelector()->unregisterForInvalidationCallbacks(this); + static_cast<CSSFontSelector*>(m_font.fontSelector())->unregisterForInvalidationCallbacks(this); +#endif } -void CanvasRenderingContext2D::State::fontsNeedUpdate(FontSelector* fontSelector) +void CanvasRenderingContext2D::State::fontsNeedUpdate(CSSFontSelector* fontSelector) { ASSERT_ARG(fontSelector, fontSelector == m_font.fontSelector()); ASSERT(m_realizedFont); @@ -231,22 +347,33 @@ void CanvasRenderingContext2D::State::fontsNeedUpdate(FontSelector* fontSelector m_font.update(fontSelector); } -void CanvasRenderingContext2D::realizeSavesLoop() -{ - ASSERT(m_unrealizedSaveCount); - ASSERT(m_stateStack.size() >= 1); - GraphicsContext* context = drawingContext(); - do { - m_stateStack.append(state()); +void CanvasRenderingContext2D::realizeSaves() +{ + validateStateStack(); + if (state().m_unrealizedSaveCount) { + ASSERT(m_stateStack.size() >= 1); + // Reduce the current state's unrealized count by one now, + // to reflect the fact we are saving one state. + m_stateStack.last()->m_unrealizedSaveCount--; + m_stateStack.append(adoptPtrWillBeNoop(new State(state()))); + // Set the new state's unrealized count to 0, because it has no outstanding saves. + // We need to do this explicitly because the copy constructor and operator= used + // by the Vector operations copy the unrealized count from the previous state (in + // turn necessary to support correct resizing and unwinding of the stack). + m_stateStack.last()->m_unrealizedSaveCount = 0; + GraphicsContext* context = drawingContext(); if (context) context->save(); - } while (--m_unrealizedSaveCount); + validateStateStack(); + } } void CanvasRenderingContext2D::restore() { - if (m_unrealizedSaveCount) { - --m_unrealizedSaveCount; + validateStateStack(); + if (state().m_unrealizedSaveCount) { + // We never realized the save, so just record that it was unnecessary. + --m_stateStack.last()->m_unrealizedSaveCount; return; } ASSERT(m_stateStack.size() >= 1); @@ -256,9 +383,9 @@ void CanvasRenderingContext2D::restore() m_stateStack.removeLast(); m_path.transform(state().m_transform.inverse()); GraphicsContext* c = drawingContext(); - if (!c) - return; - c->restore(); + if (c) + c->restore(); + validateStateStack(); } CanvasStyle* CanvasRenderingContext2D::strokeStyle() const @@ -281,8 +408,9 @@ void CanvasRenderingContext2D::setStrokeStyle(PassRefPtr<CanvasStyle> prpStyle) style = CanvasStyle::createFromRGBA(colorWithOverrideAlpha(currentColor(canvas()), style->overrideAlpha())); else style = CanvasStyle::createFromRGBA(currentColor(canvas())); - } else - checkOrigin(style->canvasPattern()); + } else if (canvas()->originClean() && style->canvasPattern() && !style->canvasPattern()->originClean()) { + canvas()->setOriginTainted(); + } realizeSaves(); modifiableState().m_strokeStyle = style.release(); @@ -313,8 +441,9 @@ void CanvasRenderingContext2D::setFillStyle(PassRefPtr<CanvasStyle> prpStyle) style = CanvasStyle::createFromRGBA(colorWithOverrideAlpha(currentColor(canvas()), style->overrideAlpha())); else style = CanvasStyle::createFromRGBA(currentColor(canvas())); - } else - checkOrigin(style->canvasPattern()); + } else if (canvas()->originClean() && style->canvasPattern() && !style->canvasPattern()->originClean()) { + canvas()->setOriginTainted(); + } realizeSaves(); modifiableState().m_fillStyle = style.release(); @@ -492,18 +621,7 @@ void CanvasRenderingContext2D::setLineDash(const Vector<float>& 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.append(dash); - - applyLineDash(); -} - -void CanvasRenderingContext2D::setWebkitLineDash(const Vector<float>& dash) -{ - if (!lineDashSequenceIsValid(dash)) - return; - - realizeSaves(); - modifiableState().m_lineDash = dash; + modifiableState().m_lineDash.appendVector(dash); applyLineDash(); } @@ -523,16 +641,6 @@ void CanvasRenderingContext2D::setLineDashOffset(float offset) applyLineDash(); } -float CanvasRenderingContext2D::webkitLineDashOffset() const -{ - return lineDashOffset(); -} - -void CanvasRenderingContext2D::setWebkitLineDashOffset(float offset) -{ - setLineDashOffset(offset); -} - void CanvasRenderingContext2D::applyLineDash() const { GraphicsContext* c = drawingContext(); @@ -560,7 +668,7 @@ void CanvasRenderingContext2D::setGlobalAlpha(float alpha) GraphicsContext* c = drawingContext(); if (!c) return; - c->setAlpha(alpha); + c->setAlphaAsFloat(alpha); } String CanvasRenderingContext2D::globalCompositeOperation() const @@ -585,9 +693,11 @@ void CanvasRenderingContext2D::setGlobalCompositeOperation(const String& operati c->setCompositeOperation(op, blendMode); } -void CanvasRenderingContext2D::setCurrentTransform(const SVGMatrix& matrix) +void CanvasRenderingContext2D::setCurrentTransform(PassRefPtr<SVGMatrixTearOff> passMatrixTearOff) { - setTransform(matrix.a(), matrix.b(), matrix.c(), matrix.d(), matrix.e(), matrix.f()); + RefPtr<SVGMatrixTearOff> matrixTearOff = passMatrixTearOff; + const AffineTransform& transform = matrixTearOff->value(); + setTransform(transform.a(), transform.b(), transform.c(), transform.d(), transform.e(), transform.f()); } void CanvasRenderingContext2D::scale(float sx, float sy) @@ -614,7 +724,7 @@ void CanvasRenderingContext2D::scale(float sx, float sy) } modifiableState().m_transform = newTransform; - c->scale(FloatSize(sx, sy)); + c->scale(sx, sy); m_path.transform(AffineTransform().scaleNonUniform(1.0 / sx, 1.0 / sy)); } @@ -630,7 +740,7 @@ void CanvasRenderingContext2D::rotate(float angleInRadians) return; AffineTransform newTransform = state().m_transform; - newTransform.rotate(angleInRadians / piDouble * 180.0); + newTransform.rotateRadians(angleInRadians); if (state().m_transform == newTransform) return; @@ -643,7 +753,7 @@ void CanvasRenderingContext2D::rotate(float angleInRadians) modifiableState().m_transform = newTransform; c->rotate(angleInRadians); - m_path.transform(AffineTransform().rotate(-angleInRadians / piDouble * 180.0)); + m_path.transform(AffineTransform().rotateRadians(-angleInRadians)); } void CanvasRenderingContext2D::translate(float tx, float ty) @@ -745,7 +855,7 @@ void CanvasRenderingContext2D::setStrokeColor(const String& color) if (color == state().m_unparsedStrokeColor) return; realizeSaves(); - setStrokeStyle(CanvasStyle::createFromString(color, &canvas()->document())); + setStrokeStyle(CanvasStyle::createFromString(color)); modifiableState().m_unparsedStrokeColor = color; } @@ -787,7 +897,7 @@ void CanvasRenderingContext2D::setFillColor(const String& color) if (color == state().m_unparsedFillColor) return; realizeSaves(); - setFillStyle(CanvasStyle::createFromString(color, &canvas()->document())); + setFillStyle(CanvasStyle::createFromString(color)); modifiableState().m_unparsedFillColor = color; } @@ -829,18 +939,6 @@ void CanvasRenderingContext2D::beginPath() m_path.clear(); } -PassRefPtr<DOMPath> CanvasRenderingContext2D::currentPath() -{ - return DOMPath::create(m_path); -} - -void CanvasRenderingContext2D::setCurrentPath(DOMPath* path) -{ - if (!path) - return; - m_path = path->path(); -} - static bool validateRectForCanvas(float& x, float& y, float& width, float& height) { if (!std::isfinite(x) | !std::isfinite(y) | !std::isfinite(width) | !std::isfinite(height)) @@ -870,102 +968,157 @@ static bool isFullCanvasCompositeMode(CompositeOperator op) return op == CompositeSourceIn || op == CompositeSourceOut || op == CompositeDestinationIn || op == CompositeDestinationAtop; } -static bool parseWinding(const String& windingRuleString, WindRule& windRule) +static WindRule parseWinding(const String& windingRuleString) { if (windingRuleString == "nonzero") - windRule = RULE_NONZERO; - else if (windingRuleString == "evenodd") - windRule = RULE_EVENODD; - else - return false; + return RULE_NONZERO; + if (windingRuleString == "evenodd") + return RULE_EVENODD; - return true; + ASSERT_NOT_REACHED(); + return RULE_EVENODD; } -void CanvasRenderingContext2D::fill(const String& windingRuleString) +void CanvasRenderingContext2D::fillInternal(const Path& path, const String& windingRuleString) { + if (path.isEmpty()) { + return; + } GraphicsContext* c = drawingContext(); - if (!c) + if (!c) { return; - if (!state().m_invertibleCTM) + } + if (!state().m_invertibleCTM) { return; + } FloatRect clipBounds; - if (!drawingContext()->getTransformedClipBounds(&clipBounds)) + if (!c->getTransformedClipBounds(&clipBounds)) { return; + } // If gradient size is zero, then paint nothing. Gradient* gradient = c->fillGradient(); - if (gradient && gradient->isZeroSize()) + 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); + WindRule windRule = c->fillRule(); + c->setFillRule(parseWinding(windingRuleString)); - if (isFullCanvasCompositeMode(state().m_globalComposite)) { - fullCanvasCompositedFill(m_path); - didDraw(clipBounds); - } else if (state().m_globalComposite == CompositeCopy) { - clearCanvas(); - c->fillPath(m_path); - didDraw(clipBounds); - } else { - FloatRect dirtyRect; - if (computeDirtyRect(m_path.boundingRect(), clipBounds, &dirtyRect)) { - c->fillPath(m_path); - didDraw(dirtyRect); - } + if (isFullCanvasCompositeMode(state().m_globalComposite)) { + fullCanvasCompositedFill(path); + didDraw(clipBounds); + } else if (state().m_globalComposite == CompositeCopy) { + clearCanvas(); + c->fillPath(path); + didDraw(clipBounds); + } else { + FloatRect dirtyRect; + if (computeDirtyRect(path.boundingRect(), clipBounds, &dirtyRect)) { + c->fillPath(path); + didDraw(dirtyRect); } - - c->setFillRule(windRule); } + + c->setFillRule(windRule); } -void CanvasRenderingContext2D::stroke() +void CanvasRenderingContext2D::fill(const String& windingRuleString) +{ + fillInternal(m_path, windingRuleString); +} + +void CanvasRenderingContext2D::fill(Path2D* domPath, const String& windingRuleString) { + fillInternal(domPath->path(), windingRuleString); +} + +void CanvasRenderingContext2D::strokeInternal(const Path& path) +{ + if (path.isEmpty()) { + return; + } GraphicsContext* c = drawingContext(); - if (!c) + if (!c) { return; - if (!state().m_invertibleCTM) + } + if (!state().m_invertibleCTM) { + return; + } + FloatRect clipBounds; + if (!c->getTransformedClipBounds(&clipBounds)) return; // If gradient size is zero, then paint nothing. Gradient* gradient = c->strokeGradient(); - if (gradient && gradient->isZeroSize()) + if (gradient && gradient->isZeroSize()) { return; + } - if (!m_path.isEmpty()) { - FloatRect bounds = m_path.boundingRect(); + if (isFullCanvasCompositeMode(state().m_globalComposite)) { + fullCanvasCompositedStroke(path); + didDraw(clipBounds); + } else if (state().m_globalComposite == CompositeCopy) { + clearCanvas(); + c->strokePath(path); + didDraw(clipBounds); + } else { + FloatRect bounds = path.boundingRect(); inflateStrokeRect(bounds); FloatRect dirtyRect; - if (computeDirtyRect(bounds, &dirtyRect)) { - c->strokePath(m_path); + if (computeDirtyRect(bounds, clipBounds, &dirtyRect)) { + c->strokePath(path); didDraw(dirtyRect); } } } -void CanvasRenderingContext2D::clip(const String& windingRuleString) +void CanvasRenderingContext2D::stroke() +{ + strokeInternal(m_path); +} + +void CanvasRenderingContext2D::stroke(Path2D* domPath) +{ + strokeInternal(domPath->path()); +} + +void CanvasRenderingContext2D::clipInternal(const Path& path, const String& windingRuleString) { GraphicsContext* c = drawingContext(); - if (!c) + if (!c) { return; - if (!state().m_invertibleCTM) - return; - - WindRule newWindRule = RULE_NONZERO; - if (!parseWinding(windingRuleString, newWindRule)) + } + if (!state().m_invertibleCTM) { return; + } realizeSaves(); - c->canvasClip(m_path, newWindRule); + c->canvasClip(path, parseWinding(windingRuleString)); +} + +void CanvasRenderingContext2D::clip(const String& windingRuleString) +{ + clipInternal(m_path, windingRuleString); +} + +void CanvasRenderingContext2D::clip(Path2D* domPath, const String& windingRuleString) +{ + clipInternal(domPath->path(), windingRuleString); } bool CanvasRenderingContext2D::isPointInPath(const float x, const float y, const String& windingRuleString) { + return isPointInPathInternal(m_path, x, y, windingRuleString); +} + +bool CanvasRenderingContext2D::isPointInPath(Path2D* domPath, const float x, const float y, const String& windingRuleString) +{ + return isPointInPathInternal(domPath->path(), x, y, windingRuleString); +} + +bool CanvasRenderingContext2D::isPointInPathInternal(const Path& path, const float x, const float y, const String& windingRuleString) +{ GraphicsContext* c = drawingContext(); if (!c) return false; @@ -978,15 +1131,20 @@ bool CanvasRenderingContext2D::isPointInPath(const float x, const float y, const if (!std::isfinite(transformedPoint.x()) || !std::isfinite(transformedPoint.y())) return false; - WindRule windRule = RULE_NONZERO; - if (!parseWinding(windingRuleString, windRule)) - return false; + return path.contains(transformedPoint, parseWinding(windingRuleString)); +} - return m_path.contains(transformedPoint, windRule); +bool CanvasRenderingContext2D::isPointInStroke(const float x, const float y) +{ + return isPointInStrokeInternal(m_path, x, y); } +bool CanvasRenderingContext2D::isPointInStroke(Path2D* domPath, const float x, const float y) +{ + return isPointInStrokeInternal(domPath->path(), x, y); +} -bool CanvasRenderingContext2D::isPointInStroke(const float x, const float y) +bool CanvasRenderingContext2D::isPointInStrokeInternal(const Path& path, const float x, const float y) { GraphicsContext* c = drawingContext(); if (!c) @@ -1006,7 +1164,46 @@ bool CanvasRenderingContext2D::isPointInStroke(const float x, const float y) strokeData.setLineJoin(getLineJoin()); strokeData.setMiterLimit(miterLimit()); strokeData.setLineDash(getLineDash(), lineDashOffset()); - return m_path.strokeContains(transformedPoint, strokeData); + return path.strokeContains(transformedPoint, strokeData); +} + +void CanvasRenderingContext2D::scrollPathIntoView() +{ + scrollPathIntoViewInternal(m_path); +} + +void CanvasRenderingContext2D::scrollPathIntoView(Path2D* path2d) +{ + scrollPathIntoViewInternal(path2d->path()); +} + +void CanvasRenderingContext2D::scrollPathIntoViewInternal(const Path& path) +{ + if (!state().m_invertibleCTM || path.isEmpty()) + return; + + canvas()->document().updateLayoutIgnorePendingStylesheets(); + + // Apply transformation and get the bounding rect + Path transformedPath = path; + transformedPath.transform(state().m_transform); + FloatRect boundingRect = transformedPath.boundingRect(); + + // Offset by the canvas rect (We should take border and padding into account). + RenderBoxModelObject* rbmo = canvas()->renderBoxModelObject(); + IntRect canvasRect = canvas()->renderer()->absoluteBoundingBoxRect(); + canvasRect.move(rbmo->borderLeft() + rbmo->paddingLeft(), + rbmo->borderTop() + rbmo->paddingTop()); + LayoutRect pathRect = enclosingLayoutRect(boundingRect); + pathRect.moveBy(canvasRect.location()); + + if (canvas()->renderer()) { + canvas()->renderer()->scrollRectToVisible( + pathRect, ScrollAlignment::alignCenterAlways, ScrollAlignment::alignTopAlways); + } + + // TODO: should implement "inform the user" that the caret and/or + // selection the specified rectangle of the canvas. See http://crbug.com/357987 } void CanvasRenderingContext2D::clearRect(float x, float y, float width, float height) @@ -1035,7 +1232,7 @@ void CanvasRenderingContext2D::clearRect(float x, float y, float width, float he context->save(); saved = true; } - context->setAlpha(1); + context->setAlphaAsFloat(1); } if (state().m_globalComposite != CompositeSourceOver) { if (!saved) { @@ -1048,6 +1245,7 @@ void CanvasRenderingContext2D::clearRect(float x, float y, float width, float he if (saved) context->restore(); + validateStateStack(); didDraw(dirtyRect); } @@ -1062,7 +1260,7 @@ void CanvasRenderingContext2D::fillRect(float x, float y, float width, float hei if (!state().m_invertibleCTM) return; FloatRect clipBounds; - if (!drawingContext()->getTransformedClipBounds(&clipBounds)) + if (!c->getTransformedClipBounds(&clipBounds)) return; // from the HTML5 Canvas spec: @@ -1105,6 +1303,9 @@ void CanvasRenderingContext2D::strokeRect(float x, float y, float width, float h return; if (!state().m_invertibleCTM) return; + FloatRect clipBounds; + if (!c->getTransformedClipBounds(&clipBounds)) + return; // If gradient size is zero, then paint nothing. Gradient* gradient = c->strokeGradient(); @@ -1113,12 +1314,21 @@ void CanvasRenderingContext2D::strokeRect(float x, float y, float width, float h FloatRect rect(x, y, width, height); - FloatRect boundingRect = rect; - boundingRect.inflate(state().m_lineWidth / 2); - FloatRect dirtyRect; - if (computeDirtyRect(boundingRect, &dirtyRect)) { - c->strokeRect(rect, state().m_lineWidth); - didDraw(dirtyRect); + if (isFullCanvasCompositeMode(state().m_globalComposite)) { + fullCanvasCompositedStroke(rect); + didDraw(clipBounds); + } else if (state().m_globalComposite == CompositeCopy) { + clearCanvas(); + c->strokeRect(rect); + didDraw(clipBounds); + } else { + FloatRect boundingRect = rect; + boundingRect.inflate(state().m_lineWidth / 2); + FloatRect dirtyRect; + if (computeDirtyRect(boundingRect, clipBounds, &dirtyRect)) { + c->strokeRect(rect); + didDraw(dirtyRect); + } } } @@ -1190,7 +1400,7 @@ void CanvasRenderingContext2D::applyShadow() if (shouldDrawShadows()) { c->setShadow(state().m_shadowOffset, state().m_shadowBlur, state().m_shadowColor, - DrawLooper::ShadowIgnoresTransforms); + DrawLooperBuilder::ShadowIgnoresTransforms); } else { c->clearShadow(); } @@ -1201,37 +1411,12 @@ bool CanvasRenderingContext2D::shouldDrawShadows() const return alphaChannel(state().m_shadowColor) && (state().m_shadowBlur || !state().m_shadowOffset.isZero()); } -enum ImageSizeType { - ImageSizeAfterDevicePixelRatio, - ImageSizeBeforeDevicePixelRatio -}; - -static LayoutSize sizeFor(HTMLImageElement* image, ImageSizeType sizeType) -{ - LayoutSize size; - ImageResource* cachedImage = image->cachedImage(); - if (cachedImage) { - size = cachedImage->imageSizeForRenderer(image->renderer(), 1.0f); // FIXME: Not sure about this. - - if (sizeType == ImageSizeAfterDevicePixelRatio && image->renderer() && image->renderer()->isRenderImage() && cachedImage->image() && !cachedImage->image()->hasRelativeWidth()) - size.scale(toRenderImage(image->renderer())->imageDevicePixelRatio()); - } - return size; -} - -static IntSize sizeFor(HTMLVideoElement* video) -{ - if (MediaPlayer* player = video->player()) - return player->naturalSize(); - return IntSize(); -} - static inline FloatRect normalizeRect(const FloatRect& rect) { - return FloatRect(min(rect.x(), rect.maxX()), - min(rect.y(), rect.maxY()), - max(rect.width(), -rect.width()), - max(rect.height(), -rect.height())); + return FloatRect(std::min(rect.x(), rect.maxX()), + std::min(rect.y(), rect.maxY()), + std::max(rect.width(), -rect.width()), + std::max(rect.height(), -rect.height())); } static inline void clipRectsToImageRect(const FloatRect& imageRect, FloatRect* srcRect, FloatRect* dstRect) @@ -1253,363 +1438,110 @@ static inline void clipRectsToImageRect(const FloatRect& imageRect, FloatRect* s dstRect->move(offset); } -void CanvasRenderingContext2D::drawImageInternal(Image* image, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator& op, const blink::WebBlendMode& blendMode) -{ - if (!image) - return; - - GraphicsContext* c = drawingContext(); - if (!c) - return; - if (!state().m_invertibleCTM) - return; - FloatRect clipBounds; - if (!drawingContext()->getTransformedClipBounds(&clipBounds)) - return; - - if (rectContainsTransformedRect(dstRect, clipBounds)) { - c->drawImage(image, dstRect, srcRect, op, blendMode); - didDraw(clipBounds); - } else if (isFullCanvasCompositeMode(op)) { - fullCanvasCompositedDrawImage(image, dstRect, srcRect, op); - didDraw(clipBounds); - } else if (op == CompositeCopy) { - clearCanvas(); - c->drawImage(image, dstRect, srcRect, op, blendMode); - didDraw(clipBounds); - } else { - FloatRect dirtyRect; - if (computeDirtyRect(dstRect, &dirtyRect)) { - c->drawImage(image, dstRect, srcRect, op, blendMode); - didDraw(dirtyRect); - } - } -} - -void CanvasRenderingContext2D::drawImage(ImageBitmap* bitmap, float x, float y, ExceptionState& exceptionState) +void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, float x, float y, ExceptionState& exceptionState) { - if (!bitmap) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - drawImage(bitmap, x, y, bitmap->width(), bitmap->height(), exceptionState); + FloatSize destRectSize = imageSource->defaultDestinationSize(); + drawImage(imageSource, x, y, destRectSize.width(), destRectSize.height(), exceptionState); } -void CanvasRenderingContext2D::drawImage(ImageBitmap* bitmap, +void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, float x, float y, float width, float height, ExceptionState& exceptionState) { - if (!bitmap) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - if (!bitmap->bitmapRect().width() || !bitmap->bitmapRect().height()) - return; - - drawImage(bitmap, 0, 0, bitmap->width(), bitmap->height(), x, y, width, height, exceptionState); + FloatSize sourceRectSize = imageSource->sourceSize(); + drawImage(imageSource, 0, 0, sourceRectSize.width(), sourceRectSize.height(), x, y, width, height, exceptionState); } -void CanvasRenderingContext2D::drawImage(ImageBitmap* bitmap, +void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionState& exceptionState) { - if (!bitmap) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - - FloatRect srcRect(sx, sy, sw, sh); - FloatRect dstRect(dx, dy, dw, dh); - FloatRect bitmapRect = bitmap->bitmapRect(); - - 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; - - if (!dstRect.width() || !dstRect.height()) - return; - if (!srcRect.width() || !srcRect.height()) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); - return; - } - - ASSERT(bitmap->height() && bitmap->width()); - FloatRect normalizedSrcRect = normalizeRect(srcRect); - FloatRect normalizedDstRect = normalizeRect(dstRect); - - // Clip the rects to where the user thinks that the image is situated. - clipRectsToImageRect(IntRect(IntPoint(), bitmap->size()), &normalizedSrcRect, &normalizedDstRect); - - FloatRect intersectRect = intersection(bitmapRect, normalizedSrcRect); - FloatRect actualSrcRect(intersectRect); - - IntPoint bitmapOffset = bitmap->bitmapOffset(); - actualSrcRect.move(bitmapOffset - bitmapRect.location()); - FloatRect imageRect = FloatRect(bitmapOffset, bitmapRect.size()); - - FloatRect actualDstRect(FloatPoint(intersectRect.location() - normalizedSrcRect.location()), bitmapRect.size()); - actualDstRect.scale(normalizedDstRect.width() / normalizedSrcRect.width() * intersectRect.width() / bitmapRect.width(), - normalizedDstRect.height() / normalizedSrcRect.height() * intersectRect.height() / bitmapRect.height()); - actualDstRect.moveBy(normalizedDstRect.location()); - - if (!imageRect.intersects(actualSrcRect)) - return; - - RefPtr<Image> imageForRendering = bitmap->bitmapImage(); - if (!imageForRendering) - return; - - drawImageInternal(imageForRendering.get(), actualSrcRect, actualDstRect, state().m_globalComposite, state().m_globalBlend); -} - -void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, float x, float y, ExceptionState& exceptionState) -{ - if (!image) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - LayoutSize destRectSize = sizeFor(image, ImageSizeAfterDevicePixelRatio); - drawImage(image, x, y, destRectSize.width(), destRectSize.height(), exceptionState); -} - -void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, - float x, float y, float width, float height, ExceptionState& exceptionState) -{ - if (!image) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - LayoutSize sourceRectSize = sizeFor(image, ImageSizeBeforeDevicePixelRatio); - drawImage(image, FloatRect(0, 0, sourceRectSize.width(), sourceRectSize.height()), FloatRect(x, y, width, height), exceptionState); -} - -void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, - float sx, float sy, float sw, float sh, - float dx, float dy, float dw, float dh, ExceptionState& exceptionState) -{ - drawImage(image, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), exceptionState); -} - -void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionState& exceptionState) -{ - drawImage(image, srcRect, dstRect, state().m_globalComposite, state().m_globalBlend, exceptionState); -} - -void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator& op, const blink::WebBlendMode& blendMode, ExceptionState& exceptionState) -{ - if (!image) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - - 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; - - ImageResource* cachedImage = image->cachedImage(); - if (!cachedImage || !image->complete()) - return; - - LayoutSize size = sizeFor(image, ImageSizeBeforeDevicePixelRatio); - if (!size.width() || !size.height()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return; - } - - if (!dstRect.width() || !dstRect.height()) - return; - - FloatRect normalizedSrcRect = normalizeRect(srcRect); - FloatRect normalizedDstRect = normalizeRect(dstRect); - - FloatRect imageRect = FloatRect(FloatPoint(), size); - if (!srcRect.width() || !srcRect.height()) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); - return; - } - if (!imageRect.intersects(normalizedSrcRect)) - return; - - clipRectsToImageRect(imageRect, &normalizedSrcRect, &normalizedDstRect); - - checkOrigin(image); - - Image* imageForRendering = cachedImage->imageForRenderer(image->renderer()); - - // For images that depend on an unavailable container size, we need to fall back to the intrinsic - // object size. http://www.w3.org/TR/2dcontext2/#dom-context-2d-drawimage - // FIXME: Without a specified image size this should resolve against the canvas element's size, see: crbug.com/230163. - if (!image->renderer() && imageForRendering->usesContainerSize()) - imageForRendering->setContainerSize(imageForRendering->size()); - - drawImageInternal(imageForRendering, normalizedSrcRect, normalizedDstRect, op, blendMode); -} - -void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, float x, float y, ExceptionState& exceptionState) -{ - drawImage(sourceCanvas, 0, 0, sourceCanvas->width(), sourceCanvas->height(), x, y, sourceCanvas->width(), sourceCanvas->height(), exceptionState); -} - -void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, - float x, float y, float width, float height, ExceptionState& exceptionState) -{ - drawImage(sourceCanvas, FloatRect(0, 0, sourceCanvas->width(), sourceCanvas->height()), FloatRect(x, y, width, height), exceptionState); + GraphicsContext* c = drawingContext(); // Do not exit yet if !c because we may need to throw exceptions first + CompositeOperator op = c ? c->compositeOperation() : CompositeSourceOver; + blink::WebBlendMode blendMode = c ? c->blendModeOperation() : blink::WebBlendModeNormal; + drawImageInternal(imageSource, sx, sy, sw, sh, dx, dy, dw, dh, exceptionState, op, blendMode); } -void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, +void CanvasRenderingContext2D::drawImageInternal(CanvasImageSource* imageSource, float sx, float sy, float sw, float sh, - float dx, float dy, float dw, float dh, ExceptionState& exceptionState) -{ - drawImage(sourceCanvas, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), exceptionState); -} - -void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, const FloatRect& srcRect, - const FloatRect& dstRect, ExceptionState& exceptionState) -{ - if (!sourceCanvas) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - - FloatRect srcCanvasRect = FloatRect(FloatPoint(), sourceCanvas->size()); - - if (!srcCanvasRect.width() || !srcCanvasRect.height()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return; - } - - if (!srcRect.width() || !srcRect.height()) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); - return; + float dx, float dy, float dw, float dh, ExceptionState& exceptionState, + CompositeOperator op, blink::WebBlendMode blendMode) +{ + RefPtr<Image> image; + SourceImageStatus sourceImageStatus; + if (!imageSource->isVideoElement()) { + SourceImageMode mode = canvas() == imageSource ? CopySourceImageIfVolatile : DontCopySourceImage; // Thunking for == + image = imageSource->getSourceImageForCanvas(mode, &sourceImageStatus); + if (sourceImageStatus == UndecodableSourceImageStatus) + exceptionState.throwDOMException(InvalidStateError, "The HTMLImageElement provided is in the 'broken' state."); + if (!image || !image->width() || !image->height()) + return; } - FloatRect normalizedSrcRect = normalizeRect(srcRect); - FloatRect normalizedDstRect = normalizeRect(dstRect); - - if (!srcCanvasRect.intersects(normalizedSrcRect) || !normalizedDstRect.width() || !normalizedDstRect.height()) - return; - - clipRectsToImageRect(srcCanvasRect, &normalizedSrcRect, &normalizedDstRect); - GraphicsContext* c = drawingContext(); if (!c) return; + if (!state().m_invertibleCTM) return; - // FIXME: Do this through platform-independent GraphicsContext API. - ImageBuffer* buffer = sourceCanvas->buffer(); - if (!buffer) + if (!std::isfinite(dx) || !std::isfinite(dy) || !std::isfinite(dw) || !std::isfinite(dh) + || !std::isfinite(sx) || !std::isfinite(sy) || !std::isfinite(sw) || !std::isfinite(sh) + || !dw || !dh || !sw || !sh) return; FloatRect clipBounds; - if (!drawingContext()->getTransformedClipBounds(&clipBounds)) + if (!c->getTransformedClipBounds(&clipBounds)) return; - checkOrigin(sourceCanvas); + FloatRect srcRect = normalizeRect(FloatRect(sx, sy, sw, sh)); + FloatRect dstRect = normalizeRect(FloatRect(dx, dy, dw, dh)); - // 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(); - // FIXME: Implement an accelerated path for drawing from a WebGL canvas to a 2d canvas when possible. - if (sourceContext && sourceContext->is3d()) - sourceContext->paintRenderingResultsToCanvas(); + clipRectsToImageRect(FloatRect(FloatPoint(), imageSource->sourceSize()), &srcRect, &dstRect); - if (rectContainsTransformedRect(normalizedDstRect, clipBounds)) { - c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, state().m_globalComposite, state().m_globalBlend); - didDraw(clipBounds); - } else if (isFullCanvasCompositeMode(state().m_globalComposite)) { - fullCanvasCompositedDrawImage(buffer, normalizedDstRect, normalizedSrcRect, state().m_globalComposite); - didDraw(clipBounds); - } else if (state().m_globalComposite == CompositeCopy) { - clearCanvas(); - c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, state().m_globalComposite, state().m_globalBlend); - didDraw(clipBounds); + imageSource->adjustDrawRects(&srcRect, &dstRect); + + if (srcRect.isEmpty()) + return; + + FloatRect dirtyRect = clipBounds; + if (imageSource->isVideoElement()) { + drawVideo(static_cast<HTMLVideoElement*>(imageSource), srcRect, dstRect); + computeDirtyRect(dstRect, clipBounds, &dirtyRect); } else { - FloatRect dirtyRect; - if (computeDirtyRect(normalizedDstRect, clipBounds, &dirtyRect)) { - c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, state().m_globalComposite, state().m_globalBlend); - didDraw(dirtyRect); + if (rectContainsTransformedRect(dstRect, clipBounds)) { + c->drawImage(image.get(), dstRect, srcRect, op, blendMode); + } else if (isFullCanvasCompositeMode(op)) { + fullCanvasCompositedDrawImage(image.get(), dstRect, srcRect, op); + } else if (op == CompositeCopy) { + clearCanvas(); + c->drawImage(image.get(), dstRect, srcRect, op, blendMode); + } else { + FloatRect dirtyRect; + computeDirtyRect(dstRect, clipBounds, &dirtyRect); + c->drawImage(image.get(), dstRect, srcRect, op, blendMode); } - } - - // Flush canvas's ImageBuffer when drawImage from WebGL to HW accelerated 2d canvas - if (sourceContext && sourceContext->is3d() && is2d() && isAccelerated() && canvas()->buffer()) - canvas()->buffer()->flush(); -} -void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, float x, float y, ExceptionState& exceptionState) -{ - if (!video) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; + if (sourceImageStatus == ExternalSourceImageStatus && isAccelerated() && canvas()->buffer()) + canvas()->buffer()->flush(); } - IntSize size = sizeFor(video); - drawImage(video, x, y, size.width(), size.height(), exceptionState); -} -void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, - float x, float y, float width, float height, ExceptionState& exceptionState) -{ - if (!video) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - IntSize size = sizeFor(video); - drawImage(video, FloatRect(0, 0, size.width(), size.height()), FloatRect(x, y, width, height), exceptionState); -} + if (canvas()->originClean() && wouldTaintOrigin(imageSource)) + canvas()->setOriginTainted(); -void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, - float sx, float sy, float sw, float sh, - float dx, float dy, float dw, float dh, ExceptionState& exceptionState) -{ - drawImage(video, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), exceptionState); + didDraw(dirtyRect); } -void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionState& exceptionState) +void CanvasRenderingContext2D::drawVideo(HTMLVideoElement* video, FloatRect srcRect, FloatRect dstRect) { - if (!video) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - - if (video->readyState() == HTMLMediaElement::HAVE_NOTHING || video->readyState() == HTMLMediaElement::HAVE_METADATA) - return; - - FloatRect videoRect = FloatRect(FloatPoint(), sizeFor(video)); - if (!srcRect.width() || !srcRect.height()) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); - return; - } - - FloatRect normalizedSrcRect = normalizeRect(srcRect); - FloatRect normalizedDstRect = normalizeRect(dstRect); - - if (!videoRect.intersects(normalizedSrcRect) || !normalizedDstRect.width() || !normalizedDstRect.height()) - return; - - clipRectsToImageRect(videoRect, &normalizedSrcRect, &normalizedDstRect); - GraphicsContext* c = drawingContext(); - if (!c) - return; - if (!state().m_invertibleCTM) - return; - - checkOrigin(video); - - FloatRect dirtyRect; - if (!computeDirtyRect(normalizedDstRect, &dirtyRect)) - return; - GraphicsContextStateSaver stateSaver(*c); - c->clip(normalizedDstRect); - c->translate(normalizedDstRect.x(), normalizedDstRect.y()); - c->scale(FloatSize(normalizedDstRect.width() / normalizedSrcRect.width(), normalizedDstRect.height() / normalizedSrcRect.height())); - c->translate(-normalizedSrcRect.x(), -normalizedSrcRect.y()); - video->paintCurrentFrameInContext(c, IntRect(IntPoint(), sizeFor(video))); + c->clip(dstRect); + c->translate(dstRect.x(), dstRect.y()); + c->scale(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height()); + c->translate(-srcRect.x(), -srcRect.y()); + video->paintCurrentFrameInContext(c, IntRect(IntPoint(), IntSize(video->videoWidth(), video->videoHeight()))); stateSaver.restore(); - - didDraw(dirtyRect); + validateStateStack(); } void CanvasRenderingContext2D::drawImageFromRect(HTMLImageElement* image, @@ -1617,12 +1549,14 @@ void CanvasRenderingContext2D::drawImageFromRect(HTMLImageElement* image, float dx, float dy, float dw, float dh, const String& compositeOperation) { + if (!image) + return; CompositeOperator op; blink::WebBlendMode blendOp = blink::WebBlendModeNormal; if (!parseCompositeAndBlendOperator(compositeOperation, op, blendOp) || blendOp != blink::WebBlendModeNormal) op = CompositeSourceOver; - drawImage(image, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), op, blink::WebBlendModeNormal, IGNORE_EXCEPTION); + drawImageInternal(image, sx, sy, sw, sh, dx, dy, dw, dh, IGNORE_EXCEPTION, op, blendOp); } void CanvasRenderingContext2D::setAlpha(float alpha) @@ -1660,18 +1594,14 @@ static void drawImageToContext(Image* image, GraphicsContext* context, const Flo context->drawImage(image, dest, src, op); } -static void drawImageToContext(ImageBuffer* imageBuffer, GraphicsContext* context, const FloatRect& dest, const FloatRect& src, CompositeOperator op) -{ - context->drawImageBuffer(imageBuffer, dest, src, op); -} - template<class T> void CanvasRenderingContext2D::fullCanvasCompositedDrawImage(T* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op) { ASSERT(isFullCanvasCompositeMode(op)); - drawingContext()->beginLayer(1, op); - drawImageToContext(image, drawingContext(), dest, src, CompositeSourceOver); - drawingContext()->endLayer(); + GraphicsContext* c = drawingContext(); + c->beginLayer(1, op); + drawImageToContext(image, c, dest, src, CompositeSourceOver); + c->endLayer(); } static void fillPrimitive(const FloatRect& rect, GraphicsContext* context) @@ -1698,78 +1628,82 @@ template<class T> void CanvasRenderingContext2D::fullCanvasCompositedFill(const c->endLayer(); } -PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createLinearGradient(float x0, float y0, float x1, float y1, ExceptionState& exceptionState) +static void strokePrimitive(const FloatRect& rect, GraphicsContext* context) { - if (!std::isfinite(x0) || !std::isfinite(y0) || !std::isfinite(x1) || !std::isfinite(y1)) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); - return 0; - } + context->strokeRect(rect); +} + +static void strokePrimitive(const Path& path, GraphicsContext* context) +{ + context->strokePath(path); +} +template<class T> void CanvasRenderingContext2D::fullCanvasCompositedStroke(const T& area) +{ + ASSERT(isFullCanvasCompositeMode(state().m_globalComposite)); + + GraphicsContext* c = drawingContext(); + ASSERT(c); + c->beginLayer(1, state().m_globalComposite); + CompositeOperator previousOperator = c->compositeOperation(); + c->setCompositeOperation(CompositeSourceOver); + strokePrimitive(area, c); + c->setCompositeOperation(previousOperator); + c->endLayer(); +} + +PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createLinearGradient(float x0, float y0, float x1, float y1) +{ RefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), FloatPoint(x1, y1)); return gradient.release(); } PassRefPtr<CanvasGradient> CanvasRenderingContext2D::createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1, ExceptionState& exceptionState) { - if (!std::isfinite(x0) || !std::isfinite(y0) || !std::isfinite(r0) || !std::isfinite(x1) || !std::isfinite(y1) || !std::isfinite(r1)) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); - return 0; - } - if (r0 < 0 || r1 < 0) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); - return 0; + exceptionState.throwDOMException(IndexSizeError, String::format("The %s provided is less than 0.", r0 < 0 ? "r0" : "r1")); + return nullptr; } RefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), r0, FloatPoint(x1, y1), r1); return gradient.release(); } -PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLImageElement* image, +PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(CanvasImageSource* imageSource, const String& repetitionType, ExceptionState& exceptionState) { - if (!image) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return 0; - } bool repeatX, repeatY; CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, exceptionState); if (exceptionState.hadException()) - return 0; - - if (!image->complete()) - return 0; - - ImageResource* cachedImage = image->cachedImage(); - Image* imageForRendering = cachedImage ? cachedImage->imageForRenderer(image->renderer()) : 0; - if (!imageForRendering) - return CanvasPattern::create(Image::nullImage(), repeatX, repeatY, true); + return nullptr; - // We need to synthesize a container size if a renderer is not available to provide one. - if (!image->renderer() && imageForRendering->usesContainerSize()) - imageForRendering->setContainerSize(imageForRendering->size()); + SourceImageStatus status; + RefPtr<Image> imageForRendering = imageSource->getSourceImageForCanvas(CopySourceImageIfVolatile, &status); - bool originClean = cachedImage->isAccessAllowed(canvas()->securityOrigin()); - return CanvasPattern::create(imageForRendering, repeatX, repeatY, originClean); -} - -PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLCanvasElement* canvas, - const String& repetitionType, ExceptionState& exceptionState) -{ - if (!canvas) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return 0; - } - if (!canvas->width() || !canvas->height()) { - exceptionState.throwUninformativeAndGenericDOMException(InvalidStateError); - return 0; + switch (status) { + case NormalSourceImageStatus: + break; + case ZeroSizeCanvasSourceImageStatus: + exceptionState.throwDOMException(InvalidStateError, String::format("The canvas %s is 0.", imageSource->sourceSize().width() ? "height" : "width")); + return nullptr; + case UndecodableSourceImageStatus: + exceptionState.throwDOMException(InvalidStateError, "Source image is in the 'broken' state."); + return nullptr; + case InvalidSourceImageStatus: + imageForRendering = Image::nullImage(); + break; + case IncompleteSourceImageStatus: + return nullptr; + default: + case ExternalSourceImageStatus: // should not happen when mode is CopySourceImageIfVolatile + ASSERT_NOT_REACHED(); + return nullptr; } + ASSERT(imageForRendering); - bool repeatX, repeatY; - CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, exceptionState); - if (exceptionState.hadException()) - return 0; - return CanvasPattern::create(canvas->copiedImage(), repeatX, repeatY, canvas->originClean()); + bool originClean = !wouldTaintOrigin(imageSource); + + return CanvasPattern::create(imageForRendering.release(), repeatX, repeatY, originClean); } bool CanvasRenderingContext2D::computeDirtyRect(const FloatRect& localRect, FloatRect* dirtyRect) @@ -1822,46 +1756,36 @@ void CanvasRenderingContext2D::didDraw(const FloatRect& dirtyRect) GraphicsContext* CanvasRenderingContext2D::drawingContext() const { + if (isContextLost()) + return 0; return canvas()->drawingContext(); } -static PassRefPtr<ImageData> createEmptyImageData(const IntSize& size) +static PassRefPtrWillBeRawPtr<ImageData> createEmptyImageData(const IntSize& size) { - Checked<int, RecordOverflow> dataSize = 4; - dataSize *= size.width(); - dataSize *= size.height(); - if (dataSize.hasOverflowed()) - return 0; + if (RefPtrWillBeRawPtr<ImageData> data = ImageData::create(size)) { + data->data()->zeroFill(); + return data.release(); + } - RefPtr<ImageData> data = ImageData::create(size); - data->data()->zeroFill(); - return data.release(); + return nullptr; } -PassRefPtr<ImageData> CanvasRenderingContext2D::createImageData(PassRefPtr<ImageData> imageData, ExceptionState& exceptionState) const +PassRefPtrWillBeRawPtr<ImageData> CanvasRenderingContext2D::createImageData(PassRefPtrWillBeRawPtr<ImageData> imageData) const { - if (!imageData) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); - return 0; - } - return createEmptyImageData(imageData->size()); } -PassRefPtr<ImageData> CanvasRenderingContext2D::createImageData(float sw, float sh, ExceptionState& exceptionState) const +PassRefPtrWillBeRawPtr<ImageData> CanvasRenderingContext2D::createImageData(float sw, float sh, ExceptionState& exceptionState) const { if (!sw || !sh) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); - return 0; - } - if (!std::isfinite(sw) || !std::isfinite(sh)) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); - return 0; + exceptionState.throwDOMException(IndexSizeError, String::format("The source %s is 0.", sw ? "height" : "width")); + return nullptr; } FloatSize logicalSize(fabs(sw), fabs(sh)); if (!logicalSize.isExpressibleAsIntSize()) - return 0; + return nullptr; IntSize size = expandedIntSize(logicalSize); if (size.width() < 1) @@ -1872,26 +1796,15 @@ PassRefPtr<ImageData> CanvasRenderingContext2D::createImageData(float sw, float return createEmptyImageData(size); } -PassRefPtr<ImageData> CanvasRenderingContext2D::webkitGetImageDataHD(float sx, float sy, float sw, float sh, ExceptionState& exceptionState) const +PassRefPtrWillBeRawPtr<ImageData> CanvasRenderingContext2D::getImageData(float sx, float sy, float sw, float sh, ExceptionState& exceptionState) const { - return getImageData(sx, sy, sw, sh, exceptionState); -} - -PassRefPtr<ImageData> CanvasRenderingContext2D::getImageData(float sx, float sy, float sw, float sh, ExceptionState& exceptionState) const -{ - if (!canvas()->originClean()) { + if (!canvas()->originClean()) exceptionState.throwSecurityError("The canvas has been tainted by cross-origin data."); - return 0; - } + else if (!sw || !sh) + exceptionState.throwDOMException(IndexSizeError, String::format("The source %s is 0.", sw ? "height" : "width")); - if (!sw || !sh) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); - return 0; - } - if (!std::isfinite(sx) || !std::isfinite(sy) || !std::isfinite(sw) || !std::isfinite(sh)) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); - return 0; - } + if (exceptionState.hadException()) + return nullptr; if (sw < 0) { sx += sw; @@ -1908,41 +1821,27 @@ PassRefPtr<ImageData> CanvasRenderingContext2D::getImageData(float sx, float sy, if (logicalRect.height() < 1) logicalRect.setHeight(1); if (!logicalRect.isExpressibleAsIntRect()) - return 0; + return nullptr; IntRect imageDataRect = enclosingIntRect(logicalRect); ImageBuffer* buffer = canvas()->buffer(); - if (!buffer) + if (!buffer || isContextLost()) return createEmptyImageData(imageDataRect.size()); RefPtr<Uint8ClampedArray> byteArray = buffer->getUnmultipliedImageData(imageDataRect); if (!byteArray) - return 0; + return nullptr; return ImageData::create(imageDataRect.size(), byteArray.release()); } -void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy, ExceptionState& exceptionState) +void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy) { - if (!data) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - putImageData(data, dx, dy, 0, 0, data->width(), data->height(), exceptionState); + putImageData(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, ExceptionState& exceptionState) +void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight) { - if (!data) { - exceptionState.throwUninformativeAndGenericDOMException(TypeMismatchError); - return; - } - if (!std::isfinite(dx) || !std::isfinite(dy) || !std::isfinite(dirtyX) || !std::isfinite(dirtyY) || !std::isfinite(dirtyWidth) || !std::isfinite(dirtyHeight)) { - exceptionState.throwUninformativeAndGenericDOMException(NotSupportedError); - return; - } - ImageBuffer* buffer = canvas()->buffer(); if (!buffer) return; @@ -1981,11 +1880,11 @@ String CanvasRenderingContext2D::font() const StringBuilder serializedFont; const FontDescription& fontDescription = state().m_font.fontDescription(); - if (fontDescription.italic()) + if (fontDescription.style() == FontStyleItalic) serializedFont.appendLiteral("italic "); if (fontDescription.weight() == FontWeightBold) serializedFont.appendLiteral("bold "); - if (fontDescription.smallCaps() == FontSmallCapsOn) + if (fontDescription.variant() == FontVariantSmallCaps) serializedFont.appendLiteral("small-caps "); serializedFont.appendNumber(fontDescription.computedPixelSize()); @@ -2012,13 +1911,17 @@ String CanvasRenderingContext2D::font() const void CanvasRenderingContext2D::setFont(const String& newFont) { + // The style resolution required for rendering text is not available in frame-less documents. + if (!canvas()->document().frame()) + return; + MutableStylePropertyMap::iterator i = m_fetchedFonts.find(newFont); - RefPtr<MutableStylePropertySet> parsedStyle = i != m_fetchedFonts.end() ? i->value : 0; + RefPtrWillBeRawPtr<MutableStylePropertySet> parsedStyle = i != m_fetchedFonts.end() ? i->value : nullptr; if (!parsedStyle) { parsedStyle = MutableStylePropertySet::create(); CSSParserMode mode = m_usesCSSCompatibilityParseMode ? HTMLQuirksMode : HTMLStandardMode; - CSSParser::parseValue(parsedStyle.get(), CSSPropertyFont, newFont, true, mode, 0); + BisonCSSParser::parseValue(parsedStyle.get(), CSSPropertyFont, newFont, true, mode, 0); m_fetchedFonts.add(newFont, parsedStyle); } if (parsedStyle->isEmpty()) @@ -2039,9 +1942,12 @@ void CanvasRenderingContext2D::setFont(const String& newFont) // 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()) - newStyle->setFontDescription(computedStyle->fontDescription()); - else { + if (RenderStyle* computedStyle = canvas()->computedStyle()) { + FontDescription elementFontDescription(computedStyle->fontDescription()); + // Reset the computed size to avoid inheriting the zoom factor from the <canvas> element. + elementFontDescription.setComputedSize(elementFontDescription.specifiedSize()); + newStyle->setFontDescription(elementFontDescription); + } else { FontFamily fontFamily; fontFamily.setFamily(defaultFontFamily); @@ -2068,8 +1974,10 @@ void CanvasRenderingContext2D::setFont(const String& newFont) StyleResolver& styleResolver = canvas()->document().ensureStyleResolver(); styleResolver.applyPropertiesToStyle(properties, WTF_ARRAY_LENGTH(properties), newStyle.get()); +#if !ENABLE(OILPAN) if (state().m_realizedFont) - state().m_font.fontSelector()->unregisterForInvalidationCallbacks(&modifiableState()); + static_cast<CSSFontSelector*>(state().m_font.fontSelector())->unregisterForInvalidationCallbacks(&modifiableState()); +#endif modifiableState().m_font = newStyle->font(); modifiableState().m_font.update(canvas()->document().styleEngine()->fontSelector()); modifiableState().m_realizedFont = true; @@ -2128,31 +2036,84 @@ void CanvasRenderingContext2D::strokeText(const String& text, float x, float y, drawTextInternal(text, x, y, false, maxWidth, true); } -PassRefPtr<TextMetrics> CanvasRenderingContext2D::measureText(const String& text) +static inline bool isSpaceCharacter(UChar c) { - FontCachePurgePreventer fontCachePurgePreventer; - RefPtr<TextMetrics> metrics = TextMetrics::create(); - canvas()->document().updateStyleIfNeeded(); - metrics->setWidth(accessFont().width(TextRun(text))); - return metrics.release(); + // According to specification all space characters should be replaced with 0x0020 space character. + // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#text-preparation-algorithm + // The space characters according to specification are : U+0020, U+0009, U+000A, U+000C, and U+000D. + // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#space-character + // This function returns true for 0x000B also, so that this is backward compatible. + // Otherwise, the test LayoutTests/canvas/philip/tests/2d.text.draw.space.collapse.space.html will fail + return c == 0x0009 || c == 0x000A || c == 0x000B || c == 0x000C || c == 0x000D; } -static void replaceCharacterInString(String& text, WTF::CharacterMatchFunctionPtr matchFunction, const String& replacement) +static String normalizeSpaces(const String& text) { - const size_t replacementLength = replacement.length(); - size_t index = 0; - while ((index = text.find(matchFunction, index)) != kNotFound) { - text.replace(index, 1, replacement); - index += replacementLength; + unsigned textLength = text.length(); + Vector<UChar> charVector(textLength); + + for (unsigned i = 0; i < textLength; i++) { + if (isSpaceCharacter(text[i])) + charVector[i] = ' '; + else + charVector[i] = text[i]; } + + return String(charVector); +} + +PassRefPtr<TextMetrics> CanvasRenderingContext2D::measureText(const String& text) +{ + RefPtr<TextMetrics> metrics = TextMetrics::create(); + + // The style resolution required for rendering text is not available in frame-less documents. + if (!canvas()->document().frame()) + return metrics.release(); + + FontCachePurgePreventer fontCachePurgePreventer; + canvas()->document().updateRenderTreeIfNeeded(); + const Font& font = accessFont(); + String normalizedText = normalizeSpaces(text); + const TextRun textRun(normalizedText); + FloatRect textBounds = font.selectionRectForText(textRun, FloatPoint(), font.fontDescription().computedSize(), 0, -1, true); + + // x direction + metrics->setWidth(font.width(textRun)); + metrics->setActualBoundingBoxLeft(-textBounds.x()); + metrics->setActualBoundingBoxRight(textBounds.maxX()); + + // y direction + const FontMetrics& fontMetrics = font.fontMetrics(); + const float ascent = fontMetrics.floatAscent(); + const float descent = fontMetrics.floatDescent(); + const float baselineY = getFontBaseline(fontMetrics); + + metrics->setFontBoundingBoxAscent(ascent - baselineY); + metrics->setFontBoundingBoxDescent(descent + baselineY); + metrics->setActualBoundingBoxAscent(-textBounds.y() - baselineY); + metrics->setActualBoundingBoxDescent(textBounds.maxY() + baselineY); + + // Note : top/bottom and ascend/descend are currently the same, so there's no difference + // between the EM box's top and bottom and the font's ascend and descend + metrics->setEmHeightAscent(0); + metrics->setEmHeightDescent(0); + + metrics->setHangingBaseline(-0.8f * ascent + baselineY); + metrics->setAlphabeticBaseline(baselineY); + metrics->setIdeographicBaseline(descent + baselineY); + return metrics.release(); } void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, float y, bool fill, float maxWidth, bool useMaxWidth) { + // The style resolution required for rendering text is not available in frame-less documents. + if (!canvas()->document().frame()) + return; + // accessFont needs the style to be up to date, but updating style can cause script to run, // (e.g. due to autofocus) which can free the GraphicsContext, so update style before grabbing // the GraphicsContext. - canvas()->document().updateStyleIfNeeded(); + canvas()->document().updateRenderTreeIfNeeded(); GraphicsContext* c = drawingContext(); if (!c) @@ -2177,9 +2138,7 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo const Font& font = accessFont(); const FontMetrics& fontMetrics = font.fontMetrics(); - // According to spec, all the space characters must be replaced with U+0020 SPACE characters. - String normalizedText = text; - replaceCharacterInString(normalizedText, isSpaceOrNewline, " "); + String normalizedText = normalizeSpaces(text); // FIXME: Need to turn off font smoothing. @@ -2190,24 +2149,7 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo TextRun textRun(normalizedText, 0, 0, TextRun::AllowTrailingExpansion, direction, override, true, TextRun::NoRounding); // Draw the item text at the correct point. - FloatPoint location(x, y); - switch (state().m_textBaseline) { - case TopTextBaseline: - case HangingTextBaseline: - location.setY(y + fontMetrics.ascent()); - break; - case BottomTextBaseline: - case IdeographicTextBaseline: - location.setY(y - fontMetrics.descent()); - break; - case MiddleTextBaseline: - location.setY(y - fontMetrics.descent() + fontMetrics.height() / 2); - break; - case AlphabeticTextBaseline: - default: - // Do nothing. - break; - } + FloatPoint location(x, y + getFontBaseline(fontMetrics)); float fontWidth = font.width(TextRun(normalizedText, 0, 0, TextRun::AllowTrailingExpansion, direction, override)); @@ -2240,21 +2182,40 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo if (!fill) inflateStrokeRect(textRunPaintInfo.bounds); - FloatRect dirtyRect; - if (!computeDirtyRect(textRunPaintInfo.bounds, &dirtyRect)) - return; - 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, textRunPaintInfo, FloatPoint(0, 0), Font::UseFallbackIfFontNotReady); - } else - c->drawBidiText(font, textRunPaintInfo, location, Font::UseFallbackIfFontNotReady); + c->scale((fontWidth > 0 ? (width / fontWidth) : 0), 1); + location = FloatPoint(); + } - didDraw(dirtyRect); + FloatRect clipBounds; + if (!c->getTransformedClipBounds(&clipBounds)) { + return; + } + + if (isFullCanvasCompositeMode(state().m_globalComposite)) { + c->beginLayer(1, state().m_globalComposite); + CompositeOperator previousOperator = c->compositeOperation(); + c->setCompositeOperation(CompositeSourceOver); + c->drawBidiText(font, textRunPaintInfo, location, Font::UseFallbackIfFontNotReady); + c->setCompositeOperation(previousOperator); + c->endLayer(); + didDraw(clipBounds); + } else if (state().m_globalComposite == CompositeCopy) { + clearCanvas(); + c->drawBidiText(font, textRunPaintInfo, location, Font::UseFallbackIfFontNotReady); + didDraw(clipBounds); + } else { + FloatRect dirtyRect; + if (computeDirtyRect(textRunPaintInfo.bounds, clipBounds, &dirtyRect)) { + c->drawBidiText(font, textRunPaintInfo, location, Font::UseFallbackIfFontNotReady); + didDraw(dirtyRect); + } + } } void CanvasRenderingContext2D::inflateStrokeRect(FloatRect& rect) const @@ -2281,6 +2242,28 @@ const Font& CanvasRenderingContext2D::accessFont() return state().m_font; } +int CanvasRenderingContext2D::getFontBaseline(const FontMetrics& fontMetrics) const +{ + switch (state().m_textBaseline) { + case TopTextBaseline: + return fontMetrics.ascent(); + case HangingTextBaseline: + // According to http://wiki.apache.org/xmlgraphics-fop/LineLayout/AlignmentHandling + // "FOP (Formatting Objects Processor) puts the hanging baseline at 80% of the ascender height" + return (fontMetrics.ascent() * 4) / 5; + case BottomTextBaseline: + case IdeographicTextBaseline: + return -fontMetrics.descent(); + case MiddleTextBaseline: + return -fontMetrics.descent() + fontMetrics.height() / 2; + case AlphabeticTextBaseline: + default: + // Do nothing. + break; + } + return 0; +} + blink::WebLayer* CanvasRenderingContext2D::platformLayer() const { return canvas()->buffer() ? canvas()->buffer()->platformLayer() : 0; @@ -2300,7 +2283,7 @@ void CanvasRenderingContext2D::setImageSmoothingEnabled(bool enabled) modifiableState().m_imageSmoothingEnabled = enabled; GraphicsContext* c = drawingContext(); if (c) - c->setImageInterpolationQuality(enabled ? DefaultInterpolationQuality : InterpolationNone); + c->setImageInterpolationQuality(enabled ? CanvasDefaultInterpolationQuality : InterpolationNone); } PassRefPtr<Canvas2DContextAttributes> CanvasRenderingContext2D::getContextAttributes() const @@ -2310,33 +2293,31 @@ PassRefPtr<Canvas2DContextAttributes> CanvasRenderingContext2D::getContextAttrib return attributes.release(); } -void CanvasRenderingContext2D::drawSystemFocusRing(Element* element) +void CanvasRenderingContext2D::drawFocusIfNeeded(Element* element) +{ + drawFocusIfNeededInternal(m_path, element); +} + +void CanvasRenderingContext2D::drawFocusIfNeeded(Path2D* path2d, Element* element) { - if (!focusRingCallIsValid(m_path, element)) + drawFocusIfNeededInternal(path2d->path(), element); +} + +void CanvasRenderingContext2D::drawFocusIfNeededInternal(const Path& path, Element* element) +{ + if (!focusRingCallIsValid(path, element)) return; - updateFocusRingAccessibility(m_path, element); // Note: we need to check document->focusedElement() rather than just calling // element->focused(), because element->focused() isn't updated until after // focus events fire. if (element->document().focusedElement() == element) - drawFocusRing(m_path); -} - -bool CanvasRenderingContext2D::drawCustomFocusRing(Element* element) -{ - if (!focusRingCallIsValid(m_path, element)) - return false; - - updateFocusRingAccessibility(m_path, element); - - // Return true if the application should draw the focus ring. The spec allows us to - // override this for accessibility, but currently Blink doesn't take advantage of this. - return element->focused(); + drawFocusRing(path); } bool CanvasRenderingContext2D::focusRingCallIsValid(const Path& path, Element* element) { + ASSERT(element); if (!state().m_invertibleCTM) return false; if (path.isEmpty()) @@ -2347,62 +2328,32 @@ bool CanvasRenderingContext2D::focusRingCallIsValid(const Path& path, Element* e return true; } -void CanvasRenderingContext2D::updateFocusRingAccessibility(const Path& path, Element* element) -{ - if (!canvas()->renderer()) - return; - - // If accessibility is already enabled in this frame, associate this path's - // bounding box with the accessible object. Do this even if the element - // isn't focused because assistive technology might try to explore the object's - // location before it gets focus. - if (AXObjectCache* axObjectCache = element->document().existingAXObjectCache()) { - if (AXObject* obj = axObjectCache->getOrCreate(element)) { - // Get the bounding rect and apply transformations. - FloatRect bounds = m_path.boundingRect(); - AffineTransform ctm = state().m_transform; - FloatRect transformedBounds = ctm.mapRect(bounds); - LayoutRect elementRect = LayoutRect(transformedBounds); - - // Offset by the canvas rect and set the bounds of the accessible element. - IntRect canvasRect = canvas()->renderer()->absoluteBoundingBoxRect(); - elementRect.moveBy(canvasRect.location()); - obj->setElementRect(elementRect); - - // Set the bounds of any ancestor accessible elements, up to the canvas element, - // otherwise this element will appear to not be within its parent element. - obj = obj->parentObject(); - while (obj && obj->node() != canvas()) { - obj->setElementRect(elementRect); - obj = obj->parentObject(); - } - } - } -} - void CanvasRenderingContext2D::drawFocusRing(const Path& path) { GraphicsContext* c = drawingContext(); if (!c) return; + // These should match the style defined in html.css. + Color focusRingColor = RenderTheme::theme().focusRingColor(); + const int focusRingWidth = 5; + const int focusRingOutline = 0; + + // We need to add focusRingWidth to dirtyRect. + StrokeData strokeData; + strokeData.setThickness(focusRingWidth); + FloatRect dirtyRect; - if (!computeDirtyRect(path.boundingRect(), &dirtyRect)) + if (!computeDirtyRect(path.strokeBoundingRect(strokeData), &dirtyRect)) return; c->save(); - c->setAlpha(1.0); + c->setAlphaAsFloat(1.0); c->clearShadow(); c->setCompositeOperation(CompositeSourceOver, blink::WebBlendModeNormal); - - // These should match the style defined in html.css. - Color focusRingColor = RenderTheme::focusRingColor(); - const int focusRingWidth = 5; - const int focusRingOutline = 0; c->drawFocusRing(path, focusRingWidth, focusRingOutline, focusRingColor); - c->restore(); - + validateStateStack(); didDraw(dirtyRect); } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.h b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.h index 8493b10b149..65d883d220c 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.h @@ -26,10 +26,12 @@ #ifndef CanvasRenderingContext2D_h #define CanvasRenderingContext2D_h +#include "bindings/v8/ScriptWrappable.h" +#include "core/css/CSSFontSelectorClient.h" #include "core/html/canvas/Canvas2DContextAttributes.h" #include "core/html/canvas/CanvasPathMethods.h" #include "core/html/canvas/CanvasRenderingContext.h" -#include "core/svg/SVGMatrix.h" +#include "core/svg/SVGMatrixTearOff.h" #include "platform/fonts/Font.h" #include "platform/graphics/Color.h" #include "platform/geometry/FloatSize.h" @@ -45,10 +47,11 @@ namespace blink { class WebLayer; } namespace WebCore { +class CanvasImageSource; class CanvasGradient; class CanvasPattern; class CanvasStyle; -class DOMPath; +class Path2D; class Element; class ExceptionState; class FloatRect; @@ -60,13 +63,13 @@ class ImageBitmap; class ImageData; class TextMetrics; -typedef HashMap<String, RefPtr<MutableStylePropertySet> > MutableStylePropertyMap; +typedef WillBeHeapHashMap<String, RefPtrWillBeMember<MutableStylePropertySet> > MutableStylePropertyMap; -class CanvasRenderingContext2D : public CanvasRenderingContext, public CanvasPathMethods { +class CanvasRenderingContext2D FINAL: public CanvasRenderingContext, public ScriptWrappable, public CanvasPathMethods { public: - static PassOwnPtr<CanvasRenderingContext2D> create(HTMLCanvasElement* canvas, const Canvas2DContextAttributes* attrs, bool usesCSSCompatibilityParseMode) + static PassOwnPtrWillBeRawPtr<CanvasRenderingContext2D> create(HTMLCanvasElement* canvas, const Canvas2DContextAttributes* attrs, bool usesCSSCompatibilityParseMode) { - return adoptPtr(new CanvasRenderingContext2D(canvas, attrs, usesCSSCompatibilityParseMode)); + return adoptPtrWillBeNoop(new CanvasRenderingContext2D(canvas, attrs, usesCSSCompatibilityParseMode)); } virtual ~CanvasRenderingContext2D(); @@ -90,12 +93,9 @@ public: const Vector<float>& getLineDash() const; void setLineDash(const Vector<float>&); - void setWebkitLineDash(const Vector<float>&); float lineDashOffset() const; void setLineDashOffset(float); - float webkitLineDashOffset() const; - void setWebkitLineDashOffset(float); float shadowOffsetX() const; void setShadowOffsetX(float); @@ -112,17 +112,19 @@ public: float globalAlpha() const; void setGlobalAlpha(float); + bool isContextLost() const; + String globalCompositeOperation() const; void setGlobalCompositeOperation(const String&); - void save() { ++m_unrealizedSaveCount; } + void save() { ++m_stateStack.last()->m_unrealizedSaveCount; } void restore(); - SVGMatrix currentTransform() const + PassRefPtr<SVGMatrixTearOff> currentTransform() const { - return SVGMatrix(state().m_transform); + return SVGMatrixTearOff::create(state().m_transform); } - void setCurrentTransform(const SVGMatrix&); + void setCurrentTransform(PassRefPtr<SVGMatrixTearOff>); void scale(float sx, float sy); void rotate(float angleInRadians); @@ -147,14 +149,20 @@ public: void beginPath(); - PassRefPtr<DOMPath> currentPath(); - void setCurrentPath(DOMPath*); void fill(const String& winding = "nonzero"); + void fill(Path2D*, const String& winding = "nonzero"); void stroke(); + void stroke(Path2D*); void clip(const String& winding = "nonzero"); + void clip(Path2D*, const String& winding = "nonzero"); bool isPointInPath(const float x, const float y, const String& winding = "nonzero"); + bool isPointInPath(Path2D*, const float x, const float y, const String& winding = "nonzero"); bool isPointInStroke(const float x, const float y); + bool isPointInStroke(Path2D*, const float x, const float y); + + void scrollPathIntoView(); + void scrollPathIntoView(Path2D*); void clearRect(float x, float y, float width, float height); void fillRect(float x, float y, float width, float height); @@ -170,22 +178,9 @@ public: void clearShadow(); - void drawImage(ImageBitmap*, float x, float y, ExceptionState&); - void drawImage(ImageBitmap*, float x, float y, float width, float height, ExceptionState&); - void drawImage(ImageBitmap*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionState&); - void drawImage(HTMLImageElement*, float x, float y, ExceptionState&); - void drawImage(HTMLImageElement*, float x, float y, float width, float height, ExceptionState&); - void drawImage(HTMLImageElement*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionState&); - void drawImage(HTMLImageElement*, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionState&); - void drawImage(HTMLImageElement*, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator&, const blink::WebBlendMode&, ExceptionState&); - void drawImage(HTMLCanvasElement*, float x, float y, ExceptionState&); - void drawImage(HTMLCanvasElement*, float x, float y, float width, float height, ExceptionState&); - void drawImage(HTMLCanvasElement*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionState&); - void drawImage(HTMLCanvasElement*, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionState&); - void drawImage(HTMLVideoElement*, float x, float y, ExceptionState&); - void drawImage(HTMLVideoElement*, float x, float y, float width, float height, ExceptionState&); - void drawImage(HTMLVideoElement*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionState&); - void drawImage(HTMLVideoElement*, const FloatRect& srcRect, const FloatRect& dstRect, ExceptionState&); + void drawImage(CanvasImageSource*, float x, float y, ExceptionState&); + void drawImage(CanvasImageSource*, float x, float y, float width, float height, ExceptionState&); + void drawImage(CanvasImageSource*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionState&); 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()); @@ -194,22 +189,15 @@ public: void setCompositeOperation(const String&); - PassRefPtr<CanvasGradient> createLinearGradient(float x0, float y0, float x1, float y1, ExceptionState&); + PassRefPtr<CanvasGradient> createLinearGradient(float x0, float y0, float x1, float y1); PassRefPtr<CanvasGradient> createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1, ExceptionState&); - PassRefPtr<CanvasPattern> createPattern(HTMLImageElement*, const String& repetitionType, ExceptionState&); - PassRefPtr<CanvasPattern> createPattern(HTMLCanvasElement*, const String& repetitionType, ExceptionState&); + PassRefPtr<CanvasPattern> createPattern(CanvasImageSource*, const String& repetitionType, ExceptionState&); - PassRefPtr<ImageData> createImageData(PassRefPtr<ImageData>, ExceptionState&) const; - PassRefPtr<ImageData> createImageData(float width, float height, ExceptionState&) const; - PassRefPtr<ImageData> getImageData(float sx, float sy, float sw, float sh, ExceptionState&) const; - void putImageData(ImageData*, float dx, float dy, ExceptionState&); - void putImageData(ImageData*, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight, ExceptionState&); - - // Slated for deprecation: - void webkitPutImageDataHD(ImageData* image, float dx, float dy, ExceptionState& e) { putImageData(image, dx, dy, e); } - void webkitPutImageDataHD(ImageData* image, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight, ExceptionState& e) { putImageData(image, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight, e); } - PassRefPtr<ImageData> webkitGetImageDataHD(float sx, float sy, float sw, float sh, ExceptionState&) const; - float webkitBackingStorePixelRatio() const { return 1; } + PassRefPtrWillBeRawPtr<ImageData> createImageData(PassRefPtrWillBeRawPtr<ImageData>) const; + PassRefPtrWillBeRawPtr<ImageData> createImageData(float width, float height, ExceptionState&) const; + PassRefPtrWillBeRawPtr<ImageData> getImageData(float sx, float sy, float sw, float sh, ExceptionState&) const; + void putImageData(ImageData*, float dx, float dy); + void putImageData(ImageData*, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight); void reset(); @@ -236,18 +224,29 @@ public: PassRefPtr<Canvas2DContextAttributes> getContextAttributes() const; - void drawSystemFocusRing(Element*); - bool drawCustomFocusRing(Element*); + void drawFocusIfNeeded(Element*); + void drawFocusIfNeeded(Path2D*, Element*); + + void loseContext(); + void restoreContext(); + + virtual void trace(Visitor*) OVERRIDE; private: - struct State : FontSelectorClient { + class State FINAL : public CSSFontSelectorClient { + public: State(); virtual ~State(); State(const State&); State& operator=(const State&); - virtual void fontsNeedUpdate(FontSelector*) OVERRIDE; + // CSSFontSelectorClient implementation + virtual void fontsNeedUpdate(CSSFontSelector*) OVERRIDE; + + virtual void trace(Visitor* visitor) OVERRIDE { CSSFontSelectorClient::trace(visitor); } + + unsigned m_unrealizedSaveCount; String m_unparsedStrokeColor; String m_unparsedFillColor; @@ -280,15 +279,18 @@ private: CanvasRenderingContext2D(HTMLCanvasElement*, const Canvas2DContextAttributes* attrs, bool usesCSSCompatibilityParseMode); - State& modifiableState() { ASSERT(!m_unrealizedSaveCount); return m_stateStack.last(); } - const State& state() const { return m_stateStack.last(); } + State& modifiableState() { ASSERT(!state().m_unrealizedSaveCount); 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 applyShadow(); bool shouldDrawShadows() const; - void drawImageInternal(Image*, const FloatRect&, const FloatRect&, const CompositeOperator&, const blink::WebBlendMode&); + void dispatchContextLostEvent(Timer<CanvasRenderingContext2D>*); + void dispatchContextRestoredEvent(Timer<CanvasRenderingContext2D>*); + void tryRestoreContextEvent(Timer<CanvasRenderingContext2D>*); + bool computeDirtyRect(const FloatRect& localBounds, FloatRect*); bool computeDirtyRect(const FloatRect& localBounds, const FloatRect& transformedClipBounds, FloatRect*); void didDraw(const FloatRect&); @@ -296,19 +298,27 @@ private: GraphicsContext* drawingContext() const; void unwindStateStack(); - void realizeSaves() - { - if (m_unrealizedSaveCount) - realizeSavesLoop(); - } - void realizeSavesLoop(); + void realizeSaves(); void applyStrokePattern(); void applyFillPattern(); + void drawImageInternal(CanvasImageSource*, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh, ExceptionState&, CompositeOperator, blink::WebBlendMode); + void drawVideo(HTMLVideoElement*, FloatRect srcRect, FloatRect dstRect); + + void fillInternal(const Path&, const String& windingRuleString); + void strokeInternal(const Path&); + void clipInternal(const Path&, const String& windingRuleString); + + bool isPointInPathInternal(const Path&, const float x, const float y, const String& windingRuleString); + bool isPointInStrokeInternal(const Path&, const float x, const float y); + + void scrollPathIntoViewInternal(const Path&); + void drawTextInternal(const String& text, float x, float y, bool fill, float maxWidth = 0, bool useMaxWidth = false); const Font& accessFont(); + int getFontBaseline(const FontMetrics&) const; void clearCanvas(); bool rectContainsTransformedRect(const FloatRect&, const FloatRect&) const; @@ -316,25 +326,34 @@ private: void inflateStrokeRect(FloatRect&) const; template<class T> void fullCanvasCompositedFill(const T&); + template<class T> void fullCanvasCompositedStroke(const T&); template<class T> void fullCanvasCompositedDrawImage(T*, const FloatRect&, const FloatRect&, CompositeOperator); + void drawFocusIfNeededInternal(const Path&, Element*); bool focusRingCallIsValid(const Path&, Element*); - void updateFocusRingAccessibility(const Path&, Element*); void drawFocusRing(const Path&); + void validateStateStack(); + virtual bool is2d() const OVERRIDE { return true; } virtual bool isAccelerated() const OVERRIDE; virtual bool hasAlpha() const OVERRIDE { return m_hasAlpha; } - virtual bool isTransformInvertible() const { return state().m_invertibleCTM; } + virtual bool isTransformInvertible() const OVERRIDE { return state().m_invertibleCTM; } virtual blink::WebLayer* platformLayer() const OVERRIDE; - Vector<State, 1> m_stateStack; - unsigned m_unrealizedSaveCount; + WillBeHeapVector<OwnPtrWillBeMember<State> > m_stateStack; bool m_usesCSSCompatibilityParseMode; bool m_hasAlpha; + bool m_isContextLost; + bool m_contextRestorable; + Canvas2DContextStorage m_storageMode; MutableStylePropertyMap m_fetchedFonts; + unsigned m_tryRestoreContextAttemptCount; + Timer<CanvasRenderingContext2D> m_dispatchContextLostEventTimer; + Timer<CanvasRenderingContext2D> m_dispatchContextRestoredEventTimer; + Timer<CanvasRenderingContext2D> m_tryRestoreContextEventTimer; }; DEFINE_TYPE_CASTS(CanvasRenderingContext2D, CanvasRenderingContext, context, context->is2d(), context.is2d()); diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.idl b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.idl index 1c243a6b4a0..1738af041a4 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.idl +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContext2D.idl @@ -23,154 +23,160 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -enum CanvasWindingRule { "nonzero", "evenodd" }; - -interface CanvasRenderingContext2D : CanvasRenderingContext { - - void save(); - void restore(); - - [RuntimeEnabled=ExperimentalCanvasFeatures, Immutable] attribute SVGMatrix currentTransform; - 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); +// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#canvasrenderingcontext2d + +// FIXME: float => double throughout +// FIXME: Use union type in drawImage and createPattern once supported: +// http://crbug.com/372891 +typedef (HTMLImageElement or + HTMLVideoElement or + HTMLCanvasElement // or + // CanvasRenderingContext2D or + // ImageBitmap + ) CanvasImageSource; + +enum CanvasFillRule { "nonzero", "evenodd" }; + +[ + TypeChecking=Interface|Nullable|Unrestricted, + WillBeGarbageCollected, +] interface CanvasRenderingContext2D { + // back-reference to the canvas + readonly attribute HTMLCanvasElement canvas; + + // state + void save(); // push state on state stack + void restore(); // pop state stack and restore state + + // transformations (default transform is the identity matrix) + [RuntimeEnabled=ExperimentalCanvasFeatures] attribute SVGMatrix currentTransform; + void scale(unrestricted float x, unrestricted float y); + void rotate(unrestricted float angle); + void translate(unrestricted float x, unrestricted float y); + void transform(unrestricted float a, unrestricted float b, unrestricted float c, unrestricted float d, unrestricted float e, unrestricted float f); + void setTransform(unrestricted float a, unrestricted float b, unrestricted float c, unrestricted float d, unrestricted float e, unrestricted float f); void resetTransform(); - attribute float globalAlpha; - [TreatNullAs=NullString] attribute DOMString globalCompositeOperation; + // compositing + attribute unrestricted float globalAlpha; // (default 1.0) + [TreatNullAs=NullString] attribute DOMString globalCompositeOperation; // (default source-over) - [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 float lineWidth; - [TreatNullAs=NullString] attribute DOMString lineCap; - [TreatNullAs=NullString] attribute DOMString lineJoin; - attribute float miterLimit; + // image smoothing + [ImplementedAs=imageSmoothingEnabled, MeasureAs=PrefixedImageSmoothingEnabled] attribute boolean webkitImageSmoothingEnabled; + [MeasureAs=UnprefixedImageSmoothingEnabled] attribute boolean imageSmoothingEnabled; - attribute float shadowOffsetX; - attribute float shadowOffsetY; - attribute float shadowBlur; + // colors and styles (see also the CanvasDrawingStyles interface) + // FIXME: Use union types when supported: http://crbug.com/372891 + [Custom] attribute object strokeStyle; // (default black) + [Custom] attribute object fillStyle; // (default black) + 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); + [RaisesException] CanvasPattern createPattern(HTMLCanvasElement canvas, [TreatNullAs=NullString] DOMString repetitionType); + [RaisesException] CanvasPattern createPattern(HTMLImageElement image, [TreatNullAs=NullString] DOMString repetitionType); + [RaisesException] CanvasPattern createPattern(HTMLVideoElement image, [TreatNullAs=NullString] DOMString repetitionType); + + // shadows + attribute unrestricted float shadowOffsetX; + attribute unrestricted float shadowOffsetY; + attribute unrestricted float shadowBlur; [TreatNullAs=NullString] attribute DOMString shadowColor; - void setLineDash(sequence<float> dash); - sequence<float> getLineDash(); - attribute float lineDashOffset; - - // FIXME: These attributes should be implemented. - // [Custom] attribute Array webkitLineDash; - // attribute float webkitLineDashOffset; - - void clearRect(float x, float y, float width, float height); - void fillRect(float x, float y, float width, float height); + // rects + 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 strokeRect(unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height); + // path API (see also CanvasPathMethods) void beginPath(); - - attribute Path currentPath; - - // 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); - [RaisesException] void ellipse(float x, float y, float radiusX, float radiusY, float rotation, float startAngle, float endAngle, boolean anticlockwise); - - void fill(optional CanvasWindingRule winding); + void fill(optional CanvasFillRule winding); + [RuntimeEnabled=Path2D] void fill(Path2D path, optional CanvasFillRule winding); void stroke(); - void clip(optional CanvasWindingRule winding); - boolean isPointInPath(float x, float y, optional CanvasWindingRule winding); - boolean isPointInStroke(float x, float y); - - // text - attribute DOMString font; - attribute DOMString textAlign; - attribute DOMString textBaseline; - + [RuntimeEnabled=Path2D] void stroke(Path2D path); + // Focus rings + void drawFocusIfNeeded(Element element); + [RuntimeEnabled=Path2D] void drawFocusIfNeeded(Path2D path, Element element); + + [RuntimeEnabled=ExperimentalCanvasFeatures] void scrollPathIntoView(optional Path2D path); + void clip(optional CanvasFillRule winding); + [RuntimeEnabled=Path2D] void clip(Path2D path, optional CanvasFillRule winding); + boolean isPointInPath(unrestricted float x, unrestricted float y, optional CanvasFillRule winding); + [RuntimeEnabled=Path2D] boolean isPointInPath(Path2D path, unrestricted float x, unrestricted float y, optional CanvasFillRule winding); + boolean isPointInStroke(unrestricted float x, unrestricted float y); + [RuntimeEnabled=Path2D] boolean isPointInStroke(Path2D path, unrestricted float x, unrestricted float y); + + // text (see also the CanvasDrawingStyles interface) + 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); TextMetrics measureText(DOMString text); - // other - - void setAlpha(float alpha); - void setCompositeOperation(DOMString compositeOperation); - - void setLineWidth(float width); - void setLineCap(DOMString cap); - void setLineJoin(DOMString join); - void setMiterLimit(float limit); - - 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 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); - - 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 strokeRect(float x, float y, float width, float height); - - [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); - [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); - [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] void drawImage(ImageBitmap? imageBitmap, float x, float y); - [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] void drawImage(ImageBitmap? imageBitmap, float x, float y, float width, float height); - [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] void drawImage(ImageBitmap? imageBitmap, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh); - - 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 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); - - [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); - - [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); - - [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 object strokeStyle; - [Custom] attribute object fillStyle; + // drawing images + [RaisesException] void drawImage(HTMLImageElement image, unrestricted float x, unrestricted float y); + [RaisesException] void drawImage(HTMLImageElement image, unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height); + [RaisesException] void drawImage(HTMLImageElement 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] void drawImage(HTMLCanvasElement canvas, unrestricted float x, unrestricted float y); + [RaisesException] void drawImage(HTMLCanvasElement canvas, unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height); + [RaisesException] void drawImage(HTMLCanvasElement canvas, 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] void drawImage(HTMLVideoElement video, unrestricted float x, unrestricted float y); + [RaisesException] void drawImage(HTMLVideoElement video, unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height); + [RaisesException] void drawImage(HTMLVideoElement video, unrestricted float sx, unrestricted float sy, unrestricted float sw, unrestricted float sh, unrestricted float dx, unrestricted float dy, unrestricted float dw, unrestricted float dh); + [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] void drawImage(ImageBitmap imageBitmap, unrestricted float x, unrestricted float y); + [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] void drawImage(ImageBitmap imageBitmap, unrestricted float x, unrestricted float y, unrestricted float width, unrestricted float height); + [RuntimeEnabled=ExperimentalCanvasFeatures, RaisesException] void drawImage(ImageBitmap imageBitmap, unrestricted float sx, unrestricted float sy, unrestricted float sw, unrestricted float sh, unrestricted float dx, unrestricted float dy, unrestricted float dw, unrestricted float dh); // pixel manipulation + ImageData createImageData(ImageData imagedata); + [RaisesException] ImageData createImageData(float sw, float sh); [RaisesException] ImageData getImageData(float sx, float sy, float sw, float sh); + void putImageData(ImageData imagedata, float dx, float dy); + void putImageData(ImageData imagedata, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight); - [RaisesException] ImageData webkitGetImageDataHD(float sx, float sy, float sw, float sh); + // Context state + // Should be merged with WebGL counterpart in CanvasRenderingContext, once no-longer experimental + [RuntimeEnabled=ExperimentalCanvasFeatures] boolean isContextLost(); - // Focus rings - [RuntimeEnabled=ExperimentalCanvasFeatures] void drawSystemFocusRing(Element element); - [RuntimeEnabled=ExperimentalCanvasFeatures] boolean drawCustomFocusRing(Element element); + Canvas2DContextAttributes getContextAttributes(); - readonly attribute float webkitBackingStorePixelRatio; + // FIXME: factor out to CanvasDrawingStyles + // line caps/joins + attribute unrestricted float lineWidth; // (default 1) + [TreatNullAs=NullString] attribute DOMString lineCap; // "butt", "round", "square" (default "butt") + [TreatNullAs=NullString] attribute DOMString lineJoin; // "round", "bevel", "miter" (default "miter") + attribute unrestricted float miterLimit; // (default 10) - [ImplementedAs=imageSmoothingEnabled] attribute boolean webkitImageSmoothingEnabled; - attribute boolean imageSmoothingEnabled; + // dashed lines + void setLineDash(sequence<unrestricted float> dash); + sequence<unrestricted float> getLineDash(); + attribute unrestricted float lineDashOffset; - Canvas2DContextAttributes getContextAttributes(); + // text + attribute DOMString font; // (default 10px sans-serif) + attribute DOMString textAlign; // "start", "end", "left", "right", "center" (default: "start") + attribute DOMString textBaseline; // "top", "hanging", "middle", "alphabetic", "ideographic", "bottom" (default: "alphabetic") + + // Non-standard APIs. Candidates for deprecation + // https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D + [MeasureAs=CanvasRenderingContext2DSetAlpha] void setAlpha(unrestricted float alpha); + [MeasureAs=CanvasRenderingContext2DSetCompositeOperation] void setCompositeOperation(DOMString compositeOperation); + [MeasureAs=CanvasRenderingContext2DSetLineWidth] void setLineWidth(unrestricted float width); + [MeasureAs=CanvasRenderingContext2DSetLineCap] void setLineCap(DOMString cap); + [MeasureAs=CanvasRenderingContext2DSetLineJoin] void setLineJoin(DOMString join); + [MeasureAs=CanvasRenderingContext2DSetMiterLimit] void setMiterLimit(unrestricted float limit); + [MeasureAs=CanvasRenderingContext2DClearShadow] void clearShadow(); + [MeasureAs=CanvasRenderingContext2DSetStrokeColor] void setStrokeColor(DOMString color, optional unrestricted float alpha); + [MeasureAs=CanvasRenderingContext2DSetStrokeColor] void setStrokeColor(unrestricted float grayLevel, optional unrestricted float alpha); + [MeasureAs=CanvasRenderingContext2DSetStrokeColor] void setStrokeColor(unrestricted float r, unrestricted float g, unrestricted float b, unrestricted float a); + [MeasureAs=CanvasRenderingContext2DSetStrokeColor] void setStrokeColor(unrestricted float c, unrestricted float m, unrestricted float y, unrestricted float k, unrestricted float a); + [MeasureAs=CanvasRenderingContext2DSetFillColor] void setFillColor(DOMString color, optional unrestricted float alpha); + [MeasureAs=CanvasRenderingContext2DSetFillColor] void setFillColor(unrestricted float grayLevel, optional unrestricted float alpha); + [MeasureAs=CanvasRenderingContext2DSetFillColor] void setFillColor(unrestricted float r, unrestricted float g, unrestricted float b, unrestricted float a); + [MeasureAs=CanvasRenderingContext2DSetFillColor] void setFillColor(unrestricted float c, unrestricted float m, unrestricted float y, unrestricted float k, unrestricted float a); + [MeasureAs=CanvasRenderingContext2DDrawImageFromRect] void drawImageFromRect( + HTMLImageElement? image, optional unrestricted float sx, optional unrestricted float sy, optional unrestricted float sw, optional unrestricted float sh, + optional unrestricted float dx, optional unrestricted float dy, optional unrestricted float dw, optional unrestricted float dh, optional DOMString compositeOperation); + [MeasureAs=CanvasRenderingContext2DSetShadow] void setShadow(unrestricted float width, unrestricted float height, unrestricted float blur, optional DOMString color, optional unrestricted float alpha); + [MeasureAs=CanvasRenderingContext2DSetShadow] void setShadow(unrestricted float width, unrestricted float height, unrestricted float blur, unrestricted float grayLevel, optional unrestricted float alpha); + [MeasureAs=CanvasRenderingContext2DSetShadow] void setShadow(unrestricted float width, unrestricted float height, unrestricted float blur, unrestricted float r, unrestricted float g, unrestricted float b, unrestricted float a); + [MeasureAs=CanvasRenderingContext2DSetShadow] void setShadow(unrestricted float width, unrestricted float height, unrestricted float blur, unrestricted float c, unrestricted float m, unrestricted float y, unrestricted float k, unrestricted float a); }; +CanvasRenderingContext2D implements CanvasPathMethods; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasStyle.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasStyle.cpp index b68421af1f6..ae7e6d41b70 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasStyle.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasStyle.cpp @@ -29,8 +29,8 @@ #include "config.h" #include "core/html/canvas/CanvasStyle.h" -#include "CSSPropertyNames.h" -#include "core/css/CSSParser.h" +#include "core/CSSPropertyNames.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/StylePropertySet.h" #include "core/html/HTMLCanvasElement.h" #include "core/html/canvas/CanvasGradient.h" @@ -42,13 +42,14 @@ namespace WebCore { enum ColorParseResult { ParsedRGBA, ParsedCurrentColor, ParsedSystemColor, ParseFailed }; -static ColorParseResult parseColor(RGBA32& parsedColor, const String& colorString, Document* document = 0) +static ColorParseResult parseColor(RGBA32& parsedColor, const String& colorString) { if (equalIgnoringCase(colorString, "currentcolor")) return ParsedCurrentColor; - if (CSSParser::parseColor(parsedColor, colorString)) + const bool useStrictParsing = true; + if (BisonCSSParser::parseColor(parsedColor, colorString, useStrictParsing)) return ParsedRGBA; - if (CSSParser::parseSystemColor(parsedColor, colorString, document)) + if (BisonCSSParser::parseSystemColor(parsedColor, colorString)) return ParsedSystemColor; return ParseFailed; } @@ -58,13 +59,13 @@ RGBA32 currentColor(HTMLCanvasElement* canvas) if (!canvas || !canvas->inDocument() || !canvas->inlineStyle()) return Color::black; RGBA32 rgba = Color::black; - CSSParser::parseColor(rgba, canvas->inlineStyle()->getPropertyValue(CSSPropertyColor)); + BisonCSSParser::parseColor(rgba, canvas->inlineStyle()->getPropertyValue(CSSPropertyColor)); return rgba; } bool parseColorOrCurrentColor(RGBA32& parsedColor, const String& colorString, HTMLCanvasElement* canvas) { - ColorParseResult parseResult = parseColor(parsedColor, colorString, canvas ? &canvas->document() : 0); + ColorParseResult parseResult = parseColor(parsedColor, colorString); switch (parseResult) { case ParsedRGBA: case ParsedSystemColor: @@ -123,10 +124,10 @@ CanvasStyle::CanvasStyle(PassRefPtr<CanvasPattern> pattern) { } -PassRefPtr<CanvasStyle> CanvasStyle::createFromString(const String& color, Document* document) +PassRefPtr<CanvasStyle> CanvasStyle::createFromString(const String& color) { RGBA32 rgba; - ColorParseResult parseResult = parseColor(rgba, color, document); + ColorParseResult parseResult = parseColor(rgba, color); switch (parseResult) { case ParsedRGBA: case ParsedSystemColor: @@ -134,10 +135,10 @@ PassRefPtr<CanvasStyle> CanvasStyle::createFromString(const String& color, Docum case ParsedCurrentColor: return adoptRef(new CanvasStyle(CurrentColor)); case ParseFailed: - return 0; + return nullptr; default: ASSERT_NOT_REACHED(); - return 0; + return nullptr; } } @@ -151,23 +152,24 @@ PassRefPtr<CanvasStyle> CanvasStyle::createFromStringWithOverrideAlpha(const Str case ParsedCurrentColor: return adoptRef(new CanvasStyle(CurrentColorWithOverrideAlpha, alpha)); case ParseFailed: - return 0; + return nullptr; default: ASSERT_NOT_REACHED(); - return 0; + return nullptr; } } PassRefPtr<CanvasStyle> CanvasStyle::createFromGradient(PassRefPtr<CanvasGradient> gradient) { if (!gradient) - return 0; + return nullptr; return adoptRef(new CanvasStyle(gradient)); } + PassRefPtr<CanvasStyle> CanvasStyle::createFromPattern(PassRefPtr<CanvasPattern> pattern) { if (!pattern) - return 0; + return nullptr; return adoptRef(new CanvasStyle(pattern)); } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasStyle.h b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasStyle.h index 526ab716345..f939e3e8214 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/CanvasStyle.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/CanvasStyle.h @@ -36,14 +36,13 @@ namespace WebCore { class CanvasGradient; class CanvasPattern; - class Document; class GraphicsContext; class HTMLCanvasElement; class CanvasStyle : public RefCounted<CanvasStyle> { public: static PassRefPtr<CanvasStyle> createFromRGBA(RGBA32 rgba) { return adoptRef(new CanvasStyle(rgba)); } - static PassRefPtr<CanvasStyle> createFromString(const String& color, Document* = 0); + static PassRefPtr<CanvasStyle> createFromString(const String& color); static PassRefPtr<CanvasStyle> createFromStringWithOverrideAlpha(const String& color, float alpha); static PassRefPtr<CanvasStyle> createFromGrayLevelWithAlpha(float grayLevel, float alpha) { return adoptRef(new CanvasStyle(grayLevel, alpha)); } static PassRefPtr<CanvasStyle> createFromRGBAChannels(float r, float g, float b, float a) { return adoptRef(new CanvasStyle(r, g, b, a)); } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/DataView.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/DataView.cpp index 5a28161937c..41b6cb3332d 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/DataView.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/DataView.cpp @@ -47,19 +47,19 @@ PassRefPtr<DataView> DataView::create(unsigned length) { RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(length, sizeof(uint8_t)); if (!buffer.get()) - return 0; + return nullptr; return create(buffer, 0, length); } PassRefPtr<DataView> DataView::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned byteLength) { if (byteOffset > buffer->byteLength()) - return 0; + return nullptr; CheckedInt<uint32_t> checkedOffset(byteOffset); CheckedInt<uint32_t> checkedLength(byteLength); CheckedInt<uint32_t> checkedMax = checkedOffset + checkedLength; if (!checkedMax.isValid() || checkedMax.value() > buffer->byteLength()) - return 0; + return nullptr; return adoptRef(new DataView(buffer, byteOffset, byteLength)); } @@ -133,7 +133,7 @@ template<typename T> T DataView::getData(unsigned byteOffset, bool littleEndian, ExceptionState& exceptionState) const { if (beyondRange<T>(byteOffset)) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + exceptionState.throwDOMException(IndexSizeError, "The provided offset (" + String::number(byteOffset) + ") is outside the allowed range."); return 0; } @@ -148,7 +148,7 @@ template<typename T> void DataView::setData(unsigned byteOffset, T value, bool littleEndian, ExceptionState& exceptionState) { if (beyondRange<T>(byteOffset)) { - exceptionState.throwUninformativeAndGenericDOMException(IndexSizeError); + exceptionState.throwDOMException(IndexSizeError, "The provided offset (" + String::number(byteOffset) + ") is outside the allowed range."); return; } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/DataView.h b/chromium/third_party/WebKit/Source/core/html/canvas/DataView.h index 4a9728d845e..d497eae2f97 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/DataView.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/DataView.h @@ -34,14 +34,12 @@ namespace WebCore { class ExceptionState; -class DataView : public ArrayBufferView, public ScriptWrappable { +class DataView FINAL : public ArrayBufferView, public ScriptWrappable { public: static PassRefPtr<DataView> create(unsigned length); static PassRefPtr<DataView> create(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned byteLength); - virtual unsigned length() const { return m_byteLength; } - virtual unsigned byteLength() const { return m_byteLength; } - virtual PassRefPtr<ArrayBufferView> slice(int, int) const { return 0; } + virtual unsigned byteLength() const OVERRIDE { return m_byteLength; } int8_t getInt8(unsigned byteOffset, ExceptionState&); uint8_t getUint8(unsigned byteOffset, ExceptionState&); @@ -73,13 +71,13 @@ public: void setFloat64(unsigned byteOffset, double value, ExceptionState& ec) { setFloat64(byteOffset, value, false, ec); } void setFloat64(unsigned byteOffset, double value, bool littleEndian, ExceptionState&); - virtual ViewType getType() const + virtual ViewType type() const OVERRIDE { return TypeDataView; } protected: - virtual void neuter(); + virtual void neuter() OVERRIDE; private: DataView(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned byteLength); diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/DataView.idl b/chromium/third_party/WebKit/Source/core/html/canvas/DataView.idl index a9b9facac3e..4fc89615027 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/DataView.idl +++ b/chromium/third_party/WebKit/Source/core/html/canvas/DataView.idl @@ -26,30 +26,30 @@ [ Custom=Wrap, CustomConstructor(ArrayBuffer buffer, optional unsigned long byteOffset, optional unsigned long byteLength), - GlobalContext=Window&WorkerGlobalScope, + Exposed=Window&Worker, + TypeChecking=Interface|Nullable, ] interface DataView : ArrayBufferView { // All these methods raise an exception if they would read or write beyond the end of the view. [RaisesException] byte getInt8(unsigned long byteOffset); [RaisesException] octet getUint8(unsigned long byteOffset); - [StrictTypeChecking, RaisesException] short getInt16(unsigned long byteOffset, optional boolean littleEndian); - [StrictTypeChecking, RaisesException] unsigned short getUint16(unsigned long byteOffset, optional boolean littleEndian); - [StrictTypeChecking, RaisesException] long getInt32(unsigned long byteOffset, optional boolean littleEndian); - [StrictTypeChecking, RaisesException] unsigned long getUint32(unsigned long byteOffset, optional boolean littleEndian); + [RaisesException] short getInt16(unsigned long byteOffset, optional boolean littleEndian); + [RaisesException] unsigned short getUint16(unsigned long byteOffset, optional boolean littleEndian); + [RaisesException] long getInt32(unsigned long byteOffset, optional boolean littleEndian); + [RaisesException] unsigned long getUint32(unsigned long byteOffset, optional boolean littleEndian); // Use custom code to handle NaN case for JSC. - [StrictTypeChecking, RaisesException] float getFloat32(unsigned long byteOffset, optional boolean littleEndian); - [StrictTypeChecking, RaisesException] double getFloat64(unsigned long byteOffset, optional boolean littleEndian); + [RaisesException] float getFloat32(unsigned long byteOffset, optional boolean littleEndian); + [RaisesException] double getFloat64(unsigned long byteOffset, optional boolean littleEndian); [RaisesException] void setInt8(unsigned long byteOffset, byte value); [RaisesException] void setUint8(unsigned long byteOffset, octet value); - [StrictTypeChecking, RaisesException] void setInt16(unsigned long byteOffset, short value, optional boolean littleEndian); - [StrictTypeChecking, RaisesException] void setUint16(unsigned long byteOffset, unsigned short value, optional boolean littleEndian); - [StrictTypeChecking, RaisesException] void setInt32(unsigned long byteOffset, long value, optional boolean littleEndian); - [StrictTypeChecking, RaisesException] void setUint32(unsigned long byteOffset, unsigned long value, optional boolean littleEndian); - [StrictTypeChecking, RaisesException] void setFloat32(unsigned long byteOffset, float value, optional boolean littleEndian); - [StrictTypeChecking, RaisesException] void setFloat64(unsigned long byteOffset, double value, optional boolean littleEndian); + [RaisesException] void setInt16(unsigned long byteOffset, short value, optional boolean littleEndian); + [RaisesException] void setUint16(unsigned long byteOffset, unsigned short value, optional boolean littleEndian); + [RaisesException] void setInt32(unsigned long byteOffset, long value, optional boolean littleEndian); + [RaisesException] void setUint32(unsigned long byteOffset, unsigned long value, optional boolean littleEndian); + [RaisesException] void setFloat32(unsigned long byteOffset, float value, optional boolean littleEndian); + [RaisesException] void setFloat64(unsigned long byteOffset, double value, optional boolean littleEndian); }; - diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/EXTBlendMinMax.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/EXTBlendMinMax.cpp new file mode 100644 index 00000000000..8ded7388912 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/EXTBlendMinMax.cpp @@ -0,0 +1,42 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "core/html/canvas/EXTBlendMinMax.h" + +namespace WebCore { + +EXTBlendMinMax::EXTBlendMinMax(WebGLRenderingContextBase* context) + : WebGLExtension(context) +{ + ScriptWrappable::init(this); + context->extensionsUtil()->ensureExtensionEnabled("GL_EXT_blend_minmax"); +} + +EXTBlendMinMax::~EXTBlendMinMax() +{ +} + +WebGLExtensionName EXTBlendMinMax::name() const +{ + return EXTBlendMinMaxName; +} + +PassRefPtr<EXTBlendMinMax> EXTBlendMinMax::create(WebGLRenderingContextBase* context) +{ + return adoptRef(new EXTBlendMinMax(context)); +} + +bool EXTBlendMinMax::supported(WebGLRenderingContextBase* context) +{ + return context->extensionsUtil()->supportsExtension("GL_EXT_blend_minmax"); +} + +const char* EXTBlendMinMax::extensionName() +{ + return "EXT_blend_minmax"; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/EXTBlendMinMax.h b/chromium/third_party/WebKit/Source/core/html/canvas/EXTBlendMinMax.h new file mode 100644 index 00000000000..4c6421760de --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/EXTBlendMinMax.h @@ -0,0 +1,29 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXTBlendMinMax_h +#define EXTBlendMinMax_h + +#include "bindings/v8/ScriptWrappable.h" +#include "core/html/canvas/WebGLExtension.h" +#include "wtf/PassRefPtr.h" + +namespace WebCore { + +class EXTBlendMinMax FINAL : public WebGLExtension, public ScriptWrappable { +public: + static PassRefPtr<EXTBlendMinMax> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); + static const char* extensionName(); + + virtual ~EXTBlendMinMax(); + virtual WebGLExtensionName name() const OVERRIDE; + +private: + EXTBlendMinMax(WebGLRenderingContextBase*); +}; + +} // namespace WebCore + +#endif // EXTBlendMinMax_h diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/EXTBlendMinMax.idl b/chromium/third_party/WebKit/Source/core/html/canvas/EXTBlendMinMax.idl new file mode 100644 index 00000000000..55baea7d615 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/EXTBlendMinMax.idl @@ -0,0 +1,12 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + DoNotCheckConstants, + NoInterfaceObject, + TypeChecking=Interface|Nullable, +] interface EXTBlendMinMax { + const unsigned long MIN_EXT = 0x8007; + const unsigned long MAX_EXT = 0x8008; +}; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/EXTFragDepth.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/EXTFragDepth.cpp index a2484d283d3..002deb3df74 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/EXTFragDepth.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/EXTFragDepth.cpp @@ -27,35 +27,32 @@ #include "core/html/canvas/EXTFragDepth.h" -#include "platform/graphics/Extensions3D.h" - namespace WebCore { -EXTFragDepth::EXTFragDepth(WebGLRenderingContext* context) +EXTFragDepth::EXTFragDepth(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_EXT_frag_depth"); + context->extensionsUtil()->ensureExtensionEnabled("GL_EXT_frag_depth"); } EXTFragDepth::~EXTFragDepth() { } -WebGLExtension::ExtensionName EXTFragDepth::name() const +WebGLExtensionName EXTFragDepth::name() const { return EXTFragDepthName; } -PassRefPtr<EXTFragDepth> EXTFragDepth::create(WebGLRenderingContext* context) +PassRefPtr<EXTFragDepth> EXTFragDepth::create(WebGLRenderingContextBase* context) { return adoptRef(new EXTFragDepth(context)); } -bool EXTFragDepth::supported(WebGLRenderingContext* context) +bool EXTFragDepth::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_EXT_frag_depth"); + return context->extensionsUtil()->supportsExtension("GL_EXT_frag_depth"); } const char* EXTFragDepth::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/EXTFragDepth.h b/chromium/third_party/WebKit/Source/core/html/canvas/EXTFragDepth.h index fc8a9fa6f8e..eee90dcc021 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/EXTFragDepth.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/EXTFragDepth.h @@ -32,17 +32,17 @@ namespace WebCore { -class EXTFragDepth : public WebGLExtension, public ScriptWrappable { +class EXTFragDepth FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<EXTFragDepth> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<EXTFragDepth> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~EXTFragDepth(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - explicit EXTFragDepth(WebGLRenderingContext*); + explicit EXTFragDepth(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/EXTShaderTextureLOD.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/EXTShaderTextureLOD.cpp new file mode 100644 index 00000000000..d258bef94cf --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/EXTShaderTextureLOD.cpp @@ -0,0 +1,42 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "core/html/canvas/EXTShaderTextureLOD.h" + +namespace WebCore { + +EXTShaderTextureLOD::EXTShaderTextureLOD(WebGLRenderingContextBase* context) + : WebGLExtension(context) +{ + ScriptWrappable::init(this); + context->extensionsUtil()->ensureExtensionEnabled("GL_EXT_shader_texture_lod"); +} + +EXTShaderTextureLOD::~EXTShaderTextureLOD() +{ +} + +WebGLExtensionName EXTShaderTextureLOD::name() const +{ + return EXTShaderTextureLODName; +} + +PassRefPtr<EXTShaderTextureLOD> EXTShaderTextureLOD::create(WebGLRenderingContextBase* context) +{ + return adoptRef(new EXTShaderTextureLOD(context)); +} + +bool EXTShaderTextureLOD::supported(WebGLRenderingContextBase* context) +{ + return context->extensionsUtil()->supportsExtension("GL_EXT_shader_texture_lod"); +} + +const char* EXTShaderTextureLOD::extensionName() +{ + return "EXT_shader_texture_lod"; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/EXTShaderTextureLOD.h b/chromium/third_party/WebKit/Source/core/html/canvas/EXTShaderTextureLOD.h new file mode 100644 index 00000000000..342d94d0965 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/EXTShaderTextureLOD.h @@ -0,0 +1,29 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXTShaderTextureLOD_h +#define EXTShaderTextureLOD_h + +#include "bindings/v8/ScriptWrappable.h" +#include "core/html/canvas/WebGLExtension.h" +#include "wtf/PassRefPtr.h" + +namespace WebCore { + +class EXTShaderTextureLOD FINAL : public WebGLExtension, public ScriptWrappable { +public: + static PassRefPtr<EXTShaderTextureLOD> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); + static const char* extensionName(); + + virtual ~EXTShaderTextureLOD(); + virtual WebGLExtensionName name() const OVERRIDE; + +private: + EXTShaderTextureLOD(WebGLRenderingContextBase*); +}; + +} // namespace WebCore + +#endif // EXTShaderTextureLOD_h diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/EXTShaderTextureLOD.idl b/chromium/third_party/WebKit/Source/core/html/canvas/EXTShaderTextureLOD.idl new file mode 100644 index 00000000000..a2e18b616ad --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/EXTShaderTextureLOD.idl @@ -0,0 +1,8 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + NoInterfaceObject +] interface EXTShaderTextureLOD { +}; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/EXTTextureFilterAnisotropic.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/EXTTextureFilterAnisotropic.cpp index 231c3c58662..d98399a4ccc 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/EXTTextureFilterAnisotropic.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/EXTTextureFilterAnisotropic.cpp @@ -26,35 +26,33 @@ #include "config.h" #include "core/html/canvas/EXTTextureFilterAnisotropic.h" -#include "platform/graphics/Extensions3D.h" namespace WebCore { -EXTTextureFilterAnisotropic::EXTTextureFilterAnisotropic(WebGLRenderingContext* context) +EXTTextureFilterAnisotropic::EXTTextureFilterAnisotropic(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_EXT_texture_filter_anisotropic"); + context->extensionsUtil()->ensureExtensionEnabled("GL_EXT_texture_filter_anisotropic"); } EXTTextureFilterAnisotropic::~EXTTextureFilterAnisotropic() { } -WebGLExtension::ExtensionName EXTTextureFilterAnisotropic::name() const +WebGLExtensionName EXTTextureFilterAnisotropic::name() const { return EXTTextureFilterAnisotropicName; } -PassRefPtr<EXTTextureFilterAnisotropic> EXTTextureFilterAnisotropic::create(WebGLRenderingContext* context) +PassRefPtr<EXTTextureFilterAnisotropic> EXTTextureFilterAnisotropic::create(WebGLRenderingContextBase* context) { return adoptRef(new EXTTextureFilterAnisotropic(context)); } -bool EXTTextureFilterAnisotropic::supported(WebGLRenderingContext* context) +bool EXTTextureFilterAnisotropic::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_EXT_texture_filter_anisotropic"); + return context->extensionsUtil()->supportsExtension("GL_EXT_texture_filter_anisotropic"); } const char* EXTTextureFilterAnisotropic::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/EXTTextureFilterAnisotropic.h b/chromium/third_party/WebKit/Source/core/html/canvas/EXTTextureFilterAnisotropic.h index 727f00ee086..a69a9bc3ab2 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/EXTTextureFilterAnisotropic.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/EXTTextureFilterAnisotropic.h @@ -32,17 +32,17 @@ namespace WebCore { -class EXTTextureFilterAnisotropic : public WebGLExtension, public ScriptWrappable { +class EXTTextureFilterAnisotropic FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<EXTTextureFilterAnisotropic> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<EXTTextureFilterAnisotropic> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~EXTTextureFilterAnisotropic(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - EXTTextureFilterAnisotropic(WebGLRenderingContext*); + EXTTextureFilterAnisotropic(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESElementIndexUint.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/OESElementIndexUint.cpp index a4b0e29c94d..95fac41b58c 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESElementIndexUint.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESElementIndexUint.cpp @@ -26,35 +26,33 @@ #include "config.h" #include "core/html/canvas/OESElementIndexUint.h" -#include "platform/graphics/Extensions3D.h" namespace WebCore { -OESElementIndexUint::OESElementIndexUint(WebGLRenderingContext* context) +OESElementIndexUint::OESElementIndexUint(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_OES_element_index_uint"); + context->extensionsUtil()->ensureExtensionEnabled("GL_OES_element_index_uint"); } OESElementIndexUint::~OESElementIndexUint() { } -WebGLExtension::ExtensionName OESElementIndexUint::name() const +WebGLExtensionName OESElementIndexUint::name() const { return OESElementIndexUintName; } -PassRefPtr<OESElementIndexUint> OESElementIndexUint::create(WebGLRenderingContext* context) +PassRefPtr<OESElementIndexUint> OESElementIndexUint::create(WebGLRenderingContextBase* context) { return adoptRef(new OESElementIndexUint(context)); } -bool OESElementIndexUint::supported(WebGLRenderingContext* context) +bool OESElementIndexUint::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_OES_element_index_uint"); + return context->extensionsUtil()->supportsExtension("GL_OES_element_index_uint"); } const char* OESElementIndexUint::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESElementIndexUint.h b/chromium/third_party/WebKit/Source/core/html/canvas/OESElementIndexUint.h index 0116c1ddcf1..f11ebd251ee 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESElementIndexUint.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESElementIndexUint.h @@ -32,17 +32,17 @@ namespace WebCore { -class OESElementIndexUint : public WebGLExtension, public ScriptWrappable { +class OESElementIndexUint FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<OESElementIndexUint> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<OESElementIndexUint> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~OESElementIndexUint(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - OESElementIndexUint(WebGLRenderingContext*); + OESElementIndexUint(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESStandardDerivatives.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/OESStandardDerivatives.cpp index aec473bc686..49b7adff0d8 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESStandardDerivatives.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESStandardDerivatives.cpp @@ -26,35 +26,33 @@ #include "config.h" #include "core/html/canvas/OESStandardDerivatives.h" -#include "platform/graphics/Extensions3D.h" namespace WebCore { -OESStandardDerivatives::OESStandardDerivatives(WebGLRenderingContext* context) +OESStandardDerivatives::OESStandardDerivatives(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_OES_standard_derivatives"); + context->extensionsUtil()->ensureExtensionEnabled("GL_OES_standard_derivatives"); } OESStandardDerivatives::~OESStandardDerivatives() { } -WebGLExtension::ExtensionName OESStandardDerivatives::name() const +WebGLExtensionName OESStandardDerivatives::name() const { return OESStandardDerivativesName; } -PassRefPtr<OESStandardDerivatives> OESStandardDerivatives::create(WebGLRenderingContext* context) +PassRefPtr<OESStandardDerivatives> OESStandardDerivatives::create(WebGLRenderingContextBase* context) { return adoptRef(new OESStandardDerivatives(context)); } -bool OESStandardDerivatives::supported(WebGLRenderingContext* context) +bool OESStandardDerivatives::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_OES_standard_derivatives"); + return context->extensionsUtil()->supportsExtension("GL_OES_standard_derivatives"); } const char* OESStandardDerivatives::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESStandardDerivatives.h b/chromium/third_party/WebKit/Source/core/html/canvas/OESStandardDerivatives.h index 327a15286d1..8eb7226eb20 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESStandardDerivatives.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESStandardDerivatives.h @@ -32,17 +32,17 @@ namespace WebCore { -class OESStandardDerivatives : public WebGLExtension, public ScriptWrappable { +class OESStandardDerivatives FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<OESStandardDerivatives> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<OESStandardDerivatives> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~OESStandardDerivatives(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - OESStandardDerivatives(WebGLRenderingContext*); + OESStandardDerivatives(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloat.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloat.cpp index 99d1387376c..a949e5c54b0 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloat.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloat.cpp @@ -26,35 +26,37 @@ #include "config.h" #include "core/html/canvas/OESTextureFloat.h" -#include "platform/graphics/Extensions3D.h" namespace WebCore { -OESTextureFloat::OESTextureFloat(WebGLRenderingContext* context) +OESTextureFloat::OESTextureFloat(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_OES_texture_float"); + if (context->extensionsUtil()->ensureExtensionEnabled("GL_OES_texture_float")) { + // Implicitly enable rendering to float textures + context->extensionsUtil()->ensureExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgba"); + context->extensionsUtil()->ensureExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgb"); + } } OESTextureFloat::~OESTextureFloat() { } -WebGLExtension::ExtensionName OESTextureFloat::name() const +WebGLExtensionName OESTextureFloat::name() const { return OESTextureFloatName; } -PassRefPtr<OESTextureFloat> OESTextureFloat::create(WebGLRenderingContext* context) +PassRefPtr<OESTextureFloat> OESTextureFloat::create(WebGLRenderingContextBase* context) { return adoptRef(new OESTextureFloat(context)); } -bool OESTextureFloat::supported(WebGLRenderingContext* context) +bool OESTextureFloat::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_OES_texture_float"); + return context->extensionsUtil()->supportsExtension("GL_OES_texture_float"); } const char* OESTextureFloat::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloat.h b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloat.h index 255c6741b11..dfc59086c48 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloat.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloat.h @@ -32,17 +32,17 @@ namespace WebCore { -class OESTextureFloat : public WebGLExtension, public ScriptWrappable { +class OESTextureFloat FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<OESTextureFloat> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<OESTextureFloat> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~OESTextureFloat(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - OESTextureFloat(WebGLRenderingContext*); + OESTextureFloat(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloatLinear.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloatLinear.cpp index 1e8518d95d6..15a7cd356a4 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloatLinear.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloatLinear.cpp @@ -27,35 +27,32 @@ #include "core/html/canvas/OESTextureFloatLinear.h" -#include "platform/graphics/Extensions3D.h" - namespace WebCore { -OESTextureFloatLinear::OESTextureFloatLinear(WebGLRenderingContext* context) +OESTextureFloatLinear::OESTextureFloatLinear(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_OES_texture_float_linear"); + context->extensionsUtil()->ensureExtensionEnabled("GL_OES_texture_float_linear"); } OESTextureFloatLinear::~OESTextureFloatLinear() { } -WebGLExtension::ExtensionName OESTextureFloatLinear::name() const +WebGLExtensionName OESTextureFloatLinear::name() const { return OESTextureFloatLinearName; } -PassRefPtr<OESTextureFloatLinear> OESTextureFloatLinear::create(WebGLRenderingContext* context) +PassRefPtr<OESTextureFloatLinear> OESTextureFloatLinear::create(WebGLRenderingContextBase* context) { return adoptRef(new OESTextureFloatLinear(context)); } -bool OESTextureFloatLinear::supported(WebGLRenderingContext* context) +bool OESTextureFloatLinear::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_OES_texture_float_linear"); + return context->extensionsUtil()->supportsExtension("GL_OES_texture_float_linear"); } const char* OESTextureFloatLinear::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloatLinear.h b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloatLinear.h index 4d7f8d1af53..a0646ccd3a7 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloatLinear.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureFloatLinear.h @@ -32,17 +32,17 @@ namespace WebCore { -class OESTextureFloatLinear : public WebGLExtension, public ScriptWrappable { +class OESTextureFloatLinear FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<OESTextureFloatLinear> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<OESTextureFloatLinear> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~OESTextureFloatLinear(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - OESTextureFloatLinear(WebGLRenderingContext*); + OESTextureFloatLinear(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloat.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloat.cpp index 7253837aa42..dd7f119c947 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloat.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloat.cpp @@ -26,35 +26,33 @@ #include "config.h" #include "core/html/canvas/OESTextureHalfFloat.h" -#include "platform/graphics/Extensions3D.h" namespace WebCore { -OESTextureHalfFloat::OESTextureHalfFloat(WebGLRenderingContext* context) +OESTextureHalfFloat::OESTextureHalfFloat(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_OES_texture_half_float"); + context->extensionsUtil()->ensureExtensionEnabled("GL_OES_texture_half_float"); } OESTextureHalfFloat::~OESTextureHalfFloat() { } -WebGLExtension::ExtensionName OESTextureHalfFloat::name() const +WebGLExtensionName OESTextureHalfFloat::name() const { return OESTextureHalfFloatName; } -PassRefPtr<OESTextureHalfFloat> OESTextureHalfFloat::create(WebGLRenderingContext* context) +PassRefPtr<OESTextureHalfFloat> OESTextureHalfFloat::create(WebGLRenderingContextBase* context) { return adoptRef(new OESTextureHalfFloat(context)); } -bool OESTextureHalfFloat::supported(WebGLRenderingContext* context) +bool OESTextureHalfFloat::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_OES_texture_half_float"); + return context->extensionsUtil()->supportsExtension("GL_OES_texture_half_float"); } const char* OESTextureHalfFloat::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloat.h b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloat.h index 953d3110f07..dc5d917a345 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloat.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloat.h @@ -32,17 +32,17 @@ namespace WebCore { -class OESTextureHalfFloat : public WebGLExtension, public ScriptWrappable { +class OESTextureHalfFloat FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<OESTextureHalfFloat> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<OESTextureHalfFloat> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~OESTextureHalfFloat(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - OESTextureHalfFloat(WebGLRenderingContext*); + OESTextureHalfFloat(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloatLinear.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloatLinear.cpp index c7da9bd745b..37ceabe5197 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloatLinear.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloatLinear.cpp @@ -27,35 +27,32 @@ #include "core/html/canvas/OESTextureHalfFloatLinear.h" -#include "platform/graphics/Extensions3D.h" - namespace WebCore { -OESTextureHalfFloatLinear::OESTextureHalfFloatLinear(WebGLRenderingContext* context) +OESTextureHalfFloatLinear::OESTextureHalfFloatLinear(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_OES_texture_half_float_linear"); + context->extensionsUtil()->ensureExtensionEnabled("GL_OES_texture_half_float_linear"); } OESTextureHalfFloatLinear::~OESTextureHalfFloatLinear() { } -WebGLExtension::ExtensionName OESTextureHalfFloatLinear::name() const +WebGLExtensionName OESTextureHalfFloatLinear::name() const { return OESTextureHalfFloatLinearName; } -PassRefPtr<OESTextureHalfFloatLinear> OESTextureHalfFloatLinear::create(WebGLRenderingContext* context) +PassRefPtr<OESTextureHalfFloatLinear> OESTextureHalfFloatLinear::create(WebGLRenderingContextBase* context) { return adoptRef(new OESTextureHalfFloatLinear(context)); } -bool OESTextureHalfFloatLinear::supported(WebGLRenderingContext* context) +bool OESTextureHalfFloatLinear::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_OES_texture_half_float_linear"); + return context->extensionsUtil()->supportsExtension("GL_OES_texture_half_float_linear"); } const char* OESTextureHalfFloatLinear::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloatLinear.h b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloatLinear.h index 17532033b45..421bbbca4d0 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloatLinear.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESTextureHalfFloatLinear.h @@ -32,17 +32,17 @@ namespace WebCore { -class OESTextureHalfFloatLinear : public WebGLExtension, public ScriptWrappable { +class OESTextureHalfFloatLinear FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<OESTextureHalfFloatLinear> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<OESTextureHalfFloatLinear> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~OESTextureHalfFloatLinear(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - OESTextureHalfFloatLinear(WebGLRenderingContext*); + OESTextureHalfFloatLinear(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.cpp index 848c85f5557..932195ed611 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.cpp @@ -28,29 +28,28 @@ #include "core/html/canvas/OESVertexArrayObject.h" #include "bindings/v8/ExceptionState.h" -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" #include "core/html/canvas/WebGLVertexArrayObjectOES.h" -#include "platform/graphics/Extensions3D.h" namespace WebCore { -OESVertexArrayObject::OESVertexArrayObject(WebGLRenderingContext* context) +OESVertexArrayObject::OESVertexArrayObject(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_OES_vertex_array_object"); + context->extensionsUtil()->ensureExtensionEnabled("GL_OES_vertex_array_object"); } OESVertexArrayObject::~OESVertexArrayObject() { } -WebGLExtension::ExtensionName OESVertexArrayObject::name() const +WebGLExtensionName OESVertexArrayObject::name() const { return OESVertexArrayObjectName; } -PassRefPtr<OESVertexArrayObject> OESVertexArrayObject::create(WebGLRenderingContext* context) +PassRefPtr<OESVertexArrayObject> OESVertexArrayObject::create(WebGLRenderingContextBase* context) { return adoptRef(new OESVertexArrayObject(context)); } @@ -58,7 +57,7 @@ PassRefPtr<OESVertexArrayObject> OESVertexArrayObject::create(WebGLRenderingCont PassRefPtr<WebGLVertexArrayObjectOES> OESVertexArrayObject::createVertexArrayOES() { if (isLost()) - return 0; + return nullptr; RefPtr<WebGLVertexArrayObjectOES> o = WebGLVertexArrayObjectOES::create(m_context, WebGLVertexArrayObjectOES::VaoTypeUser); m_context->addContextObject(o.get()); @@ -71,12 +70,12 @@ void OESVertexArrayObject::deleteVertexArrayOES(WebGLVertexArrayObjectOES* array return; if (!arrayObject->isDefaultObject() && arrayObject == m_context->m_boundVertexArrayObject) - m_context->setBoundVertexArrayObject(0); + m_context->setBoundVertexArrayObject(nullptr); - arrayObject->deleteObject(m_context->graphicsContext3D()); + arrayObject->deleteObject(m_context->webContext()); } -GC3Dboolean OESVertexArrayObject::isVertexArrayOES(WebGLVertexArrayObjectOES* arrayObject) +GLboolean OESVertexArrayObject::isVertexArrayOES(WebGLVertexArrayObjectOES* arrayObject) { if (!arrayObject || isLost()) return 0; @@ -84,8 +83,7 @@ GC3Dboolean OESVertexArrayObject::isVertexArrayOES(WebGLVertexArrayObjectOES* ar if (!arrayObject->hasEverBeenBound()) return 0; - Extensions3D* extensions = m_context->graphicsContext3D()->extensions(); - return extensions->isVertexArrayOES(arrayObject->object()); + return m_context->webContext()->isVertexArrayOES(arrayObject->object()); } void OESVertexArrayObject::bindVertexArrayOES(WebGLVertexArrayObjectOES* arrayObject) @@ -94,26 +92,24 @@ void OESVertexArrayObject::bindVertexArrayOES(WebGLVertexArrayObjectOES* arrayOb return; if (arrayObject && (arrayObject->isDeleted() || !arrayObject->validate(0, context()))) { - m_context->graphicsContext3D()->synthesizeGLError(GL_INVALID_OPERATION); + m_context->webContext()->synthesizeGLError(GL_INVALID_OPERATION); return; } - Extensions3D* extensions = m_context->graphicsContext3D()->extensions(); if (arrayObject && !arrayObject->isDefaultObject() && arrayObject->object()) { - extensions->bindVertexArrayOES(arrayObject->object()); + m_context->webContext()->bindVertexArrayOES(arrayObject->object()); arrayObject->setHasEverBeenBound(); m_context->setBoundVertexArrayObject(arrayObject); } else { - extensions->bindVertexArrayOES(0); - m_context->setBoundVertexArrayObject(0); + m_context->webContext()->bindVertexArrayOES(0); + m_context->setBoundVertexArrayObject(nullptr); } } -bool OESVertexArrayObject::supported(WebGLRenderingContext* context) +bool OESVertexArrayObject::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_OES_vertex_array_object"); + return context->extensionsUtil()->supportsExtension("GL_OES_vertex_array_object"); } const char* OESVertexArrayObject::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.h b/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.h index 2fd0735f21a..3f616be0575 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.h @@ -28,30 +28,29 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/html/canvas/WebGLExtension.h" -#include "platform/graphics/GraphicsTypes3D.h" #include "wtf/PassRefPtr.h" namespace WebCore { -class WebGLRenderingContext; +class WebGLRenderingContextBase; class WebGLVertexArrayObjectOES; -class OESVertexArrayObject : public WebGLExtension, public ScriptWrappable { +class OESVertexArrayObject FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<OESVertexArrayObject> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<OESVertexArrayObject> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~OESVertexArrayObject(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; PassRefPtr<WebGLVertexArrayObjectOES> createVertexArrayOES(); void deleteVertexArrayOES(WebGLVertexArrayObjectOES*); - GC3Dboolean isVertexArrayOES(WebGLVertexArrayObjectOES*); + GLboolean isVertexArrayOES(WebGLVertexArrayObjectOES*); void bindVertexArrayOES(WebGLVertexArrayObjectOES*); private: - OESVertexArrayObject(WebGLRenderingContext*); + OESVertexArrayObject(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.idl b/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.idl index aa9a16d6377..5a21f238d79 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.idl +++ b/chromium/third_party/WebKit/Source/core/html/canvas/OESVertexArrayObject.idl @@ -24,13 +24,14 @@ */ [ + DoNotCheckConstants, NoInterfaceObject, - DoNotCheckConstants + TypeChecking=Interface|Nullable, ] interface OESVertexArrayObject { const unsigned long 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] void bindVertexArrayOES([Default=Undefined] optional WebGLVertexArrayObjectOES arrayObject); + WebGLVertexArrayObjectOES createVertexArrayOES(); + void deleteVertexArrayOES([Default=Undefined] optional WebGLVertexArrayObjectOES? arrayObject); + boolean isVertexArrayOES([Default=Undefined] optional WebGLVertexArrayObjectOES? arrayObject); + void bindVertexArrayOES([Default=Undefined] optional WebGLVertexArrayObjectOES? arrayObject); }; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/Path.idl b/chromium/third_party/WebKit/Source/core/html/canvas/Path.idl deleted file mode 100644 index 66435a5da46..00000000000 --- a/chromium/third_party/WebKit/Source/core/html/canvas/Path.idl +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, 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 - * 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. - */ - -[ - RuntimeEnabled=ExperimentalCanvasFeatures, - Constructor, - Constructor(Path path), - Constructor(DOMString text), - ImplementedAs=DOMPath -] interface Path { - - // 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); -}; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/DOMPath.h b/chromium/third_party/WebKit/Source/core/html/canvas/Path2D.h index 9ce2cba9512..f09839bb1e9 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/DOMPath.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/Path2D.h @@ -25,50 +25,60 @@ * SUCH DAMAGE. */ -#ifndef DOMPath_h -#define DOMPath_h +#ifndef Path2D_h +#define Path2D_h #include "bindings/v8/ScriptWrappable.h" #include "core/html/canvas/CanvasPathMethods.h" +#include "core/svg/SVGMatrixTearOff.h" #include "core/svg/SVGPathUtilities.h" +#include "platform/transforms/AffineTransform.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" namespace WebCore { -class DOMPath : public RefCounted<DOMPath>, public CanvasPathMethods, public ScriptWrappable { - WTF_MAKE_NONCOPYABLE(DOMPath); WTF_MAKE_FAST_ALLOCATED; +class Path2D FINAL : public RefCounted<Path2D>, public CanvasPathMethods, public ScriptWrappable { + WTF_MAKE_NONCOPYABLE(Path2D); WTF_MAKE_FAST_ALLOCATED; public: - static PassRefPtr<DOMPath> create() { return adoptRef(new DOMPath); } - static PassRefPtr<DOMPath> create(const String& pathData) { return adoptRef(new DOMPath(pathData)); } - static PassRefPtr<DOMPath> create(DOMPath* path) { return adoptRef(new DOMPath(path)); } + static PassRefPtr<Path2D> create() { return adoptRef(new Path2D); } + static PassRefPtr<Path2D> create(const String& pathData) { return adoptRef(new Path2D(pathData)); } + static PassRefPtr<Path2D> create(Path2D* path) { return adoptRef(new Path2D(path)); } - static PassRefPtr<DOMPath> create(const Path& path) { return adoptRef(new DOMPath(path)); } + static PassRefPtr<Path2D> create(const Path& path) { return adoptRef(new Path2D(path)); } const Path& path() const { return m_path; } - virtual ~DOMPath() { } + void addPath(Path2D* path) + { + addPath(path, 0); + } + + void addPath(Path2D* path, SVGMatrixTearOff* transform) + { + Path src = path->path(); + m_path.addPath(src, transform ? transform->value() : AffineTransform(1, 0, 0, 1, 0, 0)); + } + virtual ~Path2D() { } private: - DOMPath() : CanvasPathMethods() + Path2D() : CanvasPathMethods() { ScriptWrappable::init(this); } - DOMPath(const Path& path) - : CanvasPathMethods() + Path2D(const Path& path) + : CanvasPathMethods(path) { ScriptWrappable::init(this); - m_path = path; } - DOMPath(DOMPath* path) - : CanvasPathMethods() + Path2D(Path2D* path) + : CanvasPathMethods(path->path()) { ScriptWrappable::init(this); - m_path = path->path(); } - DOMPath(const String& pathData) + Path2D(const String& pathData) : CanvasPathMethods() { ScriptWrappable::init(this); diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/Path2D.idl b/chromium/third_party/WebKit/Source/core/html/canvas/Path2D.idl new file mode 100644 index 00000000000..262148560a2 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/Path2D.idl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 + * 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. + */ + +// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#path2d + +[ + Constructor, + Constructor(Path2D path), + Constructor(DOMString text), + RuntimeEnabled=Path2D, +] interface Path2D { + + [RuntimeEnabled=ExperimentalCanvasFeatures, TypeChecking=Interface|Nullable] void addPath(Path2D path, optional SVGMatrix? transform); +}; + +Path2D implements CanvasPathMethods; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLActiveInfo.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLActiveInfo.h index 7571e3681ec..b1c983484b3 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLActiveInfo.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLActiveInfo.h @@ -27,7 +27,7 @@ #define WebGLActiveInfo_h #include "bindings/v8/ScriptWrappable.h" -#include "platform/graphics/GraphicsContext3D.h" +#include "platform/graphics/GraphicsTypes3D.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" #include "wtf/text/WTFString.h" @@ -36,16 +36,16 @@ namespace WebCore { class WebGLActiveInfo : public RefCounted<WebGLActiveInfo>, public ScriptWrappable { public: - static PassRefPtr<WebGLActiveInfo> create(const String& name, GC3Denum type, GC3Dint size) + static PassRefPtr<WebGLActiveInfo> create(const String& name, GLenum type, GLint size) { return adoptRef(new WebGLActiveInfo(name, type, size)); } String name() const { return m_name; } - GC3Denum type() const { return m_type; } - GC3Dint size() const { return m_size; } + GLenum type() const { return m_type; } + GLint size() const { return m_size; } private: - WebGLActiveInfo(const String& name, GC3Denum type, GC3Dint size) + WebGLActiveInfo(const String& name, GLenum type, GLint size) : m_name(name) , m_type(type) , m_size(size) @@ -56,8 +56,8 @@ private: ScriptWrappable::init(this); } String m_name; - GC3Denum m_type; - GC3Dint m_size; + GLenum m_type; + GLint m_size; }; } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLBuffer.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLBuffer.cpp index 48bf88a1ab0..6308eccf192 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLBuffer.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLBuffer.cpp @@ -27,21 +27,21 @@ #include "core/html/canvas/WebGLBuffer.h" -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -PassRefPtr<WebGLBuffer> WebGLBuffer::create(WebGLRenderingContext* ctx) +PassRefPtr<WebGLBuffer> WebGLBuffer::create(WebGLRenderingContextBase* ctx) { return adoptRef(new WebGLBuffer(ctx)); } -WebGLBuffer::WebGLBuffer(WebGLRenderingContext* ctx) +WebGLBuffer::WebGLBuffer(WebGLRenderingContextBase* ctx) : WebGLSharedObject(ctx) , m_target(0) { ScriptWrappable::init(this); - setObject(ctx->graphicsContext3D()->createBuffer()); + setObject(ctx->webContext()->createBuffer()); } WebGLBuffer::~WebGLBuffer() @@ -49,12 +49,12 @@ WebGLBuffer::~WebGLBuffer() deleteObject(0); } -void WebGLBuffer::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object) +void WebGLBuffer::deleteObjectImpl(blink::WebGraphicsContext3D* context3d, Platform3DObject object) { context3d->deleteBuffer(object); } -void WebGLBuffer::setTarget(GC3Denum target) +void WebGLBuffer::setTarget(GLenum target) { // In WebGL, a buffer is bound to one target in its lifetime if (m_target) diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLBuffer.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLBuffer.h index 8483685f58c..9f596be4c8a 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLBuffer.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLBuffer.h @@ -33,26 +33,26 @@ namespace WebCore { -class WebGLBuffer : public WebGLSharedObject, public ScriptWrappable { +class WebGLBuffer FINAL : public WebGLSharedObject, public ScriptWrappable { public: virtual ~WebGLBuffer(); - static PassRefPtr<WebGLBuffer> create(WebGLRenderingContext*); + static PassRefPtr<WebGLBuffer> create(WebGLRenderingContextBase*); - GC3Denum getTarget() const { return m_target; } - void setTarget(GC3Denum); + GLenum getTarget() const { return m_target; } + void setTarget(GLenum); bool hasEverBeenBound() const { return object() && m_target; } protected: - WebGLBuffer(WebGLRenderingContext*); + WebGLBuffer(WebGLRenderingContextBase*); - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject); + virtual void deleteObjectImpl(blink::WebGraphicsContext3D*, Platform3DObject) OVERRIDE; private: - virtual bool isBuffer() const { return true; } + virtual bool isBuffer() const OVERRIDE { return true; } - GC3Denum m_target; + GLenum m_target; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureATC.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureATC.cpp index dad7ff49b05..3bfd7d8f0b1 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureATC.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureATC.cpp @@ -27,37 +27,34 @@ #include "core/html/canvas/WebGLCompressedTextureATC.h" -#include "platform/graphics/Extensions3D.h" - namespace WebCore { -WebGLCompressedTextureATC::WebGLCompressedTextureATC(WebGLRenderingContext* context) +WebGLCompressedTextureATC::WebGLCompressedTextureATC(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - 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(GC3D_COMPRESSED_ATC_RGB_AMD); + context->addCompressedTextureFormat(GC3D_COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD); + context->addCompressedTextureFormat(GC3D_COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD); } WebGLCompressedTextureATC::~WebGLCompressedTextureATC() { } -WebGLExtension::ExtensionName WebGLCompressedTextureATC::name() const +WebGLExtensionName WebGLCompressedTextureATC::name() const { return WebGLCompressedTextureATCName; } -PassRefPtr<WebGLCompressedTextureATC> WebGLCompressedTextureATC::create(WebGLRenderingContext* context) +PassRefPtr<WebGLCompressedTextureATC> WebGLCompressedTextureATC::create(WebGLRenderingContextBase* context) { return adoptRef(new WebGLCompressedTextureATC(context)); } -bool WebGLCompressedTextureATC::supported(WebGLRenderingContext* context) +bool WebGLCompressedTextureATC::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_AMD_compressed_ATC_texture"); + return context->extensionsUtil()->supportsExtension("GL_AMD_compressed_ATC_texture"); } const char* WebGLCompressedTextureATC::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureATC.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureATC.h index eb49bc4bfe8..069fe145bd0 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureATC.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureATC.h @@ -34,17 +34,17 @@ namespace WebCore { class WebGLTexture; -class WebGLCompressedTextureATC : public WebGLExtension, public ScriptWrappable { +class WebGLCompressedTextureATC FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<WebGLCompressedTextureATC> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<WebGLCompressedTextureATC> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~WebGLCompressedTextureATC(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - WebGLCompressedTextureATC(WebGLRenderingContext*); + WebGLCompressedTextureATC(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureETC1.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureETC1.cpp new file mode 100644 index 00000000000..a2abde855a3 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureETC1.cpp @@ -0,0 +1,45 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#include "core/html/canvas/WebGLCompressedTextureETC1.h" + +#include "core/html/canvas/WebGLRenderingContextBase.h" + +namespace WebCore { + +WebGLCompressedTextureETC1::WebGLCompressedTextureETC1(WebGLRenderingContextBase* context) + : WebGLExtension(context) +{ + ScriptWrappable::init(this); + context->addCompressedTextureFormat(GL_ETC1_RGB8_OES); +} + +WebGLCompressedTextureETC1::~WebGLCompressedTextureETC1() +{ +} + +WebGLExtensionName WebGLCompressedTextureETC1::name() const +{ + return WebGLCompressedTextureETC1Name; +} + +PassRefPtr<WebGLCompressedTextureETC1> WebGLCompressedTextureETC1::create(WebGLRenderingContextBase* context) +{ + return adoptRef(new WebGLCompressedTextureETC1(context)); +} + +bool WebGLCompressedTextureETC1::supported(WebGLRenderingContextBase* context) +{ + Extensions3DUtil* extensionsUtil = context->extensionsUtil(); + return extensionsUtil->supportsExtension("GL_OES_compressed_ETC1_RGB8_texture"); +} + +const char* WebGLCompressedTextureETC1::extensionName() +{ + return "WEBGL_compressed_texture_etc1"; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureETC1.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureETC1.h new file mode 100644 index 00000000000..4cf3a57ed74 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureETC1.h @@ -0,0 +1,31 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebGLCompressedTextureETC1_h +#define WebGLCompressedTextureETC1_h + +#include "bindings/v8/ScriptWrappable.h" +#include "core/html/canvas/WebGLExtension.h" +#include "wtf/PassRefPtr.h" + +namespace WebCore { + +class WebGLTexture; + +class WebGLCompressedTextureETC1 FINAL : public WebGLExtension, public ScriptWrappable { +public: + static PassRefPtr<WebGLCompressedTextureETC1> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); + static const char* extensionName(); + + virtual ~WebGLCompressedTextureETC1(); + virtual WebGLExtensionName name() const OVERRIDE; + +private: + WebGLCompressedTextureETC1(WebGLRenderingContextBase*); +}; + +} // namespace WebCore + +#endif // WebGLCompressedTextureETC1_h diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureETC1.idl b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureETC1.idl new file mode 100644 index 00000000000..e37d990cb6d --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureETC1.idl @@ -0,0 +1,11 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + NoInterfaceObject, + DoNotCheckConstants +] interface WebGLCompressedTextureETC1 { + /* Compressed Texture Formats */ + const unsigned long COMPRESSED_RGB_ETC1_WEBGL = 0x8D64; +}; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTexturePVRTC.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTexturePVRTC.cpp index 8ae4acd2689..d1586ff22d6 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTexturePVRTC.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTexturePVRTC.cpp @@ -27,39 +27,37 @@ #include "core/html/canvas/WebGLCompressedTexturePVRTC.h" -#include "core/html/canvas/WebGLRenderingContext.h" -#include "platform/graphics/Extensions3D.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -WebGLCompressedTexturePVRTC::WebGLCompressedTexturePVRTC(WebGLRenderingContext* context) +WebGLCompressedTexturePVRTC::WebGLCompressedTexturePVRTC(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - 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(GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG); + context->addCompressedTextureFormat(GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG); + context->addCompressedTextureFormat(GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG); + context->addCompressedTextureFormat(GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG); } WebGLCompressedTexturePVRTC::~WebGLCompressedTexturePVRTC() { } -WebGLExtension::ExtensionName WebGLCompressedTexturePVRTC::name() const +WebGLExtensionName WebGLCompressedTexturePVRTC::name() const { return WebGLCompressedTexturePVRTCName; } -PassRefPtr<WebGLCompressedTexturePVRTC> WebGLCompressedTexturePVRTC::create(WebGLRenderingContext* context) +PassRefPtr<WebGLCompressedTexturePVRTC> WebGLCompressedTexturePVRTC::create(WebGLRenderingContextBase* context) { return adoptRef(new WebGLCompressedTexturePVRTC(context)); } -bool WebGLCompressedTexturePVRTC::supported(WebGLRenderingContext* context) +bool WebGLCompressedTexturePVRTC::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_IMG_texture_compression_pvrtc"); + return context->extensionsUtil()->supportsExtension("GL_IMG_texture_compression_pvrtc"); } const char* WebGLCompressedTexturePVRTC::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTexturePVRTC.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTexturePVRTC.h index dc28e5f9522..27cde75bca7 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTexturePVRTC.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTexturePVRTC.h @@ -32,17 +32,17 @@ namespace WebCore { -class WebGLCompressedTexturePVRTC : public WebGLExtension, public ScriptWrappable { +class WebGLCompressedTexturePVRTC FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<WebGLCompressedTexturePVRTC> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<WebGLCompressedTexturePVRTC> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~WebGLCompressedTexturePVRTC(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - WebGLCompressedTexturePVRTC(WebGLRenderingContext*); + WebGLCompressedTexturePVRTC(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureS3TC.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureS3TC.cpp index 9d3f2543001..35834cc91ff 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureS3TC.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureS3TC.cpp @@ -27,42 +27,41 @@ #include "core/html/canvas/WebGLCompressedTextureS3TC.h" -#include "core/html/canvas/WebGLRenderingContext.h" -#include "platform/graphics/Extensions3D.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -WebGLCompressedTextureS3TC::WebGLCompressedTextureS3TC(WebGLRenderingContext* context) +WebGLCompressedTextureS3TC::WebGLCompressedTextureS3TC(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - 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(GL_COMPRESSED_RGB_S3TC_DXT1_EXT); + context->addCompressedTextureFormat(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); + context->addCompressedTextureFormat(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT); + context->addCompressedTextureFormat(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT); } WebGLCompressedTextureS3TC::~WebGLCompressedTextureS3TC() { } -WebGLExtension::ExtensionName WebGLCompressedTextureS3TC::name() const +WebGLExtensionName WebGLCompressedTextureS3TC::name() const { return WebGLCompressedTextureS3TCName; } -PassRefPtr<WebGLCompressedTextureS3TC> WebGLCompressedTextureS3TC::create(WebGLRenderingContext* context) +PassRefPtr<WebGLCompressedTextureS3TC> WebGLCompressedTextureS3TC::create(WebGLRenderingContextBase* context) { return adoptRef(new WebGLCompressedTextureS3TC(context)); } -bool WebGLCompressedTextureS3TC::supported(WebGLRenderingContext* context) +bool WebGLCompressedTextureS3TC::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - 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")); + Extensions3DUtil* extensionsUtil = context->extensionsUtil(); + return extensionsUtil->supportsExtension("GL_EXT_texture_compression_s3tc") + || (extensionsUtil->supportsExtension("GL_EXT_texture_compression_dxt1") + && extensionsUtil->supportsExtension("GL_CHROMIUM_texture_compression_dxt3") + && extensionsUtil->supportsExtension("GL_CHROMIUM_texture_compression_dxt5")); } const char* WebGLCompressedTextureS3TC::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureS3TC.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureS3TC.h index 615f4f587fb..aaed4a7764c 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureS3TC.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLCompressedTextureS3TC.h @@ -34,17 +34,17 @@ namespace WebCore { class WebGLTexture; -class WebGLCompressedTextureS3TC : public WebGLExtension, public ScriptWrappable { +class WebGLCompressedTextureS3TC FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<WebGLCompressedTextureS3TC> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<WebGLCompressedTextureS3TC> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~WebGLCompressedTextureS3TC(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - WebGLCompressedTextureS3TC(WebGLRenderingContext*); + WebGLCompressedTextureS3TC(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextAttributes.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextAttributes.cpp index cb26556a731..385720617fd 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextAttributes.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextAttributes.cpp @@ -28,6 +28,8 @@ #include "core/html/canvas/WebGLContextAttributes.h" +#include "core/frame/Settings.h" + namespace WebCore { PassRefPtr<WebGLContextAttributes> WebGLContextAttributes::create() @@ -35,20 +37,28 @@ PassRefPtr<WebGLContextAttributes> WebGLContextAttributes::create() return adoptRef(new WebGLContextAttributes()); } -PassRefPtr<WebGLContextAttributes> WebGLContextAttributes::create(GraphicsContext3D::Attributes attributes) -{ - return adoptRef(new WebGLContextAttributes(attributes)); -} - WebGLContextAttributes::WebGLContextAttributes() : CanvasContextAttributes() + , m_alpha(true) + , m_depth(true) + , m_stencil(false) + , m_antialias(true) + , m_premultipliedAlpha(true) + , m_preserveDrawingBuffer(false) + , m_failIfMajorPerformanceCaveat(false) { ScriptWrappable::init(this); } -WebGLContextAttributes::WebGLContextAttributes(GraphicsContext3D::Attributes attributes) +WebGLContextAttributes::WebGLContextAttributes(const WebGLContextAttributes& attrs) : CanvasContextAttributes() - , m_attrs(attributes) + , m_alpha(attrs.m_alpha) + , m_depth(attrs.m_depth) + , m_stencil(attrs.m_stencil) + , m_antialias(attrs.m_antialias) + , m_premultipliedAlpha(attrs.m_premultipliedAlpha) + , m_preserveDrawingBuffer(attrs.m_preserveDrawingBuffer) + , m_failIfMajorPerformanceCaveat(attrs.m_failIfMajorPerformanceCaveat) { ScriptWrappable::init(this); } @@ -57,79 +67,104 @@ WebGLContextAttributes::~WebGLContextAttributes() { } +PassRefPtr<WebGLContextAttributes> WebGLContextAttributes::clone() const +{ + return adoptRef(new WebGLContextAttributes(*this)); +} + bool WebGLContextAttributes::alpha() const { - return m_attrs.alpha; + return m_alpha; } void WebGLContextAttributes::setAlpha(bool alpha) { - m_attrs.alpha = alpha; + m_alpha = alpha; } bool WebGLContextAttributes::depth() const { - return m_attrs.depth; + return m_depth; } void WebGLContextAttributes::setDepth(bool depth) { - m_attrs.depth = depth; + m_depth = depth; } bool WebGLContextAttributes::stencil() const { - return m_attrs.stencil; + return m_stencil; } void WebGLContextAttributes::setStencil(bool stencil) { - m_attrs.stencil = stencil; + m_stencil = stencil; } bool WebGLContextAttributes::antialias() const { - return m_attrs.antialias; + return m_antialias; } void WebGLContextAttributes::setAntialias(bool antialias) { - m_attrs.antialias = antialias; + m_antialias = antialias; } bool WebGLContextAttributes::premultipliedAlpha() const { - return m_attrs.premultipliedAlpha; + return m_premultipliedAlpha; } void WebGLContextAttributes::setPremultipliedAlpha(bool premultipliedAlpha) { - m_attrs.premultipliedAlpha = premultipliedAlpha; + m_premultipliedAlpha = premultipliedAlpha; } bool WebGLContextAttributes::preserveDrawingBuffer() const { - return m_attrs.preserveDrawingBuffer; + return m_preserveDrawingBuffer; } void WebGLContextAttributes::setPreserveDrawingBuffer(bool preserveDrawingBuffer) { - m_attrs.preserveDrawingBuffer = preserveDrawingBuffer; + m_preserveDrawingBuffer = preserveDrawingBuffer; } bool WebGLContextAttributes::failIfMajorPerformanceCaveat() const { - return m_attrs.failIfMajorPerformanceCaveat; + return m_failIfMajorPerformanceCaveat; } void WebGLContextAttributes::setFailIfMajorPerformanceCaveat(bool failIfMajorPerformanceCaveat) { - m_attrs.failIfMajorPerformanceCaveat = failIfMajorPerformanceCaveat; + m_failIfMajorPerformanceCaveat = failIfMajorPerformanceCaveat; } -GraphicsContext3D::Attributes WebGLContextAttributes::attributes() const +blink::WebGraphicsContext3D::Attributes WebGLContextAttributes::attributes( + const blink::WebString& topDocumentURL, Settings* settings) const { - return m_attrs; + blink::WebGraphicsContext3D::Attributes attrs; + + attrs.alpha = m_alpha; + attrs.depth = m_depth; + attrs.stencil = m_stencil; + attrs.antialias = m_antialias; + if (m_antialias) { + if (settings && !settings->openGLMultisamplingEnabled()) + attrs.antialias = false; + } + attrs.premultipliedAlpha = m_premultipliedAlpha; + attrs.failIfMajorPerformanceCaveat = m_failIfMajorPerformanceCaveat; + + attrs.noExtensions = true; + attrs.shareResources = false; + attrs.preferDiscreteGPU = true; + + attrs.topDocumentURL = topDocumentURL; + + return attrs; } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextAttributes.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextAttributes.h index 62a576ef736..eeee443e2fa 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextAttributes.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextAttributes.h @@ -29,42 +29,44 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/html/canvas/CanvasContextAttributes.h" -#include "platform/graphics/GraphicsContext3D.h" +#include "public/platform/WebGraphicsContext3D.h" #include "wtf/PassRefPtr.h" namespace WebCore { -class WebGLContextAttributes : public CanvasContextAttributes, public ScriptWrappable { +class Settings; + +class WebGLContextAttributes FINAL : public CanvasContextAttributes, public ScriptWrappable { 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); + // Create a copy of this object. + PassRefPtr<WebGLContextAttributes> clone() const; // Whether or not the drawing buffer has an alpha channel; default=true bool alpha() const; - void setAlpha(bool alpha); + void setAlpha(bool); // Whether or not the drawing buffer has a depth buffer; default=true bool depth() const; - void setDepth(bool depth); + void setDepth(bool); - // Whether or not the drawing buffer has a stencil buffer; default=true + // Whether or not the drawing buffer has a stencil buffer; default=false bool stencil() const; - void setStencil(bool stencil); + void setStencil(bool); // Whether or not the drawing buffer is antialiased; default=true bool antialias() const; - void setAntialias(bool antialias); + void setAntialias(bool); // 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); + void setPremultipliedAlpha(bool); // Whether or not to preserve the drawing buffer after presentation to the // screen; default=false @@ -76,16 +78,23 @@ public: bool failIfMajorPerformanceCaveat() const; void setFailIfMajorPerformanceCaveat(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; + // Set up the attributes that can be used to initialize a WebGraphicsContext3D. + // It's mostly based on WebGLContextAttributes, but would be adjusted based + // on settings. + blink::WebGraphicsContext3D::Attributes attributes(const blink::WebString&, Settings*) const; protected: WebGLContextAttributes(); - WebGLContextAttributes(GraphicsContext3D::Attributes attributes); + WebGLContextAttributes(const WebGLContextAttributes&); private: - GraphicsContext3D::Attributes m_attrs; + bool m_alpha; + bool m_depth; + bool m_stencil; + bool m_antialias; + bool m_premultipliedAlpha; + bool m_preserveDrawingBuffer; + bool m_failIfMajorPerformanceCaveat; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextEvent.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextEvent.cpp index 7f4cf7c7576..f26e8441ea3 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextEvent.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextEvent.cpp @@ -26,8 +26,6 @@ #include "config.h" #include "core/html/canvas/WebGLContextEvent.h" -#include "core/events/ThreadLocalEventNames.h" - namespace WebCore { WebGLContextEventInit::WebGLContextEventInit() @@ -62,4 +60,9 @@ const AtomicString& WebGLContextEvent::interfaceName() const return EventNames::WebGLContextEvent; } +void WebGLContextEvent::trace(Visitor* visitor) +{ + Event::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextEvent.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextEvent.h index 18f4a4812f9..0bd83808671 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextEvent.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextEvent.h @@ -36,25 +36,27 @@ struct WebGLContextEventInit : public EventInit { String statusMessage; }; -class WebGLContextEvent : public Event { +class WebGLContextEvent FINAL : public Event { public: - static PassRefPtr<WebGLContextEvent> create() + static PassRefPtrWillBeRawPtr<WebGLContextEvent> create() { - return adoptRef(new WebGLContextEvent); + return adoptRefWillBeNoop(new WebGLContextEvent); } - static PassRefPtr<WebGLContextEvent> create(const AtomicString& type, bool canBubble, bool cancelable, const String& statusMessage) + static PassRefPtrWillBeRawPtr<WebGLContextEvent> create(const AtomicString& type, bool canBubble, bool cancelable, const String& statusMessage) { - return adoptRef(new WebGLContextEvent(type, canBubble, cancelable, statusMessage)); + return adoptRefWillBeNoop(new WebGLContextEvent(type, canBubble, cancelable, statusMessage)); } - static PassRefPtr<WebGLContextEvent> create(const AtomicString& type, const WebGLContextEventInit& initializer) + static PassRefPtrWillBeRawPtr<WebGLContextEvent> create(const AtomicString& type, const WebGLContextEventInit& initializer) { - return adoptRef(new WebGLContextEvent(type, initializer)); + return adoptRefWillBeNoop(new WebGLContextEvent(type, initializer)); } virtual ~WebGLContextEvent(); const String& statusMessage() const { return m_statusMessage; } - virtual const AtomicString& interfaceName() const; + virtual const AtomicString& interfaceName() const OVERRIDE; + + virtual void trace(Visitor*) OVERRIDE; private: WebGLContextEvent(); diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextGroup.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextGroup.cpp index 93ff6f4f4f1..e9e3ebe267e 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextGroup.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextGroup.cpp @@ -46,19 +46,19 @@ WebGLContextGroup::~WebGLContextGroup() detachAndRemoveAllObjects(); } -GraphicsContext3D* WebGLContextGroup::getAGraphicsContext3D() +blink::WebGraphicsContext3D* WebGLContextGroup::getAWebGraphicsContext3D() { ASSERT(!m_contexts.isEmpty()); - HashSet<WebGLRenderingContext*>::iterator it = m_contexts.begin(); - return (*it)->graphicsContext3D(); + HashSet<WebGLRenderingContextBase*>::iterator it = m_contexts.begin(); + return (*it)->webContext(); } -void WebGLContextGroup::addContext(WebGLRenderingContext* context) +void WebGLContextGroup::addContext(WebGLRenderingContextBase* 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)) @@ -85,13 +85,13 @@ void WebGLContextGroup::detachAndRemoveAllObjects() } } -void WebGLContextGroup::loseContextGroup(WebGLRenderingContext::LostContextMode mode) +void WebGLContextGroup::loseContextGroup(WebGLRenderingContextBase::LostContextMode mode) { // Detach must happen before loseContextImpl, which destroys the GraphicsContext3D // and prevents groupObjects from being properly deleted. detachAndRemoveAllObjects(); - for (HashSet<WebGLRenderingContext*>::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it) + for (HashSet<WebGLRenderingContextBase*>::iterator it = m_contexts.begin(); it != m_contexts.end(); ++it) (*it)->loseContextImpl(mode); } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextGroup.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextGroup.h index b1fece9111b..6c2f9953540 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextGroup.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextGroup.h @@ -26,17 +26,20 @@ #ifndef WebGLContextGroup_h #define WebGLContextGroup_h -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" #include "wtf/HashSet.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" +namespace blink { +class WebGraphicsContext3D; +} + namespace WebCore { -class GraphicsContext3D; class WebGLExtension; class WebGLSharedObject; -class WebGLRenderingContext; +class WebGLRenderingContextBase; typedef int ExceptionCode; @@ -45,15 +48,15 @@ public: static PassRefPtr<WebGLContextGroup> create(); ~WebGLContextGroup(); - void addContext(WebGLRenderingContext*); - void removeContext(WebGLRenderingContext*); + void addContext(WebGLRenderingContextBase*); + void removeContext(WebGLRenderingContextBase*); void addObject(WebGLSharedObject*); void removeObject(WebGLSharedObject*); - GraphicsContext3D* getAGraphicsContext3D(); + blink::WebGraphicsContext3D* getAWebGraphicsContext3D(); - void loseContextGroup(WebGLRenderingContext::LostContextMode); + void loseContextGroup(WebGLRenderingContextBase::LostContextMode); private: friend class WebGLObject; @@ -62,7 +65,7 @@ public: void detachAndRemoveAllObjects(); - HashSet<WebGLRenderingContext*> m_contexts; + HashSet<WebGLRenderingContextBase*> m_contexts; HashSet<WebGLSharedObject*> m_groupObjects; }; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextObject.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextObject.cpp index ea718c51e7a..83441589def 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextObject.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextObject.cpp @@ -27,11 +27,11 @@ #include "core/html/canvas/WebGLContextObject.h" -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -WebGLContextObject::WebGLContextObject(WebGLRenderingContext* context) +WebGLContextObject::WebGLContextObject(WebGLRenderingContextBase* context) : WebGLObject(context) , m_context(context) { @@ -47,15 +47,15 @@ void WebGLContextObject::detachContext() { detach(); if (m_context) { - deleteObject(m_context->graphicsContext3D()); + deleteObject(m_context->webContext()); m_context->removeContextObject(this); m_context = 0; } } -GraphicsContext3D* WebGLContextObject::getAGraphicsContext3D() const +blink::WebGraphicsContext3D* WebGLContextObject::getAWebGraphicsContext3D() const { - return m_context ? m_context->graphicsContext3D() : 0; + return m_context ? m_context->webContext() : 0; } } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextObject.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextObject.h index 1e4d2965754..21be7a53d8a 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextObject.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLContextObject.h @@ -28,20 +28,23 @@ #include "core/html/canvas/WebGLObject.h" +namespace blink { +class WebGraphicsContext3D; +} + namespace WebCore { -class GraphicsContext3D; -class WebGLRenderingContext; +class WebGLRenderingContextBase; // WebGLContextObject the base class for objects that are owned by a specific -// WebGLRenderingContext. +// WebGLRenderingContextBase. 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 + virtual bool validate(const WebGLContextGroup*, const WebGLRenderingContextBase* context) const OVERRIDE FINAL { return context == m_context; } @@ -49,17 +52,17 @@ public: void detachContext(); protected: - WebGLContextObject(WebGLRenderingContext*); + WebGLContextObject(WebGLRenderingContextBase*); - virtual bool hasGroupOrContext() const + virtual bool hasGroupOrContext() const OVERRIDE FINAL { return m_context; } - virtual GraphicsContext3D* getAGraphicsContext3D() const; + virtual blink::WebGraphicsContext3D* getAWebGraphicsContext3D() const OVERRIDE FINAL; private: - WebGLRenderingContext* m_context; + WebGLRenderingContextBase* m_context; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugRendererInfo.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugRendererInfo.cpp index bca809a7c0e..cc61d268de1 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugRendererInfo.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugRendererInfo.cpp @@ -29,7 +29,7 @@ namespace WebCore { -WebGLDebugRendererInfo::WebGLDebugRendererInfo(WebGLRenderingContext* context) +WebGLDebugRendererInfo::WebGLDebugRendererInfo(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); @@ -39,17 +39,17 @@ WebGLDebugRendererInfo::~WebGLDebugRendererInfo() { } -WebGLExtension::ExtensionName WebGLDebugRendererInfo::name() const +WebGLExtensionName WebGLDebugRendererInfo::name() const { return WebGLDebugRendererInfoName; } -PassRefPtr<WebGLDebugRendererInfo> WebGLDebugRendererInfo::create(WebGLRenderingContext* context) +PassRefPtr<WebGLDebugRendererInfo> WebGLDebugRendererInfo::create(WebGLRenderingContextBase* context) { return adoptRef(new WebGLDebugRendererInfo(context)); } -bool WebGLDebugRendererInfo::supported(WebGLRenderingContext*) +bool WebGLDebugRendererInfo::supported(WebGLRenderingContextBase*) { return true; } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugRendererInfo.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugRendererInfo.h index 2baa7abe337..8863aeb30f5 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugRendererInfo.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugRendererInfo.h @@ -32,22 +32,22 @@ namespace WebCore { -class WebGLDebugRendererInfo : public WebGLExtension, public ScriptWrappable { +class WebGLDebugRendererInfo FINAL : public WebGLExtension, public ScriptWrappable { public: enum EnumType { UNMASKED_VENDOR_WEBGL = 0x9245, UNMASKED_RENDERER_WEBGL = 0x9246 }; - static PassRefPtr<WebGLDebugRendererInfo> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<WebGLDebugRendererInfo> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~WebGLDebugRendererInfo(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - WebGLDebugRendererInfo(WebGLRenderingContext*); + WebGLDebugRendererInfo(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.cpp index 8ecb09379d2..2b4a0aa5037 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.cpp @@ -27,13 +27,12 @@ #include "core/html/canvas/WebGLDebugShaders.h" #include "bindings/v8/ExceptionState.h" -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" #include "core/html/canvas/WebGLShader.h" -#include "platform/graphics/Extensions3D.h" namespace WebCore { -WebGLDebugShaders::WebGLDebugShaders(WebGLRenderingContext* context) +WebGLDebugShaders::WebGLDebugShaders(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); @@ -43,12 +42,12 @@ WebGLDebugShaders::~WebGLDebugShaders() { } -WebGLExtension::ExtensionName WebGLDebugShaders::name() const +WebGLExtensionName WebGLDebugShaders::name() const { return WebGLDebugShadersName; } -PassRefPtr<WebGLDebugShaders> WebGLDebugShaders::create(WebGLRenderingContext* context) +PassRefPtr<WebGLDebugShaders> WebGLDebugShaders::create(WebGLRenderingContextBase* context) { return adoptRef(new WebGLDebugShaders(context)); } @@ -59,13 +58,12 @@ String WebGLDebugShaders::getTranslatedShaderSource(WebGLShader* shader) return String(); if (!m_context->validateWebGLObject("getTranslatedShaderSource", shader)) return ""; - return m_context->graphicsContext3D()->extensions()->getTranslatedShaderSourceANGLE(shader->object()); + return m_context->ensureNotNull(m_context->webContext()->getTranslatedShaderSourceANGLE(shader->object())); } -bool WebGLDebugShaders::supported(WebGLRenderingContext* context) +bool WebGLDebugShaders::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return extensions->supports("GL_ANGLE_translated_shader_source"); + return context->extensionsUtil()->supportsExtension("GL_ANGLE_translated_shader_source"); } const char* WebGLDebugShaders::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.h index 1adbd3074c1..f1ae4f04b00 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.h @@ -34,19 +34,19 @@ namespace WebCore { class WebGLShader; -class WebGLDebugShaders : public WebGLExtension, public ScriptWrappable { +class WebGLDebugShaders FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<WebGLDebugShaders> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<WebGLDebugShaders> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~WebGLDebugShaders(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; String getTranslatedShaderSource(WebGLShader*); private: - WebGLDebugShaders(WebGLRenderingContext*); + WebGLDebugShaders(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.idl b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.idl index 55a6f3cb981..74851c7c226 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.idl +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDebugShaders.idl @@ -24,7 +24,8 @@ */ [ - NoInterfaceObject + NoInterfaceObject, + TypeChecking=Interface|Nullable, ] interface WebGLDebugShaders { - [StrictTypeChecking, TreatReturnedNullStringAs=Null] DOMString getTranslatedShaderSource(WebGLShader shader); + [TreatReturnedNullStringAs=Null] DOMString getTranslatedShaderSource(WebGLShader? shader); }; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDepthTexture.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDepthTexture.cpp index d42019ff82f..eb2e41d905b 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDepthTexture.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDepthTexture.cpp @@ -27,42 +27,40 @@ #include "core/html/canvas/WebGLDepthTexture.h" -#include "platform/graphics/Extensions3D.h" - namespace WebCore { -WebGLDepthTexture::WebGLDepthTexture(WebGLRenderingContext* context) +WebGLDepthTexture::WebGLDepthTexture(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_CHROMIUM_depth_texture"); + context->extensionsUtil()->ensureExtensionEnabled("GL_CHROMIUM_depth_texture"); } WebGLDepthTexture::~WebGLDepthTexture() { } -WebGLExtension::ExtensionName WebGLDepthTexture::name() const +WebGLExtensionName WebGLDepthTexture::name() const { return WebGLDepthTextureName; } -PassRefPtr<WebGLDepthTexture> WebGLDepthTexture::create(WebGLRenderingContext* context) +PassRefPtr<WebGLDepthTexture> WebGLDepthTexture::create(WebGLRenderingContextBase* context) { return adoptRef(new WebGLDepthTexture(context)); } -bool WebGLDepthTexture::supported(WebGLRenderingContext* context) +bool WebGLDepthTexture::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); + Extensions3DUtil* extensionsUtil = context->extensionsUtil(); // Emulating the UNSIGNED_INT_24_8_WEBGL texture internal format in terms // of two separate texture objects is too difficult, so disable depth // textures unless a packed depth/stencil format is available. - if (!extensions->supports("GL_OES_packed_depth_stencil")) + if (!extensionsUtil->supportsExtension("GL_OES_packed_depth_stencil")) return false; - return extensions->supports("GL_CHROMIUM_depth_texture") - || extensions->supports("GL_OES_depth_texture") - || extensions->supports("GL_ARB_depth_texture"); + return extensionsUtil->supportsExtension("GL_CHROMIUM_depth_texture") + || extensionsUtil->supportsExtension("GL_OES_depth_texture") + || extensionsUtil->supportsExtension("GL_ARB_depth_texture"); } const char* WebGLDepthTexture::extensionName() diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDepthTexture.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDepthTexture.h index 34b052511b0..34017ee1801 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDepthTexture.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDepthTexture.h @@ -32,17 +32,17 @@ namespace WebCore { -class WebGLDepthTexture : public WebGLExtension, public ScriptWrappable { +class WebGLDepthTexture FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<WebGLDepthTexture> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<WebGLDepthTexture> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~WebGLDepthTexture(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; private: - WebGLDepthTexture(WebGLRenderingContext*); + WebGLDepthTexture(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDrawBuffers.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDrawBuffers.cpp index 20b21feb5fe..e5b6b48659f 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDrawBuffers.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDrawBuffers.cpp @@ -27,36 +27,33 @@ #include "core/html/canvas/WebGLDrawBuffers.h" -#include "platform/graphics/Extensions3D.h" - namespace WebCore { -WebGLDrawBuffers::WebGLDrawBuffers(WebGLRenderingContext* context) +WebGLDrawBuffers::WebGLDrawBuffers(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); - context->graphicsContext3D()->extensions()->ensureEnabled("GL_EXT_draw_buffers"); + context->extensionsUtil()->ensureExtensionEnabled("GL_EXT_draw_buffers"); } WebGLDrawBuffers::~WebGLDrawBuffers() { } -WebGLExtension::ExtensionName WebGLDrawBuffers::name() const +WebGLExtensionName WebGLDrawBuffers::name() const { - return WebGLExtension::WebGLDrawBuffersName; + return WebGLDrawBuffersName; } -PassRefPtr<WebGLDrawBuffers> WebGLDrawBuffers::create(WebGLRenderingContext* context) +PassRefPtr<WebGLDrawBuffers> WebGLDrawBuffers::create(WebGLRenderingContextBase* context) { return adoptRef(new WebGLDrawBuffers(context)); } // static -bool WebGLDrawBuffers::supported(WebGLRenderingContext* context) +bool WebGLDrawBuffers::supported(WebGLRenderingContextBase* context) { - Extensions3D* extensions = context->graphicsContext3D()->extensions(); - return (extensions->supports("GL_EXT_draw_buffers") + return (context->extensionsUtil()->supportsExtension("GL_EXT_draw_buffers") && satisfiesWebGLRequirements(context)); } @@ -65,12 +62,12 @@ const char* WebGLDrawBuffers::extensionName() return "WEBGL_draw_buffers"; } -void WebGLDrawBuffers::drawBuffersWEBGL(const Vector<GC3Denum>& buffers) +void WebGLDrawBuffers::drawBuffersWEBGL(const Vector<GLenum>& buffers) { if (isLost()) return; - GC3Dsizei n = buffers.size(); - const GC3Denum* bufs = buffers.data(); + GLsizei n = buffers.size(); + const GLenum* bufs = buffers.data(); if (!m_context->m_framebufferBinding) { if (n != 1) { m_context->synthesizeGLError(GL_INVALID_VALUE, "drawBuffersWEBGL", "more than one buffer"); @@ -81,16 +78,16 @@ void WebGLDrawBuffers::drawBuffersWEBGL(const Vector<GC3Denum>& buffers) return; } // Because the backbuffer is simulated on all current WebKit ports, we need to change BACK to COLOR_ATTACHMENT0. - GC3Denum value = (bufs[0] == GL_BACK) ? GL_COLOR_ATTACHMENT0 : GL_NONE; - m_context->graphicsContext3D()->extensions()->drawBuffersEXT(1, &value); + GLenum value = (bufs[0] == GL_BACK) ? GL_COLOR_ATTACHMENT0 : GL_NONE; + m_context->webContext()->drawBuffersEXT(1, &value); m_context->setBackDrawBuffer(bufs[0]); } else { if (n > m_context->maxDrawBuffers()) { m_context->synthesizeGLError(GL_INVALID_VALUE, "drawBuffersWEBGL", "more than max draw buffers"); return; } - for (GC3Dsizei i = 0; i < n; ++i) { - if (bufs[i] != GL_NONE && bufs[i] != static_cast<GC3Denum>(Extensions3D::COLOR_ATTACHMENT0_EXT + i)) { + for (GLsizei i = 0; i < n; ++i) { + if (bufs[i] != GL_NONE && bufs[i] != static_cast<GLenum>(GL_COLOR_ATTACHMENT0_EXT + i)) { m_context->synthesizeGLError(GL_INVALID_OPERATION, "drawBuffersWEBGL", "COLOR_ATTACHMENTi_EXT or NONE"); return; } @@ -100,15 +97,16 @@ void WebGLDrawBuffers::drawBuffersWEBGL(const Vector<GC3Denum>& buffers) } // static -bool WebGLDrawBuffers::satisfiesWebGLRequirements(WebGLRenderingContext* webglContext) +bool WebGLDrawBuffers::satisfiesWebGLRequirements(WebGLRenderingContextBase* webglContext) { - GraphicsContext3D* context = webglContext->graphicsContext3D(); + blink::WebGraphicsContext3D* context = webglContext->webContext(); + Extensions3DUtil* extensionsUtil = webglContext->extensionsUtil(); // This is called after we make sure GL_EXT_draw_buffers is supported. - GC3Dint maxDrawBuffers = 0; - GC3Dint maxColorAttachments = 0; - context->getIntegerv(Extensions3D::MAX_DRAW_BUFFERS_EXT, &maxDrawBuffers); - context->getIntegerv(Extensions3D::MAX_COLOR_ATTACHMENTS_EXT, &maxColorAttachments); + GLint maxDrawBuffers = 0; + GLint maxColorAttachments = 0; + context->getIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &maxDrawBuffers); + context->getIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &maxColorAttachments); if (maxDrawBuffers < 4 || maxColorAttachments < 4) return false; @@ -116,11 +114,11 @@ bool WebGLDrawBuffers::satisfiesWebGLRequirements(WebGLRenderingContext* webglCo context->bindFramebuffer(GL_FRAMEBUFFER, fbo); const unsigned char* buffer = 0; // Chromium doesn't allow init data for depth/stencil tetxures. - bool supportsDepth = (context->extensions()->supports("GL_CHROMIUM_depth_texture") - || context->extensions()->supports("GL_OES_depth_texture") - || context->extensions()->supports("GL_ARB_depth_texture")); - bool supportsDepthStencil = (context->extensions()->supports("GL_EXT_packed_depth_stencil") - || context->extensions()->supports("GL_OES_packed_depth_stencil")); + bool supportsDepth = (extensionsUtil->supportsExtension("GL_CHROMIUM_depth_texture") + || extensionsUtil->supportsExtension("GL_OES_depth_texture") + || extensionsUtil->supportsExtension("GL_ARB_depth_texture")); + bool supportsDepthStencil = (extensionsUtil->supportsExtension("GL_EXT_packed_depth_stencil") + || extensionsUtil->supportsExtension("GL_OES_packed_depth_stencil")); Platform3DObject depthStencil = 0; if (supportsDepthStencil) { depthStencil = context->createTexture(); @@ -136,8 +134,8 @@ bool WebGLDrawBuffers::satisfiesWebGLRequirements(WebGLRenderingContext* webglCo Vector<Platform3DObject> colors; bool ok = true; - GC3Dint maxAllowedBuffers = std::min(maxDrawBuffers, maxColorAttachments); - for (GC3Dint i = 0; i < maxAllowedBuffers; ++i) { + GLint maxAllowedBuffers = std::min(maxDrawBuffers, maxColorAttachments); + for (GLint i = 0; i < maxAllowedBuffers; ++i) { Platform3DObject color = context->createTexture(); colors.append(color); context->bindTexture(GL_TEXTURE_2D, color); diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDrawBuffers.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDrawBuffers.h index 58e14f12483..be66f91c99d 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDrawBuffers.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLDrawBuffers.h @@ -32,21 +32,21 @@ namespace WebCore { -class WebGLDrawBuffers : public WebGLExtension, public ScriptWrappable { +class WebGLDrawBuffers FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<WebGLDrawBuffers> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<WebGLDrawBuffers> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~WebGLDrawBuffers(); - virtual ExtensionName name() const; + virtual WebGLExtensionName name() const OVERRIDE; - void drawBuffersWEBGL(const Vector<GC3Denum>& buffers); + void drawBuffersWEBGL(const Vector<GLenum>& buffers); private: - WebGLDrawBuffers(WebGLRenderingContext*); + WebGLDrawBuffers(WebGLRenderingContextBase*); - static bool satisfiesWebGLRequirements(WebGLRenderingContext*); + static bool satisfiesWebGLRequirements(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLExtension.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLExtension.cpp index 9d3c9413c61..73efb94233b 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLExtension.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLExtension.cpp @@ -29,7 +29,7 @@ namespace WebCore { -WebGLExtension::WebGLExtension(WebGLRenderingContext* context) +WebGLExtension::WebGLExtension(WebGLRenderingContextBase* context) : m_context(context) { } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLExtension.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLExtension.h index 1bd4c8bcae9..66e072ed2de 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLExtension.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLExtension.h @@ -26,7 +26,8 @@ #ifndef WebGLExtension_h #define WebGLExtension_h -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLExtensionName.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" #include "wtf/RefCounted.h" namespace WebCore { @@ -34,36 +35,14 @@ namespace WebCore { class WebGLExtension : public RefCounted<WebGLExtension> { WTF_MAKE_FAST_ALLOCATED; public: - // Extension names are needed to properly wrap instances in JavaScript objects. - enum ExtensionName { - ANGLEInstancedArraysName, - EXTFragDepthName, - EXTTextureFilterAnisotropicName, - OESElementIndexUintName, - OESStandardDerivativesName, - OESTextureFloatLinearName, - OESTextureFloatName, - OESTextureHalfFloatLinearName, - OESTextureHalfFloatName, - OESVertexArrayObjectName, - WebGLCompressedTextureATCName, - WebGLCompressedTexturePVRTCName, - WebGLCompressedTextureS3TCName, - WebGLDebugRendererInfoName, - WebGLDebugShadersName, - WebGLDepthTextureName, - WebGLDrawBuffersName, - WebGLLoseContextName, - }; - - WebGLRenderingContext* context() { return m_context; } + WebGLRenderingContextBase* context() { return m_context; } virtual ~WebGLExtension(); - virtual ExtensionName name() const = 0; + virtual WebGLExtensionName name() const = 0; // Lose this extension. Passing true = force loss. Some extensions // like WEBGL_lose_context are not normally lost when the context - // is lost but must be lost when destroying their WebGLRenderingContext. + // is lost but must be lost when destroying their WebGLRenderingContextBase. virtual void lose(bool) { m_context = 0; @@ -75,9 +54,9 @@ public: } protected: - WebGLExtension(WebGLRenderingContext*); + WebGLExtension(WebGLRenderingContextBase*); - WebGLRenderingContext* m_context; + WebGLRenderingContextBase* m_context; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLExtensionName.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLExtensionName.h new file mode 100644 index 00000000000..6946fb1cd96 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLExtensionName.h @@ -0,0 +1,38 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WebGLExtensionName_h +#define WebGLExtensionName_h + +namespace WebCore { + +// Extension names are needed to properly wrap instances in JavaScript objects. +enum WebGLExtensionName { + ANGLEInstancedArraysName, + EXTBlendMinMaxName, + EXTFragDepthName, + EXTShaderTextureLODName, + EXTTextureFilterAnisotropicName, + OESElementIndexUintName, + OESStandardDerivativesName, + OESTextureFloatLinearName, + OESTextureFloatName, + OESTextureHalfFloatLinearName, + OESTextureHalfFloatName, + OESVertexArrayObjectName, + WebGLCompressedTextureATCName, + WebGLCompressedTextureETC1Name, + WebGLCompressedTexturePVRTCName, + WebGLCompressedTextureS3TCName, + WebGLDebugRendererInfoName, + WebGLDebugShadersName, + WebGLDepthTextureName, + WebGLDrawBuffersName, + WebGLLoseContextName, + WebGLExtensionNameCount, // Must be the last entry +}; + +} + +#endif // WebGLExtensionName_h diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLFramebuffer.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLFramebuffer.cpp index 7ab97df91d1..e968a306e5d 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLFramebuffer.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLFramebuffer.cpp @@ -27,9 +27,8 @@ #include "core/html/canvas/WebGLFramebuffer.h" -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" #include "platform/NotImplemented.h" -#include "platform/graphics/Extensions3D.h" namespace WebCore { @@ -40,24 +39,22 @@ namespace { return object ? object->object() : 0; } - class WebGLRenderbufferAttachment : public WebGLFramebuffer::WebGLAttachment { + class WebGLRenderbufferAttachment FINAL : public WebGLFramebuffer::WebGLAttachment { public: static PassRefPtr<WebGLFramebuffer::WebGLAttachment> create(WebGLRenderbuffer*); private: WebGLRenderbufferAttachment(WebGLRenderbuffer*); - virtual GC3Dsizei width() const; - virtual GC3Dsizei height() const; - virtual GC3Denum format() const; - virtual GC3Denum type() const; - virtual WebGLSharedObject* object() const; - virtual bool isSharedObject(WebGLSharedObject*) const; - virtual bool valid() const; - virtual bool initialized() const; - virtual void setInitialized(); - virtual void onDetached(GraphicsContext3D*); - virtual void attach(GraphicsContext3D*, GC3Denum attachment); - virtual void unattach(GraphicsContext3D*, GC3Denum attachment); + virtual GLsizei width() const OVERRIDE; + virtual GLsizei height() const OVERRIDE; + virtual GLenum format() const OVERRIDE; + virtual GLenum type() const OVERRIDE; + virtual WebGLSharedObject* object() const OVERRIDE; + virtual bool isSharedObject(WebGLSharedObject*) const OVERRIDE; + virtual bool valid() const OVERRIDE; + virtual void onDetached(blink::WebGraphicsContext3D*) OVERRIDE; + virtual void attach(blink::WebGraphicsContext3D*, GLenum attachment) OVERRIDE; + virtual void unattach(blink::WebGraphicsContext3D*, GLenum attachment) OVERRIDE; WebGLRenderbufferAttachment() { }; @@ -74,19 +71,19 @@ namespace { { } - GC3Dsizei WebGLRenderbufferAttachment::width() const + GLsizei WebGLRenderbufferAttachment::width() const { return m_renderbuffer->width(); } - GC3Dsizei WebGLRenderbufferAttachment::height() const + GLsizei WebGLRenderbufferAttachment::height() const { return m_renderbuffer->height(); } - GC3Denum WebGLRenderbufferAttachment::format() const + GLenum WebGLRenderbufferAttachment::format() const { - GC3Denum format = m_renderbuffer->internalFormat(); + GLenum format = m_renderbuffer->internalFormat(); if (format == GL_DEPTH_STENCIL_OES && m_renderbuffer->emulatedStencilBuffer() && m_renderbuffer->emulatedStencilBuffer()->internalFormat() != GL_STENCIL_INDEX8) { @@ -110,23 +107,12 @@ namespace { return m_renderbuffer->object(); } - bool WebGLRenderbufferAttachment::initialized() const - { - return m_renderbuffer->object() && m_renderbuffer->initialized(); - } - - void WebGLRenderbufferAttachment::setInitialized() - { - if (m_renderbuffer->object()) - m_renderbuffer->setInitialized(); - } - - void WebGLRenderbufferAttachment::onDetached(GraphicsContext3D* context) + void WebGLRenderbufferAttachment::onDetached(blink::WebGraphicsContext3D* context) { m_renderbuffer->onDetached(context); } - void WebGLRenderbufferAttachment::attach(GraphicsContext3D* context, GC3Denum attachment) + void WebGLRenderbufferAttachment::attach(blink::WebGraphicsContext3D* context, GLenum attachment) { Platform3DObject object = objectOrZero(m_renderbuffer.get()); if (attachment == GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL && m_renderbuffer->emulatedStencilBuffer()) { @@ -137,7 +123,7 @@ namespace { } } - void WebGLRenderbufferAttachment::unattach(GraphicsContext3D* context, GC3Denum attachment) + void WebGLRenderbufferAttachment::unattach(blink::WebGraphicsContext3D* context, GLenum attachment) { if (attachment == GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL) { context->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); @@ -147,61 +133,59 @@ namespace { } } - GC3Denum WebGLRenderbufferAttachment::type() const + GLenum WebGLRenderbufferAttachment::type() const { notImplemented(); return 0; } - class WebGLTextureAttachment : public WebGLFramebuffer::WebGLAttachment { + class WebGLTextureAttachment FINAL : public WebGLFramebuffer::WebGLAttachment { public: - static PassRefPtr<WebGLFramebuffer::WebGLAttachment> create(WebGLTexture*, GC3Denum target, GC3Dint level); + static PassRefPtr<WebGLFramebuffer::WebGLAttachment> create(WebGLTexture*, GLenum target, GLint level); private: - WebGLTextureAttachment(WebGLTexture*, GC3Denum target, GC3Dint level); - virtual GC3Dsizei width() const; - virtual GC3Dsizei height() const; - virtual GC3Denum format() const; - virtual GC3Denum type() const; - virtual WebGLSharedObject* object() const; - virtual bool isSharedObject(WebGLSharedObject*) const; - virtual bool valid() const; - virtual bool initialized() const; - virtual void setInitialized(); - virtual void onDetached(GraphicsContext3D*); - virtual void attach(GraphicsContext3D*, GC3Denum attachment); - virtual void unattach(GraphicsContext3D*, GC3Denum attachment); + WebGLTextureAttachment(WebGLTexture*, GLenum target, GLint level); + virtual GLsizei width() const OVERRIDE; + virtual GLsizei height() const OVERRIDE; + virtual GLenum format() const OVERRIDE; + virtual GLenum type() const OVERRIDE; + virtual WebGLSharedObject* object() const OVERRIDE; + virtual bool isSharedObject(WebGLSharedObject*) const OVERRIDE; + virtual bool valid() const OVERRIDE; + virtual void onDetached(blink::WebGraphicsContext3D*) OVERRIDE; + virtual void attach(blink::WebGraphicsContext3D*, GLenum attachment) OVERRIDE; + virtual void unattach(blink::WebGraphicsContext3D*, GLenum attachment) OVERRIDE; WebGLTextureAttachment() { }; RefPtr<WebGLTexture> m_texture; - GC3Denum m_target; - GC3Dint m_level; + GLenum m_target; + GLint m_level; }; - PassRefPtr<WebGLFramebuffer::WebGLAttachment> WebGLTextureAttachment::create(WebGLTexture* texture, GC3Denum target, GC3Dint level) + PassRefPtr<WebGLFramebuffer::WebGLAttachment> WebGLTextureAttachment::create(WebGLTexture* texture, GLenum target, GLint level) { return adoptRef(new WebGLTextureAttachment(texture, target, level)); } - WebGLTextureAttachment::WebGLTextureAttachment(WebGLTexture* texture, GC3Denum target, GC3Dint level) + WebGLTextureAttachment::WebGLTextureAttachment(WebGLTexture* texture, GLenum target, GLint level) : m_texture(texture) , m_target(target) , m_level(level) { } - GC3Dsizei WebGLTextureAttachment::width() const + GLsizei WebGLTextureAttachment::width() const { return m_texture->getWidth(m_target, m_level); } - GC3Dsizei WebGLTextureAttachment::height() const + GLsizei WebGLTextureAttachment::height() const { return m_texture->getHeight(m_target, m_level); } - GC3Denum WebGLTextureAttachment::format() const + GLenum WebGLTextureAttachment::format() const { return m_texture->getInternalFormat(m_target, m_level); } @@ -221,29 +205,18 @@ namespace { return m_texture->object(); } - bool WebGLTextureAttachment::initialized() const - { - // Textures are assumed to be initialized. - return true; - } - - void WebGLTextureAttachment::setInitialized() - { - // Textures are assumed to be initialized. - } - - void WebGLTextureAttachment::onDetached(GraphicsContext3D* context) + void WebGLTextureAttachment::onDetached(blink::WebGraphicsContext3D* context) { m_texture->onDetached(context); } - void WebGLTextureAttachment::attach(GraphicsContext3D* context, GC3Denum attachment) + void WebGLTextureAttachment::attach(blink::WebGraphicsContext3D* context, GLenum attachment) { Platform3DObject object = objectOrZero(m_texture.get()); context->framebufferTexture2D(GL_FRAMEBUFFER, attachment, m_target, object, m_level); } - void WebGLTextureAttachment::unattach(GraphicsContext3D* context, GC3Denum attachment) + void WebGLTextureAttachment::unattach(blink::WebGraphicsContext3D* context, GLenum attachment) { if (attachment == GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL) { context->framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_target, 0, m_level); @@ -253,12 +226,12 @@ namespace { } } - GC3Denum WebGLTextureAttachment::type() const + GLenum WebGLTextureAttachment::type() const { return m_texture->getType(m_target, m_level); } - bool isColorRenderable(GC3Denum internalformat) + bool isColorRenderable(GLenum internalformat) { switch (internalformat) { case GL_RGBA4: @@ -280,17 +253,17 @@ WebGLFramebuffer::WebGLAttachment::~WebGLAttachment() { } -PassRefPtr<WebGLFramebuffer> WebGLFramebuffer::create(WebGLRenderingContext* ctx) +PassRefPtr<WebGLFramebuffer> WebGLFramebuffer::create(WebGLRenderingContextBase* ctx) { return adoptRef(new WebGLFramebuffer(ctx)); } -WebGLFramebuffer::WebGLFramebuffer(WebGLRenderingContext* ctx) +WebGLFramebuffer::WebGLFramebuffer(WebGLRenderingContextBase* ctx) : WebGLContextObject(ctx) , m_hasEverBeenBound(false) { ScriptWrappable::init(this); - setObject(ctx->graphicsContext3D()->createFramebuffer()); + setObject(ctx->webContext()->createFramebuffer()); } WebGLFramebuffer::~WebGLFramebuffer() @@ -298,7 +271,7 @@ WebGLFramebuffer::~WebGLFramebuffer() deleteObject(0); } -void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GC3Denum attachment, GC3Denum texTarget, WebGLTexture* texture, GC3Dint level) +void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GLenum attachment, GLenum texTarget, WebGLTexture* texture, GLint level) { ASSERT(isBound()); removeAttachmentFromBoundFramebuffer(attachment); @@ -311,7 +284,7 @@ void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GC3Denum attachment, GC3 } } -void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GC3Denum attachment, WebGLRenderbuffer* renderbuffer) +void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GLenum attachment, WebGLRenderbuffer* renderbuffer) { ASSERT(isBound()); removeAttachmentFromBoundFramebuffer(attachment); @@ -324,15 +297,15 @@ void WebGLFramebuffer::setAttachmentForBoundFramebuffer(GC3Denum attachment, Web } } -void WebGLFramebuffer::attach(GC3Denum attachment, GC3Denum attachmentPoint) +void WebGLFramebuffer::attach(GLenum attachment, GLenum attachmentPoint) { ASSERT(isBound()); WebGLAttachment* attachmentObject = getAttachment(attachment); if (attachmentObject) - attachmentObject->attach(context()->graphicsContext3D(), attachmentPoint); + attachmentObject->attach(context()->webContext(), attachmentPoint); } -WebGLSharedObject* WebGLFramebuffer::getAttachmentObject(GC3Denum attachment) const +WebGLSharedObject* WebGLFramebuffer::getAttachmentObject(GLenum attachment) const { if (!object()) return 0; @@ -340,12 +313,12 @@ WebGLSharedObject* WebGLFramebuffer::getAttachmentObject(GC3Denum attachment) co return attachmentObject ? attachmentObject->object() : 0; } -bool WebGLFramebuffer::isAttachmentComplete(WebGLAttachment* attachedObject, GC3Denum attachment, const char** reason) const +bool WebGLFramebuffer::isAttachmentComplete(WebGLAttachment* attachedObject, GLenum attachment, const char** reason) const { ASSERT(attachedObject && attachedObject->valid()); ASSERT(reason); - GC3Denum internalformat = attachedObject->format(); + GLenum internalformat = attachedObject->format(); WebGLSharedObject* object = attachedObject->object(); ASSERT(object && (object->isTexture() || object->isRenderbuffer())); @@ -356,8 +329,8 @@ bool WebGLFramebuffer::isAttachmentComplete(WebGLAttachment* attachedObject, GC3 return false; } } else if (object->isTexture()) { - GC3Denum type = attachedObject->type(); - if (!(context()->m_webglDepthTexture && internalformat == GL_DEPTH_COMPONENT + GLenum type = attachedObject->type(); + if (!(context()->extensionEnabled(WebGLDepthTextureName) && internalformat == GL_DEPTH_COMPONENT && (type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT))) { *reason = "the attached texture is not a depth texture"; return false; @@ -379,23 +352,23 @@ bool WebGLFramebuffer::isAttachmentComplete(WebGLAttachment* attachedObject, GC3 return false; } } else if (object->isTexture()) { - GC3Denum type = attachedObject->type(); - if (!(context()->m_webglDepthTexture && internalformat == GL_DEPTH_STENCIL_OES + GLenum type = attachedObject->type(); + if (!(context()->extensionEnabled(WebGLDepthTextureName) && internalformat == GL_DEPTH_STENCIL_OES && type == GL_UNSIGNED_INT_24_8_OES)) { *reason = "the attached texture is not a DEPTH_STENCIL texture"; return false; } } } else if (attachment == GL_COLOR_ATTACHMENT0 - || (context()->m_webglDrawBuffers && attachment > GL_COLOR_ATTACHMENT0 - && attachment < static_cast<GC3Denum>(GL_COLOR_ATTACHMENT0 + context()->maxColorAttachments()))) { + || (context()->extensionEnabled(WebGLDrawBuffersName) && attachment > GL_COLOR_ATTACHMENT0 + && attachment < static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + context()->maxColorAttachments()))) { if (object->isRenderbuffer()) { if (!isColorRenderable(internalformat)) { *reason = "the internalformat of the attached renderbuffer is not color-renderable"; return false; } } else if (object->isTexture()) { - GC3Denum type = attachedObject->type(); + GLenum type = attachedObject->type(); if (internalformat != GL_RGBA && internalformat != GL_RGB) { *reason = "the internalformat of the attached texture is not color-renderable"; return false; @@ -408,8 +381,8 @@ bool WebGLFramebuffer::isAttachmentComplete(WebGLAttachment* attachedObject, GC3 && type != GL_UNSIGNED_SHORT_5_6_5 && type != GL_UNSIGNED_SHORT_4_4_4_4 && type != GL_UNSIGNED_SHORT_5_5_5_1 - && !(type == GL_FLOAT && context()->m_oesTextureFloat) - && !(type == GL_HALF_FLOAT_OES && context()->m_oesTextureHalfFloat)) { + && !(type == GL_FLOAT && context()->extensionEnabled(OESTextureFloatName)) + && !(type == GL_HALF_FLOAT_OES && context()->extensionEnabled(OESTextureHalfFloatName))) { *reason = "unsupported type: The attached texture is not supported to be rendered to"; return false; } @@ -426,13 +399,13 @@ bool WebGLFramebuffer::isAttachmentComplete(WebGLAttachment* attachedObject, GC3 return true; } -WebGLFramebuffer::WebGLAttachment* WebGLFramebuffer::getAttachment(GC3Denum attachment) const +WebGLFramebuffer::WebGLAttachment* WebGLFramebuffer::getAttachment(GLenum attachment) const { const AttachmentMap::const_iterator it = m_attachments.find(attachment); return (it != m_attachments.end()) ? it->value.get() : 0; } -void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer(GC3Denum attachment) +void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer(GLenum attachment) { ASSERT(isBound()); if (!object()) @@ -440,7 +413,7 @@ void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer(GC3Denum attachment) WebGLAttachment* attachmentObject = getAttachment(attachment); if (attachmentObject) { - attachmentObject->onDetached(context()->graphicsContext3D()); + attachmentObject->onDetached(context()->webContext()); m_attachments.remove(attachment); drawBuffersIfNecessary(false); switch (attachment) { @@ -472,8 +445,8 @@ void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer(WebGLSharedObject* a for (AttachmentMap::iterator it = m_attachments.begin(); it != m_attachments.end(); ++it) { WebGLAttachment* attachmentObject = it->value.get(); if (attachmentObject->isSharedObject(attachment)) { - GC3Denum attachmentType = it->key; - attachmentObject->unattach(context()->graphicsContext3D(), attachmentType); + GLenum attachmentType = it->key; + attachmentObject->unattach(context()->webContext(), attachmentType); removeAttachmentFromBoundFramebuffer(attachmentType); checkMore = true; break; @@ -482,29 +455,7 @@ void WebGLFramebuffer::removeAttachmentFromBoundFramebuffer(WebGLSharedObject* a } } -GC3Dsizei WebGLFramebuffer::colorBufferWidth() const -{ - if (!object()) - return 0; - WebGLAttachment* attachment = getAttachment(GL_COLOR_ATTACHMENT0); - if (!attachment) - return 0; - - return attachment->width(); -} - -GC3Dsizei WebGLFramebuffer::colorBufferHeight() const -{ - if (!object()) - return 0; - WebGLAttachment* attachment = getAttachment(GL_COLOR_ATTACHMENT0); - if (!attachment) - return 0; - - return attachment->height(); -} - -GC3Denum WebGLFramebuffer::colorBufferFormat() const +GLenum WebGLFramebuffer::colorBufferFormat() const { if (!object()) return 0; @@ -514,10 +465,10 @@ GC3Denum WebGLFramebuffer::colorBufferFormat() const return attachment->format(); } -GC3Denum WebGLFramebuffer::checkStatus(const char** reason) const +GLenum WebGLFramebuffer::checkStatus(const char** reason) const { - unsigned int count = 0; - GC3Dsizei width = 0, height = 0; + unsigned count = 0; + GLsizei width = 0, height = 0; bool haveDepth = false; bool haveStencil = false; bool haveDepthStencil = false; @@ -571,7 +522,7 @@ GC3Denum WebGLFramebuffer::checkStatus(const char** reason) const return GL_FRAMEBUFFER_COMPLETE; } -bool WebGLFramebuffer::onAccess(GraphicsContext3D* context3d, const char** reason) +bool WebGLFramebuffer::onAccess(blink::WebGraphicsContext3D* context3d, const char** reason) { if (checkStatus(reason) != GL_FRAMEBUFFER_COMPLETE) return false; @@ -586,7 +537,7 @@ bool WebGLFramebuffer::hasStencilBuffer() const return attachment && attachment->valid(); } -void WebGLFramebuffer::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object) +void WebGLFramebuffer::deleteObjectImpl(blink::WebGraphicsContext3D* context3d, Platform3DObject object) { for (AttachmentMap::iterator it = m_attachments.begin(); it != m_attachments.end(); ++it) it->value->onDetached(context3d); @@ -599,7 +550,7 @@ bool WebGLFramebuffer::isBound() const return (context()->m_framebufferBinding.get() == this); } -void WebGLFramebuffer::drawBuffers(const Vector<GC3Denum>& bufs) +void WebGLFramebuffer::drawBuffers(const Vector<GLenum>& bufs) { m_drawBuffers = bufs; m_filteredDrawBuffers.resize(m_drawBuffers.size()); @@ -610,7 +561,7 @@ void WebGLFramebuffer::drawBuffers(const Vector<GC3Denum>& bufs) void WebGLFramebuffer::drawBuffersIfNecessary(bool force) { - if (!context()->m_webglDrawBuffers) + if (!context()->extensionEnabled(WebGLDrawBuffersName)) return; bool reset = force; // This filtering works around graphics driver bugs on Mac OS X. @@ -628,18 +579,18 @@ void WebGLFramebuffer::drawBuffersIfNecessary(bool force) } } if (reset) { - context()->graphicsContext3D()->extensions()->drawBuffersEXT( + context()->webContext()->drawBuffersEXT( m_filteredDrawBuffers.size(), m_filteredDrawBuffers.data()); } } -GC3Denum WebGLFramebuffer::getDrawBuffer(GC3Denum drawBuffer) +GLenum WebGLFramebuffer::getDrawBuffer(GLenum drawBuffer) { - int index = static_cast<int>(drawBuffer - Extensions3D::DRAW_BUFFER0_EXT); + int index = static_cast<int>(drawBuffer - GL_DRAW_BUFFER0_EXT); ASSERT(index >= 0); if (index < static_cast<int>(m_drawBuffers.size())) return m_drawBuffers[index]; - if (drawBuffer == Extensions3D::DRAW_BUFFER0_EXT) + if (drawBuffer == GL_DRAW_BUFFER0_EXT) return GL_COLOR_ATTACHMENT0; return GL_NONE; } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLFramebuffer.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLFramebuffer.h index 86e2aebf4e8..e8705e61187 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLFramebuffer.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLFramebuffer.h @@ -37,28 +37,26 @@ namespace WebCore { class WebGLRenderbuffer; class WebGLTexture; -class WebGLFramebuffer : public WebGLContextObject, public ScriptWrappable { +class WebGLFramebuffer FINAL : public WebGLContextObject, public ScriptWrappable { public: class WebGLAttachment : public RefCounted<WebGLAttachment> { public: virtual ~WebGLAttachment(); - virtual GC3Dsizei width() const = 0; - virtual GC3Dsizei height() const = 0; - virtual GC3Denum format() const = 0; + virtual GLsizei width() const = 0; + virtual GLsizei height() const = 0; + virtual GLenum format() const = 0; // For texture attachment, type() returns the type of the attached texture. // For renderbuffer attachment, the type of the renderbuffer may vary with GL implementation. // To avoid confusion, it would be better to not implement type() for renderbuffer attachment and // we should always use the internalformat of the renderbuffer and avoid using type() API. - virtual GC3Denum type() const = 0; + virtual GLenum type() const = 0; virtual WebGLSharedObject* object() const = 0; virtual bool isSharedObject(WebGLSharedObject*) const = 0; virtual bool valid() const = 0; - virtual bool initialized() const = 0; - virtual void setInitialized() = 0; - virtual void onDetached(GraphicsContext3D*) = 0; - virtual void attach(GraphicsContext3D*, GC3Denum attachment) = 0; - virtual void unattach(GraphicsContext3D*, GC3Denum attachment) = 0; + virtual void onDetached(blink::WebGraphicsContext3D*) = 0; + virtual void attach(blink::WebGraphicsContext3D*, GLenum attachment) = 0; + virtual void unattach(blink::WebGraphicsContext3D*, GLenum attachment) = 0; protected: WebGLAttachment(); @@ -66,33 +64,29 @@ public: virtual ~WebGLFramebuffer(); - static PassRefPtr<WebGLFramebuffer> create(WebGLRenderingContext*); + static PassRefPtr<WebGLFramebuffer> create(WebGLRenderingContextBase*); - void setAttachmentForBoundFramebuffer(GC3Denum attachment, GC3Denum texTarget, WebGLTexture*, GC3Dint level); - void setAttachmentForBoundFramebuffer(GC3Denum attachment, WebGLRenderbuffer*); + void setAttachmentForBoundFramebuffer(GLenum attachment, GLenum texTarget, WebGLTexture*, GLint level); + void setAttachmentForBoundFramebuffer(GLenum attachment, WebGLRenderbuffer*); // If an object is attached to the currently bound framebuffer, remove it. void removeAttachmentFromBoundFramebuffer(WebGLSharedObject*); // If a given attachment point for the currently bound framebuffer is not null, remove the attached object. - void removeAttachmentFromBoundFramebuffer(GC3Denum); - WebGLSharedObject* getAttachmentObject(GC3Denum) const; + void removeAttachmentFromBoundFramebuffer(GLenum); + WebGLSharedObject* getAttachmentObject(GLenum) const; - GC3Denum colorBufferFormat() const; - GC3Dsizei colorBufferWidth() const; - GC3Dsizei colorBufferHeight() const; + GLenum colorBufferFormat() const; // This should always be called before drawArray, drawElements, clear, // readPixels, copyTexImage2D, copyTexSubImage2D if this framebuffer is // currently bound. - // Return false if the framebuffer is incomplete; otherwise initialize - // the buffers if they haven't been initialized and - // needToInitializeAttachments is true. - bool onAccess(GraphicsContext3D*, const char** reason); + // Return false if the framebuffer is incomplete. + bool onAccess(blink::WebGraphicsContext3D*, const char** reason); // Software version of glCheckFramebufferStatus(), except that when // FRAMEBUFFER_COMPLETE is returned, it is still possible for // glCheckFramebufferStatus() to return FRAMEBUFFER_UNSUPPORTED, // depending on hardware implementation. - GC3Denum checkStatus(const char** reason) const; + GLenum checkStatus(const char** reason) const; bool hasEverBeenBound() const { return object() && m_hasEverBeenBound; } @@ -101,38 +95,36 @@ public: bool hasStencilBuffer() const; // Wrapper for drawBuffersEXT/drawBuffersARB to work around a driver bug. - void drawBuffers(const Vector<GC3Denum>& bufs); + void drawBuffers(const Vector<GLenum>& bufs); - GC3Denum getDrawBuffer(GC3Denum); + GLenum getDrawBuffer(GLenum); protected: - WebGLFramebuffer(WebGLRenderingContext*); + WebGLFramebuffer(WebGLRenderingContextBase*); - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject); + virtual void deleteObjectImpl(blink::WebGraphicsContext3D*, Platform3DObject) OVERRIDE; private: - virtual bool isFramebuffer() const { return true; } - - WebGLAttachment* getAttachment(GC3Denum) const; - bool isAttachmentComplete(WebGLAttachment* attachedObject, GC3Denum attachment, const char** reason) const; + WebGLAttachment* getAttachment(GLenum) const; + bool isAttachmentComplete(WebGLAttachment* attachedObject, GLenum attachment, const char** reason) const; // Check if the framebuffer is currently bound. bool isBound() const; // attach 'attachment' at 'attachmentPoint'. - void attach(GC3Denum attachment, GC3Denum attachmentPoint); + void attach(GLenum attachment, GLenum attachmentPoint); // Check if a new drawBuffers call should be issued. This is called when we add or remove an attachment. void drawBuffersIfNecessary(bool force); - typedef WTF::HashMap<GC3Denum, RefPtr<WebGLAttachment> > AttachmentMap; + typedef WTF::HashMap<GLenum, RefPtr<WebGLAttachment> > AttachmentMap; AttachmentMap m_attachments; bool m_hasEverBeenBound; - Vector<GC3Denum> m_drawBuffers; - Vector<GC3Denum> m_filteredDrawBuffers; + Vector<GLenum> m_drawBuffers; + Vector<GLenum> m_filteredDrawBuffers; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLGetInfo.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLGetInfo.cpp index 55cead3c16f..d4f893bc0d2 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLGetInfo.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLGetInfo.cpp @@ -90,7 +90,7 @@ WebGLGetInfo::WebGLGetInfo(const String& value) { } -WebGLGetInfo::WebGLGetInfo(unsigned int value) +WebGLGetInfo::WebGLGetInfo(unsigned value) : m_type(kTypeUnsignedInt) , m_bool(false) , m_float(0) @@ -234,7 +234,7 @@ const String& WebGLGetInfo::getString() const return m_string; } -unsigned int WebGLGetInfo::getUnsignedInt() const +unsigned WebGLGetInfo::getUnsignedInt() const { ASSERT(getType() == kTypeUnsignedInt); return m_unsignedInt; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLGetInfo.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLGetInfo.h index d72e7f9c65a..4528bb4a2b5 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLGetInfo.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLGetInfo.h @@ -78,7 +78,7 @@ public: // Represents the null value and type. WebGLGetInfo(); explicit WebGLGetInfo(const String& value); - explicit WebGLGetInfo(unsigned int value); + explicit WebGLGetInfo(unsigned value); explicit WebGLGetInfo(PassRefPtr<WebGLBuffer> value); explicit WebGLGetInfo(PassRefPtr<Float32Array> value); explicit WebGLGetInfo(PassRefPtr<WebGLFramebuffer> value); @@ -99,7 +99,7 @@ public: float getFloat() const; int getInt() const; const String& getString() const; - unsigned int getUnsignedInt() const; + unsigned getUnsignedInt() const; PassRefPtr<WebGLBuffer> getWebGLBuffer() const; PassRefPtr<Float32Array> getWebGLFloatArray() const; PassRefPtr<WebGLFramebuffer> getWebGLFramebuffer() const; @@ -120,7 +120,7 @@ private: float m_float; int m_int; String m_string; - unsigned int m_unsignedInt; + unsigned m_unsignedInt; RefPtr<WebGLBuffer> m_webglBuffer; RefPtr<Float32Array> m_webglFloatArray; RefPtr<WebGLFramebuffer> m_webglFramebuffer; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.cpp index ca1226a9ba2..e2fe7bd738d 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.cpp @@ -27,11 +27,11 @@ #include "core/html/canvas/WebGLLoseContext.h" -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -WebGLLoseContext::WebGLLoseContext(WebGLRenderingContext* context) +WebGLLoseContext::WebGLLoseContext(WebGLRenderingContextBase* context) : WebGLExtension(context) { ScriptWrappable::init(this); @@ -47,12 +47,12 @@ void WebGLLoseContext::lose(bool force) WebGLExtension::lose(true); } -WebGLExtension::ExtensionName WebGLLoseContext::name() const +WebGLExtensionName WebGLLoseContext::name() const { return WebGLLoseContextName; } -PassRefPtr<WebGLLoseContext> WebGLLoseContext::create(WebGLRenderingContext* context) +PassRefPtr<WebGLLoseContext> WebGLLoseContext::create(WebGLRenderingContextBase* context) { return adoptRef(new WebGLLoseContext(context)); } @@ -60,7 +60,7 @@ PassRefPtr<WebGLLoseContext> WebGLLoseContext::create(WebGLRenderingContext* con void WebGLLoseContext::loseContext() { if (!isLost()) - m_context->forceLostContext(WebGLRenderingContext::SyntheticLostContext); + m_context->forceLostContext(WebGLRenderingContextBase::SyntheticLostContext); } void WebGLLoseContext::restoreContext() @@ -69,7 +69,7 @@ void WebGLLoseContext::restoreContext() m_context->forceRestoreContext(); } -bool WebGLLoseContext::supported(WebGLRenderingContext*) +bool WebGLLoseContext::supported(WebGLRenderingContextBase*) { return true; } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.h index 23140d62632..cab49f34740 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.h @@ -32,23 +32,23 @@ namespace WebCore { -class WebGLRenderingContext; +class WebGLRenderingContextBase; -class WebGLLoseContext : public WebGLExtension, public ScriptWrappable { +class WebGLLoseContext FINAL : public WebGLExtension, public ScriptWrappable { public: - static PassRefPtr<WebGLLoseContext> create(WebGLRenderingContext*); - static bool supported(WebGLRenderingContext*); + static PassRefPtr<WebGLLoseContext> create(WebGLRenderingContextBase*); + static bool supported(WebGLRenderingContextBase*); static const char* extensionName(); virtual ~WebGLLoseContext(); - virtual ExtensionName name() const; - virtual void lose(bool); + virtual WebGLExtensionName name() const OVERRIDE; + virtual void lose(bool) OVERRIDE; void loseContext(); void restoreContext(); private: - WebGLLoseContext(WebGLRenderingContext*); + WebGLLoseContext(WebGLRenderingContextBase*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.idl b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.idl index 1ac288f2489..117fcf221ec 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.idl +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLLoseContext.idl @@ -24,8 +24,9 @@ */ [ - NoInterfaceObject + NoInterfaceObject, + TypeChecking=Interface|Nullable, ] interface WebGLLoseContext { - [StrictTypeChecking] void loseContext(); - [StrictTypeChecking] void restoreContext(); + void loseContext(); + void restoreContext(); }; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLObject.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLObject.cpp index 3ffddaad3fd..14dd8ba5ee8 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLObject.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLObject.cpp @@ -29,7 +29,7 @@ namespace WebCore { -WebGLObject::WebGLObject(WebGLRenderingContext*) +WebGLObject::WebGLObject(WebGLRenderingContextBase*) : m_object(0) , m_attachmentCount(0) , m_deleted(false) @@ -47,7 +47,7 @@ void WebGLObject::setObject(Platform3DObject object) m_object = object; } -void WebGLObject::deleteObject(GraphicsContext3D* context3d) +void WebGLObject::deleteObject(blink::WebGraphicsContext3D* context3d) { m_deleted = true; if (!m_object) @@ -58,7 +58,7 @@ void WebGLObject::deleteObject(GraphicsContext3D* context3d) if (!m_attachmentCount) { if (!context3d) - context3d = getAGraphicsContext3D(); + context3d = getAWebGraphicsContext3D(); if (context3d) deleteObjectImpl(context3d, m_object); @@ -73,7 +73,7 @@ void WebGLObject::detach() } -void WebGLObject::onDetached(GraphicsContext3D* context3d) +void WebGLObject::onDetached(blink::WebGraphicsContext3D* context3d) { if (m_attachmentCount) --m_attachmentCount; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLObject.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLObject.h index 55a7d51e2da..ae5c439c8a6 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLObject.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLObject.h @@ -26,14 +26,17 @@ #ifndef WebGLObject_h #define WebGLObject_h -#include "platform/graphics/GraphicsContext3D.h" +#include "platform/graphics/GraphicsTypes3D.h" #include "wtf/RefCounted.h" +namespace blink { +class WebGraphicsContext3D; +} + namespace WebCore { -class GraphicsContext3D; class WebGLContextGroup; -class WebGLRenderingContext; +class WebGLRenderingContextBase; class WebGLObject : public RefCounted<WebGLObject> { public: @@ -44,10 +47,10 @@ public: // deleteObject may not always delete the OpenGL resource. For programs and // shaders, deletion is delayed until they are no longer attached. // FIXME: revisit this when resource sharing between contexts are implemented. - void deleteObject(GraphicsContext3D*); + void deleteObject(blink::WebGraphicsContext3D*); void onAttached() { ++m_attachmentCount; } - void onDetached(GraphicsContext3D*); + void onDetached(blink::WebGraphicsContext3D*); // This indicates whether the client side issue a delete call already, not // whether the OpenGL resource is deleted. @@ -55,22 +58,22 @@ 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(WebGLRenderingContextBase*); // setObject should be only called once right after creating a WebGLObject. void setObject(Platform3DObject); // deleteObjectImpl should be only called once to delete the OpenGL resource. - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject) = 0; + virtual void deleteObjectImpl(blink::WebGraphicsContext3D*, Platform3DObject) = 0; virtual bool hasGroupOrContext() const = 0; virtual void detach(); - virtual GraphicsContext3D* getAGraphicsContext3D() const = 0; + virtual blink::WebGraphicsContext3D* getAWebGraphicsContext3D() const = 0; private: Platform3DObject m_object; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLProgram.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLProgram.cpp index 6a1539331f9..e1e49594139 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLProgram.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLProgram.cpp @@ -27,23 +27,23 @@ #include "core/html/canvas/WebGLProgram.h" -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -PassRefPtr<WebGLProgram> WebGLProgram::create(WebGLRenderingContext* ctx) +PassRefPtr<WebGLProgram> WebGLProgram::create(WebGLRenderingContextBase* 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) { ScriptWrappable::init(this); - setObject(ctx->graphicsContext3D()->createProgram()); + setObject(ctx->webContext()->createProgram()); } WebGLProgram::~WebGLProgram() @@ -51,16 +51,16 @@ WebGLProgram::~WebGLProgram() deleteObject(0); } -void WebGLProgram::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject obj) +void WebGLProgram::deleteObjectImpl(blink::WebGraphicsContext3D* context3d, Platform3DObject obj) { 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; } } @@ -70,7 +70,7 @@ unsigned WebGLProgram::numActiveAttribLocations() return m_activeAttribLocations.size(); } -GC3Dint WebGLProgram::getActiveAttribLocation(GC3Duint index) +GLint WebGLProgram::getActiveAttribLocation(GLuint index) { cacheInfoIfNeeded(); if (index >= numActiveAttribLocations()) @@ -94,19 +94,13 @@ bool WebGLProgram::linkStatus() return m_linkStatus; } -void WebGLProgram::setLinkStatus(bool status) -{ - cacheInfoIfNeeded(); - m_linkStatus = status; -} - void WebGLProgram::increaseLinkCount() { ++m_linkCount; m_infoValid = false; } -WebGLShader* WebGLProgram::getAttachedShader(GC3Denum type) +WebGLShader* WebGLProgram::getAttachedShader(GLenum type) { switch (type) { case GL_VERTEX_SHADER: @@ -146,29 +140,29 @@ bool WebGLProgram::detachShader(WebGLShader* shader) case GL_VERTEX_SHADER: if (m_vertexShader != shader) return false; - m_vertexShader = 0; + m_vertexShader = nullptr; return true; case GL_FRAGMENT_SHADER: if (m_fragmentShader != shader) return false; - m_fragmentShader = 0; + m_fragmentShader = nullptr; return true; default: return false; } } -void WebGLProgram::cacheActiveAttribLocations(GraphicsContext3D* context3d) +void WebGLProgram::cacheActiveAttribLocations(blink::WebGraphicsContext3D* context3d) { m_activeAttribLocations.clear(); - GC3Dint numAttribs = 0; + GLint numAttribs = 0; context3d->getProgramiv(object(), GL_ACTIVE_ATTRIBUTES, &numAttribs); m_activeAttribLocations.resize(static_cast<size_t>(numAttribs)); for (int i = 0; i < numAttribs; ++i) { - ActiveInfo info; + blink::WebGraphicsContext3D::ActiveInfo info; context3d->getActiveAttrib(object(), i, info); - m_activeAttribLocations[i] = context3d->getAttribLocation(object(), info.name); + m_activeAttribLocations[i] = context3d->getAttribLocation(object(), info.name.utf8().data()); } } @@ -180,10 +174,10 @@ void WebGLProgram::cacheInfoIfNeeded() if (!object()) return; - GraphicsContext3D* context = getAGraphicsContext3D(); + blink::WebGraphicsContext3D* context = getAWebGraphicsContext3D(); if (!context) return; - GC3Dint linkStatus = 0; + GLint linkStatus = 0; context->getProgramiv(object(), GL_LINK_STATUS, &linkStatus); m_linkStatus = linkStatus; if (m_linkStatus) diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLProgram.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLProgram.h index 5ba00e7cf70..f68b33048ae 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLProgram.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLProgram.h @@ -34,19 +34,18 @@ namespace WebCore { -class WebGLProgram : public WebGLSharedObject, public ScriptWrappable { +class WebGLProgram FINAL : public WebGLSharedObject, public ScriptWrappable { public: virtual ~WebGLProgram(); - static PassRefPtr<WebGLProgram> create(WebGLRenderingContext*); + static PassRefPtr<WebGLProgram> create(WebGLRenderingContextBase*); unsigned numActiveAttribLocations(); - GC3Dint getActiveAttribLocation(GC3Duint index); + GLint getActiveAttribLocation(GLuint index); bool isUsingVertexAttrib0(); bool linkStatus(); - void setLinkStatus(bool); unsigned linkCount() const { return m_linkCount; } @@ -56,24 +55,24 @@ public: // Also, we invalidate the cached program info. void increaseLinkCount(); - WebGLShader* getAttachedShader(GC3Denum); + WebGLShader* getAttachedShader(GLenum); bool attachShader(WebGLShader*); bool detachShader(WebGLShader*); protected: - WebGLProgram(WebGLRenderingContext*); + WebGLProgram(WebGLRenderingContextBase*); - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject); + virtual void deleteObjectImpl(blink::WebGraphicsContext3D*, Platform3DObject) OVERRIDE; private: - virtual bool isProgram() const { return true; } + virtual bool isProgram() const OVERRIDE { return true; } - void cacheActiveAttribLocations(GraphicsContext3D*); + void cacheActiveAttribLocations(blink::WebGraphicsContext3D*); void cacheInfoIfNeeded(); - Vector<GC3Dint> m_activeAttribLocations; + Vector<GLint> m_activeAttribLocations; - GC3Dint m_linkStatus; + GLint m_linkStatus; // This is used to track whether a WebGLUniformLocation belongs to this // program or not. diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderbuffer.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderbuffer.cpp index da27596f273..76ef482e037 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderbuffer.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderbuffer.cpp @@ -27,11 +27,11 @@ #include "core/html/canvas/WebGLRenderbuffer.h" -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -PassRefPtr<WebGLRenderbuffer> WebGLRenderbuffer::create(WebGLRenderingContext* ctx) +PassRefPtr<WebGLRenderbuffer> WebGLRenderbuffer::create(WebGLRenderingContextBase* ctx) { return adoptRef(new WebGLRenderbuffer(ctx)); } @@ -41,25 +41,24 @@ WebGLRenderbuffer::~WebGLRenderbuffer() deleteObject(0); } -WebGLRenderbuffer::WebGLRenderbuffer(WebGLRenderingContext* ctx) +WebGLRenderbuffer::WebGLRenderbuffer(WebGLRenderingContextBase* ctx) : WebGLSharedObject(ctx) , m_internalFormat(GL_RGBA4) - , m_initialized(false) , m_width(0) , m_height(0) , m_hasEverBeenBound(false) { ScriptWrappable::init(this); - setObject(ctx->graphicsContext3D()->createRenderbuffer()); + setObject(ctx->webContext()->createRenderbuffer()); } -void WebGLRenderbuffer::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object) +void WebGLRenderbuffer::deleteObjectImpl(blink::WebGraphicsContext3D* context3d, Platform3DObject object) { context3d->deleteRenderbuffer(object); deleteEmulatedStencilBuffer(context3d); } -void WebGLRenderbuffer::deleteEmulatedStencilBuffer(GraphicsContext3D* context3d) +void WebGLRenderbuffer::deleteEmulatedStencilBuffer(blink::WebGraphicsContext3D* context3d) { if (!m_emulatedStencilBuffer) return; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderbuffer.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderbuffer.h index 95688a20d26..4c08712de63 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderbuffer.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderbuffer.h @@ -32,29 +32,25 @@ namespace WebCore { -class WebGLRenderbuffer : public WebGLSharedObject, public ScriptWrappable { +class WebGLRenderbuffer FINAL : public WebGLSharedObject, public ScriptWrappable { public: virtual ~WebGLRenderbuffer(); - static PassRefPtr<WebGLRenderbuffer> create(WebGLRenderingContext*); + static PassRefPtr<WebGLRenderbuffer> create(WebGLRenderingContextBase*); - void setInternalFormat(GC3Denum internalformat) + void setInternalFormat(GLenum internalformat) { m_internalFormat = internalformat; - m_initialized = false; } - GC3Denum internalFormat() const { return m_internalFormat; } + GLenum internalFormat() const { return m_internalFormat; } - void setSize(GC3Dsizei width, GC3Dsizei height) + void setSize(GLsizei width, GLsizei height) { m_width = width; m_height = height; } - GC3Dsizei width() const { return m_width; } - GC3Dsizei height() const { return m_height; } - - bool initialized() const { return m_initialized; } - void setInitialized() { m_initialized = true; } + GLsizei width() const { return m_width; } + GLsizei height() const { return m_height; } bool hasEverBeenBound() const { return object() && m_hasEverBeenBound; } @@ -62,19 +58,18 @@ public: void setEmulatedStencilBuffer(PassRefPtr<WebGLRenderbuffer> buffer) { m_emulatedStencilBuffer = buffer; } WebGLRenderbuffer* emulatedStencilBuffer() const { return m_emulatedStencilBuffer.get(); } - void deleteEmulatedStencilBuffer(GraphicsContext3D* context3d); + void deleteEmulatedStencilBuffer(blink::WebGraphicsContext3D* context3d); protected: - WebGLRenderbuffer(WebGLRenderingContext*); + WebGLRenderbuffer(WebGLRenderingContextBase*); - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject); + virtual void deleteObjectImpl(blink::WebGraphicsContext3D*, Platform3DObject) OVERRIDE; private: - virtual bool isRenderbuffer() const { return true; } + virtual bool isRenderbuffer() const OVERRIDE { return true; } - GC3Denum m_internalFormat; - bool m_initialized; - GC3Dsizei m_width, m_height; + GLenum m_internalFormat; + GLsizei m_width, m_height; bool m_hasEverBeenBound; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.cpp index ed0d58811ad..e1d1c070724 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.cpp @@ -26,17 +26,11 @@ #include "config.h" #include "core/html/canvas/WebGLRenderingContext.h" -#include "RuntimeEnabledFeatures.h" -#include "bindings/v8/ExceptionMessages.h" -#include "bindings/v8/ExceptionState.h" -#include "core/dom/ExceptionCode.h" -#include "core/fetch/ImageResource.h" -#include "core/html/HTMLCanvasElement.h" -#include "core/html/HTMLImageElement.h" -#include "core/html/HTMLVideoElement.h" -#include "core/html/ImageData.h" +#include "core/frame/LocalFrame.h" #include "core/html/canvas/ANGLEInstancedArrays.h" +#include "core/html/canvas/EXTBlendMinMax.h" #include "core/html/canvas/EXTFragDepth.h" +#include "core/html/canvas/EXTShaderTextureLOD.h" #include "core/html/canvas/EXTTextureFilterAnisotropic.h" #include "core/html/canvas/OESElementIndexUint.h" #include "core/html/canvas/OESStandardDerivatives.h" @@ -45,458 +39,36 @@ #include "core/html/canvas/OESTextureHalfFloat.h" #include "core/html/canvas/OESTextureHalfFloatLinear.h" #include "core/html/canvas/OESVertexArrayObject.h" -#include "core/html/canvas/WebGLActiveInfo.h" -#include "core/html/canvas/WebGLBuffer.h" #include "core/html/canvas/WebGLCompressedTextureATC.h" +#include "core/html/canvas/WebGLCompressedTextureETC1.h" #include "core/html/canvas/WebGLCompressedTexturePVRTC.h" #include "core/html/canvas/WebGLCompressedTextureS3TC.h" #include "core/html/canvas/WebGLContextAttributes.h" #include "core/html/canvas/WebGLContextEvent.h" -#include "core/html/canvas/WebGLContextGroup.h" #include "core/html/canvas/WebGLDebugRendererInfo.h" #include "core/html/canvas/WebGLDebugShaders.h" #include "core/html/canvas/WebGLDepthTexture.h" #include "core/html/canvas/WebGLDrawBuffers.h" -#include "core/html/canvas/WebGLFramebuffer.h" #include "core/html/canvas/WebGLLoseContext.h" -#include "core/html/canvas/WebGLProgram.h" -#include "core/html/canvas/WebGLRenderbuffer.h" -#include "core/html/canvas/WebGLShader.h" -#include "core/html/canvas/WebGLShaderPrecisionFormat.h" -#include "core/html/canvas/WebGLTexture.h" -#include "core/html/canvas/WebGLUniformLocation.h" -#include "core/inspector/InspectorInstrumentation.h" #include "core/loader/FrameLoader.h" #include "core/loader/FrameLoaderClient.h" -#include "core/frame/Frame.h" #include "core/frame/Settings.h" #include "core/rendering/RenderBox.h" #include "platform/CheckedInt.h" #include "platform/NotImplemented.h" -#include "platform/geometry/IntSize.h" -#include "platform/graphics/Extensions3D.h" -#include "platform/graphics/UnacceleratedImageBufferSurface.h" #include "platform/graphics/gpu/DrawingBuffer.h" - -#include "wtf/PassOwnPtr.h" -#include "wtf/Uint32Array.h" -#include "wtf/text/StringBuilder.h" +#include "public/platform/Platform.h" namespace WebCore { -const double secondsBetweenRestoreAttempts = 1.0; -const int maxGLErrorsAllowedToConsole = 256; -const unsigned maxGLActiveContexts = 16; - -Vector<WebGLRenderingContext*>& WebGLRenderingContext::activeContexts() -{ - DEFINE_STATIC_LOCAL(Vector<WebGLRenderingContext*>, activeContexts, ()); - return activeContexts; -} - -Vector<WebGLRenderingContext*>& WebGLRenderingContext::forciblyEvictedContexts() -{ - DEFINE_STATIC_LOCAL(Vector<WebGLRenderingContext*>, forciblyEvictedContexts, ()); - return forciblyEvictedContexts; -} - -void WebGLRenderingContext::forciblyLoseOldestContext(const String& reason) -{ - size_t candidateID = oldestContextIndex(); - if (candidateID >= activeContexts().size()) - return; - - WebGLRenderingContext* candidate = activeContexts()[candidateID]; - - activeContexts().remove(candidateID); - - candidate->printWarningToConsole(reason); - InspectorInstrumentation::didFireWebGLWarning(candidate->canvas()); - - // This will call deactivateContext once the context has actually been lost. - candidate->forceLostContext(WebGLRenderingContext::SyntheticLostContext); -} - -size_t WebGLRenderingContext::oldestContextIndex() -{ - if (!activeContexts().size()) - return maxGLActiveContexts; - - WebGLRenderingContext* candidate = activeContexts().first(); - size_t candidateID = 0; - for (size_t ii = 1; ii < activeContexts().size(); ++ii) { - WebGLRenderingContext* context = activeContexts()[ii]; - if (context->graphicsContext3D() && candidate->graphicsContext3D() && context->graphicsContext3D()->lastFlushID() < candidate->graphicsContext3D()->lastFlushID()) { - candidate = context; - candidateID = ii; - } - } - - return candidateID; -} - -IntSize WebGLRenderingContext::oldestContextSize() -{ - IntSize size; - - size_t candidateID = oldestContextIndex(); - if (candidateID < activeContexts().size()) { - WebGLRenderingContext* candidate = activeContexts()[candidateID]; - size.setWidth(candidate->drawingBufferWidth()); - size.setHeight(candidate->drawingBufferHeight()); - } - - return size; -} - -void WebGLRenderingContext::activateContext(WebGLRenderingContext* context) -{ - unsigned removedContexts = 0; - while (activeContexts().size() >= maxGLActiveContexts && removedContexts < maxGLActiveContexts) { - forciblyLoseOldestContext("WARNING: Too many active WebGL contexts. Oldest context will be lost."); - removedContexts++; - } - - if (!activeContexts().contains(context)) - activeContexts().append(context); -} - -void WebGLRenderingContext::deactivateContext(WebGLRenderingContext* context, bool addToEvictedList) -{ - size_t position = activeContexts().find(context); - if (position != WTF::kNotFound) - activeContexts().remove(position); - - if (addToEvictedList && !forciblyEvictedContexts().contains(context)) - forciblyEvictedContexts().append(context); -} - -void WebGLRenderingContext::willDestroyContext(WebGLRenderingContext* context) -{ - size_t position = forciblyEvictedContexts().find(context); - if (position != WTF::kNotFound) - forciblyEvictedContexts().remove(position); - - deactivateContext(context, false); - - // Try to re-enable the oldest inactive contexts. - while(activeContexts().size() < maxGLActiveContexts && forciblyEvictedContexts().size()) { - WebGLRenderingContext* evictedContext = forciblyEvictedContexts().first(); - if (!evictedContext->m_restoreAllowed) { - forciblyEvictedContexts().remove(0); - continue; - } - - IntSize desiredSize = evictedContext->m_drawingBuffer->adjustSize(evictedContext->clampedCanvasSize()); - - // If there's room in the pixel budget for this context, restore it. - if (!desiredSize.isEmpty()) { - forciblyEvictedContexts().remove(0); - evictedContext->forceRestoreContext(); - activeContexts().append(evictedContext); - } - break; - } -} - -class WebGLRenderingContextEvictionManager : public ContextEvictionManager { -public: - void forciblyLoseOldestContext(const String& reason) { - WebGLRenderingContext::forciblyLoseOldestContext(reason); - }; - IntSize oldestContextSize() { - return WebGLRenderingContext::oldestContextSize(); - }; -}; - -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; - } - - 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() - { - ASSERT_WITH_SECURITY_IMPLICATION(m_position < m_length); - return m_sourceString[m_position]; - } - - void advance() - { - ++m_position; - } - - static bool isNewline(UChar character) - { - // 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; - } - } - - GraphicsContext3D::Attributes adjustAttributes(const GraphicsContext3D::Attributes& attributes, Settings* settings) - { - GraphicsContext3D::Attributes adjustedAttributes = attributes; - if (adjustedAttributes.antialias) { - if (settings && !settings->openGLMultisamplingEnabled()) - adjustedAttributes.antialias = false; - } - - return adjustedAttributes; - } -} // namespace anonymous - -class WebGLRenderingContextLostCallback : public GraphicsContext3D::ContextLostCallback { - WTF_MAKE_FAST_ALLOCATED; -public: - explicit WebGLRenderingContextLostCallback(WebGLRenderingContext* cb) : m_context(cb) { } - virtual void onContextLost() { 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) - { - if (m_context->m_synthesizedErrorsToConsole) - m_context->printGLErrorToConsole(message); - InspectorInstrumentation::didFireWebGLErrorOrWarning(m_context->canvas(), message); - } - virtual ~WebGLRenderingContextErrorMessageCallback() { } -private: - WebGLRenderingContext* m_context; -}; - -PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElement* canvas, WebGLContextAttributes* attrs) +PassOwnPtrWillBeRawPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElement* canvas, WebGLContextAttributes* attrs) { Document& document = canvas->document(); - Frame* frame = document.frame(); - if (!frame) + LocalFrame* frame = document.frame(); + if (!frame) { + canvas->dispatchEvent(WebGLContextEvent::create(EventTypeNames::webglcontextcreationerror, false, true, "Web page was not allowed to create a WebGL context.")); return nullptr; + } Settings* settings = frame->settings(); // The FrameLoaderClient might block creation of a new WebGL context despite the page settings; in @@ -506,29 +78,30 @@ PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElemen return nullptr; } - GraphicsContext3D::Attributes requestedAttributes = attrs ? attrs->attributes() : GraphicsContext3D::Attributes(); - requestedAttributes.noExtensions = true; - requestedAttributes.shareResources = true; - requestedAttributes.preferDiscreteGPU = true; - requestedAttributes.topDocumentURL = document.topDocument()->url(); - - GraphicsContext3D::Attributes attributes = adjustAttributes(requestedAttributes, settings); - - RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(attributes)); - + // The only situation that attrs is null is through Document::getCSSCanvasContext(). + RefPtr<WebGLContextAttributes> defaultAttrs; + if (!attrs) { + defaultAttrs = WebGLContextAttributes::create(); + attrs = defaultAttrs.get(); + } + blink::WebGraphicsContext3D::Attributes attributes = attrs->attributes(document.topDocument().url().string(), settings); + OwnPtr<blink::WebGraphicsContext3D> context = adoptPtr(blink::Platform::current()->createOffscreenGraphicsContext3D(attributes, 0)); if (!context || !context->makeContextCurrent()) { canvas->dispatchEvent(WebGLContextEvent::create(EventTypeNames::webglcontextcreationerror, false, true, "Could not create a WebGL context.")); return nullptr; } - Extensions3D* extensions = context->extensions(); - if (extensions->supports("GL_EXT_debug_marker")) - extensions->pushGroupMarkerEXT("WebGLRenderingContext"); + OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(context.get()); + if (!extensionsUtil) + return nullptr; + if (extensionsUtil->supportsExtension("GL_EXT_debug_marker")) + context->pushGroupMarkerEXT("WebGLRenderingContext"); - OwnPtr<WebGLRenderingContext> renderingContext = adoptPtr(new WebGLRenderingContext(canvas, context, attributes, requestedAttributes)); + OwnPtrWillBeRawPtr<WebGLRenderingContext> renderingContext = adoptPtrWillBeNoop(new WebGLRenderingContext(canvas, context.release(), attrs)); + renderingContext->registerContextExtensions(); renderingContext->suspendIfNeeded(); - if (renderingContext->m_drawingBuffer->isZeroSized()) { + if (!renderingContext->m_drawingBuffer) { canvas->dispatchEvent(WebGLContextEvent::create(EventTypeNames::webglcontextcreationerror, false, true, "Could not create a WebGL context.")); return nullptr; } @@ -536,53 +109,25 @@ PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElemen return renderingContext.release(); } -WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassRefPtr<GraphicsContext3D> context, GraphicsContext3D::Attributes attributes, GraphicsContext3D::Attributes requestedAttributes) - : 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_requestedAttributes(requestedAttributes) - , m_synthesizedErrorsToConsole(true) - , m_numGLErrorsToConsoleAllowed(maxGLErrorsAllowedToConsole) - , m_multisamplingAllowed(false) - , m_multisamplingObserverRegistered(false) - , m_onePlusMaxEnabledAttribIndex(0) - , m_onePlusMaxNonDefaultTextureUnit(0) +WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassOwnPtr<blink::WebGraphicsContext3D> context, WebGLContextAttributes* requestedAttributes) + : WebGLRenderingContextBase(passedCanvas, context, requestedAttributes) { - ASSERT(m_context); ScriptWrappable::init(this); +} - m_contextGroup = WebGLContextGroup::create(); - m_contextGroup->addContext(this); - - m_maxViewportDims[0] = m_maxViewportDims[1] = 0; - m_context->getIntegerv(GL_MAX_VIEWPORT_DIMS, m_maxViewportDims); - - RefPtr<WebGLRenderingContextEvictionManager> contextEvictionManager = adoptRef(new WebGLRenderingContextEvictionManager()); - - // Create the DrawingBuffer and initialize the platform layer. - DrawingBuffer::PreserveDrawingBuffer preserve = m_attributes.preserveDrawingBuffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard; - m_drawingBuffer = DrawingBuffer::create(m_context.get(), clampedCanvasSize(), preserve, contextEvictionManager.release()); +WebGLRenderingContext::~WebGLRenderingContext() +{ - if (!m_drawingBuffer->isZeroSized()) { - m_drawingBuffer->bind(); - setupFlags(); - initializeNewContext(); - } +} +void WebGLRenderingContext::registerContextExtensions() +{ // Register extensions. static const char* const webkitPrefix[] = { "WEBKIT_", 0, }; static const char* const bothPrefixes[] = { "", "WEBKIT_", 0, }; registerExtension<ANGLEInstancedArrays>(m_angleInstancedArrays); - registerExtension<EXTTextureFilterAnisotropic>(m_extTextureFilterAnisotropic, PrefixedExtension, webkitPrefix); + registerExtension<EXTTextureFilterAnisotropic>(m_extTextureFilterAnisotropic, ApprovedExtension, bothPrefixes); registerExtension<OESElementIndexUint>(m_oesElementIndexUint); registerExtension<OESStandardDerivatives>(m_oesStandardDerivatives); registerExtension<OESTextureFloat>(m_oesTextureFloat); @@ -590,5046 +135,20 @@ WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, Pa registerExtension<OESTextureHalfFloat>(m_oesTextureHalfFloat); registerExtension<OESTextureHalfFloatLinear>(m_oesTextureHalfFloatLinear); registerExtension<OESVertexArrayObject>(m_oesVertexArrayObject); - registerExtension<WebGLCompressedTextureATC>(m_webglCompressedTextureATC, PrefixedExtension, webkitPrefix); - registerExtension<WebGLCompressedTexturePVRTC>(m_webglCompressedTexturePVRTC, PrefixedExtension, webkitPrefix); - registerExtension<WebGLCompressedTextureS3TC>(m_webglCompressedTextureS3TC, PrefixedExtension, bothPrefixes); - registerExtension<WebGLDepthTexture>(m_webglDepthTexture, PrefixedExtension, bothPrefixes); + registerExtension<WebGLCompressedTextureATC>(m_webglCompressedTextureATC, EnabledDraftExtension, webkitPrefix); + registerExtension<WebGLCompressedTexturePVRTC>(m_webglCompressedTexturePVRTC, EnabledDraftExtension, webkitPrefix); + registerExtension<WebGLCompressedTextureS3TC>(m_webglCompressedTextureS3TC, ApprovedExtension, bothPrefixes); + registerExtension<WebGLDebugRendererInfo>(m_webglDebugRendererInfo); + registerExtension<WebGLDebugShaders>(m_webglDebugShaders); + registerExtension<WebGLDepthTexture>(m_webglDepthTexture, ApprovedExtension, bothPrefixes); registerExtension<WebGLDrawBuffers>(m_webglDrawBuffers); registerExtension<WebGLLoseContext>(m_webglLoseContext, ApprovedExtension, bothPrefixes); // Register draft extensions. + registerExtension<EXTBlendMinMax>(m_extBlendMinMax, DraftExtension); registerExtension<EXTFragDepth>(m_extFragDepth, DraftExtension); - - // Register privileged extensions. - registerExtension<WebGLDebugRendererInfo>(m_webglDebugRendererInfo, WebGLDebugRendererInfoExtension); - registerExtension<WebGLDebugShaders>(m_webglDebugShaders, PrivilegedExtension); -} - -void WebGLRenderingContext::initializeNewContext() -{ - ASSERT(!isContextLost()); - m_needsUpdate = true; - m_markedCanvasDirty = false; - m_activeTextureUnit = 0; - m_packAlignment = 4; - m_unpackAlignment = 4; - m_unpackFlipY = false; - m_unpackPremultiplyAlpha = false; - m_unpackColorspaceConversion = GC3D_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(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numCombinedTextureImageUnits); - m_textureUnits.clear(); - m_textureUnits.resize(numCombinedTextureImageUnits); - - GC3Dint numVertexAttribs = 0; - m_context->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &numVertexAttribs); - m_maxVertexAttribs = numVertexAttribs; - - m_maxTextureSize = 0; - m_context->getIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize); - m_maxTextureLevel = WebGLTexture::computeLevelCount(m_maxTextureSize, m_maxTextureSize); - m_maxCubeMapTextureSize = 0; - m_context->getIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &m_maxCubeMapTextureSize); - m_maxCubeMapTextureLevel = WebGLTexture::computeLevelCount(m_maxCubeMapTextureSize, m_maxCubeMapTextureSize); - m_maxRenderbufferSize = 0; - m_context->getIntegerv(GL_MAX_RENDERBUFFER_SIZE, &m_maxRenderbufferSize); - - // These two values from EXT_draw_buffers are lazily queried. - m_maxDrawBuffers = 0; - m_maxColorAttachments = 0; - - m_backDrawBuffer = GL_BACK; - - m_defaultVertexArrayObject = WebGLVertexArrayObjectOES::create(this, WebGLVertexArrayObjectOES::VaoTypeDefault); - addContextObject(m_defaultVertexArrayObject.get()); - m_boundVertexArrayObject = m_defaultVertexArrayObject; - - m_vertexAttribValue.resize(m_maxVertexAttribs); - - createFallbackBlackTextures1x1(); - - IntSize canvasSize = clampedCanvasSize(); - m_drawingBuffer->reset(canvasSize); - - 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))); - - // This ensures that the context has a valid "lastFlushID" and won't be mistakenly identified as the "least recently used" context. - m_context->flush(); - - activateContext(this); -} - -void WebGLRenderingContext::setupFlags() -{ - ASSERT(m_context); - if (Page* p = canvas()->document().page()) { - m_synthesizedErrorsToConsole = p->settings().webGLErrorsToConsoleEnabled(); - - if (!m_multisamplingObserverRegistered && m_requestedAttributes.antialias) { - m_multisamplingAllowed = m_drawingBuffer->multisample(); - p->addMultisamplingChangedObserver(this); - m_multisamplingObserverRegistered = true; - } - } - - m_isGLES2NPOTStrict = !m_context->extensions()->isEnabled("GL_OES_texture_npot"); - m_isDepthStencilSupported = m_context->extensions()->isEnabled("GL_OES_packed_depth_stencil"); -} - -bool WebGLRenderingContext::allowPrivilegedExtensions() const -{ - if (Page* p = canvas()->document().page()) - return p->settings().privilegedWebGLExtensionsEnabled(); - return false; -} - -bool WebGLRenderingContext::allowWebGLDebugRendererInfo() const -{ - return true; -} - -void WebGLRenderingContext::addCompressedTextureFormat(GC3Denum format) -{ - if (!m_compressedTextureFormats.contains(format)) - m_compressedTextureFormats.append(format); -} - -void WebGLRenderingContext::removeAllCompressedTextureFormats() -{ - m_compressedTextureFormats.clear(); -} - -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 = 0; - m_defaultVertexArrayObject = 0; - m_boundVertexArrayObject = 0; - m_vertexAttrib0Buffer = 0; - m_currentProgram = 0; - m_framebufferBinding = 0; - m_renderbufferBinding = 0; - - for (size_t i = 0; i < m_textureUnits.size(); ++i) { - m_textureUnits[i].m_texture2DBinding = 0; - m_textureUnits[i].m_textureCubeMapBinding = 0; - } - - m_blackTexture2D = 0; - m_blackTextureCubeMap = 0; - - detachAndRemoveAllObjects(); - - // release all extensions - for (size_t i = 0; i < m_extensions.size(); ++i) - delete m_extensions[i]; - - // Context must be removed from the group prior to the destruction of the - // GraphicsContext3D, otherwise shared objects may not be properly deleted. - m_contextGroup->removeContext(this); - - destroyGraphicsContext3D(); - - if (m_multisamplingObserverRegistered) { - Page* page = canvas()->document().page(); - if (page) - page->removeMultisamplingChangedObserver(this); - } - - willDestroyContext(this); -} - -void WebGLRenderingContext::destroyGraphicsContext3D() -{ - m_contextLost = true; - - // The drawing buffer holds a context reference. It must also be destroyed - // in order for the context to be released. - m_drawingBuffer->releaseResources(); - - if (m_context) { - m_context->setContextLostCallback(nullptr); - m_context->setErrorMessageCallback(nullptr); - m_context.clear(); - } -} - -void WebGLRenderingContext::markContextChanged() -{ - if (m_framebufferBinding || isContextLost()) - return; - - m_context->markContextChanged(); - m_drawingBuffer->markContentsChanged(); - - m_layerCleared = false; - RenderBox* renderBox = canvas()->renderBox(); - if (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 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(GL_SCISSOR_TEST); - if (combinedClear && (mask & GL_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 = GL_COLOR_BUFFER_BIT; - if (contextAttributes->depth()) { - if (!combinedClear || !m_depthMask || !(mask & GL_DEPTH_BUFFER_BIT)) - m_context->clearDepth(1.0f); - clearMask |= GL_DEPTH_BUFFER_BIT; - m_context->depthMask(true); - } - if (contextAttributes->stencil()) { - if (combinedClear && (mask & GL_STENCIL_BUFFER_BIT)) - m_context->clearStencil(m_clearStencil & m_stencilMask); - else - m_context->clearStencil(0); - clearMask |= GL_STENCIL_BUFFER_BIT; - m_context->stencilMaskSeparate(GL_FRONT, 0xFFFFFFFF); - } - - m_drawingBuffer->clearFramebuffers(clearMask); - - restoreStateAfterClear(); - if (m_framebufferBinding) - m_context->bindFramebuffer(GL_FRAMEBUFFER, objectOrZero(m_framebufferBinding.get())); - m_layerCleared = true; - - return combinedClear; -} - -void WebGLRenderingContext::restoreStateAfterClear() -{ - if (isContextLost()) - return; - - // Restore the state that the context set. - if (m_scissorEnabled) - m_context->enable(GL_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(GL_FRONT, m_stencilMask); - m_context->depthMask(m_depthMask); -} - -void WebGLRenderingContext::markLayerComposited() -{ - if (!isContextLost()) - m_context->markLayerComposited(); -} - -void WebGLRenderingContext::paintRenderingResultsToCanvas() -{ - if (isContextLost()) { - canvas()->clearPresentationCopy(); - 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_drawingBuffer->paintCompositedResultsToCanvas(canvas()->buffer()); - - canvas()->makePresentationCopy(); - } else - canvas()->clearPresentationCopy(); - clearIfComposited(); - - if (!m_markedCanvasDirty && !m_layerCleared) - return; - - canvas()->clearCopiedImage(); - m_markedCanvasDirty = false; - - m_drawingBuffer->commit(); - if (!(canvas()->buffer())->copyRenderingResultsFromDrawingBuffer(m_drawingBuffer.get())) { - canvas()->ensureUnacceleratedImageBuffer(); - if (canvas()->hasImageBuffer()) - m_context->paintRenderingResultsToCanvas(canvas()->buffer(), m_drawingBuffer.get()); - } - - if (m_framebufferBinding) - m_context->bindFramebuffer(GL_FRAMEBUFFER, objectOrZero(m_framebufferBinding.get())); - else - m_drawingBuffer->bind(); -} - -PassRefPtr<ImageData> WebGLRenderingContext::paintRenderingResultsToImageData() -{ - if (isContextLost()) - return 0; - - clearIfComposited(); - m_drawingBuffer->commit(); - int width, height; - RefPtr<Uint8ClampedArray> imageDataPixels = m_context->paintRenderingResultsToImageData(m_drawingBuffer.get(), width, height); - if (!imageDataPixels) - return 0; - - if (m_framebufferBinding) - m_context->bindFramebuffer(GL_FRAMEBUFFER, objectOrZero(m_framebufferBinding.get())); - else - m_drawingBuffer->bind(); - - return ImageData::create(IntSize(width, height), imageDataPixels); -} - -void WebGLRenderingContext::reshape(int width, int height) -{ - if (isContextLost()) - 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_drawingBuffer->reset(IntSize(width, height)); - restoreStateAfterClear(); - - m_context->bindTexture(GL_TEXTURE_2D, objectOrZero(m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get())); - m_context->bindRenderbuffer(GL_RENDERBUFFER, objectOrZero(m_renderbufferBinding.get())); - if (m_framebufferBinding) - m_context->bindFramebuffer(GL_FRAMEBUFFER, objectOrZero(m_framebufferBinding.get())); -} - -int WebGLRenderingContext::drawingBufferWidth() const -{ - return m_drawingBuffer->size().width(); -} - -int WebGLRenderingContext::drawingBufferHeight() const -{ - return m_drawingBuffer->size().height(); -} - -unsigned int WebGLRenderingContext::sizeInBytes(GC3Denum type) -{ - switch (type) { - case GL_BYTE: - return sizeof(GC3Dbyte); - case GL_UNSIGNED_BYTE: - return sizeof(GC3Dubyte); - case GL_SHORT: - return sizeof(GC3Dshort); - case GL_UNSIGNED_SHORT: - return sizeof(GC3Dushort); - case GL_INT: - return sizeof(GC3Dint); - case GL_UNSIGNED_INT: - return sizeof(GC3Duint); - case GL_FLOAT: - return sizeof(GC3Dfloat); - } - ASSERT_NOT_REACHED(); - return 0; -} - -void WebGLRenderingContext::activeTexture(GC3Denum texture) -{ - if (isContextLost()) - return; - if (texture - GL_TEXTURE0 >= m_textureUnits.size()) { - synthesizeGLError(GL_INVALID_ENUM, "activeTexture", "texture unit out of range"); - return; - } - m_activeTextureUnit = texture - GL_TEXTURE0; - m_context->activeTexture(texture); - - m_drawingBuffer->setActiveTextureUnit(texture); - -} - -void WebGLRenderingContext::attachShader(WebGLProgram* program, WebGLShader* shader) -{ - if (isContextLost() || !validateWebGLObject("attachShader", program) || !validateWebGLObject("attachShader", shader)) - return; - if (!program->attachShader(shader)) { - synthesizeGLError(GL_INVALID_OPERATION, "attachShader", "shader attachment already has shader"); - return; - } - m_context->attachShader(objectOrZero(program), objectOrZero(shader)); - shader->onAttached(); -} - -void WebGLRenderingContext::bindAttribLocation(WebGLProgram* program, GC3Duint index, const String& name) -{ - if (isContextLost() || !validateWebGLObject("bindAttribLocation", program)) - return; - if (!validateLocationLength("bindAttribLocation", name)) - return; - if (!validateString("bindAttribLocation", name)) - return; - if (isPrefixReserved(name)) { - synthesizeGLError(GL_INVALID_OPERATION, "bindAttribLocation", "reserved prefix"); - return; - } - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GL_INVALID_VALUE, "bindAttribLocation", "index out of range"); - return; - } - m_context->bindAttribLocation(objectOrZero(program), index, name); -} - -bool WebGLRenderingContext::checkObjectToBeBound(const char* functionName, WebGLObject* object, bool& deleted) -{ - deleted = false; - if (isContextLost()) - return false; - if (object) { - if (!object->validate(contextGroup(), this)) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "object not from this context"); - return false; - } - deleted = !object->object(); - } - return true; -} - -void WebGLRenderingContext::bindBuffer(GC3Denum target, WebGLBuffer* buffer) -{ - bool deleted; - if (!checkObjectToBeBound("bindBuffer", buffer, deleted)) - return; - if (deleted) - buffer = 0; - if (buffer && buffer->getTarget() && buffer->getTarget() != target) { - synthesizeGLError(GL_INVALID_OPERATION, "bindBuffer", "buffers can not be used with multiple targets"); - return; - } - if (target == GL_ARRAY_BUFFER) - m_boundArrayBuffer = buffer; - else if (target == GL_ELEMENT_ARRAY_BUFFER) - m_boundVertexArrayObject->setElementArrayBuffer(buffer); - else { - synthesizeGLError(GL_INVALID_ENUM, "bindBuffer", "invalid target"); - return; - } - - m_context->bindBuffer(target, objectOrZero(buffer)); - if (buffer) - buffer->setTarget(target); -} - -void WebGLRenderingContext::bindFramebuffer(GC3Denum target, WebGLFramebuffer* buffer) -{ - bool deleted; - if (!checkObjectToBeBound("bindFramebuffer", buffer, deleted)) - return; - if (deleted) - buffer = 0; - if (target != GL_FRAMEBUFFER) { - synthesizeGLError(GL_INVALID_ENUM, "bindFramebuffer", "invalid target"); - return; - } - m_framebufferBinding = buffer; - m_drawingBuffer->setFramebufferBinding(objectOrZero(m_framebufferBinding.get())); - if (!m_framebufferBinding) { - // Instead of binding fb 0, bind the drawing buffer. - m_drawingBuffer->bind(); - } else - m_context->bindFramebuffer(target, objectOrZero(buffer)); - if (buffer) - buffer->setHasEverBeenBound(); - applyStencilTest(); -} - -void WebGLRenderingContext::bindRenderbuffer(GC3Denum target, WebGLRenderbuffer* renderBuffer) -{ - bool deleted; - if (!checkObjectToBeBound("bindRenderbuffer", renderBuffer, deleted)) - return; - if (deleted) - renderBuffer = 0; - if (target != GL_RENDERBUFFER) { - synthesizeGLError(GL_INVALID_ENUM, "bindRenderbuffer", "invalid target"); - return; - } - m_renderbufferBinding = renderBuffer; - m_context->bindRenderbuffer(target, objectOrZero(renderBuffer)); - if (renderBuffer) - renderBuffer->setHasEverBeenBound(); -} - -void WebGLRenderingContext::bindTexture(GC3Denum target, WebGLTexture* texture) -{ - bool deleted; - if (!checkObjectToBeBound("bindTexture", texture, deleted)) - return; - if (deleted) - texture = 0; - if (texture && texture->getTarget() && texture->getTarget() != target) { - synthesizeGLError(GL_INVALID_OPERATION, "bindTexture", "textures can not be used with multiple targets"); - return; - } - GC3Dint maxLevel = 0; - if (target == GL_TEXTURE_2D) { - m_textureUnits[m_activeTextureUnit].m_texture2DBinding = texture; - maxLevel = m_maxTextureLevel; - - if (!m_activeTextureUnit) - m_drawingBuffer->setTexture2DBinding(objectOrZero(texture)); - - } else if (target == GL_TEXTURE_CUBE_MAP) { - m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding = texture; - maxLevel = m_maxCubeMapTextureLevel; - } else { - synthesizeGLError(GL_INVALID_ENUM, "bindTexture", "invalid target"); - return; - } - - m_context->bindTexture(target, objectOrZero(texture)); - if (texture) { - texture->setTarget(target, maxLevel); - m_onePlusMaxNonDefaultTextureUnit = max(m_activeTextureUnit + 1, m_onePlusMaxNonDefaultTextureUnit); - } else { - // If the disabled index is the current maximum, trace backwards to find the new max enabled texture index - if (m_onePlusMaxNonDefaultTextureUnit == m_activeTextureUnit + 1) { - findNewMaxNonDefaultTextureUnit(); - } - } - - // 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 WebGLRenderingContext::blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha) -{ - if (isContextLost()) - return; - m_context->blendColor(red, green, blue, alpha); -} - -void WebGLRenderingContext::blendEquation(GC3Denum mode) -{ - if (isContextLost() || !validateBlendEquation("blendEquation", mode)) - return; - m_context->blendEquation(mode); -} - -void WebGLRenderingContext::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha) -{ - if (isContextLost() || !validateBlendEquation("blendEquationSeparate", modeRGB) || !validateBlendEquation("blendEquationSeparate", modeAlpha)) - return; - m_context->blendEquationSeparate(modeRGB, modeAlpha); -} - - -void WebGLRenderingContext::blendFunc(GC3Denum sfactor, GC3Denum dfactor) -{ - if (isContextLost() || !validateBlendFuncFactors("blendFunc", sfactor, dfactor)) - return; - m_context->blendFunc(sfactor, dfactor); -} - -void WebGLRenderingContext::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha) -{ - // Note: Alpha does not have the same restrictions as RGB. - if (isContextLost() || !validateBlendFuncFactors("blendFuncSeparate", srcRGB, dstRGB)) - return; - m_context->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); -} - -void WebGLRenderingContext::bufferData(GC3Denum target, long long size, GC3Denum usage) -{ - if (isContextLost()) - return; - WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage); - if (!buffer) - return; - if (size < 0) { - synthesizeGLError(GL_INVALID_VALUE, "bufferData", "size < 0"); - return; - } - if (!size) { - synthesizeGLError(GL_INVALID_VALUE, "bufferData", "size == 0"); - return; - } - - m_context->bufferData(target, static_cast<GC3Dsizeiptr>(size), usage); -} - -void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBuffer* data, GC3Denum usage) -{ - if (isContextLost()) - return; - WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage); - if (!buffer) - return; - if (!data) { - synthesizeGLError(GL_INVALID_VALUE, "bufferData", "no data"); - return; - } - m_context->bufferData(target, data->byteLength(), data->data(), usage); -} - -void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBufferView* data, GC3Denum usage) -{ - if (isContextLost()) - return; - WebGLBuffer* buffer = validateBufferDataParameters("bufferData", target, usage); - if (!buffer) - return; - if (!data) { - synthesizeGLError(GL_INVALID_VALUE, "bufferData", "no data"); - return; - } - - m_context->bufferData(target, data->byteLength(), data->baseAddress(), usage); -} - -void WebGLRenderingContext::bufferSubData(GC3Denum target, long long offset, ArrayBuffer* data) -{ - if (isContextLost()) - return; - WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GL_STATIC_DRAW); - if (!buffer) - return; - if (offset < 0) { - synthesizeGLError(GL_INVALID_VALUE, "bufferSubData", "offset < 0"); - return; - } - if (!data) - return; - - m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byteLength(), data->data()); -} - -void WebGLRenderingContext::bufferSubData(GC3Denum target, long long offset, ArrayBufferView* data) -{ - if (isContextLost()) - return; - WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GL_STATIC_DRAW); - if (!buffer) - return; - if (offset < 0) { - synthesizeGLError(GL_INVALID_VALUE, "bufferSubData", "offset < 0"); - return; - } - if (!data) - return; - - m_context->bufferSubData(target, static_cast<GC3Dintptr>(offset), data->byteLength(), data->baseAddress()); -} - -GC3Denum WebGLRenderingContext::checkFramebufferStatus(GC3Denum target) -{ - if (isContextLost()) - return GL_FRAMEBUFFER_UNSUPPORTED; - if (target != GL_FRAMEBUFFER) { - synthesizeGLError(GL_INVALID_ENUM, "checkFramebufferStatus", "invalid target"); - return 0; - } - if (!m_framebufferBinding || !m_framebufferBinding->object()) - return GL_FRAMEBUFFER_COMPLETE; - const char* reason = "framebuffer incomplete"; - GC3Denum result = m_framebufferBinding->checkStatus(&reason); - if (result != GL_FRAMEBUFFER_COMPLETE) { - emitGLWarning("checkFramebufferStatus", reason); - return result; - } - result = m_context->checkFramebufferStatus(target); - return result; -} - -void WebGLRenderingContext::clear(GC3Dbitfield mask) -{ - if (isContextLost()) - return; - if (mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) { - synthesizeGLError(GL_INVALID_VALUE, "clear", "invalid mask"); - return; - } - const char* reason = "framebuffer incomplete"; - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { - synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, "clear", reason); - return; - } - if (!clearIfComposited(mask)) - m_context->clear(mask); - markContextChanged(); -} - -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); -} - -void WebGLRenderingContext::clearDepth(GC3Dfloat depth) -{ - if (isContextLost()) - return; - m_clearDepth = depth; - m_context->clearDepth(depth); -} - -void WebGLRenderingContext::clearStencil(GC3Dint s) -{ - if (isContextLost()) - return; - m_clearStencil = s; - m_context->clearStencil(s); -} - -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); -} - -void WebGLRenderingContext::compileShader(WebGLShader* shader) -{ - if (isContextLost() || !validateWebGLObject("compileShader", shader)) - return; - m_context->compileShader(objectOrZero(shader)); -} - -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(GL_INVALID_ENUM, "compressedTexImage2D", "invalid internalformat"); - return; - } - if (border) { - synthesizeGLError(GL_INVALID_VALUE, "compressedTexImage2D", "border not 0"); - return; - } - if (!validateCompressedTexDimensions("compressedTexImage2D", NotTexSubImage2D, 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(GL_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, GL_UNSIGNED_BYTE); -} - -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(GL_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(GL_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()); -} - -bool WebGLRenderingContext::validateSettableTexFormat(const char* functionName, GC3Denum format) -{ - if (GraphicsContext3D::getClearBitsByFormat(format) & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) { - synthesizeGLError(GL_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, GL_UNSIGNED_BYTE)) - return; - if (!validateSettableTexFormat("copyTexImage2D", internalformat)) - return; - WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true); - if (!tex) - return; - if (!isTexInternalFormatColorBufferCombinationValid(internalformat, boundFramebufferColorFormat())) { - synthesizeGLError(GL_INVALID_OPERATION, "copyTexImage2D", "framebuffer is incompatible format"); - return; - } - if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) { - synthesizeGLError(GL_INVALID_VALUE, "copyTexImage2D", "level > 0 not power of 2"); - return; - } - const char* reason = "framebuffer incomplete"; - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { - synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason); - return; - } - clearIfComposited(); - ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get()); - 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, GL_UNSIGNED_BYTE); -} - -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. - Checked<GC3Dint, RecordOverflow> maxX = xoffset; - maxX += width; - Checked<GC3Dint, RecordOverflow> maxY = yoffset; - maxY += height; - - if (maxX.hasOverflowed() || maxY.hasOverflowed()) { - synthesizeGLError(GL_INVALID_VALUE, "copyTexSubImage2D", "bad dimensions"); - return; - } - if (maxX.unsafeGet() > tex->getWidth(target, level) || maxY.unsafeGet() > tex->getHeight(target, level)) { - synthesizeGLError(GL_INVALID_VALUE, "copyTexSubImage2D", "rectangle out of range"); - return; - } - GC3Denum internalformat = tex->getInternalFormat(target, level); - if (!validateSettableTexFormat("copyTexSubImage2D", internalformat)) - return; - if (!isTexInternalFormatColorBufferCombinationValid(internalformat, boundFramebufferColorFormat())) { - synthesizeGLError(GL_INVALID_OPERATION, "copyTexSubImage2D", "framebuffer is incompatible format"); - return; - } - const char* reason = "framebuffer incomplete"; - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { - synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, "copyTexSubImage2D", reason); - return; - } - clearIfComposited(); - ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get()); - m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); -} - -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; -} - -WebGLRenderbuffer* WebGLRenderingContext::ensureEmulatedStencilBuffer(GC3Denum target, WebGLRenderbuffer* renderbuffer) -{ - if (isContextLost()) - return 0; - if (!renderbuffer->emulatedStencilBuffer()) { - renderbuffer->setEmulatedStencilBuffer(createRenderbuffer()); - m_context->bindRenderbuffer(target, objectOrZero(renderbuffer->emulatedStencilBuffer())); - m_context->bindRenderbuffer(target, objectOrZero(m_renderbufferBinding.get())); - } - return renderbuffer->emulatedStencilBuffer(); -} - -PassRefPtr<WebGLShader> WebGLRenderingContext::createShader(GC3Denum type) -{ - if (isContextLost()) - return 0; - if (type != GL_VERTEX_SHADER && type != GL_FRAGMENT_SHADER) { - synthesizeGLError(GL_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; - switch (mode) { - case GL_FRONT_AND_BACK: - case GL_FRONT: - case GL_BACK: - break; - default: - synthesizeGLError(GL_INVALID_ENUM, "cullFace", "invalid mode"); - return; - } - m_context->cullFace(mode); -} - -bool WebGLRenderingContext::deleteObject(WebGLObject* object) -{ - if (isContextLost() || !object) - return false; - if (!object->validate(contextGroup(), this)) { - synthesizeGLError(GL_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; - m_drawingBuffer->setFramebufferBinding(0); - // Have to call bindFramebuffer here to bind back to internal fbo. - m_drawingBuffer->bind(); - } -} - -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; - - int maxBoundTextureIndex = -1; - for (size_t i = 0; i < m_onePlusMaxNonDefaultTextureUnit; ++i) { - if (texture == m_textureUnits[i].m_texture2DBinding) { - m_textureUnits[i].m_texture2DBinding = 0; - maxBoundTextureIndex = i; - if (!i) - m_drawingBuffer->setTexture2DBinding(0); - } - if (texture == m_textureUnits[i].m_textureCubeMapBinding) { - m_textureUnits[i].m_textureCubeMapBinding = 0; - maxBoundTextureIndex = i; - } - } - if (m_framebufferBinding) - m_framebufferBinding->removeAttachmentFromBoundFramebuffer(texture); - - // If the deleted was bound to the the current maximum index, trace backwards to find the new max texture index - if (m_onePlusMaxNonDefaultTextureUnit == static_cast<unsigned long>(maxBoundTextureIndex + 1)) { - findNewMaxNonDefaultTextureUnit(); - } -} - -void WebGLRenderingContext::depthFunc(GC3Denum func) -{ - if (isContextLost()) - return; - if (!validateStencilOrDepthFunc("depthFunc", func)) - return; - m_context->depthFunc(func); -} - -void WebGLRenderingContext::depthMask(GC3Dboolean flag) -{ - if (isContextLost()) - return; - m_depthMask = flag; - m_context->depthMask(flag); -} - -void WebGLRenderingContext::depthRange(GC3Dfloat zNear, GC3Dfloat zFar) -{ - if (isContextLost()) - return; - if (zNear > zFar) { - synthesizeGLError(GL_INVALID_OPERATION, "depthRange", "zNear > zFar"); - return; - } - m_context->depthRange(zNear, zFar); -} - -void WebGLRenderingContext::detachShader(WebGLProgram* program, WebGLShader* shader) -{ - if (isContextLost() || !validateWebGLObject("detachShader", program) || !validateWebGLObject("detachShader", shader)) - return; - if (!program->detachShader(shader)) { - synthesizeGLError(GL_INVALID_OPERATION, "detachShader", "shader not attached"); - return; - } - m_context->detachShader(objectOrZero(program), objectOrZero(shader)); - shader->onDetached(graphicsContext3D()); -} - -void WebGLRenderingContext::disable(GC3Denum cap) -{ - if (isContextLost() || !validateCapability("disable", cap)) - return; - if (cap == GL_STENCIL_TEST) { - m_stencilEnabled = false; - applyStencilTest(); - return; - } - if (cap == GL_SCISSOR_TEST) { - m_scissorEnabled = false; - m_drawingBuffer->setScissorEnabled(m_scissorEnabled); - } - m_context->disable(cap); -} - -void WebGLRenderingContext::disableVertexAttribArray(GC3Duint index) -{ - if (isContextLost()) - return; - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GL_INVALID_VALUE, "disableVertexAttribArray", "index out of range"); - return; - } - - WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index); - state.enabled = false; - - // If the disabled index is the current maximum, trace backwards to find the new max enabled attrib index - if (m_onePlusMaxEnabledAttribIndex == index + 1) { - findNewMaxEnabledAttribIndex(); - } - - m_context->disableVertexAttribArray(index); -} - -bool WebGLRenderingContext::validateRenderingState() -{ - 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_onePlusMaxEnabledAttribIndex; ++i) { - const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(i); - if (state.enabled - && (!state.bufferBinding || !state.bufferBinding->object())) - return false; - } - - return true; -} - -bool WebGLRenderingContext::validateWebGLObject(const char* functionName, WebGLObject* object) -{ - if (!object || !object->object()) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "no object or object deleted"); - return false; - } - if (!object->validate(contextGroup(), this)) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "object does not belong to this context"); - return false; - } - return true; -} - -void WebGLRenderingContext::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count) -{ - if (!validateDrawArrays("drawArrays", mode, first, count)) - return; - - clearIfComposited(); - - handleTextureCompleteness("drawArrays", true); - m_context->drawArrays(mode, first, count); - handleTextureCompleteness("drawArrays", false); - markContextChanged(); -} - -void WebGLRenderingContext::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset) -{ - if (!validateDrawElements("drawElements", mode, count, type, offset)) - return; - - clearIfComposited(); - - handleTextureCompleteness("drawElements", true); - m_context->drawElements(mode, count, type, static_cast<GC3Dintptr>(offset)); - handleTextureCompleteness("drawElements", false); - markContextChanged(); -} - -void WebGLRenderingContext::drawArraysInstancedANGLE(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount) -{ - if (!validateDrawArrays("drawArraysInstancedANGLE", mode, first, count)) - return; - - if (!validateDrawInstanced("drawArraysInstancedANGLE", primcount)) - return; - - clearIfComposited(); - - handleTextureCompleteness("drawArraysInstancedANGLE", true); - m_context->extensions()->drawArraysInstancedANGLE(mode, first, count, primcount); - handleTextureCompleteness("drawArraysInstancedANGLE", false); - markContextChanged(); -} - -void WebGLRenderingContext::drawElementsInstancedANGLE(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset, GC3Dsizei primcount) -{ - if (!validateDrawElements("drawElementsInstancedANGLE", mode, count, type, offset)) - return; - - if (!validateDrawInstanced("drawElementsInstancedANGLE", primcount)) - return; - - clearIfComposited(); - - handleTextureCompleteness("drawElementsInstancedANGLE", true); - m_context->extensions()->drawElementsInstancedANGLE(mode, count, type, static_cast<GC3Dintptr>(offset), primcount); - handleTextureCompleteness("drawElementsInstancedANGLE", false); - markContextChanged(); -} - -void WebGLRenderingContext::enable(GC3Denum cap) -{ - if (isContextLost() || !validateCapability("enable", cap)) - return; - if (cap == GL_STENCIL_TEST) { - m_stencilEnabled = true; - applyStencilTest(); - return; - } - if (cap == GL_SCISSOR_TEST) { - m_scissorEnabled = true; - m_drawingBuffer->setScissorEnabled(m_scissorEnabled); - } - m_context->enable(cap); -} - -void WebGLRenderingContext::enableVertexAttribArray(GC3Duint index) -{ - if (isContextLost()) - return; - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GL_INVALID_VALUE, "enableVertexAttribArray", "index out of range"); - return; - } - - WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index); - state.enabled = true; - - m_onePlusMaxEnabledAttribIndex = max(index + 1, m_onePlusMaxEnabledAttribIndex); - - m_context->enableVertexAttribArray(index); -} - -void WebGLRenderingContext::finish() -{ - if (isContextLost()) - return; - m_context->flush(); // Intentionally a flush, not a finish. -} - -void WebGLRenderingContext::flush() -{ - if (isContextLost()) - return; - m_context->flush(); -} - -void WebGLRenderingContext::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer* buffer) -{ - if (isContextLost() || !validateFramebufferFuncParameters("framebufferRenderbuffer", target, attachment)) - return; - if (renderbuffertarget != GL_RENDERBUFFER) { - synthesizeGLError(GL_INVALID_ENUM, "framebufferRenderbuffer", "invalid target"); - return; - } - if (buffer && !buffer->validate(contextGroup(), this)) { - synthesizeGLError(GL_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(GL_INVALID_OPERATION, "framebufferRenderbuffer", "no framebuffer bound"); - return; - } - Platform3DObject bufferObject = objectOrZero(buffer); - switch (attachment) { - case GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL: - if (isDepthStencilSupported() || !buffer) { - m_context->framebufferRenderbuffer(target, GL_DEPTH_ATTACHMENT, renderbuffertarget, bufferObject); - m_context->framebufferRenderbuffer(target, GL_STENCIL_ATTACHMENT, renderbuffertarget, bufferObject); - } else { - WebGLRenderbuffer* emulatedStencilBuffer = ensureEmulatedStencilBuffer(renderbuffertarget, buffer); - if (!emulatedStencilBuffer) { - synthesizeGLError(GL_OUT_OF_MEMORY, "framebufferRenderbuffer", "out of memory"); - return; - } - m_context->framebufferRenderbuffer(target, GL_DEPTH_ATTACHMENT, renderbuffertarget, bufferObject); - m_context->framebufferRenderbuffer(target, GL_STENCIL_ATTACHMENT, renderbuffertarget, objectOrZero(emulatedStencilBuffer)); - } - break; - default: - m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, bufferObject); - } - m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, buffer); - applyStencilTest(); -} - -void WebGLRenderingContext::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture* texture, GC3Dint level) -{ - if (isContextLost() || !validateFramebufferFuncParameters("framebufferTexture2D", target, attachment)) - return; - if (level) { - synthesizeGLError(GL_INVALID_VALUE, "framebufferTexture2D", "level not 0"); - return; - } - if (texture && !texture->validate(contextGroup(), this)) { - synthesizeGLError(GL_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(GL_INVALID_OPERATION, "framebufferTexture2D", "no framebuffer bound"); - return; - } - Platform3DObject textureObject = objectOrZero(texture); - switch (attachment) { - case GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL: - m_context->framebufferTexture2D(target, GL_DEPTH_ATTACHMENT, textarget, textureObject, level); - m_context->framebufferTexture2D(target, GL_STENCIL_ATTACHMENT, textarget, textureObject, level); - break; - case GL_DEPTH_ATTACHMENT: - m_context->framebufferTexture2D(target, attachment, textarget, textureObject, level); - break; - case GL_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 WebGLRenderingContext::frontFace(GC3Denum mode) -{ - if (isContextLost()) - return; - switch (mode) { - case GL_CW: - case GL_CCW: - break; - default: - synthesizeGLError(GL_INVALID_ENUM, "frontFace", "invalid mode"); - return; - } - m_context->frontFace(mode); -} - -void WebGLRenderingContext::generateMipmap(GC3Denum target) -{ - if (isContextLost()) - return; - WebGLTexture* tex = validateTextureBinding("generateMipmap", target, false); - if (!tex) - return; - if (!tex->canGenerateMipmaps()) { - synthesizeGLError(GL_INVALID_OPERATION, "generateMipmap", "level 0 not power of 2 or not all the same size"); - 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(MACOSX) - bool needToResetMinFilter = false; - if (tex->getMinFilter() != GL_NEAREST_MIPMAP_LINEAR) { - m_context->texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); - needToResetMinFilter = true; - } -#endif - m_context->generateMipmap(target); -#if OS(MACOSX) - if (needToResetMinFilter) - m_context->texParameteri(target, GL_TEXTURE_MIN_FILTER, tex->getMinFilter()); -#endif - tex->generateMipmapLevelInfo(); -} - -PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveAttrib(WebGLProgram* program, GC3Duint index) -{ - if (isContextLost() || !validateWebGLObject("getActiveAttrib", program)) - return 0; - ActiveInfo info; - if (!m_context->getActiveAttrib(objectOrZero(program), index, info)) - return 0; - return WebGLActiveInfo::create(info.name, info.type, info.size); -} - -PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveUniform(WebGLProgram* program, GC3Duint index) -{ - if (isContextLost() || !validateWebGLObject("getActiveUniform", program)) - return 0; - ActiveInfo info; - if (!m_context->getActiveUniform(objectOrZero(program), index, info)) - return 0; - return WebGLActiveInfo::create(info.name, info.type, info.size); -} - -bool WebGLRenderingContext::getAttachedShaders(WebGLProgram* program, Vector<RefPtr<WebGLShader> >& shaderObjects) -{ - shaderObjects.clear(); - if (isContextLost() || !validateWebGLObject("getAttachedShaders", program)) - return false; - - const GC3Denum shaderType[] = { - GL_VERTEX_SHADER, - GL_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->linkStatus()) { - synthesizeGLError(GL_INVALID_OPERATION, "getAttribLocation", "program not linked"); - return 0; - } - return m_context->getAttribLocation(objectOrZero(program), name); -} - -WebGLGetInfo WebGLRenderingContext::getBufferParameter(GC3Denum target, GC3Denum pname) -{ - if (isContextLost()) - return WebGLGetInfo(); - if (target != GL_ARRAY_BUFFER && target != GL_ELEMENT_ARRAY_BUFFER) { - synthesizeGLError(GL_INVALID_ENUM, "getBufferParameter", "invalid target"); - return WebGLGetInfo(); - } - - if (pname != GL_BUFFER_SIZE && pname != GL_BUFFER_USAGE) { - synthesizeGLError(GL_INVALID_ENUM, "getBufferParameter", "invalid parameter name"); - return WebGLGetInfo(); - } - - GC3Dint value = 0; - m_context->getBufferParameteriv(target, pname, &value); - if (pname == GL_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); - // 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() -{ - if (lost_context_errors_.size()) { - GC3Denum err = lost_context_errors_.first(); - lost_context_errors_.remove(0); - return err; - } - - if (isContextLost()) - return GL_NO_ERROR; - - return m_context->getError(); -} - -bool WebGLRenderingContext::ExtensionTracker::matchesNameWithPrefixes(const String& name) const -{ - static const char* const unprefixed[] = { "", 0, }; - - const char* const* prefixes = m_prefixes ? m_prefixes : unprefixed; - for (; *prefixes; ++prefixes) { - String prefixedName = String(*prefixes) + extensionName(); - if (equalIgnoringCase(prefixedName, name)) { - return true; - } - } - return false; -} - -PassRefPtr<WebGLExtension> WebGLRenderingContext::getExtension(const String& name) -{ - if (isContextLost()) - return 0; - - for (size_t i = 0; i < m_extensions.size(); ++i) { - ExtensionTracker* tracker = m_extensions[i]; - if (tracker->matchesNameWithPrefixes(name)) { - if (tracker->webglDebugRendererInfo() && !allowWebGLDebugRendererInfo()) - return 0; - if (tracker->privileged() && !allowPrivilegedExtensions()) - return 0; - if (tracker->draft() && !RuntimeEnabledFeatures::webGLDraftExtensionsEnabled()) - return 0; - if (!tracker->supported(this)) - return 0; - return tracker->getExtension(this); - } - } - - return 0; -} - -WebGLGetInfo WebGLRenderingContext::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname) -{ - if (isContextLost() || !validateFramebufferFuncParameters("getFramebufferAttachmentParameter", target, attachment)) - return WebGLGetInfo(); - - if (!m_framebufferBinding || !m_framebufferBinding->object()) { - synthesizeGLError(GL_INVALID_OPERATION, "getFramebufferAttachmentParameter", "no framebuffer bound"); - return WebGLGetInfo(); - } - - WebGLSharedObject* object = m_framebufferBinding->getAttachmentObject(attachment); - if (!object) { - if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) - return WebGLGetInfo(GL_NONE); - // OpenGL ES 2.0 specifies INVALID_ENUM in this case, while desktop GL - // specifies INVALID_OPERATION. - synthesizeGLError(GL_INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name"); - return WebGLGetInfo(); - } - - ASSERT(object->isTexture() || object->isRenderbuffer()); - if (object->isTexture()) { - switch (pname) { - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: - return WebGLGetInfo(GL_TEXTURE); - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: - return WebGLGetInfo(PassRefPtr<WebGLTexture>(static_cast<WebGLTexture*>(object))); - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: - { - GC3Dint value = 0; - m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value); - return WebGLGetInfo(value); - } - default: - synthesizeGLError(GL_INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for texture attachment"); - return WebGLGetInfo(); - } - } else { - switch (pname) { - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: - return WebGLGetInfo(GL_RENDERBUFFER); - case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: - return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(static_cast<WebGLRenderbuffer*>(object))); - default: - synthesizeGLError(GL_INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for renderbuffer attachment"); - return WebGLGetInfo(); - } - } -} - -WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname) -{ - if (isContextLost()) - return WebGLGetInfo(); - const int intZero = 0; - switch (pname) { - case GL_ACTIVE_TEXTURE: - return getUnsignedIntParameter(pname); - case GL_ALIASED_LINE_WIDTH_RANGE: - return getWebGLFloatArrayParameter(pname); - case GL_ALIASED_POINT_SIZE_RANGE: - return getWebGLFloatArrayParameter(pname); - case GL_ALPHA_BITS: - return getIntParameter(pname); - case GL_ARRAY_BUFFER_BINDING: - return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundArrayBuffer)); - case GL_BLEND: - return getBooleanParameter(pname); - case GL_BLEND_COLOR: - return getWebGLFloatArrayParameter(pname); - case GL_BLEND_DST_ALPHA: - return getUnsignedIntParameter(pname); - case GL_BLEND_DST_RGB: - return getUnsignedIntParameter(pname); - case GL_BLEND_EQUATION_ALPHA: - return getUnsignedIntParameter(pname); - case GL_BLEND_EQUATION_RGB: - return getUnsignedIntParameter(pname); - case GL_BLEND_SRC_ALPHA: - return getUnsignedIntParameter(pname); - case GL_BLEND_SRC_RGB: - return getUnsignedIntParameter(pname); - case GL_BLUE_BITS: - return getIntParameter(pname); - case GL_COLOR_CLEAR_VALUE: - return getWebGLFloatArrayParameter(pname); - case GL_COLOR_WRITEMASK: - return getBooleanArrayParameter(pname); - case GL_COMPRESSED_TEXTURE_FORMATS: - return WebGLGetInfo(Uint32Array::create(m_compressedTextureFormats.data(), m_compressedTextureFormats.size())); - case GL_CULL_FACE: - return getBooleanParameter(pname); - case GL_CULL_FACE_MODE: - return getUnsignedIntParameter(pname); - case GL_CURRENT_PROGRAM: - return WebGLGetInfo(PassRefPtr<WebGLProgram>(m_currentProgram)); - case GL_DEPTH_BITS: - if (!m_framebufferBinding && !m_attributes.depth) - return WebGLGetInfo(intZero); - return getIntParameter(pname); - case GL_DEPTH_CLEAR_VALUE: - return getFloatParameter(pname); - case GL_DEPTH_FUNC: - return getUnsignedIntParameter(pname); - case GL_DEPTH_RANGE: - return getWebGLFloatArrayParameter(pname); - case GL_DEPTH_TEST: - return getBooleanParameter(pname); - case GL_DEPTH_WRITEMASK: - return getBooleanParameter(pname); - case GL_DITHER: - return getBooleanParameter(pname); - case GL_ELEMENT_ARRAY_BUFFER_BINDING: - return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundVertexArrayObject->boundElementArrayBuffer())); - case GL_FRAMEBUFFER_BINDING: - return WebGLGetInfo(PassRefPtr<WebGLFramebuffer>(m_framebufferBinding)); - case GL_FRONT_FACE: - return getUnsignedIntParameter(pname); - case GL_GENERATE_MIPMAP_HINT: - return getUnsignedIntParameter(pname); - case GL_GREEN_BITS: - return getIntParameter(pname); - case GL_LINE_WIDTH: - return getFloatParameter(pname); - case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: - return getIntParameter(pname); - case GL_MAX_CUBE_MAP_TEXTURE_SIZE: - return getIntParameter(pname); - case GL_MAX_FRAGMENT_UNIFORM_VECTORS: - return getIntParameter(pname); - case GL_MAX_RENDERBUFFER_SIZE: - return getIntParameter(pname); - case GL_MAX_TEXTURE_IMAGE_UNITS: - return getIntParameter(pname); - case GL_MAX_TEXTURE_SIZE: - return getIntParameter(pname); - case GL_MAX_VARYING_VECTORS: - return getIntParameter(pname); - case GL_MAX_VERTEX_ATTRIBS: - return getIntParameter(pname); - case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: - return getIntParameter(pname); - case GL_MAX_VERTEX_UNIFORM_VECTORS: - return getIntParameter(pname); - case GL_MAX_VIEWPORT_DIMS: - return getWebGLIntArrayParameter(pname); - case GL_NUM_SHADER_BINARY_FORMATS: - // FIXME: should we always return 0 for this? - return getIntParameter(pname); - case GL_PACK_ALIGNMENT: - return getIntParameter(pname); - case GL_POLYGON_OFFSET_FACTOR: - return getFloatParameter(pname); - case GL_POLYGON_OFFSET_FILL: - return getBooleanParameter(pname); - case GL_POLYGON_OFFSET_UNITS: - return getFloatParameter(pname); - case GL_RED_BITS: - return getIntParameter(pname); - case GL_RENDERBUFFER_BINDING: - return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(m_renderbufferBinding)); - case GL_RENDERER: - return WebGLGetInfo(String("WebKit WebGL")); - case GL_SAMPLE_BUFFERS: - return getIntParameter(pname); - case GL_SAMPLE_COVERAGE_INVERT: - return getBooleanParameter(pname); - case GL_SAMPLE_COVERAGE_VALUE: - return getFloatParameter(pname); - case GL_SAMPLES: - return getIntParameter(pname); - case GL_SCISSOR_BOX: - return getWebGLIntArrayParameter(pname); - case GL_SCISSOR_TEST: - return getBooleanParameter(pname); - case GL_SHADING_LANGUAGE_VERSION: - return WebGLGetInfo("WebGL GLSL ES 1.0 (" + m_context->getString(GL_SHADING_LANGUAGE_VERSION) + ")"); - case GL_STENCIL_BACK_FAIL: - return getUnsignedIntParameter(pname); - case GL_STENCIL_BACK_FUNC: - return getUnsignedIntParameter(pname); - case GL_STENCIL_BACK_PASS_DEPTH_FAIL: - return getUnsignedIntParameter(pname); - case GL_STENCIL_BACK_PASS_DEPTH_PASS: - return getUnsignedIntParameter(pname); - case GL_STENCIL_BACK_REF: - return getIntParameter(pname); - case GL_STENCIL_BACK_VALUE_MASK: - return getUnsignedIntParameter(pname); - case GL_STENCIL_BACK_WRITEMASK: - return getUnsignedIntParameter(pname); - case GL_STENCIL_BITS: - if (!m_framebufferBinding && !m_attributes.stencil) - return WebGLGetInfo(intZero); - return getIntParameter(pname); - case GL_STENCIL_CLEAR_VALUE: - return getIntParameter(pname); - case GL_STENCIL_FAIL: - return getUnsignedIntParameter(pname); - case GL_STENCIL_FUNC: - return getUnsignedIntParameter(pname); - case GL_STENCIL_PASS_DEPTH_FAIL: - return getUnsignedIntParameter(pname); - case GL_STENCIL_PASS_DEPTH_PASS: - return getUnsignedIntParameter(pname); - case GL_STENCIL_REF: - return getIntParameter(pname); - case GL_STENCIL_TEST: - return getBooleanParameter(pname); - case GL_STENCIL_VALUE_MASK: - return getUnsignedIntParameter(pname); - case GL_STENCIL_WRITEMASK: - return getUnsignedIntParameter(pname); - case GL_SUBPIXEL_BITS: - return getIntParameter(pname); - case GL_TEXTURE_BINDING_2D: - return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].m_texture2DBinding)); - case GL_TEXTURE_BINDING_CUBE_MAP: - return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding)); - case GL_UNPACK_ALIGNMENT: - return getIntParameter(pname); - case GC3D_UNPACK_FLIP_Y_WEBGL: - return WebGLGetInfo(m_unpackFlipY); - case GC3D_UNPACK_PREMULTIPLY_ALPHA_WEBGL: - return WebGLGetInfo(m_unpackPremultiplyAlpha); - case GC3D_UNPACK_COLORSPACE_CONVERSION_WEBGL: - return WebGLGetInfo(m_unpackColorspaceConversion); - case GL_VENDOR: - return WebGLGetInfo(String("WebKit")); - case GL_VERSION: - return WebGLGetInfo("WebGL 1.0 (" + m_context->getString(GL_VERSION) + ")"); - case GL_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(GL_INVALID_ENUM, "getParameter", "invalid parameter name, OES_standard_derivatives not enabled"); - return WebGLGetInfo(); - case WebGLDebugRendererInfo::UNMASKED_RENDERER_WEBGL: - if (m_webglDebugRendererInfo) - return WebGLGetInfo(m_context->getString(GL_RENDERER)); - synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled"); - return WebGLGetInfo(); - case WebGLDebugRendererInfo::UNMASKED_VENDOR_WEBGL: - if (m_webglDebugRendererInfo) - return WebGLGetInfo(m_context->getString(GL_VENDOR)); - synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled"); - return WebGLGetInfo(); - 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(); - } - synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, OES_vertex_array_object not enabled"); - return WebGLGetInfo(); - case Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic - if (m_extTextureFilterAnisotropic) - return getUnsignedIntParameter(Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT); - synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled"); - return WebGLGetInfo(); - case Extensions3D::MAX_COLOR_ATTACHMENTS_EXT: // EXT_draw_buffers BEGIN - if (m_webglDrawBuffers) - return WebGLGetInfo(maxColorAttachments()); - synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled"); - return WebGLGetInfo(); - case Extensions3D::MAX_DRAW_BUFFERS_EXT: - if (m_webglDrawBuffers) - return WebGLGetInfo(maxDrawBuffers()); - synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled"); - return WebGLGetInfo(); - default: - if (m_webglDrawBuffers - && pname >= Extensions3D::DRAW_BUFFER0_EXT - && pname < static_cast<GC3Denum>(Extensions3D::DRAW_BUFFER0_EXT + maxDrawBuffers())) { - GC3Dint value = GL_NONE; - if (m_framebufferBinding) - value = m_framebufferBinding->getDrawBuffer(pname); - else // emulated backbuffer - value = m_backDrawBuffer; - return WebGLGetInfo(value); - } - synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name"); - return WebGLGetInfo(); - } -} - -WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, GC3Denum pname) -{ - if (isContextLost() || !validateWebGLObject("getProgramParameter", program)) - return WebGLGetInfo(); - - GC3Dint value = 0; - switch (pname) { - case GL_DELETE_STATUS: - return WebGLGetInfo(program->isDeleted()); - case GL_VALIDATE_STATUS: - m_context->getProgramiv(objectOrZero(program), pname, &value); - return WebGLGetInfo(static_cast<bool>(value)); - case GL_LINK_STATUS: - return WebGLGetInfo(program->linkStatus()); - case GL_ATTACHED_SHADERS: - case GL_ACTIVE_ATTRIBUTES: - case GL_ACTIVE_UNIFORMS: - m_context->getProgramiv(objectOrZero(program), pname, &value); - return WebGLGetInfo(value); - default: - synthesizeGLError(GL_INVALID_ENUM, "getProgramParameter", "invalid parameter name"); - return WebGLGetInfo(); - } -} - -String WebGLRenderingContext::getProgramInfoLog(WebGLProgram* program) -{ - if (isContextLost()) - return String(); - if (!validateWebGLObject("getProgramInfoLog", program)) - return ""; - return ensureNotNull(m_context->getProgramInfoLog(objectOrZero(program))); -} - -WebGLGetInfo WebGLRenderingContext::getRenderbufferParameter(GC3Denum target, GC3Denum pname) -{ - if (isContextLost()) - return WebGLGetInfo(); - if (target != GL_RENDERBUFFER) { - synthesizeGLError(GL_INVALID_ENUM, "getRenderbufferParameter", "invalid target"); - return WebGLGetInfo(); - } - if (!m_renderbufferBinding || !m_renderbufferBinding->object()) { - synthesizeGLError(GL_INVALID_OPERATION, "getRenderbufferParameter", "no renderbuffer bound"); - return WebGLGetInfo(); - } - - GC3Dint value = 0; - switch (pname) { - case GL_RENDERBUFFER_WIDTH: - case GL_RENDERBUFFER_HEIGHT: - case GL_RENDERBUFFER_RED_SIZE: - case GL_RENDERBUFFER_GREEN_SIZE: - case GL_RENDERBUFFER_BLUE_SIZE: - case GL_RENDERBUFFER_ALPHA_SIZE: - case GL_RENDERBUFFER_DEPTH_SIZE: - m_context->getRenderbufferParameteriv(target, pname, &value); - return WebGLGetInfo(value); - case GL_RENDERBUFFER_STENCIL_SIZE: - if (m_renderbufferBinding->emulatedStencilBuffer()) { - m_context->bindRenderbuffer(target, objectOrZero(m_renderbufferBinding->emulatedStencilBuffer())); - m_context->getRenderbufferParameteriv(target, pname, &value); - m_context->bindRenderbuffer(target, objectOrZero(m_renderbufferBinding.get())); - } else { - m_context->getRenderbufferParameteriv(target, pname, &value); - } - return WebGLGetInfo(value); - case GL_RENDERBUFFER_INTERNAL_FORMAT: - return WebGLGetInfo(m_renderbufferBinding->internalFormat()); - default: - synthesizeGLError(GL_INVALID_ENUM, "getRenderbufferParameter", "invalid parameter name"); - return WebGLGetInfo(); - } -} - -WebGLGetInfo WebGLRenderingContext::getShaderParameter(WebGLShader* shader, GC3Denum pname) -{ - if (isContextLost() || !validateWebGLObject("getShaderParameter", shader)) - return WebGLGetInfo(); - GC3Dint value = 0; - switch (pname) { - case GL_DELETE_STATUS: - return WebGLGetInfo(shader->isDeleted()); - case GL_COMPILE_STATUS: - m_context->getShaderiv(objectOrZero(shader), pname, &value); - return WebGLGetInfo(static_cast<bool>(value)); - case GL_SHADER_TYPE: - m_context->getShaderiv(objectOrZero(shader), pname, &value); - return WebGLGetInfo(static_cast<unsigned int>(value)); - default: - synthesizeGLError(GL_INVALID_ENUM, "getShaderParameter", "invalid parameter name"); - return WebGLGetInfo(); - } -} - -String WebGLRenderingContext::getShaderInfoLog(WebGLShader* shader) -{ - if (isContextLost()) - return String(); - if (!validateWebGLObject("getShaderInfoLog", shader)) - return ""; - return ensureNotNull(m_context->getShaderInfoLog(objectOrZero(shader))); -} - -PassRefPtr<WebGLShaderPrecisionFormat> WebGLRenderingContext::getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType) -{ - if (isContextLost()) - return 0; - switch (shaderType) { - case GL_VERTEX_SHADER: - case GL_FRAGMENT_SHADER: - break; - default: - synthesizeGLError(GL_INVALID_ENUM, "getShaderPrecisionFormat", "invalid shader type"); - return 0; - } - switch (precisionType) { - case GL_LOW_FLOAT: - case GL_MEDIUM_FLOAT: - case GL_HIGH_FLOAT: - case GL_LOW_INT: - case GL_MEDIUM_INT: - case GL_HIGH_INT: - break; - default: - synthesizeGLError(GL_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) -{ - if (isContextLost()) - return String(); - if (!validateWebGLObject("getShaderSource", shader)) - return ""; - return ensureNotNull(shader->source()); -} - -Vector<String> WebGLRenderingContext::getSupportedExtensions() -{ - Vector<String> result; - if (isContextLost()) - return result; - - for (size_t i = 0; i < m_extensions.size(); ++i) { - ExtensionTracker* tracker = m_extensions[i]; - if (tracker->webglDebugRendererInfo() && !allowWebGLDebugRendererInfo()) - continue; - if (tracker->privileged() && !allowPrivilegedExtensions()) - continue; - if (tracker->draft() && !RuntimeEnabledFeatures::webGLDraftExtensionsEnabled()) - continue; - if (tracker->supported(this)) - result.append(String(tracker->prefixed() ? "WEBKIT_" : "") + tracker->extensionName()); - } - - return result; -} - -WebGLGetInfo WebGLRenderingContext::getTexParameter(GC3Denum target, GC3Denum pname) -{ - if (isContextLost()) - return WebGLGetInfo(); - WebGLTexture* tex = validateTextureBinding("getTexParameter", target, false); - if (!tex) - return WebGLGetInfo(); - GC3Dint value = 0; - switch (pname) { - case GL_TEXTURE_MAG_FILTER: - case GL_TEXTURE_MIN_FILTER: - case GL_TEXTURE_WRAP_S: - case GL_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(GL_INVALID_ENUM, "getTexParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled"); - return WebGLGetInfo(); - default: - synthesizeGLError(GL_INVALID_ENUM, "getTexParameter", "invalid parameter name"); - return WebGLGetInfo(); - } -} - -WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebGLUniformLocation* uniformLocation) -{ - if (isContextLost() || !validateWebGLObject("getUniform", program)) - return WebGLGetInfo(); - if (!uniformLocation || uniformLocation->program() != program) { - synthesizeGLError(GL_INVALID_OPERATION, "getUniform", "no uniformlocation or not valid for this program"); - return WebGLGetInfo(); - } - GC3Dint location = uniformLocation->location(); - - // FIXME: make this more efficient using WebGLUniformLocation and caching types in it - GC3Dint activeUniforms = 0; - m_context->getProgramiv(objectOrZero(program), GL_ACTIVE_UNIFORMS, &activeUniforms); - for (GC3Dint i = 0; i < activeUniforms; i++) { - ActiveInfo info; - if (!m_context->getActiveUniform(objectOrZero(program), i, info)) - return WebGLGetInfo(); - // Strip "[0]" from the name if it's an array. - if (info.size > 1 && 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 name = info.name; - if (info.size > 1 && index >= 1) { - name.append('['); - name.append(String::number(index)); - name.append(']'); - } - // Now need to look this up by name again to find its location - GC3Dint loc = m_context->getUniformLocation(objectOrZero(program), name); - if (loc == location) { - // Found it. Use the type in the ActiveInfo to determine the return type. - GC3Denum baseType; - unsigned int length; - switch (info.type) { - case GL_BOOL: - baseType = GL_BOOL; - length = 1; - break; - case GL_BOOL_VEC2: - baseType = GL_BOOL; - length = 2; - break; - case GL_BOOL_VEC3: - baseType = GL_BOOL; - length = 3; - break; - case GL_BOOL_VEC4: - baseType = GL_BOOL; - length = 4; - break; - case GL_INT: - baseType = GL_INT; - length = 1; - break; - case GL_INT_VEC2: - baseType = GL_INT; - length = 2; - break; - case GL_INT_VEC3: - baseType = GL_INT; - length = 3; - break; - case GL_INT_VEC4: - baseType = GL_INT; - length = 4; - break; - case GL_FLOAT: - baseType = GL_FLOAT; - length = 1; - break; - case GL_FLOAT_VEC2: - baseType = GL_FLOAT; - length = 2; - break; - case GL_FLOAT_VEC3: - baseType = GL_FLOAT; - length = 3; - break; - case GL_FLOAT_VEC4: - baseType = GL_FLOAT; - length = 4; - break; - case GL_FLOAT_MAT2: - baseType = GL_FLOAT; - length = 4; - break; - case GL_FLOAT_MAT3: - baseType = GL_FLOAT; - length = 9; - break; - case GL_FLOAT_MAT4: - baseType = GL_FLOAT; - length = 16; - break; - case GL_SAMPLER_2D: - case GL_SAMPLER_CUBE: - baseType = GL_INT; - length = 1; - break; - default: - // Can't handle this type - synthesizeGLError(GL_INVALID_VALUE, "getUniform", "unhandled type"); - return WebGLGetInfo(); - } - switch (baseType) { - case GL_FLOAT: { - GC3Dfloat value[16] = {0}; - m_context->getUniformfv(objectOrZero(program), location, value); - if (length == 1) - return WebGLGetInfo(value[0]); - return WebGLGetInfo(Float32Array::create(value, length)); - } - case GL_INT: { - GC3Dint value[4] = {0}; - m_context->getUniformiv(objectOrZero(program), location, value); - if (length == 1) - return WebGLGetInfo(value[0]); - return WebGLGetInfo(Int32Array::create(value, length)); - } - case GL_BOOL: { - GC3Dint value[4] = {0}; - 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(GL_INVALID_VALUE, "getUniform", "unknown error"); - return WebGLGetInfo(); -} - -PassRefPtr<WebGLUniformLocation> WebGLRenderingContext::getUniformLocation(WebGLProgram* program, const String& name) -{ - if (isContextLost() || !validateWebGLObject("getUniformLocation", program)) - return 0; - if (!validateLocationLength("getUniformLocation", name)) - return 0; - if (!validateString("getUniformLocation", name)) - return 0; - if (isPrefixReserved(name)) - return 0; - if (!program->linkStatus()) { - synthesizeGLError(GL_INVALID_OPERATION, "getUniformLocation", "program not linked"); - return 0; - } - GC3Dint uniformLocation = m_context->getUniformLocation(objectOrZero(program), name); - if (uniformLocation == -1) - return 0; - return WebGLUniformLocation::create(program, uniformLocation); -} - -WebGLGetInfo WebGLRenderingContext::getVertexAttrib(GC3Duint index, GC3Denum pname) -{ - if (isContextLost()) - return WebGLGetInfo(); - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GL_INVALID_VALUE, "getVertexAttrib", "index out of range"); - return WebGLGetInfo(); - } - const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index); - - if (m_angleInstancedArrays && pname == Extensions3D::VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE) - return WebGLGetInfo(state.divisor); - - switch (pname) { - case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: - if (!state.bufferBinding || !state.bufferBinding->object()) - return WebGLGetInfo(); - return WebGLGetInfo(PassRefPtr<WebGLBuffer>(state.bufferBinding)); - case GL_VERTEX_ATTRIB_ARRAY_ENABLED: - return WebGLGetInfo(state.enabled); - case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: - return WebGLGetInfo(state.normalized); - case GL_VERTEX_ATTRIB_ARRAY_SIZE: - return WebGLGetInfo(state.size); - case GL_VERTEX_ATTRIB_ARRAY_STRIDE: - return WebGLGetInfo(state.originalStride); - case GL_VERTEX_ATTRIB_ARRAY_TYPE: - return WebGLGetInfo(state.type); - case GL_CURRENT_VERTEX_ATTRIB: - return WebGLGetInfo(Float32Array::create(m_vertexAttribValue[index].value, 4)); - default: - synthesizeGLError(GL_INVALID_ENUM, "getVertexAttrib", "invalid parameter name"); - return WebGLGetInfo(); - } -} - -long long WebGLRenderingContext::getVertexAttribOffset(GC3Duint index, GC3Denum pname) -{ - if (isContextLost()) - return 0; - if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER) { - synthesizeGLError(GL_INVALID_ENUM, "getVertexAttribOffset", "invalid parameter name"); - return 0; - } - GC3Dsizeiptr result = m_context->getVertexAttribOffset(index, pname); - return static_cast<long long>(result); -} - -void WebGLRenderingContext::hint(GC3Denum target, GC3Denum mode) -{ - if (isContextLost()) - return; - bool isValid = false; - switch (target) { - case GL_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(GL_INVALID_ENUM, "hint", "invalid target"); - return; - } - m_context->hint(target, mode); -} - -GC3Dboolean WebGLRenderingContext::isBuffer(WebGLBuffer* buffer) -{ - if (!buffer || isContextLost()) - return 0; - - if (!buffer->hasEverBeenBound()) - return 0; - - return m_context->isBuffer(buffer->object()); -} - -bool WebGLRenderingContext::isContextLost() -{ - return m_contextLost; -} - -GC3Dboolean WebGLRenderingContext::isEnabled(GC3Denum cap) -{ - if (isContextLost() || !validateCapability("isEnabled", cap)) - return 0; - if (cap == GL_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) -{ - if (!shader || isContextLost()) - return 0; - - return m_context->isShader(shader->object()); -} - -GC3Dboolean WebGLRenderingContext::isTexture(WebGLTexture* texture) -{ - if (!texture || isContextLost()) - return 0; - - if (!texture->hasEverBeenBound()) - return 0; - - return m_context->isTexture(texture->object()); -} - -void WebGLRenderingContext::lineWidth(GC3Dfloat width) -{ - if (isContextLost()) - return; - m_context->lineWidth(width); -} - -void WebGLRenderingContext::linkProgram(WebGLProgram* program) -{ - if (isContextLost() || !validateWebGLObject("linkProgram", program)) - return; - - m_context->linkProgram(objectOrZero(program)); - program->increaseLinkCount(); -} - -void WebGLRenderingContext::pixelStorei(GC3Denum pname, GC3Dint param) -{ - if (isContextLost()) - return; - switch (pname) { - case GC3D_UNPACK_FLIP_Y_WEBGL: - m_unpackFlipY = param; - break; - case GC3D_UNPACK_PREMULTIPLY_ALPHA_WEBGL: - m_unpackPremultiplyAlpha = param; - break; - case GC3D_UNPACK_COLORSPACE_CONVERSION_WEBGL: - if (static_cast<GC3Denum>(param) == GC3D_BROWSER_DEFAULT_WEBGL || param == GL_NONE) - m_unpackColorspaceConversion = static_cast<GC3Denum>(param); - else { - synthesizeGLError(GL_INVALID_VALUE, "pixelStorei", "invalid parameter for UNPACK_COLORSPACE_CONVERSION_WEBGL"); - return; - } - break; - case GL_PACK_ALIGNMENT: - case GL_UNPACK_ALIGNMENT: - if (param == 1 || param == 2 || param == 4 || param == 8) { - if (pname == GL_PACK_ALIGNMENT) - m_packAlignment = param; - else // GL_UNPACK_ALIGNMENT: - m_unpackAlignment = param; - m_context->pixelStorei(pname, param); - } else { - synthesizeGLError(GL_INVALID_VALUE, "pixelStorei", "invalid parameter for alignment"); - return; - } - break; - default: - synthesizeGLError(GL_INVALID_ENUM, "pixelStorei", "invalid parameter name"); - return; - } -} - -void WebGLRenderingContext::polygonOffset(GC3Dfloat factor, GC3Dfloat units) -{ - if (isContextLost()) - return; - m_context->polygonOffset(factor, units); -} - -void WebGLRenderingContext::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels) -{ - 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(GL_INVALID_VALUE, "readPixels", "no destination ArrayBufferView"); - return; - } - switch (format) { - case GL_ALPHA: - case GL_RGB: - case GL_RGBA: - break; - default: - synthesizeGLError(GL_INVALID_ENUM, "readPixels", "invalid format"); - return; - } - switch (type) { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT_5_6_5: - case GL_UNSIGNED_SHORT_4_4_4_4: - case GL_UNSIGNED_SHORT_5_5_5_1: - break; - default: - synthesizeGLError(GL_INVALID_ENUM, "readPixels", "invalid type"); - return; - } - if (format != GL_RGBA || type != GL_UNSIGNED_BYTE) { - synthesizeGLError(GL_INVALID_OPERATION, "readPixels", "format not RGBA or type not UNSIGNED_BYTE"); - return; - } - // Validate array type against pixel type. - if (pixels->getType() != ArrayBufferView::TypeUint8) { - synthesizeGLError(GL_INVALID_OPERATION, "readPixels", "ArrayBufferView not Uint8Array"); - return; - } - const char* reason = "framebuffer incomplete"; - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { - synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, "readPixels", reason); - return; - } - // Calculate array size, taking into consideration of PACK_ALIGNMENT. - unsigned int totalBytesRequired = 0; - unsigned int padding = 0; - GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding); - if (error != GL_NO_ERROR) { - synthesizeGLError(error, "readPixels", "invalid dimensions"); - return; - } - if (pixels->byteLength() < totalBytesRequired) { - synthesizeGLError(GL_INVALID_OPERATION, "readPixels", "ArrayBufferView not large enough for dimensions"); - return; - } - - clearIfComposited(); - void* data = pixels->baseAddress(); - - { - ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get()); - m_context->readPixels(x, y, width, height, format, type, data); - } - -#if OS(MACOSX) - // FIXME: remove this section when GL driver bug on Mac 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 -} - -void WebGLRenderingContext::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) -{ - if (isContextLost()) - return; - if (target != GL_RENDERBUFFER) { - synthesizeGLError(GL_INVALID_ENUM, "renderbufferStorage", "invalid target"); - return; - } - if (!m_renderbufferBinding || !m_renderbufferBinding->object()) { - synthesizeGLError(GL_INVALID_OPERATION, "renderbufferStorage", "no bound renderbuffer"); - return; - } - if (!validateSize("renderbufferStorage", width, height)) - return; - switch (internalformat) { - case GL_DEPTH_COMPONENT16: - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGB565: - case GL_STENCIL_INDEX8: - m_context->renderbufferStorage(target, internalformat, width, height); - m_renderbufferBinding->setInternalFormat(internalformat); - m_renderbufferBinding->setSize(width, height); - m_renderbufferBinding->deleteEmulatedStencilBuffer(m_context.get()); - break; - case GL_DEPTH_STENCIL_OES: - if (isDepthStencilSupported()) { - m_context->renderbufferStorage(target, Extensions3D::DEPTH24_STENCIL8, width, height); - } else { - WebGLRenderbuffer* emulatedStencilBuffer = ensureEmulatedStencilBuffer(target, m_renderbufferBinding.get()); - if (!emulatedStencilBuffer) { - synthesizeGLError(GL_OUT_OF_MEMORY, "renderbufferStorage", "out of memory"); - return; - } - m_context->renderbufferStorage(target, GL_DEPTH_COMPONENT16, width, height); - m_context->bindRenderbuffer(target, objectOrZero(emulatedStencilBuffer)); - m_context->renderbufferStorage(target, GL_STENCIL_INDEX8, width, height); - m_context->bindRenderbuffer(target, objectOrZero(m_renderbufferBinding.get())); - emulatedStencilBuffer->setSize(width, height); - emulatedStencilBuffer->setInternalFormat(GL_STENCIL_INDEX8); - } - m_renderbufferBinding->setSize(width, height); - m_renderbufferBinding->setInternalFormat(internalformat); - break; - default: - synthesizeGLError(GL_INVALID_ENUM, "renderbufferStorage", "invalid internalformat"); - return; - } - applyStencilTest(); -} - -void WebGLRenderingContext::sampleCoverage(GC3Dfloat value, GC3Dboolean invert) -{ - if (isContextLost()) - return; - m_context->sampleCoverage(value, invert); -} - -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); -} - -void WebGLRenderingContext::shaderSource(WebGLShader* shader, const String& string) -{ - 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); -} - -void WebGLRenderingContext::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask) -{ - if (isContextLost()) - return; - if (!validateStencilOrDepthFunc("stencilFunc", func)) - return; - m_stencilFuncRef = ref; - m_stencilFuncRefBack = ref; - m_stencilFuncMask = mask; - m_stencilFuncMaskBack = mask; - m_context->stencilFunc(func, ref, mask); -} - -void WebGLRenderingContext::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask) -{ - if (isContextLost()) - return; - if (!validateStencilOrDepthFunc("stencilFuncSeparate", func)) - return; - switch (face) { - case GL_FRONT_AND_BACK: - m_stencilFuncRef = ref; - m_stencilFuncRefBack = ref; - m_stencilFuncMask = mask; - m_stencilFuncMaskBack = mask; - break; - case GL_FRONT: - m_stencilFuncRef = ref; - m_stencilFuncMask = mask; - break; - case GL_BACK: - m_stencilFuncRefBack = ref; - m_stencilFuncMaskBack = mask; - break; - default: - synthesizeGLError(GL_INVALID_ENUM, "stencilFuncSeparate", "invalid face"); - return; - } - m_context->stencilFuncSeparate(face, func, ref, mask); -} - -void WebGLRenderingContext::stencilMask(GC3Duint mask) -{ - if (isContextLost()) - return; - m_stencilMask = mask; - m_stencilMaskBack = mask; - m_context->stencilMask(mask); -} - -void WebGLRenderingContext::stencilMaskSeparate(GC3Denum face, GC3Duint mask) -{ - if (isContextLost()) - return; - switch (face) { - case GL_FRONT_AND_BACK: - m_stencilMask = mask; - m_stencilMaskBack = mask; - break; - case GL_FRONT: - m_stencilMask = mask; - break; - case GL_BACK: - m_stencilMaskBack = mask; - break; - default: - synthesizeGLError(GL_INVALID_ENUM, "stencilMaskSeparate", "invalid face"); - return; - } - m_context->stencilMaskSeparate(face, mask); -} - -void WebGLRenderingContext::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass) -{ - if (isContextLost()) - return; - m_context->stencilOp(fail, zfail, zpass); -} - -void WebGLRenderingContext::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass) -{ - if (isContextLost()) - return; - m_context->stencilOpSeparate(face, fail, zfail, zpass); -} - -void WebGLRenderingContext::texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels, ExceptionState& exceptionState) -{ - // All calling functions check isContextLost, so a duplicate check is not needed here. - // FIXME: Handle errors. - 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)); - ASSERT(!pixels || validateSettableTexFormat("texImage2D", internalformat)); - m_context->texImage2D(target, level, internalformat, width, height, - border, format, type, pixels); - tex->setLevelInfo(target, level, internalformat, width, height, type); -} - -void WebGLRenderingContext::texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionState& exceptionState) -{ - // All calling functions check isContextLost, so a duplicate check is not needed here. - Vector<uint8_t> data; - GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GL_NONE); - if (!imageExtractor.extractSucceeded()) { - synthesizeGLError(GL_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 == GL_UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GL_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(GL_INVALID_VALUE, "texImage2D", "packImage error"); - return; - } - } - - if (m_unpackAlignment != 1) - m_context->pixelStorei(GL_UNPACK_ALIGNMENT, 1); - texImage2DBase(target, level, internalformat, image->width(), image->height(), 0, format, type, needConversion ? data.data() : imagePixelData, exceptionState); - if (m_unpackAlignment != 1) - m_context->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); -} - -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) -{ - 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 == NotTexSubImage2D) { - if (level && WebGLTexture::isNPOT(width, height)) { - synthesizeGLError(GL_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(GL_INVALID_VALUE, functionName, "bad dimensions"); - return false; - } - if (xoffset + width > texture->getWidth(target, level) || yoffset + height > texture->getHeight(target, level)) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "dimensions out of range"); - return false; - } - if (texture->getInternalFormat(target, level) != format || texture->getType(target, level) != type) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "type and format do not match texture"); - return false; - } - } - - return true; -} - -PassRefPtr<Image> WebGLRenderingContext::drawImageIntoBuffer(Image* image, int width, int height) -{ - IntSize size(width, height); - ImageBuffer* buf = m_generatedImageCache.imageBuffer(size); - if (!buf) { - synthesizeGLError(GL_OUT_OF_MEMORY, "texImage2D", "out of memory"); - return 0; - } - - IntRect srcRect(IntPoint(), image->size()); - IntRect destRect(0, 0, size.width(), size.height()); - buf->context()->drawImage(image, destRect, srcRect); - return buf->copyImage(ImageBuffer::fastCopyImageMode()); -} - -void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Dsizei width, GC3Dsizei height, GC3Dint border, - GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionState& exceptionState) -{ - 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(GL_UNPACK_ALIGNMENT, 1); - texImage2DBase(target, level, internalformat, width, height, border, format, type, data, exceptionState); - if (changeUnpackAlignment) - m_context->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); -} - -void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionState& exceptionState) -{ - 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 == GL_RGBA && type == GL_UNSIGNED_BYTE) - needConversion = false; - else { - if (!m_context->extractImageData(pixels->data()->data(), pixels->size(), format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) { - synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "bad image data"); - return; - } - } - if (m_unpackAlignment != 1) - m_context->pixelStorei(GL_UNPACK_ALIGNMENT, 1); - texImage2DBase(target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, needConversion ? data.data() : pixels->data()->data(), exceptionState); - if (m_unpackAlignment != 1) - m_context->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); -} - -void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionState& exceptionState) -{ - if (isContextLost() || !validateHTMLImageElement("texImage2D", image, exceptionState)) - return; - - RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer()); - if (imageForRender->isSVGImage()) - imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height()); - - 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, exceptionState); -} - -void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionState& exceptionState) -{ - if (isContextLost() || !validateHTMLCanvasElement("texImage2D", canvas, exceptionState) || !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. - if (GL_TEXTURE_2D == target && texture) { - if (!canvas->is3D()) { - ImageBuffer* buffer = canvas->buffer(); - if (buffer && buffer->copyToPlatformTexture(*m_context.get(), texture->object(), internalformat, type, - level, m_unpackPremultiplyAlpha, m_unpackFlipY)) { - texture->setLevelInfo(target, level, internalformat, canvas->width(), canvas->height(), type); - return; - } - } else { - WebGLRenderingContext* gl = toWebGLRenderingContext(canvas->renderingContext()); - if (gl && gl->m_drawingBuffer->copyToPlatformTexture(*m_context.get(), texture->object(), internalformat, type, - level, 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, imageData.get(), exceptionState); - else - texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState); -} - -PassRefPtr<Image> WebGLRenderingContext::videoFrameToImage(HTMLVideoElement* video, BackingStoreCopy backingStoreCopy) -{ - IntSize size(video->videoWidth(), video->videoHeight()); - ImageBuffer* buf = m_generatedImageCache.imageBuffer(size); - if (!buf) { - synthesizeGLError(GL_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, ExceptionState& exceptionState) -{ - if (isContextLost() || !validateHTMLVideoElement("texImage2D", video, exceptionState) - || !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. - WebGLTexture* texture = validateTextureBinding("texImage2D", target, true); - if (GL_TEXTURE_2D == target && texture) { - 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); - return; - } - } - - // Normal pure SW path. - RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode()); - if (!image) - return; - texImage2DImpl(target, level, internalformat, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState); -} - -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 GL_TEXTURE_MIN_FILTER: - case GL_TEXTURE_MAG_FILTER: - break; - case GL_TEXTURE_WRAP_S: - case GL_TEXTURE_WRAP_T: - if ((isFloat && paramf != GL_CLAMP_TO_EDGE && paramf != GL_MIRRORED_REPEAT && paramf != GL_REPEAT) - || (!isFloat && parami != GL_CLAMP_TO_EDGE && parami != GL_MIRRORED_REPEAT && parami != GL_REPEAT)) { - synthesizeGLError(GL_INVALID_ENUM, "texParameter", "invalid parameter"); - return; - } - break; - case Extensions3D::TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic - if (!m_extTextureFilterAnisotropic) { - synthesizeGLError(GL_INVALID_ENUM, "texParameter", "invalid parameter, EXT_texture_filter_anisotropic not enabled"); - return; - } - break; - default: - synthesizeGLError(GL_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 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, ExceptionState& exceptionState) -{ - // FIXME: Handle errors. - 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); -} - -void WebGLRenderingContext::texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image* image, GraphicsContext3D::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionState& exceptionState) -{ - // All calling functions check isContextLost, so a duplicate check is not needed here. - Vector<uint8_t> data; - GraphicsContext3D::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GL_NONE); - if (!imageExtractor.extractSucceeded()) { - synthesizeGLError(GL_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 == GL_UNSIGNED_BYTE && sourceDataFormat == GraphicsContext3D::DataFormatRGBA8 && format == GL_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(GL_INVALID_VALUE, "texImage2D", "bad image data"); - return; - } - } - - if (m_unpackAlignment != 1) - m_context->pixelStorei(GL_UNPACK_ALIGNMENT, 1); - texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(), format, type, needConversion ? data.data() : imagePixelData, exceptionState); - if (m_unpackAlignment != 1) - m_context->pixelStorei(GL_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, ExceptionState& exceptionState) -{ - 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(GL_UNPACK_ALIGNMENT, 1); - texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, type, data, exceptionState); - if (changeUnpackAlignment) - m_context->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); -} - -void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionState& exceptionState) -{ - 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 == GL_RGBA && type == GL_UNSIGNED_BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha) - needConversion = false; - else { - if (!m_context->extractImageData(pixels->data()->data(), pixels->size(), format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) { - synthesizeGLError(GL_INVALID_VALUE, "texSubImage2D", "bad image data"); - return; - } - } - if (m_unpackAlignment != 1) - m_context->pixelStorei(GL_UNPACK_ALIGNMENT, 1); - texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(), format, type, needConversion ? data.data() : pixels->data()->data(), exceptionState); - if (m_unpackAlignment != 1) - m_context->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); -} - -void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionState& exceptionState) -{ - if (isContextLost() || !validateHTMLImageElement("texSubImage2D", image, exceptionState)) - return; - - RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer()); - if (imageForRender->isSVGImage()) - imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height()); - - 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, exceptionState); -} - -void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionState& exceptionState) -{ - if (isContextLost() || !validateHTMLCanvasElement("texSubImage2D", canvas, exceptionState) - || !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(), exceptionState); - else - texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), GraphicsContext3D::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState); -} - -void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionState& exceptionState) -{ - if (isContextLost() || !validateHTMLVideoElement("texSubImage2D", video, exceptionState) - || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLVideoElement, target, level, format, video->videoWidth(), video->videoHeight(), 0, format, type, xoffset, yoffset)) - return; - - RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode()); - if (!image) - return; - texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), GraphicsContext3D::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState); -} - -void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, GC3Dfloat x) -{ - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GL_INVALID_OPERATION, "uniform1f", "location not for current program"); - return; - } - - m_context->uniform1f(location->location(), x); -} - -void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Float32Array* v) -{ - if (isContextLost() || !validateUniformParameters("uniform1fv", location, v, 1)) - return; - - m_context->uniform1fv(location->location(), v->length(), v->data()); -} - -void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size) -{ - if (isContextLost() || !validateUniformParameters("uniform1fv", location, v, size, 1)) - return; - - m_context->uniform1fv(location->location(), size, v); -} - -void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, GC3Dint x) -{ - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GL_INVALID_OPERATION, "uniform1i", "location not for current program"); - return; - } - - m_context->uniform1i(location->location(), x); -} - -void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Int32Array* v) -{ - if (isContextLost() || !validateUniformParameters("uniform1iv", location, v, 1)) - return; - - m_context->uniform1iv(location->location(), v->length(), v->data()); -} - -void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size) -{ - if (isContextLost() || !validateUniformParameters("uniform1iv", location, v, size, 1)) - return; - - m_context->uniform1iv(location->location(), size, v); -} - -void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y) -{ - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GL_INVALID_OPERATION, "uniform2f", "location not for current program"); - return; - } - - m_context->uniform2f(location->location(), x, y); -} - -void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Float32Array* v) -{ - if (isContextLost() || !validateUniformParameters("uniform2fv", location, v, 2)) - return; - - m_context->uniform2fv(location->location(), v->length() / 2, v->data()); -} - -void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size) -{ - if (isContextLost() || !validateUniformParameters("uniform2fv", location, v, size, 2)) - return; - - m_context->uniform2fv(location->location(), size / 2, v); -} - -void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y) -{ - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GL_INVALID_OPERATION, "uniform2i", "location not for current program"); - return; - } - - m_context->uniform2i(location->location(), x, y); -} - -void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Int32Array* v) -{ - if (isContextLost() || !validateUniformParameters("uniform2iv", location, v, 2)) - return; - - m_context->uniform2iv(location->location(), v->length() / 2, v->data()); -} - -void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size) -{ - if (isContextLost() || !validateUniformParameters("uniform2iv", location, v, size, 2)) - return; - - m_context->uniform2iv(location->location(), size / 2, v); -} - -void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z) -{ - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GL_INVALID_OPERATION, "uniform3f", "location not for current program"); - return; - } - - m_context->uniform3f(location->location(), x, y, z); -} - -void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Float32Array* v) -{ - if (isContextLost() || !validateUniformParameters("uniform3fv", location, v, 3)) - return; - - m_context->uniform3fv(location->location(), v->length() / 3, v->data()); -} - -void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size) -{ - if (isContextLost() || !validateUniformParameters("uniform3fv", location, v, size, 3)) - return; - - m_context->uniform3fv(location->location(), size / 3, v); -} - -void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z) -{ - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GL_INVALID_OPERATION, "uniform3i", "location not for current program"); - return; - } - - m_context->uniform3i(location->location(), x, y, z); -} - -void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Int32Array* v) -{ - if (isContextLost() || !validateUniformParameters("uniform3iv", location, v, 3)) - return; - - m_context->uniform3iv(location->location(), v->length() / 3, v->data()); -} - -void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size) -{ - if (isContextLost() || !validateUniformParameters("uniform3iv", location, v, size, 3)) - return; - - m_context->uniform3iv(location->location(), size / 3, v); -} - -void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w) -{ - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GL_INVALID_OPERATION, "uniform4f", "location not for current program"); - return; - } - - m_context->uniform4f(location->location(), x, y, z, w); -} - -void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Float32Array* v) -{ - if (isContextLost() || !validateUniformParameters("uniform4fv", location, v, 4)) - return; - - m_context->uniform4fv(location->location(), v->length() / 4, v->data()); -} - -void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size) -{ - if (isContextLost() || !validateUniformParameters("uniform4fv", location, v, size, 4)) - return; - - m_context->uniform4fv(location->location(), size / 4, v); -} - -void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w) -{ - if (isContextLost() || !location) - return; - - if (location->program() != m_currentProgram) { - synthesizeGLError(GL_INVALID_OPERATION, "uniform4i", "location not for current program"); - return; - } - - m_context->uniform4i(location->location(), x, y, z, w); -} - -void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Int32Array* v) -{ - if (isContextLost() || !validateUniformParameters("uniform4iv", location, v, 4)) - return; - - m_context->uniform4iv(location->location(), v->length() / 4, v->data()); -} - -void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size) -{ - if (isContextLost() || !validateUniformParameters("uniform4iv", location, v, size, 4)) - return; - - m_context->uniform4iv(location->location(), size / 4, v); -} - -void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v) -{ - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, 4)) - return; - m_context->uniformMatrix2fv(location->location(), v->length() / 4, transpose, v->data()); -} - -void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size) -{ - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, size, 4)) - return; - m_context->uniformMatrix2fv(location->location(), size / 4, transpose, v); -} - -void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v) -{ - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, 9)) - return; - m_context->uniformMatrix3fv(location->location(), v->length() / 9, transpose, v->data()); -} - -void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size) -{ - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, size, 9)) - return; - m_context->uniformMatrix3fv(location->location(), size / 9, transpose, v); -} - -void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v) -{ - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, 16)) - return; - m_context->uniformMatrix4fv(location->location(), v->length() / 16, transpose, v->data()); -} - -void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size) -{ - if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, size, 16)) - return; - m_context->uniformMatrix4fv(location->location(), size / 16, transpose, v); -} - -void WebGLRenderingContext::useProgram(WebGLProgram* program) -{ - bool deleted; - if (!checkObjectToBeBound("useProgram", program, deleted)) - return; - if (deleted) - program = 0; - if (program && !program->linkStatus()) { - synthesizeGLError(GL_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 WebGLRenderingContext::validateProgram(WebGLProgram* program) -{ - if (isContextLost() || !validateWebGLObject("validateProgram", program)) - return; - m_context->validateProgram(objectOrZero(program)); -} - -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) -{ - if (isContextLost()) - return; - switch (type) { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - case GL_SHORT: - case GL_UNSIGNED_SHORT: - case GL_FLOAT: - break; - default: - synthesizeGLError(GL_INVALID_ENUM, "vertexAttribPointer", "invalid type"); - return; - } - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GL_INVALID_VALUE, "vertexAttribPointer", "index out of range"); - return; - } - if (size < 1 || size > 4 || stride < 0 || stride > 255 || offset < 0) { - synthesizeGLError(GL_INVALID_VALUE, "vertexAttribPointer", "bad size, stride or offset"); - return; - } - if (!m_boundArrayBuffer) { - synthesizeGLError(GL_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(GL_INVALID_ENUM, "vertexAttribPointer", "invalid type"); - return; - } - if ((stride % typeSize) || (static_cast<GC3Dintptr>(offset) % typeSize)) { - synthesizeGLError(GL_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 WebGLRenderingContext::vertexAttribDivisorANGLE(GC3Duint index, GC3Duint divisor) -{ - if (isContextLost()) - return; - - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GL_INVALID_VALUE, "vertexAttribDivisorANGLE", "index out of range"); - return; - } - - m_boundVertexArrayObject->setVertexAttribDivisor(index, divisor); - m_context->extensions()->vertexAttribDivisorANGLE(index, divisor); -} - -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); -} - -void WebGLRenderingContext::forceLostContext(WebGLRenderingContext::LostContextMode mode) -{ - if (isContextLost()) { - synthesizeGLError(GL_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->extensions()->getGraphicsResetStatusARB()); - } - - // Make absolutely sure we do not refer to an already-deleted texture or framebuffer. - m_drawingBuffer->setTexture2DBinding(0); - m_drawingBuffer->setFramebufferBinding(0); - - detachAndRemoveAllObjects(); - - // Lose all the extensions. - for (size_t i = 0; i < m_extensions.size(); ++i) { - ExtensionTracker* tracker = m_extensions[i]; - tracker->loseExtension(); - } - - removeAllCompressedTextureFormats(); - - if (mode != RealLostContext) - destroyGraphicsContext3D(); - - ConsoleDisplayPreference display = (mode == RealLostContext) ? DisplayInConsole: DontDisplayInConsole; - synthesizeGLError(GC3D_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(GL_INVALID_OPERATION, "restoreContext", "context not lost"); - return; - } - - if (!m_restoreAllowed) { - if (m_contextLostMode == SyntheticLostContext) - synthesizeGLError(GL_INVALID_OPERATION, "restoreContext", "context restoration not allowed"); - return; - } - - if (!m_restoreTimer.isActive()) - m_restoreTimer.startOneShot(0); -} - -blink::WebLayer* WebGLRenderingContext::platformLayer() const -{ - return m_drawingBuffer->platformLayer(); -} - -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; - if (!isContextLost()) - m_context->getBooleanv(pname, &value); - return WebGLGetInfo(static_cast<bool>(value)); -} - -WebGLGetInfo WebGLRenderingContext::getBooleanArrayParameter(GC3Denum pname) -{ - if (pname != GL_COLOR_WRITEMASK) { - notImplemented(); - return WebGLGetInfo(0, 0); - } - GC3Dboolean value[4] = {0}; - if (!isContextLost()) - 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; - if (!isContextLost()) - m_context->getFloatv(pname, &value); - return WebGLGetInfo(value); -} - -WebGLGetInfo WebGLRenderingContext::getIntParameter(GC3Denum pname) -{ - GC3Dint value = 0; - if (!isContextLost()) - m_context->getIntegerv(pname, &value); - return WebGLGetInfo(value); -} - -WebGLGetInfo WebGLRenderingContext::getUnsignedIntParameter(GC3Denum pname) -{ - GC3Dint value = 0; - if (!isContextLost()) - m_context->getIntegerv(pname, &value); - return WebGLGetInfo(static_cast<unsigned int>(value)); -} - -WebGLGetInfo WebGLRenderingContext::getWebGLFloatArrayParameter(GC3Denum pname) -{ - GC3Dfloat value[4] = {0}; - if (!isContextLost()) - m_context->getFloatv(pname, value); - unsigned length = 0; - switch (pname) { - case GL_ALIASED_POINT_SIZE_RANGE: - case GL_ALIASED_LINE_WIDTH_RANGE: - case GL_DEPTH_RANGE: - length = 2; - break; - case GL_BLEND_COLOR: - case GL_COLOR_CLEAR_VALUE: - length = 4; - break; - default: - notImplemented(); - } - return WebGLGetInfo(Float32Array::create(value, length)); -} - -WebGLGetInfo WebGLRenderingContext::getWebGLIntArrayParameter(GC3Denum pname) -{ - GC3Dint value[4] = {0}; - if (!isContextLost()) - m_context->getIntegerv(pname, value); - unsigned length = 0; - switch (pname) { - case GL_MAX_VIEWPORT_DIMS: - length = 2; - break; - case GL_SCISSOR_BOX: - case GL_VIEWPORT: - length = 4; - break; - default: - notImplemented(); - } - return WebGLGetInfo(Int32Array::create(value, length)); -} - -void WebGLRenderingContext::handleTextureCompleteness(const char* functionName, bool prepareToDraw) -{ - // All calling functions check isContextLost, so a duplicate check is not needed here. - bool resetActiveUnit = false; - WebGLTexture::TextureExtensionFlag flag = static_cast<WebGLTexture::TextureExtensionFlag>((m_oesTextureFloatLinear ? WebGLTexture::TextureFloatLinearExtensionEnabled : 0) - | (m_oesTextureHalfFloatLinear ? WebGLTexture::TextureHalfFloatLinearExtensionEnabled : 0)); - for (unsigned ii = 0; ii < m_onePlusMaxNonDefaultTextureUnit; ++ii) { - if ((m_textureUnits[ii].m_texture2DBinding.get() && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture(flag)) - || (m_textureUnits[ii].m_textureCubeMapBinding.get() && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture(flag))) { - 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 the texture is Float or Half Float type with linear filtering while OES_float_linear or OES_half_float_linear extension is not enabled."); - emitGLWarning(functionName, msg.utf8().data()); - tex2D = m_blackTexture2D.get(); - texCubeMap = m_blackTextureCubeMap.get(); - } else { - tex2D = m_textureUnits[ii].m_texture2DBinding.get(); - texCubeMap = m_textureUnits[ii].m_textureCubeMapBinding.get(); - } - if (m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture(flag)) - m_context->bindTexture(GL_TEXTURE_2D, objectOrZero(tex2D)); - if (m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture(flag)) - m_context->bindTexture(GL_TEXTURE_CUBE_MAP, objectOrZero(texCubeMap)); - } - } - if (resetActiveUnit) - m_context->activeTexture(m_activeTextureUnit); -} - -void WebGLRenderingContext::createFallbackBlackTextures1x1() -{ - // All calling functions check isContextLost, so a duplicate check is not needed here. - unsigned char black[] = {0, 0, 0, 255}; - m_blackTexture2D = createTexture(); - m_context->bindTexture(GL_TEXTURE_2D, m_blackTexture2D->object()); - m_context->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, - 0, GL_RGBA, GL_UNSIGNED_BYTE, black); - m_context->bindTexture(GL_TEXTURE_2D, 0); - m_blackTextureCubeMap = createTexture(); - m_context->bindTexture(GL_TEXTURE_CUBE_MAP, m_blackTextureCubeMap->object()); - m_context->texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 1, 1, - 0, GL_RGBA, GL_UNSIGNED_BYTE, black); - m_context->texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 1, 1, - 0, GL_RGBA, GL_UNSIGNED_BYTE, black); - m_context->texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 1, 1, - 0, GL_RGBA, GL_UNSIGNED_BYTE, black); - m_context->texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 1, 1, - 0, GL_RGBA, GL_UNSIGNED_BYTE, black); - m_context->texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 1, 1, - 0, GL_RGBA, GL_UNSIGNED_BYTE, black); - m_context->texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 1, 1, - 0, GL_RGBA, GL_UNSIGNED_BYTE, black); - m_context->bindTexture(GL_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::boundFramebufferColorFormat() -{ - if (m_framebufferBinding && m_framebufferBinding->object()) - return m_framebufferBinding->colorBufferFormat(); - if (m_attributes.alpha) - return GL_RGBA; - return GL_RGB; -} - -int WebGLRenderingContext::boundFramebufferWidth() -{ - if (m_framebufferBinding && m_framebufferBinding->object()) - return m_framebufferBinding->colorBufferWidth(); - return m_drawingBuffer->size().width(); -} - -int WebGLRenderingContext::boundFramebufferHeight() -{ - if (m_framebufferBinding && m_framebufferBinding->object()) - return m_framebufferBinding->colorBufferHeight(); - return m_drawingBuffer->size().height(); -} - -WebGLTexture* WebGLRenderingContext::validateTextureBinding(const char* functionName, GC3Denum target, bool useSixEnumsForCubeMap) -{ - WebGLTexture* tex = 0; - switch (target) { - case GL_TEXTURE_2D: - tex = m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get(); - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - if (!useSixEnumsForCubeMap) { - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture target"); - return 0; - } - tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding.get(); - break; - case GL_TEXTURE_CUBE_MAP: - if (useSixEnumsForCubeMap) { - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture target"); - return 0; - } - tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding.get(); - break; - default: - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture target"); - return 0; - } - if (!tex) - synthesizeGLError(GL_INVALID_OPERATION, functionName, "no texture"); - return tex; -} - -bool WebGLRenderingContext::validateLocationLength(const char* functionName, const String& string) -{ - const unsigned maxWebGLLocationLength = 256; - if (string.length() > maxWebGLLocationLength) { - synthesizeGLError(GL_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(GL_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(GL_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 GL_ALPHA: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - case GL_RGB: - case GL_RGBA: - break; - case GL_DEPTH_STENCIL_OES: - case GL_DEPTH_COMPONENT: - if (m_webglDepthTexture) - break; - synthesizeGLError(GL_INVALID_ENUM, functionName, "depth texture formats not enabled"); - return false; - default: - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture format"); - return false; - } - - switch (type) { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT_5_6_5: - case GL_UNSIGNED_SHORT_4_4_4_4: - case GL_UNSIGNED_SHORT_5_5_5_1: - break; - case GL_FLOAT: - if (m_oesTextureFloat) - break; - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture type"); - return false; - case GL_HALF_FLOAT_OES: - if (m_oesTextureHalfFloat) - break; - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture type"); - return false; - case GL_UNSIGNED_INT: - case GL_UNSIGNED_INT_24_8_OES: - case GL_UNSIGNED_SHORT: - if (m_webglDepthTexture) - break; - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture type"); - return false; - default: - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture type"); - return false; - } - - // Verify that the combination of format and type is supported. - switch (format) { - case GL_ALPHA: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - if (type != GL_UNSIGNED_BYTE - && type != GL_FLOAT - && type != GL_HALF_FLOAT_OES) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "invalid type for format"); - return false; - } - break; - case GL_RGB: - if (type != GL_UNSIGNED_BYTE - && type != GL_UNSIGNED_SHORT_5_6_5 - && type != GL_FLOAT - && type != GL_HALF_FLOAT_OES) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "invalid type for RGB format"); - return false; - } - break; - case GL_RGBA: - if (type != GL_UNSIGNED_BYTE - && type != GL_UNSIGNED_SHORT_4_4_4_4 - && type != GL_UNSIGNED_SHORT_5_5_5_1 - && type != GL_FLOAT - && type != GL_HALF_FLOAT_OES) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "invalid type for RGBA format"); - return false; - } - break; - case GL_DEPTH_COMPONENT: - if (!m_webglDepthTexture) { - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid format. DEPTH_COMPONENT not enabled"); - return false; - } - if (type != GL_UNSIGNED_SHORT - && type != GL_UNSIGNED_INT) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "invalid type for DEPTH_COMPONENT format"); - return false; - } - if (level > 0) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "level must be 0 for DEPTH_COMPONENT format"); - return false; - } - break; - case GL_DEPTH_STENCIL_OES: - if (!m_webglDepthTexture) { - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid format. DEPTH_STENCIL not enabled"); - return false; - } - if (type != GL_UNSIGNED_INT_24_8_OES) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "invalid type for DEPTH_STENCIL format"); - return false; - } - if (level > 0) { - synthesizeGLError(GL_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(GL_INVALID_VALUE, functionName, "level < 0"); - return false; - } - switch (target) { - case GL_TEXTURE_2D: - if (level >= m_maxTextureLevel) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "level out of range"); - return false; - } - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - if (level >= m_maxCubeMapTextureLevel) { - synthesizeGLError(GL_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::validateTexFuncDimensions(const char* functionName, TexFuncValidationFunctionType functionType, - GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height) -{ - if (width < 0 || height < 0) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "width or height < 0"); - return false; - } - - switch (target) { - case GL_TEXTURE_2D: - if (width > (m_maxTextureSize >> level) || height > (m_maxTextureSize >> level)) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "width or height out of range"); - return false; - } - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - if (functionType != TexSubImage2D && width != height) { - synthesizeGLError(GL_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 > (m_maxCubeMapTextureSize >> level)) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "width or height out of range for cube map"); - return false; - } - break; - default: - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid target"); - return false; - } - 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 (!validateTexFuncDimensions(functionName, functionType, target, level, width, height)) - return false; - - if (format != internalformat) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "format != internalformat"); - return false; - } - - if (border) { - synthesizeGLError(GL_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) -{ - // All calling functions check isContextLost, so a duplicate check is not needed here. - if (!pixels) { - if (disposition == NullAllowed) - return true; - synthesizeGLError(GL_INVALID_VALUE, functionName, "no pixels"); - return false; - } - - if (!validateTexFuncFormatAndType(functionName, format, type, level)) - return false; - if (!validateSettableTexFormat(functionName, format)) - return false; - - switch (type) { - case GL_UNSIGNED_BYTE: - if (pixels->getType() != ArrayBufferView::TypeUint8) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "type UNSIGNED_BYTE but ArrayBufferView not Uint8Array"); - return false; - } - break; - case GL_UNSIGNED_SHORT_5_6_5: - case GL_UNSIGNED_SHORT_4_4_4_4: - case GL_UNSIGNED_SHORT_5_5_5_1: - if (pixels->getType() != ArrayBufferView::TypeUint16) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "type UNSIGNED_SHORT but ArrayBufferView not Uint16Array"); - return false; - } - break; - case GL_FLOAT: // OES_texture_float - if (pixels->getType() != ArrayBufferView::TypeFloat32) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "type FLOAT but ArrayBufferView not Float32Array"); - return false; - } - break; - case GL_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(GL_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 != GL_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(GL_INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request with UNPACK_ALIGNMENT > 1"); - return false; - } - } - synthesizeGLError(GL_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(GL_INVALID_VALUE, functionName, "no pixels"); - return false; - } - if (width < 0 || height < 0) { - synthesizeGLError(GL_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: - { - const int kBlockWidth = 4; - const int kBlockHeight = 4; - const int kBlockSize = 8; - int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth; - int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight; - int numBlocks = numBlocksAcross * numBlocksDown; - bytesRequired = numBlocks * kBlockSize; - } - break; - case Extensions3D::COMPRESSED_RGBA_S3TC_DXT3_EXT: - case Extensions3D::COMPRESSED_RGBA_S3TC_DXT5_EXT: - { - const int kBlockWidth = 4; - const int kBlockHeight = 4; - const int kBlockSize = 16; - int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth; - int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight; - int numBlocks = numBlocksAcross * numBlocksDown; - bytesRequired = numBlocks * kBlockSize; - } - break; - case Extensions3D::COMPRESSED_ATC_RGB_AMD: - { - bytesRequired = floor(static_cast<double>((width + 3) / 4)) * floor(static_cast<double>((height + 3) / 4)) * 8; - } - break; - case Extensions3D::COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD: - case Extensions3D::COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD: - { - bytesRequired = floor(static_cast<double>((width + 3) / 4)) * floor(static_cast<double>((height + 3) / 4)) * 16; - } - case Extensions3D::COMPRESSED_RGB_PVRTC_4BPPV1_IMG: - case Extensions3D::COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: - { - bytesRequired = max(width, 8) * max(height, 8) / 2; - } - break; - case Extensions3D::COMPRESSED_RGB_PVRTC_2BPPV1_IMG: - case Extensions3D::COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: - { - bytesRequired = max(width, 8) * max(height, 8) / 4; - } - break; - default: - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid format"); - return false; - } - - if (pixels->byteLength() != bytesRequired) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "length of ArrayBufferView is not correct for dimensions"); - return false; - } - - return true; -} - -bool WebGLRenderingContext::validateCompressedTexDimensions(const char* functionName, TexFuncValidationFunctionType functionType, GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum format) -{ - if (!validateTexFuncDimensions(functionName, functionType, target, level, width, height)) - 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; - bool widthValid = (level && width == 1) || (level && width == 2) || !(width % kBlockWidth); - bool heightValid = (level && height == 1) || (level && height == 2) || !(height % kBlockHeight); - if (!widthValid || !heightValid) { - synthesizeGLError(GL_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(GL_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(GL_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(GL_INVALID_OPERATION, functionName, "dimensions out of range"); - return false; - } - return validateCompressedTexDimensions(functionName, TexSubImage2D, target, level, width, height, format); - } - default: - return false; - } -} - -bool WebGLRenderingContext::validateDrawMode(const char* functionName, GC3Denum mode) -{ - switch (mode) { - case GL_POINTS: - case GL_LINE_STRIP: - case GL_LINE_LOOP: - case GL_LINES: - case GL_TRIANGLE_STRIP: - case GL_TRIANGLE_FAN: - case GL_TRIANGLES: - return true; - default: - synthesizeGLError(GL_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(GL_INVALID_OPERATION, functionName, "front and back stencils settings do not match"); - return false; - } - return true; -} - -bool WebGLRenderingContext::validateStencilOrDepthFunc(const char* functionName, GC3Denum func) -{ - switch (func) { - case GL_NEVER: - case GL_LESS: - case GL_LEQUAL: - case GL_GREATER: - case GL_GEQUAL: - case GL_EQUAL: - case GL_NOTEQUAL: - case GL_ALWAYS: - return true; - default: - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid function"); - 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."); - - return; -} - -void WebGLRenderingContext::printWarningToConsole(const String& message) -{ - if (!canvas()) - return; - canvas()->document().addConsoleMessage(RenderingMessageSource, WarningMessageLevel, message); -} - -bool WebGLRenderingContext::validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment) -{ - if (target != GL_FRAMEBUFFER) { - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid target"); - return false; - } - switch (attachment) { - case GL_COLOR_ATTACHMENT0: - case GL_DEPTH_ATTACHMENT: - case GL_STENCIL_ATTACHMENT: - case GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL: - break; - default: - if (m_webglDrawBuffers - && attachment > GL_COLOR_ATTACHMENT0 - && attachment < static_cast<GC3Denum>(GL_COLOR_ATTACHMENT0 + maxColorAttachments())) - break; - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid attachment"); - return false; - } - return true; -} - -bool WebGLRenderingContext::validateBlendEquation(const char* functionName, GC3Denum mode) -{ - switch (mode) { - case GL_FUNC_ADD: - case GL_FUNC_SUBTRACT: - case GL_FUNC_REVERSE_SUBTRACT: - return true; - default: - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid mode"); - return false; - } -} - -bool WebGLRenderingContext::validateBlendFuncFactors(const char* functionName, GC3Denum src, GC3Denum dst) -{ - if (((src == GL_CONSTANT_COLOR || src == GL_ONE_MINUS_CONSTANT_COLOR) - && (dst == GL_CONSTANT_ALPHA || dst == GL_ONE_MINUS_CONSTANT_ALPHA)) - || ((dst == GL_CONSTANT_COLOR || dst == GL_ONE_MINUS_CONSTANT_COLOR) - && (src == GL_CONSTANT_ALPHA || src == GL_ONE_MINUS_CONSTANT_ALPHA))) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "incompatible src and dst"); - return false; - } - return true; -} - -bool WebGLRenderingContext::validateCapability(const char* functionName, GC3Denum cap) -{ - switch (cap) { - case GL_BLEND: - case GL_CULL_FACE: - case GL_DEPTH_TEST: - case GL_DITHER: - case GL_POLYGON_OFFSET_FILL: - case GL_SAMPLE_ALPHA_TO_COVERAGE: - case GL_SAMPLE_COVERAGE: - case GL_SCISSOR_TEST: - case GL_STENCIL_TEST: - return true; - default: - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid capability"); - return false; - } -} - -bool WebGLRenderingContext::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Float32Array* v, GC3Dsizei requiredMinSize) -{ - if (!v) { - synthesizeGLError(GL_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(GL_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(GL_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(GL_INVALID_OPERATION, functionName, "location is not from current program"); - return false; - } - if (!v) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "no array"); - return false; - } - if (transpose) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "transpose not FALSE"); - return false; - } - if (size < requiredMinSize || (size % requiredMinSize)) { - synthesizeGLError(GL_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 GL_ELEMENT_ARRAY_BUFFER: - buffer = m_boundVertexArrayObject->boundElementArrayBuffer().get(); - break; - case GL_ARRAY_BUFFER: - buffer = m_boundArrayBuffer.get(); - break; - default: - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid target"); - return 0; - } - if (!buffer) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "no buffer"); - return 0; - } - switch (usage) { - case GL_STREAM_DRAW: - case GL_STATIC_DRAW: - case GL_DYNAMIC_DRAW: - return buffer; - } - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid usage"); - return 0; -} - -bool WebGLRenderingContext::validateHTMLImageElement(const char* functionName, HTMLImageElement* image, ExceptionState& exceptionState) -{ - if (!image || !image->cachedImage()) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "no image"); - return false; - } - const KURL& url = image->cachedImage()->response().url(); - if (url.isNull() || url.isEmpty() || !url.isValid()) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "invalid image"); - return false; - } - if (wouldTaintOrigin(image)) { - exceptionState.throwSecurityError("The cross-origin image at " + url.elidedString() + " may not be loaded."); - return false; - } - return true; -} - -bool WebGLRenderingContext::validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement* canvas, ExceptionState& exceptionState) -{ - if (!canvas || !canvas->buffer()) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "no canvas"); - return false; - } - if (wouldTaintOrigin(canvas)) { - exceptionState.throwSecurityError("Tainted canvases may not be loaded."); - return false; - } - return true; -} - -bool WebGLRenderingContext::validateHTMLVideoElement(const char* functionName, HTMLVideoElement* video, ExceptionState& exceptionState) -{ - if (!video || !video->videoWidth() || !video->videoHeight()) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "no video"); - return false; - } - if (wouldTaintOrigin(video)) { - exceptionState.throwSecurityError("The video element contains cross-origin data, and may not be loaded."); - return false; - } - return true; -} - -bool WebGLRenderingContext::validateDrawArrays(const char* functionName, GC3Denum mode, GC3Dint first, GC3Dsizei count) -{ - if (isContextLost() || !validateDrawMode(functionName, mode)) - return false; - - if (!validateStencilSettings(functionName)) - return false; - - if (first < 0 || count < 0) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "first or count < 0"); - return false; - } - - if (!count) { - markContextChanged(); - return false; - } - - if (!validateRenderingState()) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "attribs not setup correctly"); - return false; - } - - const char* reason = "framebuffer incomplete"; - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { - synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, functionName, reason); - return false; - } - - return true; -} - -bool WebGLRenderingContext::validateDrawElements(const char* functionName, GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset) -{ - if (isContextLost() || !validateDrawMode(functionName, mode)) - return false; - - if (!validateStencilSettings(functionName)) - return false; - - switch (type) { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT: - break; - case GL_UNSIGNED_INT: - if (m_oesElementIndexUint) - break; - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid type"); - return false; - default: - synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid type"); - return false; - } - - if (count < 0 || offset < 0) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "count or offset < 0"); - return false; - } - - if (!count) { - markContextChanged(); - return false; - } - - if (!m_boundVertexArrayObject->boundElementArrayBuffer()) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "no ELEMENT_ARRAY_BUFFER bound"); - return false; - } - - if (!validateRenderingState()) { - synthesizeGLError(GL_INVALID_OPERATION, functionName, "attribs not setup correctly"); - return false; - } - - const char* reason = "framebuffer incomplete"; - if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) { - synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, functionName, reason); - return false; - } - - return true; -} - -// Helper function to validate draw*Instanced calls -bool WebGLRenderingContext::validateDrawInstanced(const char* functionName, GC3Dsizei primcount) -{ - if (primcount < 0) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "primcount < 0"); - return false; - } - - // Ensure at least one enabled vertex attrib has a divisor of 0. - for (unsigned i = 0; i < m_onePlusMaxEnabledAttribIndex; ++i) { - const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(i); - if (state.enabled && !state.divisor) - return true; - } - - synthesizeGLError(GL_INVALID_OPERATION, functionName, "at least one enabled attribute must have a divisor of 0"); - return false; -} - -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(GL_INVALID_VALUE, functionName, "index out of range"); - return; - } - // In GL, we skip setting vertexAttrib0 values. - 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 WebGLRenderingContext::vertexAttribfvImpl(const char* functionName, GC3Duint index, Float32Array* v, GC3Dsizei expectedSize) -{ - if (isContextLost()) - return; - if (!v) { - synthesizeGLError(GL_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(GL_INVALID_VALUE, functionName, "no array"); - return; - } - if (size < expectedSize) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "invalid size"); - return; - } - if (index >= m_maxVertexAttribs) { - synthesizeGLError(GL_INVALID_VALUE, functionName, "index out of range"); - return; - } - // In GL, we skip setting vertexAttrib0 values. - 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; - } - VertexAttribValue& attribValue = m_vertexAttribValue[index]; - attribValue.initValue(); - for (int ii = 0; ii < expectedSize; ++ii) - attribValue.value[ii] = v[ii]; -} - -void WebGLRenderingContext::dispatchContextLostEvent(Timer<WebGLRenderingContext>*) -{ - RefPtr<WebGLContextEvent> event = WebGLContextEvent::create(EventTypeNames::webglcontextlost, false, true, ""); - canvas()->dispatchEvent(event); - m_restoreAllowed = event->defaultPrevented(); - deactivateContext(this, m_contextLostMode != RealLostContext && m_restoreAllowed); - if ((m_contextLostMode == RealLostContext || m_contextLostMode == AutoRecoverSyntheticLostContext) && m_restoreAllowed) - m_restoreTimer.startOneShot(0); -} - -void WebGLRenderingContext::maybeRestoreContext(Timer<WebGLRenderingContext>*) -{ - ASSERT(isContextLost()); - - // 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; - - Frame* frame = canvas()->document().frame(); - if (!frame) - return; - - Settings* settings = frame->settings(); - - if (!frame->loader().client()->allowWebGL(settings && settings->webGLEnabled())) - return; - - // Reset the context attributes back to the requested attributes and re-apply restrictions - m_attributes = adjustAttributes(m_requestedAttributes, settings); - - RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(m_attributes)); - - 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(GL_INVALID_OPERATION, "", "error restoring context"); - } - return; - } - - RefPtr<WebGLRenderingContextEvictionManager> contextEvictionManager = adoptRef(new WebGLRenderingContextEvictionManager()); - - // Construct a new drawing buffer with the new GraphicsContext3D. - m_drawingBuffer->releaseResources(); - DrawingBuffer::PreserveDrawingBuffer preserve = m_attributes.preserveDrawingBuffer ? DrawingBuffer::Preserve : DrawingBuffer::Discard; - m_drawingBuffer = DrawingBuffer::create(context.get(), clampedCanvasSize(), preserve, contextEvictionManager.release()); - - if (m_drawingBuffer->isZeroSized()) - return; - - m_drawingBuffer->bind(); - - lost_context_errors_.clear(); - - m_context = context; - m_contextLost = false; - - setupFlags(); - initializeNewContext(); - canvas()->dispatchEvent(WebGLContextEvent::create(EventTypeNames::webglcontextrestored, false, true, "")); -} - -String WebGLRenderingContext::ensureNotNull(const String& text) const -{ - if (text.isNull()) - return WTF::emptyString(); - return text; -} - -WebGLRenderingContext::LRUImageBufferCache::LRUImageBufferCache(int capacity) - : m_buffers(adoptArrayPtr(new OwnPtr<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->size() != size) - continue; - bubbleToFront(i); - return buf; - } - - OwnPtr<ImageBuffer> temp(ImageBuffer::create(size)); - if (!temp) - return 0; - i = std::min(m_capacity - 1, i); - m_buffers[i] = temp.release(); - - 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 GL_INVALID_ENUM: - return "INVALID_ENUM"; - case GL_INVALID_VALUE: - return "INVALID_VALUE"; - case GL_INVALID_OPERATION: - return "INVALID_OPERATION"; - case GL_OUT_OF_MEMORY: - return "OUT_OF_MEMORY"; - case GL_INVALID_FRAMEBUFFER_OPERATION: - return "INVALID_FRAMEBUFFER_OPERATION"; - case GC3D_CONTEXT_LOST_WEBGL: - return "CONTEXT_LOST_WEBGL"; - default: - return String::format("WebGL ERROR(0x%04X)", error); - } - } - -} // namespace anonymous - -void WebGLRenderingContext::synthesizeGLError(GC3Denum error, const char* functionName, const char* description, ConsoleDisplayPreference display) -{ - String errorType = GetErrorString(error); - if (m_synthesizedErrorsToConsole && display == DisplayInConsole) { - String message = String("WebGL: ") + errorType + ": " + String(functionName) + ": " + String(description); - printGLErrorToConsole(message); - } - if (!isContextLost()) - m_context->synthesizeGLError(error); - else { - if (lost_context_errors_.find(error) == WTF::kNotFound) - lost_context_errors_.append(error); - } - InspectorInstrumentation::didFireWebGLError(canvas(), errorType); -} - -void WebGLRenderingContext::emitGLWarning(const char* functionName, const char* description) -{ - if (m_synthesizedErrorsToConsole) { - String message = String("WebGL: ") + String(functionName) + ": " + String(description); - printGLErrorToConsole(message); - } - InspectorInstrumentation::didFireWebGLWarning(canvas()); -} - -void WebGLRenderingContext::applyStencilTest() -{ - bool haveStencilBuffer = false; - - if (m_framebufferBinding) - haveStencilBuffer = m_framebufferBinding->hasStencilBuffer(); - else { - RefPtr<WebGLContextAttributes> attributes = getContextAttributes(); - haveStencilBuffer = attributes->stencil(); - } - enableOrDisable(GL_STENCIL_TEST, - m_stencilEnabled && haveStencilBuffer); -} - -void WebGLRenderingContext::enableOrDisable(GC3Denum capability, bool enable) -{ - if (isContextLost()) - return; - 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::maxDrawBuffers() -{ - if (isContextLost() || !m_webglDrawBuffers) - 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::maxColorAttachments() -{ - if (isContextLost() || !m_webglDrawBuffers) - 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() -{ - bindFramebuffer(GL_FRAMEBUFFER, m_framebufferBinding.get()); -} - -void WebGLRenderingContext::restoreCurrentTexture2D() -{ - bindTexture(GL_TEXTURE_2D, m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get()); -} - -void WebGLRenderingContext::multisamplingChanged(bool enabled) -{ - if (m_multisamplingAllowed != enabled) { - m_multisamplingAllowed = enabled; - forceLostContext(WebGLRenderingContext::AutoRecoverSyntheticLostContext); - } -} - -void WebGLRenderingContext::findNewMaxEnabledAttribIndex() -{ - // Trace backwards from the current max to find the new max enabled attrib index - int startIndex = m_onePlusMaxEnabledAttribIndex - 1; - for (int i = startIndex; i >= 0; --i) { - if (m_boundVertexArrayObject->getVertexAttribState(i).enabled) { - m_onePlusMaxEnabledAttribIndex = i + 1; - return; - } - } - m_onePlusMaxEnabledAttribIndex = 0; -} - -void WebGLRenderingContext::findNewMaxNonDefaultTextureUnit() -{ - // Trace backwards from the current max to find the new max non-default texture unit - int startIndex = m_onePlusMaxNonDefaultTextureUnit - 1; - for (int i = startIndex; i >= 0; --i) { - if (m_textureUnits[i].m_texture2DBinding - || m_textureUnits[i].m_textureCubeMapBinding) { - m_onePlusMaxNonDefaultTextureUnit = i + 1; - return; - } - } - m_onePlusMaxNonDefaultTextureUnit = 0; + registerExtension<EXTShaderTextureLOD>(m_extShaderTextureLOD, DraftExtension); + registerExtension<WebGLCompressedTextureETC1>(m_webglCompressedTextureETC1, DraftExtension); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.h index e1e3911e9f1..db0e651b39c 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.h @@ -26,497 +26,28 @@ #ifndef WebGLRenderingContext_h #define WebGLRenderingContext_h -#include "core/dom/ActiveDOMObject.h" -#include "core/html/canvas/CanvasRenderingContext.h" -#include "core/html/canvas/WebGLGetInfo.h" -#include "core/page/Page.h" -#include "platform/Timer.h" -#include "platform/graphics/GraphicsContext3D.h" -#include "platform/graphics/ImageBuffer.h" - -#include "wtf/Float32Array.h" -#include "wtf/Int32Array.h" -#include "wtf/OwnPtr.h" -#include "wtf/text/WTFString.h" - -namespace blink { class WebLayer; } +#include "bindings/v8/ScriptWrappable.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -class ANGLEInstancedArrays; -class DrawingBuffer; -class EXTFragDepth; -class EXTTextureFilterAnisotropic; -class ExceptionState; -class HTMLImageElement; -class HTMLVideoElement; -class ImageBuffer; -class ImageData; -class IntSize; -class OESElementIndexUint; -class OESStandardDerivatives; -class OESTextureFloat; -class OESTextureFloatLinear; -class OESTextureHalfFloat; -class OESTextureHalfFloatLinear; -class OESVertexArrayObject; -class WebGLActiveInfo; -class WebGLBuffer; -class WebGLCompressedTextureATC; -class WebGLCompressedTexturePVRTC; -class WebGLCompressedTextureS3TC; -class WebGLContextAttributes; -class WebGLContextGroup; -class WebGLContextObject; -class WebGLDebugRendererInfo; -class WebGLDebugShaders; -class WebGLDepthTexture; -class WebGLDrawBuffers; -class WebGLExtension; -class WebGLFramebuffer; -class WebGLLoseContext; -class WebGLObject; -class WebGLProgram; -class WebGLRenderbuffer; -class WebGLShader; -class WebGLShaderPrecisionFormat; -class WebGLSharedObject; -class WebGLTexture; -class WebGLUniformLocation; -class WebGLVertexArrayObjectOES; - -class WebGLRenderingContext : public CanvasRenderingContext, public ActiveDOMObject, private Page::MultisamplingChangedObserver { +class WebGLRenderingContext FINAL : public WebGLRenderingContextBase, public ScriptWrappable { public: - static PassOwnPtr<WebGLRenderingContext> create(HTMLCanvasElement*, WebGLContextAttributes*); + static PassOwnPtrWillBeRawPtr<WebGLRenderingContext> create(HTMLCanvasElement*, WebGLContextAttributes*); virtual ~WebGLRenderingContext(); - virtual bool is3d() const { return true; } - virtual bool isAccelerated() const { return true; } - - 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); - - void bufferData(GC3Denum target, long long size, GC3Denum usage); - void bufferData(GC3Denum target, ArrayBuffer* data, GC3Denum usage); - void bufferData(GC3Denum target, ArrayBufferView* data, GC3Denum usage); - void bufferSubData(GC3Denum target, long long offset, ArrayBuffer* data); - void bufferSubData(GC3Denum target, long long offset, ArrayBufferView* data); - - 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*); - - 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); - 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*); - 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 drawArraysInstancedANGLE(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount); - void drawElementsInstancedANGLE(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset, GC3Dsizei primcount); - - 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); - - PassRefPtr<WebGLActiveInfo> getActiveAttrib(WebGLProgram*, GC3Duint index); - PassRefPtr<WebGLActiveInfo> getActiveUniform(WebGLProgram*, GC3Duint index); - bool getAttachedShaders(WebGLProgram*, Vector<RefPtr<WebGLShader> >&); - GC3Dint getAttribLocation(WebGLProgram*, const String& name); - WebGLGetInfo getBufferParameter(GC3Denum target, GC3Denum pname); - PassRefPtr<WebGLContextAttributes> getContextAttributes(); - GC3Denum getError(); - PassRefPtr<WebGLExtension> getExtension(const String& name); - WebGLGetInfo getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname); - WebGLGetInfo getParameter(GC3Denum pname); - WebGLGetInfo getProgramParameter(WebGLProgram*, GC3Denum pname); - String getProgramInfoLog(WebGLProgram*); - WebGLGetInfo getRenderbufferParameter(GC3Denum target, GC3Denum pname); - WebGLGetInfo getShaderParameter(WebGLShader*, GC3Denum pname); - String getShaderInfoLog(WebGLShader*); - PassRefPtr<WebGLShaderPrecisionFormat> getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType); - String getShaderSource(WebGLShader*); - Vector<String> getSupportedExtensions(); - WebGLGetInfo getTexParameter(GC3Denum target, GC3Denum pname); - WebGLGetInfo getUniform(WebGLProgram*, const WebGLUniformLocation*); - PassRefPtr<WebGLUniformLocation> getUniformLocation(WebGLProgram*, const String&); - WebGLGetInfo getVertexAttrib(GC3Duint index, GC3Denum pname); - long long getVertexAttribOffset(GC3Duint index, GC3Denum pname); - - void hint(GC3Denum target, GC3Denum mode); - GC3Dboolean isBuffer(WebGLBuffer*); - bool isContextLost(); - 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 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&); - 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*, ExceptionState&); - void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, ImageData*, ExceptionState&); - void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionState&); - void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionState&); - void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, - GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionState&); - - 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*, ExceptionState&); - void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, ImageData*, ExceptionState&); - void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, HTMLImageElement*, ExceptionState&); - void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, HTMLCanvasElement*, ExceptionState&); - void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, - GC3Denum format, GC3Denum type, HTMLVideoElement*, ExceptionState&); - - void uniform1f(const WebGLUniformLocation*, GC3Dfloat x); - void uniform1fv(const WebGLUniformLocation*, Float32Array* v); - void uniform1fv(const WebGLUniformLocation*, GC3Dfloat* v, GC3Dsizei); - void uniform1i(const WebGLUniformLocation*, GC3Dint x); - void uniform1iv(const WebGLUniformLocation*, Int32Array* v); - void uniform1iv(const WebGLUniformLocation*, GC3Dint* v, GC3Dsizei); - void uniform2f(const WebGLUniformLocation*, GC3Dfloat x, GC3Dfloat y); - void uniform2fv(const WebGLUniformLocation*, Float32Array* v); - void uniform2fv(const WebGLUniformLocation*, GC3Dfloat* v, GC3Dsizei); - void uniform2i(const WebGLUniformLocation*, GC3Dint x, GC3Dint y); - void uniform2iv(const WebGLUniformLocation*, Int32Array* v); - void uniform2iv(const WebGLUniformLocation*, GC3Dint* v, GC3Dsizei); - void uniform3f(const WebGLUniformLocation*, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z); - void uniform3fv(const WebGLUniformLocation*, Float32Array* v); - void uniform3fv(const WebGLUniformLocation*, GC3Dfloat* v, GC3Dsizei); - void uniform3i(const WebGLUniformLocation*, GC3Dint x, GC3Dint y, GC3Dint z); - void uniform3iv(const WebGLUniformLocation*, Int32Array* v); - void uniform3iv(const WebGLUniformLocation*, GC3Dint* v, GC3Dsizei); - void uniform4f(const WebGLUniformLocation*, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w); - void uniform4fv(const WebGLUniformLocation*, Float32Array* v); - void uniform4fv(const WebGLUniformLocation*, GC3Dfloat* v, GC3Dsizei); - void uniform4i(const WebGLUniformLocation*, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w); - void uniform4iv(const WebGLUniformLocation*, Int32Array* v); - void uniform4iv(const WebGLUniformLocation*, GC3Dint* v, GC3Dsizei); - void uniformMatrix2fv(const WebGLUniformLocation*, GC3Dboolean transpose, Float32Array* value); - void uniformMatrix2fv(const WebGLUniformLocation*, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei); - void uniformMatrix3fv(const WebGLUniformLocation*, GC3Dboolean transpose, Float32Array* value); - void uniformMatrix3fv(const WebGLUniformLocation*, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei); - void uniformMatrix4fv(const WebGLUniformLocation*, GC3Dboolean transpose, Float32Array* value); - void uniformMatrix4fv(const WebGLUniformLocation*, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei); - - void useProgram(WebGLProgram*); - void validateProgram(WebGLProgram*); - - void vertexAttrib1f(GC3Duint index, GC3Dfloat x); - void vertexAttrib1fv(GC3Duint index, Float32Array* values); - void vertexAttrib1fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei); - void vertexAttrib2f(GC3Duint index, GC3Dfloat x, GC3Dfloat y); - void vertexAttrib2fv(GC3Duint index, Float32Array* values); - void vertexAttrib2fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei); - void vertexAttrib3f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z); - void vertexAttrib3fv(GC3Duint index, Float32Array* values); - void vertexAttrib3fv(GC3Duint index, GC3Dfloat* values, GC3Dsizei); - 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); - void vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, - GC3Dsizei stride, long long offset); - - void vertexAttribDivisorANGLE(GC3Duint index, GC3Duint divisor); - - 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, - - // A synthetic lost context that should attempt to recover automatically - AutoRecoverSyntheticLostContext - }; - void forceLostContext(LostContextMode); - void forceRestoreContext(); - void loseContextImpl(LostContextMode); - - GraphicsContext3D* graphicsContext3D() const { return m_context.get(); } - WebGLContextGroup* contextGroup() const { return m_contextGroup.get(); } - virtual blink::WebLayer* platformLayer() const; - - void reshape(int width, int height); - - void markLayerComposited(); - virtual void paintRenderingResultsToCanvas(); - virtual PassRefPtr<ImageData> paintRenderingResultsToImageData(); - - void removeSharedObject(WebGLSharedObject*); - void removeContextObject(WebGLContextObject*); - - unsigned maxVertexAttribs() const { return m_maxVertexAttribs; } - - // ActiveDOMObject notifications - virtual bool hasPendingActivity() const; - virtual void stop(); - - private: - 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; - - WebGLRenderingContext(HTMLCanvasElement*, PassRefPtr<GraphicsContext3D>, GraphicsContext3D::Attributes, GraphicsContext3D::Attributes); - void initializeNewContext(); - void setupFlags(); - - void addSharedObject(WebGLSharedObject*); - void addContextObject(WebGLContextObject*); - void detachAndRemoveAllObjects(); - - void destroyGraphicsContext3D(); - void markContextChanged(); + virtual unsigned version() const OVERRIDE { return 1; } + virtual String contextName() const OVERRIDE { return "WebGLRenderingContext"; } + virtual void registerContextExtensions() OVERRIDE; - // 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); - - // Check if each enabled vertex attribute is bound to a buffer. - bool validateRenderingState(); - - bool validateWebGLObject(const char*, WebGLObject*); - - // Adds a compressed texture format. - void addCompressedTextureFormat(GC3Denum); - void removeAllCompressedTextureFormats(); - - PassRefPtr<Image> drawImageIntoBuffer(Image*, int width, int height); - - PassRefPtr<Image> videoFrameToImage(HTMLVideoElement*, BackingStoreCopy); - - WebGLRenderbuffer* ensureEmulatedStencilBuffer(GC3Denum target, WebGLRenderbuffer*); - - RefPtr<GraphicsContext3D> m_context; - RefPtr<WebGLContextGroup> m_contextGroup; - - // 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; - class TextureUnitState { - public: - RefPtr<WebGLTexture> m_texture2DBinding; - RefPtr<WebGLTexture> m_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); - OwnPtr<OwnPtr<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; - GraphicsContext3D::Attributes m_requestedAttributes; - - 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_isGLES2NPOTStrict; - bool m_isDepthStencilSupported; - - bool m_synthesizedErrorsToConsole; - int m_numGLErrorsToConsoleAllowed; - - bool m_multisamplingAllowed; - bool m_multisamplingObserverRegistered; - - GC3Duint m_onePlusMaxEnabledAttribIndex; - unsigned long m_onePlusMaxNonDefaultTextureUnit; +private: + WebGLRenderingContext(HTMLCanvasElement*, PassOwnPtr<blink::WebGraphicsContext3D>, WebGLContextAttributes*); // Enabled extension objects. RefPtr<ANGLEInstancedArrays> m_angleInstancedArrays; + RefPtr<EXTBlendMinMax> m_extBlendMinMax; RefPtr<EXTFragDepth> m_extFragDepth; + RefPtr<EXTShaderTextureLOD> m_extShaderTextureLOD; RefPtr<EXTTextureFilterAnisotropic> m_extTextureFilterAnisotropic; RefPtr<OESTextureFloat> m_oesTextureFloat; RefPtr<OESTextureFloatLinear> m_oesTextureFloatLinear; @@ -530,403 +61,15 @@ public: RefPtr<WebGLDebugShaders> m_webglDebugShaders; RefPtr<WebGLDrawBuffers> m_webglDrawBuffers; RefPtr<WebGLCompressedTextureATC> m_webglCompressedTextureATC; + RefPtr<WebGLCompressedTextureETC1> m_webglCompressedTextureETC1; RefPtr<WebGLCompressedTexturePVRTC> m_webglCompressedTexturePVRTC; RefPtr<WebGLCompressedTextureS3TC> m_webglCompressedTextureS3TC; RefPtr<WebGLDepthTexture> m_webglDepthTexture; - - enum ExtensionFlags { - ApprovedExtension = 0x00, - DraftExtension = 0x01, - PrivilegedExtension = 0x02, - PrefixedExtension = 0x04, - WebGLDebugRendererInfoExtension = 0x08, - }; - - class ExtensionTracker { - public: - ExtensionTracker(ExtensionFlags flags, const char* const* prefixes) - : m_privileged(flags & PrivilegedExtension) - , m_draft(flags & DraftExtension) - , m_prefixed(flags & PrefixedExtension) - , m_webglDebugRendererInfo(flags & WebGLDebugRendererInfoExtension) - , m_prefixes(prefixes) - { - } - - virtual ~ExtensionTracker() - { - } - - bool prefixed() const - { - return m_prefixed; - } - - bool privileged() const - { - return m_privileged; - } - - bool draft() const - { - return m_draft; - } - - bool webglDebugRendererInfo() const - { - return m_webglDebugRendererInfo; - } - - bool matchesNameWithPrefixes(const String&) const; - - virtual PassRefPtr<WebGLExtension> getExtension(WebGLRenderingContext*) const = 0; - virtual bool supported(WebGLRenderingContext*) const = 0; - virtual const char* extensionName() const = 0; - virtual void loseExtension() = 0; - - private: - bool m_privileged; - bool m_draft; - bool m_prefixed; - bool m_webglDebugRendererInfo; - const char* const* m_prefixes; - }; - - template <typename T> - class TypedExtensionTracker : public ExtensionTracker { - public: - TypedExtensionTracker(RefPtr<T>& extensionField, ExtensionFlags flags, const char* const* prefixes) - : ExtensionTracker(flags, prefixes) - , m_extensionField(extensionField) - { - } - - ~TypedExtensionTracker() - { - if (m_extensionField) { - m_extensionField->lose(true); - m_extensionField = 0; - } - } - - virtual PassRefPtr<WebGLExtension> getExtension(WebGLRenderingContext* context) const - { - if (!m_extensionField) - m_extensionField = T::create(context); - - return m_extensionField; - } - - virtual bool supported(WebGLRenderingContext* context) const - { - return T::supported(context); - } - - virtual const char* extensionName() const - { - return T::extensionName(); - } - - virtual void loseExtension() - { - if (m_extensionField) { - m_extensionField->lose(false); - if (m_extensionField->isLost()) - m_extensionField = 0; - } - } - - private: - RefPtr<T>& m_extensionField; - }; - - Vector<ExtensionTracker*> m_extensions; - - template <typename T> - void registerExtension(RefPtr<T>& extensionPtr, ExtensionFlags flags = ApprovedExtension, const char* const* prefixes = 0) - { - m_extensions.append(new TypedExtensionTracker<T>(extensionPtr, flags, prefixes)); - } - - // Errors raised by synthesizeGLError() while the context is lost. - Vector<GC3Denum> lost_context_errors_; - - // 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, ExceptionState&); - void texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionState&); - void texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels, ExceptionState&); - void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionState&); - - void handleTextureCompleteness(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 boundFramebufferColorFormat(); - - // Helper function to get the bound framebuffer's width. - int boundFramebufferWidth(); - - // Helper function to get the bound framebuffer's height. - int boundFramebufferHeight(); - - // 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 width and height for functions {copy, compressed}Tex{Sub}Image. - // Generates GL error and returns false if width or height is invalid. - bool validateTexFuncDimensions(const char* functionName, TexFuncValidationFunctionType, - GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height); - - // 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, TexFuncValidationFunctionType, 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 or depth func. - bool validateStencilOrDepthFunc(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&); - - // 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*, ExceptionState&); - - // Helper function for tex{Sub}Image2D to make sure canvas is ready and wouldn't taint Origin. - bool validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement*, ExceptionState&); - - // Helper function for tex{Sub}Image2D to make sure video is ready wouldn't taint Origin. - bool validateHTMLVideoElement(const char* functionName, HTMLVideoElement*, ExceptionState&); - - // Helper function to validate drawArrays(Instanced) calls - bool validateDrawArrays(const char* functionName, GC3Denum mode, GC3Dint first, GC3Dsizei count); - - // Helper function to validate drawElements(Instanced) calls - bool validateDrawElements(const char* functionName, GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset); - - // Helper function to validate draw*Instanced calls - bool validateDrawInstanced(const char* functionName, GC3Dsizei primcount); - - // 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); - - 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; - - // Determine if WEBGL_debug_renderer_info extension is enabled. For the - // moment it can be enabled either through a chromium finch experiment - // or for privileged code in the browser. - bool allowWebGLDebugRendererInfo() 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); - void emitGLWarning(const char* function, const char* reason); - - 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 maxDrawBuffers(); - GC3Dint maxColorAttachments(); - - void setBackDrawBuffer(GC3Denum); - - void restoreCurrentFramebuffer(); - void restoreCurrentTexture2D(); - - virtual void multisamplingChanged(bool); - - void findNewMaxEnabledAttribIndex(); - void findNewMaxNonDefaultTextureUnit(); - - friend class WebGLStateRestorer; - friend class WebGLRenderingContextEvictionManager; - - static Vector<WebGLRenderingContext*>& activeContexts(); - static Vector<WebGLRenderingContext*>& forciblyEvictedContexts(); - - static void activateContext(WebGLRenderingContext*); - static void deactivateContext(WebGLRenderingContext*, bool addToInactiveList); - static void willDestroyContext(WebGLRenderingContext*); - static void forciblyLoseOldestContext(const String& reason); - // Return the least recently used context's position in the active context vector. - // If the vector is empty, return the maximum allowed active context number. - static size_t oldestContextIndex(); - static IntSize oldestContextSize(); }; -DEFINE_TYPE_CASTS(WebGLRenderingContext, CanvasRenderingContext, context, context->is3d(), context.is3d()); +DEFINE_TYPE_CASTS(WebGLRenderingContext, CanvasRenderingContext, context, + context->is3d() && WebGLRenderingContextBase::getWebGLVersion(context) == 1, + context.is3d() && WebGLRenderingContextBase::getWebGLVersion(&context) == 1); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.idl b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.idl index a006bae1c53..ce2d4837ff3 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.idl +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContext.idl @@ -23,640 +23,11 @@ * 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; +// http://www.khronos.org/registry/webgl/specs/latest/1.0/#WebGLRenderingContext [ - 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] void activeTexture(GLenum texture); - [StrictTypeChecking] void attachShader(WebGLProgram program, WebGLShader shader); - [StrictTypeChecking] void bindAttribLocation(WebGLProgram program, GLuint index, DOMString name); - [StrictTypeChecking] void bindBuffer(GLenum target, WebGLBuffer buffer); - [StrictTypeChecking] void bindFramebuffer(GLenum target, WebGLFramebuffer framebuffer); - [StrictTypeChecking] void bindRenderbuffer(GLenum target, WebGLRenderbuffer renderbuffer); - [StrictTypeChecking] 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] void bufferData(GLenum target, ArrayBuffer? data, GLenum usage); - [StrictTypeChecking] void bufferData(GLenum target, ArrayBufferView? data, GLenum usage); - [StrictTypeChecking] void bufferData(GLenum target, GLsizeiptr size, GLenum usage); - [StrictTypeChecking] void bufferSubData(GLenum target, GLintptr offset, ArrayBuffer? data); - [StrictTypeChecking] 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] 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] 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] void detachShader(WebGLProgram program, WebGLShader shader); - [StrictTypeChecking] void disable(GLenum cap); - [StrictTypeChecking] void disableVertexAttribArray(GLuint index); - [StrictTypeChecking] void drawArrays(GLenum mode, GLint first, GLsizei count); - [StrictTypeChecking] void drawElements(GLenum mode, GLsizei count, GLenum type, GLintptr offset); - - [StrictTypeChecking] void enable(GLenum cap); - [StrictTypeChecking] void enableVertexAttribArray(GLuint index); - [StrictTypeChecking] void finish(); - [StrictTypeChecking] void flush(); - [StrictTypeChecking] void framebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, WebGLRenderbuffer renderbuffer); - [StrictTypeChecking] void framebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, WebGLTexture texture, GLint level); - [StrictTypeChecking] void frontFace(GLenum mode); - [StrictTypeChecking] void generateMipmap(GLenum target); - - [StrictTypeChecking] WebGLActiveInfo getActiveAttrib(WebGLProgram program, GLuint index); - [StrictTypeChecking] WebGLActiveInfo getActiveUniform(WebGLProgram program, GLuint index); - - [StrictTypeChecking, Custom] 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] any getFramebufferAttachmentParameter(GLenum target, GLenum attachment, GLenum pname); - [StrictTypeChecking, Custom] any getParameter(GLenum pname); - [StrictTypeChecking, Custom] any getProgramParameter(WebGLProgram program, GLenum pname); - [StrictTypeChecking, TreatReturnedNullStringAs=Null] DOMString getProgramInfoLog(WebGLProgram program); - [StrictTypeChecking, Custom] any getRenderbufferParameter(GLenum target, GLenum pname); - [StrictTypeChecking, Custom] any getShaderParameter(WebGLShader shader, GLenum pname); - - [StrictTypeChecking, TreatReturnedNullStringAs=Null] DOMString getShaderInfoLog(WebGLShader shader); - - [StrictTypeChecking] WebGLShaderPrecisionFormat getShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype); - - [StrictTypeChecking, TreatReturnedNullStringAs=Null] DOMString getShaderSource(WebGLShader shader); - - [StrictTypeChecking, Custom] sequence<DOMString> getSupportedExtensions(); - - [StrictTypeChecking, Custom] any getTexParameter(GLenum target, GLenum pname); - - [StrictTypeChecking, Custom] any getUniform(WebGLProgram program, WebGLUniformLocation location); - - [StrictTypeChecking] WebGLUniformLocation getUniformLocation(WebGLProgram program, DOMString name); - - [StrictTypeChecking, Custom] 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] void linkProgram(WebGLProgram program); - [StrictTypeChecking] void pixelStorei(GLenum pname, GLint param); - [StrictTypeChecking] void polygonOffset(GLfloat factor, GLfloat units); - - [StrictTypeChecking] void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, ArrayBufferView pixels); - - [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] 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); - [StrictTypeChecking, RaisesException] void texImage2D(GLenum target, GLint level, GLenum internalformat, - GLenum format, GLenum type, HTMLVideoElement? video); - - [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); - [StrictTypeChecking, RaisesException] void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, - GLenum format, GLenum type, HTMLVideoElement? video); - - [StrictTypeChecking] void uniform1f(WebGLUniformLocation location, GLfloat x); - [StrictTypeChecking, Custom] void uniform1fv(WebGLUniformLocation location, Float32Array v); - [StrictTypeChecking] void uniform1i(WebGLUniformLocation location, GLint x); - [StrictTypeChecking, Custom] void uniform1iv(WebGLUniformLocation location, Int32Array v); - [StrictTypeChecking] void uniform2f(WebGLUniformLocation location, GLfloat x, GLfloat y); - [StrictTypeChecking, Custom] void uniform2fv(WebGLUniformLocation location, Float32Array v); - [StrictTypeChecking] void uniform2i(WebGLUniformLocation location, GLint x, GLint y); - [StrictTypeChecking, Custom] void uniform2iv(WebGLUniformLocation location, Int32Array v); - [StrictTypeChecking] void uniform3f(WebGLUniformLocation location, GLfloat x, GLfloat y, GLfloat z); - [StrictTypeChecking, Custom] void uniform3fv(WebGLUniformLocation location, Float32Array v); - [StrictTypeChecking] void uniform3i(WebGLUniformLocation location, GLint x, GLint y, GLint z); - [StrictTypeChecking, Custom] void uniform3iv(WebGLUniformLocation location, Int32Array v); - [StrictTypeChecking] void uniform4f(WebGLUniformLocation location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); - [StrictTypeChecking, Custom] void uniform4fv(WebGLUniformLocation location, Float32Array v); - [StrictTypeChecking] void uniform4i(WebGLUniformLocation location, GLint x, GLint y, GLint z, GLint w); - [StrictTypeChecking, Custom] void uniform4iv(WebGLUniformLocation location, Int32Array v); - - [StrictTypeChecking, Custom] void uniformMatrix2fv(WebGLUniformLocation location, GLboolean transpose, Float32Array array); - [StrictTypeChecking, Custom] void uniformMatrix3fv(WebGLUniformLocation location, GLboolean transpose, Float32Array array); - [StrictTypeChecking, Custom] void uniformMatrix4fv(WebGLUniformLocation location, GLboolean transpose, Float32Array array); - - [StrictTypeChecking] void useProgram(WebGLProgram program); - [StrictTypeChecking] 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] 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); -}; + DoNotCheckConstants, + TypeChecking=Interface|Nullable, + WillBeGarbageCollected, +] interface WebGLRenderingContext { }; +WebGLRenderingContext implements WebGLRenderingContextBase; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContextBase.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContextBase.cpp new file mode 100644 index 00000000000..b587a6899c1 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContextBase.cpp @@ -0,0 +1,5728 @@ +/* + * Copyright (C) 2009 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 COMPUTER, 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 + * 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 "core/html/canvas/WebGLRenderingContextBase.h" + +#include "bindings/v8/ExceptionMessages.h" +#include "bindings/v8/ExceptionState.h" +#include "core/dom/ExceptionCode.h" +#include "core/fetch/ImageResource.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/Settings.h" +#include "core/html/HTMLCanvasElement.h" +#include "core/html/HTMLImageElement.h" +#include "core/html/HTMLVideoElement.h" +#include "core/html/ImageData.h" +#include "core/html/canvas/ANGLEInstancedArrays.h" +#include "core/html/canvas/EXTBlendMinMax.h" +#include "core/html/canvas/EXTFragDepth.h" +#include "core/html/canvas/EXTShaderTextureLOD.h" +#include "core/html/canvas/EXTTextureFilterAnisotropic.h" +#include "core/html/canvas/OESElementIndexUint.h" +#include "core/html/canvas/OESStandardDerivatives.h" +#include "core/html/canvas/OESTextureFloat.h" +#include "core/html/canvas/OESTextureFloatLinear.h" +#include "core/html/canvas/OESTextureHalfFloat.h" +#include "core/html/canvas/OESTextureHalfFloatLinear.h" +#include "core/html/canvas/OESVertexArrayObject.h" +#include "core/html/canvas/WebGLActiveInfo.h" +#include "core/html/canvas/WebGLBuffer.h" +#include "core/html/canvas/WebGLCompressedTextureATC.h" +#include "core/html/canvas/WebGLCompressedTextureETC1.h" +#include "core/html/canvas/WebGLCompressedTexturePVRTC.h" +#include "core/html/canvas/WebGLCompressedTextureS3TC.h" +#include "core/html/canvas/WebGLContextAttributes.h" +#include "core/html/canvas/WebGLContextEvent.h" +#include "core/html/canvas/WebGLContextGroup.h" +#include "core/html/canvas/WebGLDebugRendererInfo.h" +#include "core/html/canvas/WebGLDebugShaders.h" +#include "core/html/canvas/WebGLDepthTexture.h" +#include "core/html/canvas/WebGLDrawBuffers.h" +#include "core/html/canvas/WebGLFramebuffer.h" +#include "core/html/canvas/WebGLLoseContext.h" +#include "core/html/canvas/WebGLProgram.h" +#include "core/html/canvas/WebGLRenderbuffer.h" +#include "core/html/canvas/WebGLShader.h" +#include "core/html/canvas/WebGLShaderPrecisionFormat.h" +#include "core/html/canvas/WebGLTexture.h" +#include "core/html/canvas/WebGLUniformLocation.h" +#include "core/inspector/InspectorInstrumentation.h" +#include "core/loader/FrameLoader.h" +#include "core/loader/FrameLoaderClient.h" +#include "core/rendering/RenderBox.h" +#include "platform/CheckedInt.h" +#include "platform/NotImplemented.h" +#include "platform/RuntimeEnabledFeatures.h" +#include "platform/geometry/IntSize.h" +#include "platform/graphics/GraphicsContext.h" +#include "platform/graphics/UnacceleratedImageBufferSurface.h" +#include "platform/graphics/gpu/DrawingBuffer.h" +#include "public/platform/Platform.h" + +#include "wtf/PassOwnPtr.h" +#include "wtf/Uint32Array.h" +#include "wtf/text/StringBuilder.h" + +namespace WebCore { + +const double secondsBetweenRestoreAttempts = 1.0; +const int maxGLErrorsAllowedToConsole = 256; +const unsigned maxGLActiveContexts = 16; + +Vector<WebGLRenderingContextBase*>& WebGLRenderingContextBase::activeContexts() +{ + DEFINE_STATIC_LOCAL(Vector<WebGLRenderingContextBase*>, activeContexts, ()); + return activeContexts; +} + +Vector<WebGLRenderingContextBase*>& WebGLRenderingContextBase::forciblyEvictedContexts() +{ + DEFINE_STATIC_LOCAL(Vector<WebGLRenderingContextBase*>, forciblyEvictedContexts, ()); + return forciblyEvictedContexts; +} + +void WebGLRenderingContextBase::forciblyLoseOldestContext(const String& reason) +{ + size_t candidateID = oldestContextIndex(); + if (candidateID >= activeContexts().size()) + return; + + WebGLRenderingContextBase* candidate = activeContexts()[candidateID]; + + activeContexts().remove(candidateID); + + candidate->printWarningToConsole(reason); + InspectorInstrumentation::didFireWebGLWarning(candidate->canvas()); + + // This will call deactivateContext once the context has actually been lost. + candidate->forceLostContext(WebGLRenderingContextBase::SyntheticLostContext); +} + +size_t WebGLRenderingContextBase::oldestContextIndex() +{ + if (!activeContexts().size()) + return maxGLActiveContexts; + + WebGLRenderingContextBase* candidate = activeContexts().first(); + blink::WebGraphicsContext3D* candidateWGC3D = candidate->isContextLost() ? 0 : candidate->webContext(); + size_t candidateID = 0; + for (size_t ii = 1; ii < activeContexts().size(); ++ii) { + WebGLRenderingContextBase* context = activeContexts()[ii]; + blink::WebGraphicsContext3D* contextWGC3D = context->isContextLost() ? 0 : context->webContext(); + if (contextWGC3D && candidateWGC3D && contextWGC3D->lastFlushID() < candidateWGC3D->lastFlushID()) { + candidate = context; + candidateID = ii; + } + } + + return candidateID; +} + +IntSize WebGLRenderingContextBase::oldestContextSize() +{ + IntSize size; + + size_t candidateID = oldestContextIndex(); + if (candidateID < activeContexts().size()) { + WebGLRenderingContextBase* candidate = activeContexts()[candidateID]; + size.setWidth(candidate->drawingBufferWidth()); + size.setHeight(candidate->drawingBufferHeight()); + } + + return size; +} + +void WebGLRenderingContextBase::activateContext(WebGLRenderingContextBase* context) +{ + unsigned removedContexts = 0; + while (activeContexts().size() >= maxGLActiveContexts && removedContexts < maxGLActiveContexts) { + forciblyLoseOldestContext("WARNING: Too many active WebGL contexts. Oldest context will be lost."); + removedContexts++; + } + + if (!activeContexts().contains(context)) + activeContexts().append(context); +} + +void WebGLRenderingContextBase::deactivateContext(WebGLRenderingContextBase* context, bool addToEvictedList) +{ + size_t position = activeContexts().find(context); + if (position != WTF::kNotFound) + activeContexts().remove(position); + + if (addToEvictedList && !forciblyEvictedContexts().contains(context)) + forciblyEvictedContexts().append(context); +} + +void WebGLRenderingContextBase::willDestroyContext(WebGLRenderingContextBase* context) +{ + size_t position = forciblyEvictedContexts().find(context); + if (position != WTF::kNotFound) + forciblyEvictedContexts().remove(position); + + deactivateContext(context, false); + + // Try to re-enable the oldest inactive contexts. + while(activeContexts().size() < maxGLActiveContexts && forciblyEvictedContexts().size()) { + WebGLRenderingContextBase* evictedContext = forciblyEvictedContexts().first(); + if (!evictedContext->m_restoreAllowed) { + forciblyEvictedContexts().remove(0); + continue; + } + + IntSize desiredSize = DrawingBuffer::adjustSize(evictedContext->clampedCanvasSize(), IntSize(), evictedContext->m_maxTextureSize); + + // If there's room in the pixel budget for this context, restore it. + if (!desiredSize.isEmpty()) { + forciblyEvictedContexts().remove(0); + evictedContext->forceRestoreContext(); + activeContexts().append(evictedContext); + } + break; + } +} + +class WebGLRenderingContextEvictionManager : public ContextEvictionManager { +public: + void forciblyLoseOldestContext(const String& reason) { + WebGLRenderingContextBase::forciblyLoseOldestContext(reason); + }; + IntSize oldestContextSize() { + return WebGLRenderingContextBase::oldestContextSize(); + }; +}; + +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; + } + + GLint clamp(GLint value, GLint min, GLint 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() + { + ASSERT_WITH_SECURITY_IMPLICATION(m_position < m_length); + return m_sourceString[m_position]; + } + + void advance() + { + ++m_position; + } + + static bool isNewline(UChar character) + { + // 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 ScopedTexture2DRestorer { +public: + ScopedTexture2DRestorer(WebGLRenderingContextBase* context) + : m_context(context) + { + } + + ~ScopedTexture2DRestorer() + { + m_context->restoreCurrentTexture2D(); + } + +private: + WebGLRenderingContextBase* m_context; +}; + +class WebGLRenderingContextLostCallback : public blink::WebGraphicsContext3D::WebGraphicsContextLostCallback { + WTF_MAKE_FAST_ALLOCATED; +public: + explicit WebGLRenderingContextLostCallback(WebGLRenderingContextBase* cb) : m_context(cb) { } + virtual void onContextLost() { m_context->forceLostContext(WebGLRenderingContextBase::RealLostContext); } + virtual ~WebGLRenderingContextLostCallback() {} +private: + WebGLRenderingContextBase* m_context; +}; + +class WebGLRenderingContextErrorMessageCallback : public blink::WebGraphicsContext3D::WebGraphicsErrorMessageCallback { + WTF_MAKE_FAST_ALLOCATED; +public: + explicit WebGLRenderingContextErrorMessageCallback(WebGLRenderingContextBase* cb) : m_context(cb) { } + virtual void onErrorMessage(const blink::WebString& message, blink::WGC3Dint) + { + if (m_context->m_synthesizedErrorsToConsole) + m_context->printGLErrorToConsole(message); + InspectorInstrumentation::didFireWebGLErrorOrWarning(m_context->canvas(), message); + } + virtual ~WebGLRenderingContextErrorMessageCallback() { } +private: + WebGLRenderingContextBase* m_context; +}; + +WebGLRenderingContextBase::WebGLRenderingContextBase(HTMLCanvasElement* passedCanvas, PassOwnPtr<blink::WebGraphicsContext3D> context, WebGLContextAttributes* requestedAttributes) + : CanvasRenderingContext(passedCanvas) + , ActiveDOMObject(&passedCanvas->document()) + , m_drawingBuffer(nullptr) + , m_dispatchContextLostEventTimer(this, &WebGLRenderingContextBase::dispatchContextLostEvent) + , m_restoreAllowed(false) + , m_restoreTimer(this, &WebGLRenderingContextBase::maybeRestoreContext) + , m_generatedImageCache(4) + , m_contextLost(false) + , m_contextLostMode(SyntheticLostContext) + , m_requestedAttributes(requestedAttributes->clone()) + , m_synthesizedErrorsToConsole(true) + , m_numGLErrorsToConsoleAllowed(maxGLErrorsAllowedToConsole) + , m_multisamplingAllowed(false) + , m_multisamplingObserverRegistered(false) + , m_onePlusMaxEnabledAttribIndex(0) + , m_onePlusMaxNonDefaultTextureUnit(0) + , m_savingImage(false) +{ + ASSERT(context); + + m_contextGroup = WebGLContextGroup::create(); + m_contextGroup->addContext(this); + + m_maxViewportDims[0] = m_maxViewportDims[1] = 0; + context->getIntegerv(GL_MAX_VIEWPORT_DIMS, m_maxViewportDims); + + m_drawingBuffer = createDrawingBuffer(context); + if (!m_drawingBuffer) + return; + + m_drawingBuffer->bind(); + setupFlags(); + initializeNewContext(); +} + +PassRefPtr<DrawingBuffer> WebGLRenderingContextBase::createDrawingBuffer(PassOwnPtr<blink::WebGraphicsContext3D> context) +{ + RefPtr<WebGLRenderingContextEvictionManager> contextEvictionManager = adoptRef(new WebGLRenderingContextEvictionManager()); + + blink::WebGraphicsContext3D::Attributes attrs; + attrs.alpha = m_requestedAttributes->alpha(); + attrs.depth = m_requestedAttributes->depth(); + attrs.stencil = m_requestedAttributes->stencil(); + attrs.antialias = m_requestedAttributes->antialias(); + attrs.premultipliedAlpha = m_requestedAttributes->premultipliedAlpha(); + DrawingBuffer::PreserveDrawingBuffer preserve = m_requestedAttributes->preserveDrawingBuffer() ? DrawingBuffer::Preserve : DrawingBuffer::Discard; + return DrawingBuffer::create(context, clampedCanvasSize(), preserve, attrs, contextEvictionManager.release()); +} + +void WebGLRenderingContextBase::initializeNewContext() +{ + ASSERT(!isContextLost()); + m_needsUpdate = true; + m_markedCanvasDirty = false; + m_activeTextureUnit = 0; + m_packAlignment = 4; + m_unpackAlignment = 4; + m_unpackFlipY = false; + m_unpackPremultiplyAlpha = false; + m_unpackColorspaceConversion = GC3D_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; + + GLint numCombinedTextureImageUnits = 0; + webContext()->getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numCombinedTextureImageUnits); + m_textureUnits.clear(); + m_textureUnits.resize(numCombinedTextureImageUnits); + + GLint numVertexAttribs = 0; + webContext()->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &numVertexAttribs); + m_maxVertexAttribs = numVertexAttribs; + + m_maxTextureSize = 0; + webContext()->getIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize); + m_maxTextureLevel = WebGLTexture::computeLevelCount(m_maxTextureSize, m_maxTextureSize); + m_maxCubeMapTextureSize = 0; + webContext()->getIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &m_maxCubeMapTextureSize); + m_maxCubeMapTextureLevel = WebGLTexture::computeLevelCount(m_maxCubeMapTextureSize, m_maxCubeMapTextureSize); + m_maxRenderbufferSize = 0; + webContext()->getIntegerv(GL_MAX_RENDERBUFFER_SIZE, &m_maxRenderbufferSize); + + // These two values from EXT_draw_buffers are lazily queried. + m_maxDrawBuffers = 0; + m_maxColorAttachments = 0; + + m_backDrawBuffer = GL_BACK; + + m_defaultVertexArrayObject = WebGLVertexArrayObjectOES::create(this, WebGLVertexArrayObjectOES::VaoTypeDefault); + addContextObject(m_defaultVertexArrayObject.get()); + m_boundVertexArrayObject = m_defaultVertexArrayObject; + + m_vertexAttribValue.resize(m_maxVertexAttribs); + + createFallbackBlackTextures1x1(); + + webContext()->viewport(0, 0, drawingBufferWidth(), drawingBufferHeight()); + webContext()->scissor(0, 0, drawingBufferWidth(), drawingBufferHeight()); + + m_contextLostCallbackAdapter = adoptPtr(new WebGLRenderingContextLostCallback(this)); + m_errorMessageCallbackAdapter = adoptPtr(new WebGLRenderingContextErrorMessageCallback(this)); + + webContext()->setContextLostCallback(m_contextLostCallbackAdapter.get()); + webContext()->setErrorMessageCallback(m_errorMessageCallbackAdapter.get()); + + // This ensures that the context has a valid "lastFlushID" and won't be mistakenly identified as the "least recently used" context. + webContext()->flush(); + + for (int i = 0; i < WebGLExtensionNameCount; ++i) + m_extensionEnabled[i] = false; + + activateContext(this); +} + +void WebGLRenderingContextBase::setupFlags() +{ + ASSERT(m_drawingBuffer); + if (Page* p = canvas()->document().page()) { + m_synthesizedErrorsToConsole = p->settings().webGLErrorsToConsoleEnabled(); + + if (!m_multisamplingObserverRegistered && m_requestedAttributes->antialias()) { + m_multisamplingAllowed = m_drawingBuffer->multisample(); + p->addMultisamplingChangedObserver(this); + m_multisamplingObserverRegistered = true; + } + } + + m_isGLES2NPOTStrict = !extensionsUtil()->isExtensionEnabled("GL_OES_texture_npot"); + m_isDepthStencilSupported = extensionsUtil()->isExtensionEnabled("GL_OES_packed_depth_stencil"); +} + +void WebGLRenderingContextBase::addCompressedTextureFormat(GLenum format) +{ + if (!m_compressedTextureFormats.contains(format)) + m_compressedTextureFormats.append(format); +} + +void WebGLRenderingContextBase::removeAllCompressedTextureFormats() +{ + m_compressedTextureFormats.clear(); +} + +// Helper function for V8 bindings to identify what version of WebGL a CanvasRenderingContext supports. +unsigned WebGLRenderingContextBase::getWebGLVersion(const CanvasRenderingContext* context) +{ + if (!context->is3d()) + return 0; + return static_cast<const WebGLRenderingContextBase*>(context)->version(); +} + +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 (size_t i = 0; i < m_textureUnits.size(); ++i) { + m_textureUnits[i].m_texture2DBinding = nullptr; + m_textureUnits[i].m_textureCubeMapBinding = nullptr; + } + + m_blackTexture2D = nullptr; + m_blackTextureCubeMap = nullptr; + + detachAndRemoveAllObjects(); + + // release all extensions + for (size_t i = 0; i < m_extensions.size(); ++i) + delete m_extensions[i]; + + // Context must be removed from the group prior to the destruction of the + // WebGraphicsContext3D, otherwise shared objects may not be properly deleted. + m_contextGroup->removeContext(this); + + destroyContext(); + +#if !ENABLE(OILPAN) + if (m_multisamplingObserverRegistered) { + Page* page = canvas()->document().page(); + if (page) + page->removeMultisamplingChangedObserver(this); + } +#endif + + willDestroyContext(this); +} + +void WebGLRenderingContextBase::destroyContext() +{ + m_contextLost = true; + + if (!m_drawingBuffer) + return; + + m_extensionsUtil.clear(); + + webContext()->setContextLostCallback(0); + webContext()->setErrorMessageCallback(0); + + ASSERT(m_drawingBuffer); + m_drawingBuffer->beginDestruction(); + m_drawingBuffer.clear(); +} + +void WebGLRenderingContextBase::markContextChanged(ContentChangeType changeType) +{ + if (m_framebufferBinding || isContextLost()) + return; + + m_drawingBuffer->markContentsChanged(); + + m_layerCleared = false; + RenderBox* renderBox = canvas()->renderBox(); + if (renderBox && renderBox->hasAcceleratedCompositing()) { + m_markedCanvasDirty = true; + canvas()->clearCopiedImage(); + renderBox->contentChanged(changeType); + } else { + if (!m_markedCanvasDirty) { + m_markedCanvasDirty = true; + canvas()->didDraw(FloatRect(FloatPoint(0, 0), clampedCanvasSize())); + } + } +} + +bool WebGLRenderingContextBase::clearIfComposited(GLbitfield mask) +{ + if (isContextLost()) + return false; + + if (!m_drawingBuffer->layerComposited() || m_layerCleared + || m_requestedAttributes->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; + + webContext()->disable(GL_SCISSOR_TEST); + if (combinedClear && (mask & GL_COLOR_BUFFER_BIT)) { + webContext()->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 { + webContext()->clearColor(0, 0, 0, 0); + } + webContext()->colorMask(true, true, true, true); + GLbitfield clearMask = GL_COLOR_BUFFER_BIT; + if (contextAttributes->depth()) { + if (!combinedClear || !m_depthMask || !(mask & GL_DEPTH_BUFFER_BIT)) + webContext()->clearDepth(1.0f); + clearMask |= GL_DEPTH_BUFFER_BIT; + webContext()->depthMask(true); + } + if (contextAttributes->stencil()) { + if (combinedClear && (mask & GL_STENCIL_BUFFER_BIT)) + webContext()->clearStencil(m_clearStencil & m_stencilMask); + else + webContext()->clearStencil(0); + clearMask |= GL_STENCIL_BUFFER_BIT; + webContext()->stencilMaskSeparate(GL_FRONT, 0xFFFFFFFF); + } + + m_drawingBuffer->clearFramebuffers(clearMask); + + restoreStateAfterClear(); + if (m_framebufferBinding) + webContext()->bindFramebuffer(GL_FRAMEBUFFER, objectOrZero(m_framebufferBinding.get())); + m_layerCleared = true; + + return combinedClear; +} + +void WebGLRenderingContextBase::restoreStateAfterClear() +{ + if (isContextLost()) + return; + + // Restore the state that the context set. + if (m_scissorEnabled) + webContext()->enable(GL_SCISSOR_TEST); + webContext()->clearColor(m_clearColor[0], m_clearColor[1], + m_clearColor[2], m_clearColor[3]); + webContext()->colorMask(m_colorMask[0], m_colorMask[1], + m_colorMask[2], m_colorMask[3]); + webContext()->clearDepth(m_clearDepth); + webContext()->clearStencil(m_clearStencil); + webContext()->stencilMaskSeparate(GL_FRONT, m_stencilMask); + webContext()->depthMask(m_depthMask); +} + +void WebGLRenderingContextBase::markLayerComposited() +{ + if (!isContextLost()) + m_drawingBuffer->markLayerComposited(); +} + +void WebGLRenderingContextBase::paintRenderingResultsToCanvas() +{ + if (isContextLost()) { + canvas()->clearPresentationCopy(); + 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_drawingBuffer->layerComposited() && !m_requestedAttributes->preserveDrawingBuffer()) { + m_drawingBuffer->paintCompositedResultsToCanvas(canvas()->buffer()); + + canvas()->makePresentationCopy(); + } else + canvas()->clearPresentationCopy(); + + clearIfComposited(); + + if (!m_markedCanvasDirty && !m_layerCleared) + return; + + canvas()->clearCopiedImage(); + m_markedCanvasDirty = false; + + ScopedTexture2DRestorer restorer(this); + + m_drawingBuffer->commit(); + if (!(canvas()->buffer())->copyRenderingResultsFromDrawingBuffer(m_drawingBuffer.get(), m_savingImage)) { + canvas()->ensureUnacceleratedImageBuffer(); + if (canvas()->hasImageBuffer()) + m_drawingBuffer->paintRenderingResultsToCanvas(canvas()->buffer()); + } + + if (m_framebufferBinding) + webContext()->bindFramebuffer(GL_FRAMEBUFFER, objectOrZero(m_framebufferBinding.get())); + else + m_drawingBuffer->bind(); +} + +PassRefPtrWillBeRawPtr<ImageData> WebGLRenderingContextBase::paintRenderingResultsToImageData() +{ + if (isContextLost()) + return nullptr; + + clearIfComposited(); + m_drawingBuffer->commit(); + int width, height; + RefPtr<Uint8ClampedArray> imageDataPixels = m_drawingBuffer->paintRenderingResultsToImageData(width, height); + if (!imageDataPixels) + return nullptr; + + if (m_framebufferBinding) + webContext()->bindFramebuffer(GL_FRAMEBUFFER, objectOrZero(m_framebufferBinding.get())); + else + m_drawingBuffer->bind(); + + return ImageData::create(IntSize(width, height), imageDataPixels); +} + +void WebGLRenderingContextBase::reshape(int width, int height) +{ + if (isContextLost()) + return; + + // This is an approximation because at WebGLRenderingContextBase level we don't + // know if the underlying FBO uses textures or renderbuffers. + GLint 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); + GLint maxWidth = std::min(maxSize, m_maxViewportDims[0]); + GLint 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_drawingBuffer->reset(IntSize(width, height)); + restoreStateAfterClear(); + + webContext()->bindTexture(GL_TEXTURE_2D, objectOrZero(m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get())); + webContext()->bindRenderbuffer(GL_RENDERBUFFER, objectOrZero(m_renderbufferBinding.get())); + if (m_framebufferBinding) + webContext()->bindFramebuffer(GL_FRAMEBUFFER, objectOrZero(m_framebufferBinding.get())); +} + +int WebGLRenderingContextBase::drawingBufferWidth() const +{ + return isContextLost() ? 0 : m_drawingBuffer->size().width(); +} + +int WebGLRenderingContextBase::drawingBufferHeight() const +{ + return isContextLost() ? 0 : m_drawingBuffer->size().height(); +} + +unsigned WebGLRenderingContextBase::sizeInBytes(GLenum type) +{ + switch (type) { + case GL_BYTE: + return sizeof(GLbyte); + case GL_UNSIGNED_BYTE: + return sizeof(GLubyte); + case GL_SHORT: + return sizeof(GLshort); + case GL_UNSIGNED_SHORT: + return sizeof(GLushort); + case GL_INT: + return sizeof(GLint); + case GL_UNSIGNED_INT: + return sizeof(GLuint); + case GL_FLOAT: + return sizeof(GLfloat); + } + ASSERT_NOT_REACHED(); + return 0; +} + +void WebGLRenderingContextBase::activeTexture(GLenum texture) +{ + if (isContextLost()) + return; + if (texture - GL_TEXTURE0 >= m_textureUnits.size()) { + synthesizeGLError(GL_INVALID_ENUM, "activeTexture", "texture unit out of range"); + return; + } + m_activeTextureUnit = texture - GL_TEXTURE0; + webContext()->activeTexture(texture); + + m_drawingBuffer->setActiveTextureUnit(texture); + +} + +void WebGLRenderingContextBase::attachShader(WebGLProgram* program, WebGLShader* shader) +{ + if (isContextLost() || !validateWebGLObject("attachShader", program) || !validateWebGLObject("attachShader", shader)) + return; + if (!program->attachShader(shader)) { + synthesizeGLError(GL_INVALID_OPERATION, "attachShader", "shader attachment already has shader"); + return; + } + webContext()->attachShader(objectOrZero(program), objectOrZero(shader)); + shader->onAttached(); +} + +void WebGLRenderingContextBase::bindAttribLocation(WebGLProgram* program, GLuint index, const String& name) +{ + if (isContextLost() || !validateWebGLObject("bindAttribLocation", program)) + return; + if (!validateLocationLength("bindAttribLocation", name)) + return; + if (!validateString("bindAttribLocation", name)) + return; + if (isPrefixReserved(name)) { + synthesizeGLError(GL_INVALID_OPERATION, "bindAttribLocation", "reserved prefix"); + return; + } + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GL_INVALID_VALUE, "bindAttribLocation", "index out of range"); + return; + } + webContext()->bindAttribLocation(objectOrZero(program), index, name.utf8().data()); +} + +bool WebGLRenderingContextBase::checkObjectToBeBound(const char* functionName, WebGLObject* object, bool& deleted) +{ + deleted = false; + if (isContextLost()) + return false; + if (object) { + if (!object->validate(contextGroup(), this)) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "object not from this context"); + return false; + } + deleted = !object->object(); + } + return true; +} + +void WebGLRenderingContextBase::bindBuffer(GLenum target, WebGLBuffer* buffer) +{ + bool deleted; + if (!checkObjectToBeBound("bindBuffer", buffer, deleted)) + return; + if (deleted) + buffer = 0; + if (buffer && buffer->getTarget() && buffer->getTarget() != target) { + synthesizeGLError(GL_INVALID_OPERATION, "bindBuffer", "buffers can not be used with multiple targets"); + return; + } + if (target == GL_ARRAY_BUFFER) + m_boundArrayBuffer = buffer; + else if (target == GL_ELEMENT_ARRAY_BUFFER) + m_boundVertexArrayObject->setElementArrayBuffer(buffer); + else { + synthesizeGLError(GL_INVALID_ENUM, "bindBuffer", "invalid target"); + return; + } + + webContext()->bindBuffer(target, objectOrZero(buffer)); + if (buffer) + buffer->setTarget(target); +} + +void WebGLRenderingContextBase::bindFramebuffer(GLenum target, WebGLFramebuffer* buffer) +{ + bool deleted; + if (!checkObjectToBeBound("bindFramebuffer", buffer, deleted)) + return; + if (deleted) + buffer = 0; + if (target != GL_FRAMEBUFFER) { + synthesizeGLError(GL_INVALID_ENUM, "bindFramebuffer", "invalid target"); + return; + } + m_framebufferBinding = buffer; + m_drawingBuffer->setFramebufferBinding(objectOrZero(m_framebufferBinding.get())); + if (!m_framebufferBinding) { + // Instead of binding fb 0, bind the drawing buffer. + m_drawingBuffer->bind(); + } else { + webContext()->bindFramebuffer(target, objectOrZero(buffer)); + } + if (buffer) + buffer->setHasEverBeenBound(); + applyStencilTest(); +} + +void WebGLRenderingContextBase::bindRenderbuffer(GLenum target, WebGLRenderbuffer* renderBuffer) +{ + bool deleted; + if (!checkObjectToBeBound("bindRenderbuffer", renderBuffer, deleted)) + return; + if (deleted) + renderBuffer = 0; + if (target != GL_RENDERBUFFER) { + synthesizeGLError(GL_INVALID_ENUM, "bindRenderbuffer", "invalid target"); + return; + } + m_renderbufferBinding = renderBuffer; + webContext()->bindRenderbuffer(target, objectOrZero(renderBuffer)); + if (renderBuffer) + renderBuffer->setHasEverBeenBound(); +} + +void WebGLRenderingContextBase::bindTexture(GLenum target, WebGLTexture* texture) +{ + bool deleted; + if (!checkObjectToBeBound("bindTexture", texture, deleted)) + return; + if (deleted) + texture = 0; + if (texture && texture->getTarget() && texture->getTarget() != target) { + synthesizeGLError(GL_INVALID_OPERATION, "bindTexture", "textures can not be used with multiple targets"); + return; + } + GLint maxLevel = 0; + if (target == GL_TEXTURE_2D) { + m_textureUnits[m_activeTextureUnit].m_texture2DBinding = texture; + maxLevel = m_maxTextureLevel; + + if (!m_activeTextureUnit) + m_drawingBuffer->setTexture2DBinding(objectOrZero(texture)); + + } else if (target == GL_TEXTURE_CUBE_MAP) { + m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding = texture; + maxLevel = m_maxCubeMapTextureLevel; + } else { + synthesizeGLError(GL_INVALID_ENUM, "bindTexture", "invalid target"); + return; + } + + webContext()->bindTexture(target, objectOrZero(texture)); + if (texture) { + texture->setTarget(target, maxLevel); + m_onePlusMaxNonDefaultTextureUnit = max(m_activeTextureUnit + 1, m_onePlusMaxNonDefaultTextureUnit); + } else { + // If the disabled index is the current maximum, trace backwards to find the new max enabled texture index + if (m_onePlusMaxNonDefaultTextureUnit == m_activeTextureUnit + 1) { + findNewMaxNonDefaultTextureUnit(); + } + } + + // 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(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) +{ + if (isContextLost()) + return; + webContext()->blendColor(red, green, blue, alpha); +} + +void WebGLRenderingContextBase::blendEquation(GLenum mode) +{ + if (isContextLost() || !validateBlendEquation("blendEquation", mode)) + return; + webContext()->blendEquation(mode); +} + +void WebGLRenderingContextBase::blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) +{ + if (isContextLost() || !validateBlendEquation("blendEquationSeparate", modeRGB) || !validateBlendEquation("blendEquationSeparate", modeAlpha)) + return; + webContext()->blendEquationSeparate(modeRGB, modeAlpha); +} + + +void WebGLRenderingContextBase::blendFunc(GLenum sfactor, GLenum dfactor) +{ + if (isContextLost() || !validateBlendFuncFactors("blendFunc", sfactor, dfactor)) + return; + webContext()->blendFunc(sfactor, dfactor); +} + +void WebGLRenderingContextBase::blendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) +{ + // Note: Alpha does not have the same restrictions as RGB. + if (isContextLost() || !validateBlendFuncFactors("blendFuncSeparate", srcRGB, dstRGB)) + return; + webContext()->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); +} + +void WebGLRenderingContextBase::bufferDataImpl(GLenum target, long long size, const void* data, GLenum usage) +{ + WebGLBuffer* buffer = validateBufferDataTarget("bufferData", target); + if (!buffer) + return; + + switch (usage) { + case GL_STREAM_DRAW: + case GL_STATIC_DRAW: + case GL_DYNAMIC_DRAW: + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "bufferData", "invalid usage"); + return; + } + + if (!validateValueFitNonNegInt32("bufferData", "size", size)) + return; + + webContext()->bufferData(target, static_cast<GLsizeiptr>(size), data, usage); +} + +void WebGLRenderingContextBase::bufferData(GLenum target, long long size, GLenum usage) +{ + if (isContextLost()) + return; + if (!size) { + synthesizeGLError(GL_INVALID_VALUE, "bufferData", "size == 0"); + return; + } + bufferDataImpl(target, size, 0, usage); +} + +void WebGLRenderingContextBase::bufferData(GLenum target, ArrayBuffer* data, GLenum usage) +{ + if (isContextLost()) + return; + if (!data) { + synthesizeGLError(GL_INVALID_VALUE, "bufferData", "no data"); + return; + } + bufferDataImpl(target, data->byteLength(), data->data(), usage); +} + +void WebGLRenderingContextBase::bufferData(GLenum target, ArrayBufferView* data, GLenum usage) +{ + if (isContextLost()) + return; + if (!data) { + synthesizeGLError(GL_INVALID_VALUE, "bufferData", "no data"); + return; + } + bufferDataImpl(target, data->byteLength(), data->baseAddress(), usage); +} + +void WebGLRenderingContextBase::bufferSubDataImpl(GLenum target, long long offset, GLsizeiptr size, const void* data) +{ + WebGLBuffer* buffer = validateBufferDataTarget("bufferSubData", target); + if (!buffer) + return; + if (!validateValueFitNonNegInt32("bufferSubData", "offset", offset)) + return; + if (!data) + return; + + webContext()->bufferSubData(target, static_cast<GLintptr>(offset), size, data); +} + +void WebGLRenderingContextBase::bufferSubData(GLenum target, long long offset, ArrayBuffer* data) +{ + if (isContextLost()) + return; + if (!data) + return; + bufferSubDataImpl(target, offset, data->byteLength(), data->data()); +} + +void WebGLRenderingContextBase::bufferSubData(GLenum target, long long offset, ArrayBufferView* data) +{ + if (isContextLost()) + return; + if (!data) + return; + bufferSubDataImpl(target, offset, data->byteLength(), data->baseAddress()); +} + +GLenum WebGLRenderingContextBase::checkFramebufferStatus(GLenum target) +{ + if (isContextLost()) + return GL_FRAMEBUFFER_UNSUPPORTED; + if (target != GL_FRAMEBUFFER) { + synthesizeGLError(GL_INVALID_ENUM, "checkFramebufferStatus", "invalid target"); + return 0; + } + if (!m_framebufferBinding || !m_framebufferBinding->object()) + return GL_FRAMEBUFFER_COMPLETE; + const char* reason = "framebuffer incomplete"; + GLenum result = m_framebufferBinding->checkStatus(&reason); + if (result != GL_FRAMEBUFFER_COMPLETE) { + emitGLWarning("checkFramebufferStatus", reason); + return result; + } + result = webContext()->checkFramebufferStatus(target); + return result; +} + +void WebGLRenderingContextBase::clear(GLbitfield mask) +{ + if (isContextLost()) + return; + if (mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) { + synthesizeGLError(GL_INVALID_VALUE, "clear", "invalid mask"); + return; + } + const char* reason = "framebuffer incomplete"; + if (m_framebufferBinding && !m_framebufferBinding->onAccess(webContext(), &reason)) { + synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, "clear", reason); + return; + } + if (!clearIfComposited(mask)) + webContext()->clear(mask); + markContextChanged(CanvasChanged); +} + +void WebGLRenderingContextBase::clearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat 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; + webContext()->clearColor(r, g, b, a); +} + +void WebGLRenderingContextBase::clearDepth(GLfloat depth) +{ + if (isContextLost()) + return; + m_clearDepth = depth; + webContext()->clearDepth(depth); +} + +void WebGLRenderingContextBase::clearStencil(GLint s) +{ + if (isContextLost()) + return; + m_clearStencil = s; + webContext()->clearStencil(s); +} + +void WebGLRenderingContextBase::colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) +{ + if (isContextLost()) + return; + m_colorMask[0] = red; + m_colorMask[1] = green; + m_colorMask[2] = blue; + m_colorMask[3] = alpha; + webContext()->colorMask(red, green, blue, alpha); +} + +void WebGLRenderingContextBase::compileShader(WebGLShader* shader) +{ + if (isContextLost() || !validateWebGLObject("compileShader", shader)) + return; + webContext()->compileShader(objectOrZero(shader)); +} + +void WebGLRenderingContextBase::compressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, ArrayBufferView* data) +{ + if (isContextLost()) + return; + if (!validateTexFuncLevel("compressedTexImage2D", target, level)) + return; + + if (!validateCompressedTexFormat(internalformat)) { + synthesizeGLError(GL_INVALID_ENUM, "compressedTexImage2D", "invalid internalformat"); + return; + } + if (border) { + synthesizeGLError(GL_INVALID_VALUE, "compressedTexImage2D", "border not 0"); + return; + } + if (!validateCompressedTexDimensions("compressedTexImage2D", NotTexSubImage2D, 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(GL_INVALID_VALUE, "compressedTexImage2D", "level > 0 not power of 2"); + return; + } + } + webContext()->compressedTexImage2D(target, level, internalformat, width, height, + border, data->byteLength(), data->baseAddress()); + tex->setLevelInfo(target, level, internalformat, width, height, GL_UNSIGNED_BYTE); +} + +void WebGLRenderingContextBase::compressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, ArrayBufferView* data) +{ + if (isContextLost()) + return; + if (!validateTexFuncLevel("compressedTexSubImage2D", target, level)) + return; + if (!validateCompressedTexFormat(format)) { + synthesizeGLError(GL_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(GL_INVALID_OPERATION, "compressedTexSubImage2D", "format does not match texture format"); + return; + } + + if (!validateCompressedTexSubDimensions("compressedTexSubImage2D", target, level, xoffset, yoffset, width, height, format, tex)) + return; + + webContext()->compressedTexSubImage2D(target, level, xoffset, yoffset, + width, height, format, data->byteLength(), data->baseAddress()); +} + +bool WebGLRenderingContextBase::validateSettableTexFormat(const char* functionName, GLenum format) +{ + if (WebGLImageConversion::getClearBitsByFormat(format) & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "format can not be set, only rendered to"); + return false; + } + return true; +} + +void WebGLRenderingContextBase::copyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +{ + if (isContextLost()) + return; + if (!validateTexFuncParameters("copyTexImage2D", NotTexSubImage2D, target, level, internalformat, width, height, border, internalformat, GL_UNSIGNED_BYTE)) + return; + if (!validateSettableTexFormat("copyTexImage2D", internalformat)) + return; + WebGLTexture* tex = validateTextureBinding("copyTexImage2D", target, true); + if (!tex) + return; + if (!isTexInternalFormatColorBufferCombinationValid(internalformat, boundFramebufferColorFormat())) { + synthesizeGLError(GL_INVALID_OPERATION, "copyTexImage2D", "framebuffer is incompatible format"); + return; + } + if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) { + synthesizeGLError(GL_INVALID_VALUE, "copyTexImage2D", "level > 0 not power of 2"); + return; + } + const char* reason = "framebuffer incomplete"; + if (m_framebufferBinding && !m_framebufferBinding->onAccess(webContext(), &reason)) { + synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, "copyTexImage2D", reason); + return; + } + clearIfComposited(); + ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get()); + webContext()->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, GL_UNSIGNED_BYTE); +} + +void WebGLRenderingContextBase::copyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei 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. + Checked<GLint, RecordOverflow> maxX = xoffset; + maxX += width; + Checked<GLint, RecordOverflow> maxY = yoffset; + maxY += height; + if (maxX.hasOverflowed() || maxY.hasOverflowed()) { + synthesizeGLError(GL_INVALID_VALUE, "copyTexSubImage2D", "bad dimensions"); + return; + } + if (maxX.unsafeGet() > tex->getWidth(target, level) || maxY.unsafeGet() > tex->getHeight(target, level)) { + synthesizeGLError(GL_INVALID_VALUE, "copyTexSubImage2D", "rectangle out of range"); + return; + } + GLenum internalformat = tex->getInternalFormat(target, level); + if (!validateSettableTexFormat("copyTexSubImage2D", internalformat)) + return; + if (!isTexInternalFormatColorBufferCombinationValid(internalformat, boundFramebufferColorFormat())) { + synthesizeGLError(GL_INVALID_OPERATION, "copyTexSubImage2D", "framebuffer is incompatible format"); + return; + } + const char* reason = "framebuffer incomplete"; + if (m_framebufferBinding && !m_framebufferBinding->onAccess(webContext(), &reason)) { + synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, "copyTexSubImage2D", reason); + return; + } + clearIfComposited(); + ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get()); + webContext()->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); +} + +PassRefPtr<WebGLBuffer> WebGLRenderingContextBase::createBuffer() +{ + if (isContextLost()) + return nullptr; + RefPtr<WebGLBuffer> o = WebGLBuffer::create(this); + addSharedObject(o.get()); + return o; +} + +PassRefPtr<WebGLFramebuffer> WebGLRenderingContextBase::createFramebuffer() +{ + if (isContextLost()) + return nullptr; + RefPtr<WebGLFramebuffer> o = WebGLFramebuffer::create(this); + addContextObject(o.get()); + return o; +} + +PassRefPtr<WebGLTexture> WebGLRenderingContextBase::createTexture() +{ + if (isContextLost()) + return nullptr; + RefPtr<WebGLTexture> o = WebGLTexture::create(this); + addSharedObject(o.get()); + return o; +} + +PassRefPtr<WebGLProgram> WebGLRenderingContextBase::createProgram() +{ + if (isContextLost()) + return nullptr; + RefPtr<WebGLProgram> o = WebGLProgram::create(this); + addSharedObject(o.get()); + return o; +} + +PassRefPtr<WebGLRenderbuffer> WebGLRenderingContextBase::createRenderbuffer() +{ + if (isContextLost()) + return nullptr; + RefPtr<WebGLRenderbuffer> o = WebGLRenderbuffer::create(this); + addSharedObject(o.get()); + return o; +} + +WebGLRenderbuffer* WebGLRenderingContextBase::ensureEmulatedStencilBuffer(GLenum target, WebGLRenderbuffer* renderbuffer) +{ + if (isContextLost()) + return 0; + if (!renderbuffer->emulatedStencilBuffer()) { + renderbuffer->setEmulatedStencilBuffer(createRenderbuffer()); + webContext()->bindRenderbuffer(target, objectOrZero(renderbuffer->emulatedStencilBuffer())); + webContext()->bindRenderbuffer(target, objectOrZero(m_renderbufferBinding.get())); + } + return renderbuffer->emulatedStencilBuffer(); +} + +PassRefPtr<WebGLShader> WebGLRenderingContextBase::createShader(GLenum type) +{ + if (isContextLost()) + return nullptr; + if (type != GL_VERTEX_SHADER && type != GL_FRAGMENT_SHADER) { + synthesizeGLError(GL_INVALID_ENUM, "createShader", "invalid shader type"); + return nullptr; + } + + RefPtr<WebGLShader> o = WebGLShader::create(this, type); + addSharedObject(o.get()); + return o; +} + +void WebGLRenderingContextBase::cullFace(GLenum mode) +{ + if (isContextLost()) + return; + switch (mode) { + case GL_FRONT_AND_BACK: + case GL_FRONT: + case GL_BACK: + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "cullFace", "invalid mode"); + return; + } + webContext()->cullFace(mode); +} + +bool WebGLRenderingContextBase::deleteObject(WebGLObject* object) +{ + if (isContextLost() || !object) + return false; + if (!object->validate(contextGroup(), this)) { + synthesizeGLError(GL_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(webContext()); + } + 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_drawingBuffer->setFramebufferBinding(0); + // Have to call bindFramebuffer here to bind back to internal fbo. + m_drawingBuffer->bind(); + } +} + +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; + + int maxBoundTextureIndex = -1; + for (size_t i = 0; i < m_onePlusMaxNonDefaultTextureUnit; ++i) { + if (texture == m_textureUnits[i].m_texture2DBinding) { + m_textureUnits[i].m_texture2DBinding = nullptr; + maxBoundTextureIndex = i; + if (!i) + m_drawingBuffer->setTexture2DBinding(0); + } + if (texture == m_textureUnits[i].m_textureCubeMapBinding) { + m_textureUnits[i].m_textureCubeMapBinding = nullptr; + maxBoundTextureIndex = i; + } + } + if (m_framebufferBinding) + m_framebufferBinding->removeAttachmentFromBoundFramebuffer(texture); + + // If the deleted was bound to the the current maximum index, trace backwards to find the new max texture index + if (m_onePlusMaxNonDefaultTextureUnit == static_cast<unsigned long>(maxBoundTextureIndex + 1)) { + findNewMaxNonDefaultTextureUnit(); + } +} + +void WebGLRenderingContextBase::depthFunc(GLenum func) +{ + if (isContextLost()) + return; + if (!validateStencilOrDepthFunc("depthFunc", func)) + return; + webContext()->depthFunc(func); +} + +void WebGLRenderingContextBase::depthMask(GLboolean flag) +{ + if (isContextLost()) + return; + m_depthMask = flag; + webContext()->depthMask(flag); +} + +void WebGLRenderingContextBase::depthRange(GLfloat zNear, GLfloat zFar) +{ + if (isContextLost()) + return; + if (zNear > zFar) { + synthesizeGLError(GL_INVALID_OPERATION, "depthRange", "zNear > zFar"); + return; + } + webContext()->depthRange(zNear, zFar); +} + +void WebGLRenderingContextBase::detachShader(WebGLProgram* program, WebGLShader* shader) +{ + if (isContextLost() || !validateWebGLObject("detachShader", program) || !validateWebGLObject("detachShader", shader)) + return; + if (!program->detachShader(shader)) { + synthesizeGLError(GL_INVALID_OPERATION, "detachShader", "shader not attached"); + return; + } + webContext()->detachShader(objectOrZero(program), objectOrZero(shader)); + shader->onDetached(webContext()); +} + +void WebGLRenderingContextBase::disable(GLenum cap) +{ + if (isContextLost() || !validateCapability("disable", cap)) + return; + if (cap == GL_STENCIL_TEST) { + m_stencilEnabled = false; + applyStencilTest(); + return; + } + if (cap == GL_SCISSOR_TEST) { + m_scissorEnabled = false; + m_drawingBuffer->setScissorEnabled(m_scissorEnabled); + } + webContext()->disable(cap); +} + +void WebGLRenderingContextBase::disableVertexAttribArray(GLuint index) +{ + if (isContextLost()) + return; + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GL_INVALID_VALUE, "disableVertexAttribArray", "index out of range"); + return; + } + + WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index); + state.enabled = false; + + // If the disabled index is the current maximum, trace backwards to find the new max enabled attrib index + if (m_onePlusMaxEnabledAttribIndex == index + 1) { + findNewMaxEnabledAttribIndex(); + } + + webContext()->disableVertexAttribArray(index); +} + +bool WebGLRenderingContextBase::validateRenderingState(const char* functionName) +{ + if (!m_currentProgram) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "no valid shader program in use"); + return false; + } + + // Look in each enabled vertex attrib and check if they've been bound to a buffer. + for (unsigned i = 0; i < m_onePlusMaxEnabledAttribIndex; ++i) { + const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(i); + if (state.enabled + && (!state.bufferBinding || !state.bufferBinding->object())) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, String::format("attribute %d is enabled but has no buffer bound", i).utf8().data()); + return false; + } + } + + return true; +} + +bool WebGLRenderingContextBase::validateWebGLObject(const char* functionName, WebGLObject* object) +{ + if (!object || !object->object()) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "no object or object deleted"); + return false; + } + if (!object->validate(contextGroup(), this)) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "object does not belong to this context"); + return false; + } + return true; +} + +void WebGLRenderingContextBase::drawArrays(GLenum mode, GLint first, GLsizei count) +{ + if (!validateDrawArrays("drawArrays", mode, first, count)) + return; + + clearIfComposited(); + + handleTextureCompleteness("drawArrays", true); + webContext()->drawArrays(mode, first, count); + handleTextureCompleteness("drawArrays", false); + markContextChanged(CanvasChanged); +} + +void WebGLRenderingContextBase::drawElements(GLenum mode, GLsizei count, GLenum type, long long offset) +{ + if (!validateDrawElements("drawElements", mode, count, type, offset)) + return; + + clearIfComposited(); + + handleTextureCompleteness("drawElements", true); + webContext()->drawElements(mode, count, type, static_cast<GLintptr>(offset)); + handleTextureCompleteness("drawElements", false); + markContextChanged(CanvasChanged); +} + +void WebGLRenderingContextBase::drawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount) +{ + if (!validateDrawArrays("drawArraysInstancedANGLE", mode, first, count)) + return; + + if (!validateDrawInstanced("drawArraysInstancedANGLE", primcount)) + return; + + clearIfComposited(); + + handleTextureCompleteness("drawArraysInstancedANGLE", true); + webContext()->drawArraysInstancedANGLE(mode, first, count, primcount); + handleTextureCompleteness("drawArraysInstancedANGLE", false); + markContextChanged(CanvasChanged); +} + +void WebGLRenderingContextBase::drawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, long long offset, GLsizei primcount) +{ + if (!validateDrawElements("drawElementsInstancedANGLE", mode, count, type, offset)) + return; + + if (!validateDrawInstanced("drawElementsInstancedANGLE", primcount)) + return; + + clearIfComposited(); + + handleTextureCompleteness("drawElementsInstancedANGLE", true); + webContext()->drawElementsInstancedANGLE(mode, count, type, static_cast<GLintptr>(offset), primcount); + handleTextureCompleteness("drawElementsInstancedANGLE", false); + markContextChanged(CanvasChanged); +} + +void WebGLRenderingContextBase::enable(GLenum cap) +{ + if (isContextLost() || !validateCapability("enable", cap)) + return; + if (cap == GL_STENCIL_TEST) { + m_stencilEnabled = true; + applyStencilTest(); + return; + } + if (cap == GL_SCISSOR_TEST) { + m_scissorEnabled = true; + m_drawingBuffer->setScissorEnabled(m_scissorEnabled); + } + webContext()->enable(cap); +} + +void WebGLRenderingContextBase::enableVertexAttribArray(GLuint index) +{ + if (isContextLost()) + return; + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GL_INVALID_VALUE, "enableVertexAttribArray", "index out of range"); + return; + } + + WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index); + state.enabled = true; + + m_onePlusMaxEnabledAttribIndex = max(index + 1, m_onePlusMaxEnabledAttribIndex); + + webContext()->enableVertexAttribArray(index); +} + +void WebGLRenderingContextBase::finish() +{ + if (isContextLost()) + return; + webContext()->flush(); // Intentionally a flush, not a finish. +} + +void WebGLRenderingContextBase::flush() +{ + if (isContextLost()) + return; + webContext()->flush(); +} + +void WebGLRenderingContextBase::framebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, WebGLRenderbuffer* buffer) +{ + if (isContextLost() || !validateFramebufferFuncParameters("framebufferRenderbuffer", target, attachment)) + return; + if (renderbuffertarget != GL_RENDERBUFFER) { + synthesizeGLError(GL_INVALID_ENUM, "framebufferRenderbuffer", "invalid target"); + return; + } + if (buffer && !buffer->validate(contextGroup(), this)) { + synthesizeGLError(GL_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(GL_INVALID_OPERATION, "framebufferRenderbuffer", "no framebuffer bound"); + return; + } + Platform3DObject bufferObject = objectOrZero(buffer); + switch (attachment) { + case GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL: + if (isDepthStencilSupported() || !buffer) { + webContext()->framebufferRenderbuffer(target, GL_DEPTH_ATTACHMENT, renderbuffertarget, bufferObject); + webContext()->framebufferRenderbuffer(target, GL_STENCIL_ATTACHMENT, renderbuffertarget, bufferObject); + } else { + WebGLRenderbuffer* emulatedStencilBuffer = ensureEmulatedStencilBuffer(renderbuffertarget, buffer); + if (!emulatedStencilBuffer) { + synthesizeGLError(GL_OUT_OF_MEMORY, "framebufferRenderbuffer", "out of memory"); + return; + } + webContext()->framebufferRenderbuffer(target, GL_DEPTH_ATTACHMENT, renderbuffertarget, bufferObject); + webContext()->framebufferRenderbuffer(target, GL_STENCIL_ATTACHMENT, renderbuffertarget, objectOrZero(emulatedStencilBuffer)); + } + break; + default: + webContext()->framebufferRenderbuffer(target, attachment, renderbuffertarget, bufferObject); + } + m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, buffer); + applyStencilTest(); +} + +void WebGLRenderingContextBase::framebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, WebGLTexture* texture, GLint level) +{ + if (isContextLost() || !validateFramebufferFuncParameters("framebufferTexture2D", target, attachment)) + return; + if (level) { + synthesizeGLError(GL_INVALID_VALUE, "framebufferTexture2D", "level not 0"); + return; + } + if (texture && !texture->validate(contextGroup(), this)) { + synthesizeGLError(GL_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(GL_INVALID_OPERATION, "framebufferTexture2D", "no framebuffer bound"); + return; + } + Platform3DObject textureObject = objectOrZero(texture); + switch (attachment) { + case GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL: + webContext()->framebufferTexture2D(target, GL_DEPTH_ATTACHMENT, textarget, textureObject, level); + webContext()->framebufferTexture2D(target, GL_STENCIL_ATTACHMENT, textarget, textureObject, level); + break; + case GL_DEPTH_ATTACHMENT: + webContext()->framebufferTexture2D(target, attachment, textarget, textureObject, level); + break; + case GL_STENCIL_ATTACHMENT: + webContext()->framebufferTexture2D(target, attachment, textarget, textureObject, level); + break; + default: + webContext()->framebufferTexture2D(target, attachment, textarget, textureObject, level); + } + m_framebufferBinding->setAttachmentForBoundFramebuffer(attachment, textarget, texture, level); + applyStencilTest(); +} + +void WebGLRenderingContextBase::frontFace(GLenum mode) +{ + if (isContextLost()) + return; + switch (mode) { + case GL_CW: + case GL_CCW: + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "frontFace", "invalid mode"); + return; + } + webContext()->frontFace(mode); +} + +void WebGLRenderingContextBase::generateMipmap(GLenum target) +{ + if (isContextLost()) + return; + WebGLTexture* tex = validateTextureBinding("generateMipmap", target, false); + if (!tex) + return; + if (!tex->canGenerateMipmaps()) { + synthesizeGLError(GL_INVALID_OPERATION, "generateMipmap", "level 0 not power of 2 or not all the same size"); + 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(MACOSX) + bool needToResetMinFilter = false; + if (tex->getMinFilter() != GL_NEAREST_MIPMAP_LINEAR) { + webContext()->texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); + needToResetMinFilter = true; + } +#endif + webContext()->generateMipmap(target); +#if OS(MACOSX) + if (needToResetMinFilter) + webContext()->texParameteri(target, GL_TEXTURE_MIN_FILTER, tex->getMinFilter()); +#endif + tex->generateMipmapLevelInfo(); +} + +PassRefPtr<WebGLActiveInfo> WebGLRenderingContextBase::getActiveAttrib(WebGLProgram* program, GLuint index) +{ + if (isContextLost() || !validateWebGLObject("getActiveAttrib", program)) + return nullptr; + blink::WebGraphicsContext3D::ActiveInfo info; + if (!webContext()->getActiveAttrib(objectOrZero(program), index, info)) + return nullptr; + return WebGLActiveInfo::create(info.name, info.type, info.size); +} + +PassRefPtr<WebGLActiveInfo> WebGLRenderingContextBase::getActiveUniform(WebGLProgram* program, GLuint index) +{ + if (isContextLost() || !validateWebGLObject("getActiveUniform", program)) + return nullptr; + blink::WebGraphicsContext3D::ActiveInfo info; + if (!webContext()->getActiveUniform(objectOrZero(program), index, info)) + return nullptr; + return WebGLActiveInfo::create(info.name, info.type, info.size); +} + +bool WebGLRenderingContextBase::getAttachedShaders(WebGLProgram* program, Vector<RefPtr<WebGLShader> >& shaderObjects) +{ + shaderObjects.clear(); + if (isContextLost() || !validateWebGLObject("getAttachedShaders", program)) + return false; + + const GLenum shaderType[] = { + GL_VERTEX_SHADER, + GL_FRAGMENT_SHADER + }; + for (unsigned i = 0; i < sizeof(shaderType) / sizeof(GLenum); ++i) { + WebGLShader* shader = program->getAttachedShader(shaderType[i]); + if (shader) + shaderObjects.append(shader); + } + return true; +} + +GLint WebGLRenderingContextBase::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->linkStatus()) { + synthesizeGLError(GL_INVALID_OPERATION, "getAttribLocation", "program not linked"); + return 0; + } + return webContext()->getAttribLocation(objectOrZero(program), name.utf8().data()); +} + +WebGLGetInfo WebGLRenderingContextBase::getBufferParameter(GLenum target, GLenum pname) +{ + if (isContextLost()) + return WebGLGetInfo(); + if (target != GL_ARRAY_BUFFER && target != GL_ELEMENT_ARRAY_BUFFER) { + synthesizeGLError(GL_INVALID_ENUM, "getBufferParameter", "invalid target"); + return WebGLGetInfo(); + } + + if (pname != GL_BUFFER_SIZE && pname != GL_BUFFER_USAGE) { + synthesizeGLError(GL_INVALID_ENUM, "getBufferParameter", "invalid parameter name"); + return WebGLGetInfo(); + } + + GLint value = 0; + webContext()->getBufferParameteriv(target, pname, &value); + if (pname == GL_BUFFER_SIZE) + return WebGLGetInfo(value); + return WebGLGetInfo(static_cast<unsigned>(value)); +} + +PassRefPtr<WebGLContextAttributes> WebGLRenderingContextBase::getContextAttributes() +{ + if (isContextLost()) + return nullptr; + // We always need to return a new WebGLContextAttributes object to + // prevent the user from mutating any cached version. + blink::WebGraphicsContext3D::Attributes attrs = m_drawingBuffer->getActualAttributes(); + RefPtr<WebGLContextAttributes> attributes = m_requestedAttributes->clone(); + // Some requested attributes may not be honored, so we need to query the underlying + // context/drawing buffer and adjust accordingly. + if (m_requestedAttributes->depth() && !attrs.depth) + attributes->setDepth(false); + if (m_requestedAttributes->stencil() && !attrs.stencil) + attributes->setStencil(false); + attributes->setAntialias(m_drawingBuffer->multisample()); + return attributes.release(); +} + +GLenum WebGLRenderingContextBase::getError() +{ + if (m_lostContextErrors.size()) { + GLenum err = m_lostContextErrors.first(); + m_lostContextErrors.remove(0); + return err; + } + + if (isContextLost()) + return GL_NO_ERROR; + + return webContext()->getError(); +} + +const char* const* WebGLRenderingContextBase::ExtensionTracker::prefixes() const +{ + static const char* const unprefixed[] = { "", 0, }; + return m_prefixes ? m_prefixes : unprefixed; +} + +bool WebGLRenderingContextBase::ExtensionTracker::matchesNameWithPrefixes(const String& name) const +{ + const char* const* prefixSet = prefixes(); + for (; *prefixSet; ++prefixSet) { + String prefixedName = String(*prefixSet) + extensionName(); + if (equalIgnoringCase(prefixedName, name)) { + return true; + } + } + return false; +} + +bool WebGLRenderingContextBase::extensionSupportedAndAllowed(const ExtensionTracker* tracker) +{ + if (tracker->draft() && !RuntimeEnabledFeatures::webGLDraftExtensionsEnabled()) + return false; + if (!tracker->supported(this)) + return false; + return true; +} + + +PassRefPtr<WebGLExtension> WebGLRenderingContextBase::getExtension(const String& name) +{ + if (isContextLost()) + return nullptr; + + for (size_t i = 0; i < m_extensions.size(); ++i) { + ExtensionTracker* tracker = m_extensions[i]; + if (tracker->matchesNameWithPrefixes(name)) { + if (!extensionSupportedAndAllowed(tracker)) + return nullptr; + + RefPtr<WebGLExtension> extension = tracker->getExtension(this); + if (extension) + m_extensionEnabled[extension->name()] = true; + return extension.release(); + } + } + + return nullptr; +} + +WebGLGetInfo WebGLRenderingContextBase::getFramebufferAttachmentParameter(GLenum target, GLenum attachment, GLenum pname) +{ + if (isContextLost() || !validateFramebufferFuncParameters("getFramebufferAttachmentParameter", target, attachment)) + return WebGLGetInfo(); + + if (!m_framebufferBinding || !m_framebufferBinding->object()) { + synthesizeGLError(GL_INVALID_OPERATION, "getFramebufferAttachmentParameter", "no framebuffer bound"); + return WebGLGetInfo(); + } + + WebGLSharedObject* object = m_framebufferBinding->getAttachmentObject(attachment); + if (!object) { + if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) + return WebGLGetInfo(GL_NONE); + // OpenGL ES 2.0 specifies INVALID_ENUM in this case, while desktop GL + // specifies INVALID_OPERATION. + synthesizeGLError(GL_INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name"); + return WebGLGetInfo(); + } + + ASSERT(object->isTexture() || object->isRenderbuffer()); + if (object->isTexture()) { + switch (pname) { + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + return WebGLGetInfo(GL_TEXTURE); + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + return WebGLGetInfo(PassRefPtr<WebGLTexture>(static_cast<WebGLTexture*>(object))); + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: + { + GLint value = 0; + webContext()->getFramebufferAttachmentParameteriv(target, attachment, pname, &value); + return WebGLGetInfo(value); + } + default: + synthesizeGLError(GL_INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for texture attachment"); + return WebGLGetInfo(); + } + } else { + switch (pname) { + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + return WebGLGetInfo(GL_RENDERBUFFER); + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(static_cast<WebGLRenderbuffer*>(object))); + default: + synthesizeGLError(GL_INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for renderbuffer attachment"); + return WebGLGetInfo(); + } + } +} + +WebGLGetInfo WebGLRenderingContextBase::getParameter(GLenum pname) +{ + if (isContextLost()) + return WebGLGetInfo(); + const int intZero = 0; + switch (pname) { + case GL_ACTIVE_TEXTURE: + return getUnsignedIntParameter(pname); + case GL_ALIASED_LINE_WIDTH_RANGE: + return getWebGLFloatArrayParameter(pname); + case GL_ALIASED_POINT_SIZE_RANGE: + return getWebGLFloatArrayParameter(pname); + case GL_ALPHA_BITS: + return getIntParameter(pname); + case GL_ARRAY_BUFFER_BINDING: + return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundArrayBuffer)); + case GL_BLEND: + return getBooleanParameter(pname); + case GL_BLEND_COLOR: + return getWebGLFloatArrayParameter(pname); + case GL_BLEND_DST_ALPHA: + return getUnsignedIntParameter(pname); + case GL_BLEND_DST_RGB: + return getUnsignedIntParameter(pname); + case GL_BLEND_EQUATION_ALPHA: + return getUnsignedIntParameter(pname); + case GL_BLEND_EQUATION_RGB: + return getUnsignedIntParameter(pname); + case GL_BLEND_SRC_ALPHA: + return getUnsignedIntParameter(pname); + case GL_BLEND_SRC_RGB: + return getUnsignedIntParameter(pname); + case GL_BLUE_BITS: + return getIntParameter(pname); + case GL_COLOR_CLEAR_VALUE: + return getWebGLFloatArrayParameter(pname); + case GL_COLOR_WRITEMASK: + return getBooleanArrayParameter(pname); + case GL_COMPRESSED_TEXTURE_FORMATS: + return WebGLGetInfo(Uint32Array::create(m_compressedTextureFormats.data(), m_compressedTextureFormats.size())); + case GL_CULL_FACE: + return getBooleanParameter(pname); + case GL_CULL_FACE_MODE: + return getUnsignedIntParameter(pname); + case GL_CURRENT_PROGRAM: + return WebGLGetInfo(PassRefPtr<WebGLProgram>(m_currentProgram)); + case GL_DEPTH_BITS: + if (!m_framebufferBinding && !m_requestedAttributes->depth()) + return WebGLGetInfo(intZero); + return getIntParameter(pname); + case GL_DEPTH_CLEAR_VALUE: + return getFloatParameter(pname); + case GL_DEPTH_FUNC: + return getUnsignedIntParameter(pname); + case GL_DEPTH_RANGE: + return getWebGLFloatArrayParameter(pname); + case GL_DEPTH_TEST: + return getBooleanParameter(pname); + case GL_DEPTH_WRITEMASK: + return getBooleanParameter(pname); + case GL_DITHER: + return getBooleanParameter(pname); + case GL_ELEMENT_ARRAY_BUFFER_BINDING: + return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundVertexArrayObject->boundElementArrayBuffer())); + case GL_FRAMEBUFFER_BINDING: + return WebGLGetInfo(PassRefPtr<WebGLFramebuffer>(m_framebufferBinding)); + case GL_FRONT_FACE: + return getUnsignedIntParameter(pname); + case GL_GENERATE_MIPMAP_HINT: + return getUnsignedIntParameter(pname); + case GL_GREEN_BITS: + return getIntParameter(pname); + case GL_IMPLEMENTATION_COLOR_READ_FORMAT: + return getIntParameter(pname); + case GL_IMPLEMENTATION_COLOR_READ_TYPE: + return getIntParameter(pname); + case GL_LINE_WIDTH: + return getFloatParameter(pname); + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: + return getIntParameter(pname); + case GL_MAX_CUBE_MAP_TEXTURE_SIZE: + return getIntParameter(pname); + case GL_MAX_FRAGMENT_UNIFORM_VECTORS: + return getIntParameter(pname); + case GL_MAX_RENDERBUFFER_SIZE: + return getIntParameter(pname); + case GL_MAX_TEXTURE_IMAGE_UNITS: + return getIntParameter(pname); + case GL_MAX_TEXTURE_SIZE: + return getIntParameter(pname); + case GL_MAX_VARYING_VECTORS: + return getIntParameter(pname); + case GL_MAX_VERTEX_ATTRIBS: + return getIntParameter(pname); + case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: + return getIntParameter(pname); + case GL_MAX_VERTEX_UNIFORM_VECTORS: + return getIntParameter(pname); + case GL_MAX_VIEWPORT_DIMS: + return getWebGLIntArrayParameter(pname); + case GL_NUM_SHADER_BINARY_FORMATS: + // FIXME: should we always return 0 for this? + return getIntParameter(pname); + case GL_PACK_ALIGNMENT: + return getIntParameter(pname); + case GL_POLYGON_OFFSET_FACTOR: + return getFloatParameter(pname); + case GL_POLYGON_OFFSET_FILL: + return getBooleanParameter(pname); + case GL_POLYGON_OFFSET_UNITS: + return getFloatParameter(pname); + case GL_RED_BITS: + return getIntParameter(pname); + case GL_RENDERBUFFER_BINDING: + return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(m_renderbufferBinding)); + case GL_RENDERER: + return WebGLGetInfo(String("WebKit WebGL")); + case GL_SAMPLE_BUFFERS: + return getIntParameter(pname); + case GL_SAMPLE_COVERAGE_INVERT: + return getBooleanParameter(pname); + case GL_SAMPLE_COVERAGE_VALUE: + return getFloatParameter(pname); + case GL_SAMPLES: + return getIntParameter(pname); + case GL_SCISSOR_BOX: + return getWebGLIntArrayParameter(pname); + case GL_SCISSOR_TEST: + return getBooleanParameter(pname); + case GL_SHADING_LANGUAGE_VERSION: + return WebGLGetInfo("WebGL GLSL ES 1.0 (" + String(webContext()->getString(GL_SHADING_LANGUAGE_VERSION)) + ")"); + case GL_STENCIL_BACK_FAIL: + return getUnsignedIntParameter(pname); + case GL_STENCIL_BACK_FUNC: + return getUnsignedIntParameter(pname); + case GL_STENCIL_BACK_PASS_DEPTH_FAIL: + return getUnsignedIntParameter(pname); + case GL_STENCIL_BACK_PASS_DEPTH_PASS: + return getUnsignedIntParameter(pname); + case GL_STENCIL_BACK_REF: + return getIntParameter(pname); + case GL_STENCIL_BACK_VALUE_MASK: + return getUnsignedIntParameter(pname); + case GL_STENCIL_BACK_WRITEMASK: + return getUnsignedIntParameter(pname); + case GL_STENCIL_BITS: + if (!m_framebufferBinding && !m_requestedAttributes->stencil()) + return WebGLGetInfo(intZero); + return getIntParameter(pname); + case GL_STENCIL_CLEAR_VALUE: + return getIntParameter(pname); + case GL_STENCIL_FAIL: + return getUnsignedIntParameter(pname); + case GL_STENCIL_FUNC: + return getUnsignedIntParameter(pname); + case GL_STENCIL_PASS_DEPTH_FAIL: + return getUnsignedIntParameter(pname); + case GL_STENCIL_PASS_DEPTH_PASS: + return getUnsignedIntParameter(pname); + case GL_STENCIL_REF: + return getIntParameter(pname); + case GL_STENCIL_TEST: + return getBooleanParameter(pname); + case GL_STENCIL_VALUE_MASK: + return getUnsignedIntParameter(pname); + case GL_STENCIL_WRITEMASK: + return getUnsignedIntParameter(pname); + case GL_SUBPIXEL_BITS: + return getIntParameter(pname); + case GL_TEXTURE_BINDING_2D: + return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].m_texture2DBinding)); + case GL_TEXTURE_BINDING_CUBE_MAP: + return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding)); + case GL_UNPACK_ALIGNMENT: + return getIntParameter(pname); + case GC3D_UNPACK_FLIP_Y_WEBGL: + return WebGLGetInfo(m_unpackFlipY); + case GC3D_UNPACK_PREMULTIPLY_ALPHA_WEBGL: + return WebGLGetInfo(m_unpackPremultiplyAlpha); + case GC3D_UNPACK_COLORSPACE_CONVERSION_WEBGL: + return WebGLGetInfo(m_unpackColorspaceConversion); + case GL_VENDOR: + return WebGLGetInfo(String("WebKit")); + case GL_VERSION: + return WebGLGetInfo("WebGL 1.0 (" + String(webContext()->getString(GL_VERSION)) + ")"); + case GL_VIEWPORT: + return getWebGLIntArrayParameter(pname); + case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives + if (extensionEnabled(OESStandardDerivativesName)) + return getUnsignedIntParameter(GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES); + synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, OES_standard_derivatives not enabled"); + return WebGLGetInfo(); + case WebGLDebugRendererInfo::UNMASKED_RENDERER_WEBGL: + if (extensionEnabled(WebGLDebugRendererInfoName)) + return WebGLGetInfo(webContext()->getString(GL_RENDERER)); + synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled"); + return WebGLGetInfo(); + case WebGLDebugRendererInfo::UNMASKED_VENDOR_WEBGL: + if (extensionEnabled(WebGLDebugRendererInfoName)) + return WebGLGetInfo(webContext()->getString(GL_VENDOR)); + synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled"); + return WebGLGetInfo(); + case GL_VERTEX_ARRAY_BINDING_OES: // OES_vertex_array_object + if (extensionEnabled(OESVertexArrayObjectName)) { + if (!m_boundVertexArrayObject->isDefaultObject()) + return WebGLGetInfo(PassRefPtr<WebGLVertexArrayObjectOES>(m_boundVertexArrayObject)); + return WebGLGetInfo(); + } + synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, OES_vertex_array_object not enabled"); + return WebGLGetInfo(); + case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic + if (extensionEnabled(EXTTextureFilterAnisotropicName)) + return getUnsignedIntParameter(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT); + synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled"); + return WebGLGetInfo(); + case GL_MAX_COLOR_ATTACHMENTS_EXT: // EXT_draw_buffers BEGIN + if (extensionEnabled(WebGLDrawBuffersName)) + return WebGLGetInfo(maxColorAttachments()); + synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled"); + return WebGLGetInfo(); + case GL_MAX_DRAW_BUFFERS_EXT: + if (extensionEnabled(WebGLDrawBuffersName)) + return WebGLGetInfo(maxDrawBuffers()); + synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_draw_buffers not enabled"); + return WebGLGetInfo(); + default: + if (extensionEnabled(WebGLDrawBuffersName) + && pname >= GL_DRAW_BUFFER0_EXT + && pname < static_cast<GLenum>(GL_DRAW_BUFFER0_EXT + maxDrawBuffers())) { + GLint value = GL_NONE; + if (m_framebufferBinding) + value = m_framebufferBinding->getDrawBuffer(pname); + else // emulated backbuffer + value = m_backDrawBuffer; + return WebGLGetInfo(value); + } + synthesizeGLError(GL_INVALID_ENUM, "getParameter", "invalid parameter name"); + return WebGLGetInfo(); + } +} + +WebGLGetInfo WebGLRenderingContextBase::getProgramParameter(WebGLProgram* program, GLenum pname) +{ + if (isContextLost() || !validateWebGLObject("getProgramParameter", program)) + return WebGLGetInfo(); + + GLint value = 0; + switch (pname) { + case GL_DELETE_STATUS: + return WebGLGetInfo(program->isDeleted()); + case GL_VALIDATE_STATUS: + webContext()->getProgramiv(objectOrZero(program), pname, &value); + return WebGLGetInfo(static_cast<bool>(value)); + case GL_LINK_STATUS: + return WebGLGetInfo(program->linkStatus()); + case GL_ATTACHED_SHADERS: + case GL_ACTIVE_ATTRIBUTES: + case GL_ACTIVE_UNIFORMS: + webContext()->getProgramiv(objectOrZero(program), pname, &value); + return WebGLGetInfo(value); + default: + synthesizeGLError(GL_INVALID_ENUM, "getProgramParameter", "invalid parameter name"); + return WebGLGetInfo(); + } +} + +String WebGLRenderingContextBase::getProgramInfoLog(WebGLProgram* program) +{ + if (isContextLost()) + return String(); + if (!validateWebGLObject("getProgramInfoLog", program)) + return ""; + return ensureNotNull(webContext()->getProgramInfoLog(objectOrZero(program))); +} + +WebGLGetInfo WebGLRenderingContextBase::getRenderbufferParameter(GLenum target, GLenum pname) +{ + if (isContextLost()) + return WebGLGetInfo(); + if (target != GL_RENDERBUFFER) { + synthesizeGLError(GL_INVALID_ENUM, "getRenderbufferParameter", "invalid target"); + return WebGLGetInfo(); + } + if (!m_renderbufferBinding || !m_renderbufferBinding->object()) { + synthesizeGLError(GL_INVALID_OPERATION, "getRenderbufferParameter", "no renderbuffer bound"); + return WebGLGetInfo(); + } + + GLint value = 0; + switch (pname) { + case GL_RENDERBUFFER_WIDTH: + case GL_RENDERBUFFER_HEIGHT: + case GL_RENDERBUFFER_RED_SIZE: + case GL_RENDERBUFFER_GREEN_SIZE: + case GL_RENDERBUFFER_BLUE_SIZE: + case GL_RENDERBUFFER_ALPHA_SIZE: + case GL_RENDERBUFFER_DEPTH_SIZE: + webContext()->getRenderbufferParameteriv(target, pname, &value); + return WebGLGetInfo(value); + case GL_RENDERBUFFER_STENCIL_SIZE: + if (m_renderbufferBinding->emulatedStencilBuffer()) { + webContext()->bindRenderbuffer(target, objectOrZero(m_renderbufferBinding->emulatedStencilBuffer())); + webContext()->getRenderbufferParameteriv(target, pname, &value); + webContext()->bindRenderbuffer(target, objectOrZero(m_renderbufferBinding.get())); + } else { + webContext()->getRenderbufferParameteriv(target, pname, &value); + } + return WebGLGetInfo(value); + case GL_RENDERBUFFER_INTERNAL_FORMAT: + return WebGLGetInfo(m_renderbufferBinding->internalFormat()); + default: + synthesizeGLError(GL_INVALID_ENUM, "getRenderbufferParameter", "invalid parameter name"); + return WebGLGetInfo(); + } +} + +WebGLGetInfo WebGLRenderingContextBase::getShaderParameter(WebGLShader* shader, GLenum pname) +{ + if (isContextLost() || !validateWebGLObject("getShaderParameter", shader)) + return WebGLGetInfo(); + GLint value = 0; + switch (pname) { + case GL_DELETE_STATUS: + return WebGLGetInfo(shader->isDeleted()); + case GL_COMPILE_STATUS: + webContext()->getShaderiv(objectOrZero(shader), pname, &value); + return WebGLGetInfo(static_cast<bool>(value)); + case GL_SHADER_TYPE: + webContext()->getShaderiv(objectOrZero(shader), pname, &value); + return WebGLGetInfo(static_cast<unsigned>(value)); + default: + synthesizeGLError(GL_INVALID_ENUM, "getShaderParameter", "invalid parameter name"); + return WebGLGetInfo(); + } +} + +String WebGLRenderingContextBase::getShaderInfoLog(WebGLShader* shader) +{ + if (isContextLost()) + return String(); + if (!validateWebGLObject("getShaderInfoLog", shader)) + return ""; + return ensureNotNull(webContext()->getShaderInfoLog(objectOrZero(shader))); +} + +PassRefPtr<WebGLShaderPrecisionFormat> WebGLRenderingContextBase::getShaderPrecisionFormat(GLenum shaderType, GLenum precisionType) +{ + if (isContextLost()) + return nullptr; + switch (shaderType) { + case GL_VERTEX_SHADER: + case GL_FRAGMENT_SHADER: + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "getShaderPrecisionFormat", "invalid shader type"); + return nullptr; + } + switch (precisionType) { + case GL_LOW_FLOAT: + case GL_MEDIUM_FLOAT: + case GL_HIGH_FLOAT: + case GL_LOW_INT: + case GL_MEDIUM_INT: + case GL_HIGH_INT: + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "getShaderPrecisionFormat", "invalid precision type"); + return nullptr; + } + + GLint range[2] = {0, 0}; + GLint precision = 0; + webContext()->getShaderPrecisionFormat(shaderType, precisionType, range, &precision); + return WebGLShaderPrecisionFormat::create(range[0], range[1], precision); +} + +String WebGLRenderingContextBase::getShaderSource(WebGLShader* shader) +{ + if (isContextLost()) + return String(); + if (!validateWebGLObject("getShaderSource", shader)) + return ""; + return ensureNotNull(shader->source()); +} + +Vector<String> WebGLRenderingContextBase::getSupportedExtensions() +{ + Vector<String> result; + if (isContextLost()) + return result; + + for (size_t i = 0; i < m_extensions.size(); ++i) { + ExtensionTracker* tracker = m_extensions[i]; + if (extensionSupportedAndAllowed(tracker)) { + const char* const* prefixes = tracker->prefixes(); + for (; *prefixes; ++prefixes) { + String prefixedName = String(*prefixes) + tracker->extensionName(); + result.append(prefixedName); + } + } + } + + return result; +} + +WebGLGetInfo WebGLRenderingContextBase::getTexParameter(GLenum target, GLenum pname) +{ + if (isContextLost()) + return WebGLGetInfo(); + WebGLTexture* tex = validateTextureBinding("getTexParameter", target, false); + if (!tex) + return WebGLGetInfo(); + switch (pname) { + case GL_TEXTURE_MAG_FILTER: + case GL_TEXTURE_MIN_FILTER: + case GL_TEXTURE_WRAP_S: + case GL_TEXTURE_WRAP_T: + { + GLint value = 0; + webContext()->getTexParameteriv(target, pname, &value); + return WebGLGetInfo(static_cast<unsigned>(value)); + } + case GL_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic + if (extensionEnabled(EXTTextureFilterAnisotropicName)) { + GLfloat value = 0.f; + webContext()->getTexParameterfv(target, pname, &value); + return WebGLGetInfo(value); + } + synthesizeGLError(GL_INVALID_ENUM, "getTexParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled"); + return WebGLGetInfo(); + default: + synthesizeGLError(GL_INVALID_ENUM, "getTexParameter", "invalid parameter name"); + return WebGLGetInfo(); + } +} + +WebGLGetInfo WebGLRenderingContextBase::getUniform(WebGLProgram* program, const WebGLUniformLocation* uniformLocation) +{ + if (isContextLost() || !validateWebGLObject("getUniform", program)) + return WebGLGetInfo(); + if (!uniformLocation || uniformLocation->program() != program) { + synthesizeGLError(GL_INVALID_OPERATION, "getUniform", "no uniformlocation or not valid for this program"); + return WebGLGetInfo(); + } + GLint location = uniformLocation->location(); + + // FIXME: make this more efficient using WebGLUniformLocation and caching types in it + GLint activeUniforms = 0; + webContext()->getProgramiv(objectOrZero(program), GL_ACTIVE_UNIFORMS, &activeUniforms); + for (GLint i = 0; i < activeUniforms; i++) { + blink::WebGraphicsContext3D::ActiveInfo info; + if (!webContext()->getActiveUniform(objectOrZero(program), i, info)) + return WebGLGetInfo(); + String name = info.name; + StringBuilder nameBuilder; + // Strip "[0]" from the name if it's an array. + if (info.size > 1 && name.endsWith("[0]")) + info.name = name.left(name.length() - 3); + // If it's an array, we need to iterate through each element, appending "[index]" to the name. + for (GLint index = 0; index < info.size; ++index) { + nameBuilder.clear(); + nameBuilder.append(info.name); + if (info.size > 1 && index >= 1) { + nameBuilder.append('['); + nameBuilder.append(String::number(index)); + nameBuilder.append(']'); + } + // Now need to look this up by name again to find its location + GLint loc = webContext()->getUniformLocation(objectOrZero(program), nameBuilder.toString().utf8().data()); + if (loc == location) { + // Found it. Use the type in the ActiveInfo to determine the return type. + GLenum baseType; + unsigned length; + switch (info.type) { + case GL_BOOL: + baseType = GL_BOOL; + length = 1; + break; + case GL_BOOL_VEC2: + baseType = GL_BOOL; + length = 2; + break; + case GL_BOOL_VEC3: + baseType = GL_BOOL; + length = 3; + break; + case GL_BOOL_VEC4: + baseType = GL_BOOL; + length = 4; + break; + case GL_INT: + baseType = GL_INT; + length = 1; + break; + case GL_INT_VEC2: + baseType = GL_INT; + length = 2; + break; + case GL_INT_VEC3: + baseType = GL_INT; + length = 3; + break; + case GL_INT_VEC4: + baseType = GL_INT; + length = 4; + break; + case GL_FLOAT: + baseType = GL_FLOAT; + length = 1; + break; + case GL_FLOAT_VEC2: + baseType = GL_FLOAT; + length = 2; + break; + case GL_FLOAT_VEC3: + baseType = GL_FLOAT; + length = 3; + break; + case GL_FLOAT_VEC4: + baseType = GL_FLOAT; + length = 4; + break; + case GL_FLOAT_MAT2: + baseType = GL_FLOAT; + length = 4; + break; + case GL_FLOAT_MAT3: + baseType = GL_FLOAT; + length = 9; + break; + case GL_FLOAT_MAT4: + baseType = GL_FLOAT; + length = 16; + break; + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: + baseType = GL_INT; + length = 1; + break; + default: + // Can't handle this type + synthesizeGLError(GL_INVALID_VALUE, "getUniform", "unhandled type"); + return WebGLGetInfo(); + } + switch (baseType) { + case GL_FLOAT: { + GLfloat value[16] = {0}; + webContext()->getUniformfv(objectOrZero(program), location, value); + if (length == 1) + return WebGLGetInfo(value[0]); + return WebGLGetInfo(Float32Array::create(value, length)); + } + case GL_INT: { + GLint value[4] = {0}; + webContext()->getUniformiv(objectOrZero(program), location, value); + if (length == 1) + return WebGLGetInfo(value[0]); + return WebGLGetInfo(Int32Array::create(value, length)); + } + case GL_BOOL: { + GLint value[4] = {0}; + webContext()->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(GL_INVALID_VALUE, "getUniform", "unknown error"); + return WebGLGetInfo(); +} + +PassRefPtr<WebGLUniformLocation> WebGLRenderingContextBase::getUniformLocation(WebGLProgram* program, const String& name) +{ + 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->linkStatus()) { + synthesizeGLError(GL_INVALID_OPERATION, "getUniformLocation", "program not linked"); + return nullptr; + } + GLint uniformLocation = webContext()->getUniformLocation(objectOrZero(program), name.utf8().data()); + if (uniformLocation == -1) + return nullptr; + return WebGLUniformLocation::create(program, uniformLocation); +} + +WebGLGetInfo WebGLRenderingContextBase::getVertexAttrib(GLuint index, GLenum pname) +{ + if (isContextLost()) + return WebGLGetInfo(); + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GL_INVALID_VALUE, "getVertexAttrib", "index out of range"); + return WebGLGetInfo(); + } + const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index); + + if (extensionEnabled(ANGLEInstancedArraysName) && pname == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE) + return WebGLGetInfo(state.divisor); + + switch (pname) { + case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: + if (!state.bufferBinding || !state.bufferBinding->object()) + return WebGLGetInfo(); + return WebGLGetInfo(PassRefPtr<WebGLBuffer>(state.bufferBinding)); + case GL_VERTEX_ATTRIB_ARRAY_ENABLED: + return WebGLGetInfo(state.enabled); + case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: + return WebGLGetInfo(state.normalized); + case GL_VERTEX_ATTRIB_ARRAY_SIZE: + return WebGLGetInfo(state.size); + case GL_VERTEX_ATTRIB_ARRAY_STRIDE: + return WebGLGetInfo(state.originalStride); + case GL_VERTEX_ATTRIB_ARRAY_TYPE: + return WebGLGetInfo(state.type); + case GL_CURRENT_VERTEX_ATTRIB: + return WebGLGetInfo(Float32Array::create(m_vertexAttribValue[index].value, 4)); + default: + synthesizeGLError(GL_INVALID_ENUM, "getVertexAttrib", "invalid parameter name"); + return WebGLGetInfo(); + } +} + +long long WebGLRenderingContextBase::getVertexAttribOffset(GLuint index, GLenum pname) +{ + if (isContextLost()) + return 0; + if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER) { + synthesizeGLError(GL_INVALID_ENUM, "getVertexAttribOffset", "invalid parameter name"); + return 0; + } + GLsizeiptr result = webContext()->getVertexAttribOffset(index, pname); + return static_cast<long long>(result); +} + +void WebGLRenderingContextBase::hint(GLenum target, GLenum mode) +{ + if (isContextLost()) + return; + bool isValid = false; + switch (target) { + case GL_GENERATE_MIPMAP_HINT: + isValid = true; + break; + case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives + if (extensionEnabled(OESStandardDerivativesName)) + isValid = true; + break; + } + if (!isValid) { + synthesizeGLError(GL_INVALID_ENUM, "hint", "invalid target"); + return; + } + webContext()->hint(target, mode); +} + +GLboolean WebGLRenderingContextBase::isBuffer(WebGLBuffer* buffer) +{ + if (!buffer || isContextLost()) + return 0; + + if (!buffer->hasEverBeenBound()) + return 0; + + return webContext()->isBuffer(buffer->object()); +} + +bool WebGLRenderingContextBase::isContextLost() const +{ + return m_contextLost; +} + +GLboolean WebGLRenderingContextBase::isEnabled(GLenum cap) +{ + if (isContextLost() || !validateCapability("isEnabled", cap)) + return 0; + if (cap == GL_STENCIL_TEST) + return m_stencilEnabled; + return webContext()->isEnabled(cap); +} + +GLboolean WebGLRenderingContextBase::isFramebuffer(WebGLFramebuffer* framebuffer) +{ + if (!framebuffer || isContextLost()) + return 0; + + if (!framebuffer->hasEverBeenBound()) + return 0; + + return webContext()->isFramebuffer(framebuffer->object()); +} + +GLboolean WebGLRenderingContextBase::isProgram(WebGLProgram* program) +{ + if (!program || isContextLost()) + return 0; + + return webContext()->isProgram(program->object()); +} + +GLboolean WebGLRenderingContextBase::isRenderbuffer(WebGLRenderbuffer* renderbuffer) +{ + if (!renderbuffer || isContextLost()) + return 0; + + if (!renderbuffer->hasEverBeenBound()) + return 0; + + return webContext()->isRenderbuffer(renderbuffer->object()); +} + +GLboolean WebGLRenderingContextBase::isShader(WebGLShader* shader) +{ + if (!shader || isContextLost()) + return 0; + + return webContext()->isShader(shader->object()); +} + +GLboolean WebGLRenderingContextBase::isTexture(WebGLTexture* texture) +{ + if (!texture || isContextLost()) + return 0; + + if (!texture->hasEverBeenBound()) + return 0; + + return webContext()->isTexture(texture->object()); +} + +void WebGLRenderingContextBase::lineWidth(GLfloat width) +{ + if (isContextLost()) + return; + webContext()->lineWidth(width); +} + +void WebGLRenderingContextBase::linkProgram(WebGLProgram* program) +{ + if (isContextLost() || !validateWebGLObject("linkProgram", program)) + return; + + webContext()->linkProgram(objectOrZero(program)); + program->increaseLinkCount(); +} + +void WebGLRenderingContextBase::pixelStorei(GLenum pname, GLint param) +{ + if (isContextLost()) + return; + switch (pname) { + case GC3D_UNPACK_FLIP_Y_WEBGL: + m_unpackFlipY = param; + break; + case GC3D_UNPACK_PREMULTIPLY_ALPHA_WEBGL: + m_unpackPremultiplyAlpha = param; + break; + case GC3D_UNPACK_COLORSPACE_CONVERSION_WEBGL: + if (static_cast<GLenum>(param) == GC3D_BROWSER_DEFAULT_WEBGL || param == GL_NONE) { + m_unpackColorspaceConversion = static_cast<GLenum>(param); + } else { + synthesizeGLError(GL_INVALID_VALUE, "pixelStorei", "invalid parameter for UNPACK_COLORSPACE_CONVERSION_WEBGL"); + return; + } + break; + case GL_PACK_ALIGNMENT: + case GL_UNPACK_ALIGNMENT: + if (param == 1 || param == 2 || param == 4 || param == 8) { + if (pname == GL_PACK_ALIGNMENT) { + m_packAlignment = param; + m_drawingBuffer->setPackAlignment(param); + } else { // GL_UNPACK_ALIGNMENT: + m_unpackAlignment = param; + } + webContext()->pixelStorei(pname, param); + } else { + synthesizeGLError(GL_INVALID_VALUE, "pixelStorei", "invalid parameter for alignment"); + return; + } + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "pixelStorei", "invalid parameter name"); + return; + } +} + +void WebGLRenderingContextBase::polygonOffset(GLfloat factor, GLfloat units) +{ + if (isContextLost()) + return; + webContext()->polygonOffset(factor, units); +} + +void WebGLRenderingContextBase::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, ArrayBufferView* pixels) +{ + 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(GL_INVALID_VALUE, "readPixels", "no destination ArrayBufferView"); + return; + } + switch (format) { + case GL_ALPHA: + case GL_RGB: + case GL_RGBA: + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "readPixels", "invalid format"); + return; + } + + ArrayBufferView::ViewType expectedViewType; + + switch (type) { + case GL_UNSIGNED_BYTE: + expectedViewType = ArrayBufferView::TypeUint8; + break; + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_5_5_5_1: + expectedViewType = ArrayBufferView::TypeUint16; + break; + case GL_FLOAT: + expectedViewType = ArrayBufferView::TypeFloat32; + break; + case GL_HALF_FLOAT_OES: + expectedViewType = ArrayBufferView::TypeUint16; + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "readPixels", "invalid type"); + return; + } + if (format != GL_RGBA || type != GL_UNSIGNED_BYTE) { + // Check against the implementation color read format and type. + blink::WGC3Dint implFormat = 0, implType = 0; + webContext()->getIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &implFormat); + webContext()->getIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &implType); + if (!implFormat || !implType || format != static_cast<GLenum>(implFormat) || type != static_cast<GLenum>(implType)) { + synthesizeGLError(GL_INVALID_OPERATION, "readPixels", "format/type not RGBA/UNSIGNED_BYTE or implementation-defined values"); + return; + } + } + // Validate array type against pixel type. + if (pixels->type() != expectedViewType) { + synthesizeGLError(GL_INVALID_OPERATION, "readPixels", "ArrayBufferView was the wrong type for the pixel format"); + return; + } + const char* reason = "framebuffer incomplete"; + if (m_framebufferBinding && !m_framebufferBinding->onAccess(webContext(), &reason)) { + synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, "readPixels", reason); + return; + } + // Calculate array size, taking into consideration of PACK_ALIGNMENT. + unsigned totalBytesRequired = 0; + unsigned padding = 0; + GLenum error = WebGLImageConversion::computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding); + if (error != GL_NO_ERROR) { + synthesizeGLError(error, "readPixels", "invalid dimensions"); + return; + } + if (pixels->byteLength() < totalBytesRequired) { + synthesizeGLError(GL_INVALID_OPERATION, "readPixels", "ArrayBufferView not large enough for dimensions"); + return; + } + + clearIfComposited(); + void* data = pixels->baseAddress(); + + { + ScopedDrawingBufferBinder binder(m_drawingBuffer.get(), m_framebufferBinding.get()); + webContext()->readPixels(x, y, width, height, format, type, data); + } + +#if OS(MACOSX) + // FIXME: remove this section when GL driver bug on Mac is fixed, i.e., + // when alpha is off, readPixels should set alpha to 255 instead of 0. + if (!m_framebufferBinding && !m_drawingBuffer->getActualAttributes().alpha) { + unsigned char* pixels = reinterpret_cast<unsigned char*>(data); + for (GLsizei iy = 0; iy < height; ++iy) { + for (GLsizei ix = 0; ix < width; ++ix) { + pixels[3] = 255; + pixels += 4; + } + pixels += padding; + } + } +#endif +} + +void WebGLRenderingContextBase::renderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) +{ + if (isContextLost()) + return; + if (target != GL_RENDERBUFFER) { + synthesizeGLError(GL_INVALID_ENUM, "renderbufferStorage", "invalid target"); + return; + } + if (!m_renderbufferBinding || !m_renderbufferBinding->object()) { + synthesizeGLError(GL_INVALID_OPERATION, "renderbufferStorage", "no bound renderbuffer"); + return; + } + if (!validateSize("renderbufferStorage", width, height)) + return; + switch (internalformat) { + case GL_DEPTH_COMPONENT16: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGB565: + case GL_STENCIL_INDEX8: + webContext()->renderbufferStorage(target, internalformat, width, height); + m_renderbufferBinding->setInternalFormat(internalformat); + m_renderbufferBinding->setSize(width, height); + m_renderbufferBinding->deleteEmulatedStencilBuffer(webContext()); + break; + case GL_DEPTH_STENCIL_OES: + if (isDepthStencilSupported()) { + webContext()->renderbufferStorage(target, GL_DEPTH24_STENCIL8_OES, width, height); + } else { + WebGLRenderbuffer* emulatedStencilBuffer = ensureEmulatedStencilBuffer(target, m_renderbufferBinding.get()); + if (!emulatedStencilBuffer) { + synthesizeGLError(GL_OUT_OF_MEMORY, "renderbufferStorage", "out of memory"); + return; + } + webContext()->renderbufferStorage(target, GL_DEPTH_COMPONENT16, width, height); + webContext()->bindRenderbuffer(target, objectOrZero(emulatedStencilBuffer)); + webContext()->renderbufferStorage(target, GL_STENCIL_INDEX8, width, height); + webContext()->bindRenderbuffer(target, objectOrZero(m_renderbufferBinding.get())); + emulatedStencilBuffer->setSize(width, height); + emulatedStencilBuffer->setInternalFormat(GL_STENCIL_INDEX8); + } + m_renderbufferBinding->setSize(width, height); + m_renderbufferBinding->setInternalFormat(internalformat); + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "renderbufferStorage", "invalid internalformat"); + return; + } + applyStencilTest(); +} + +void WebGLRenderingContextBase::sampleCoverage(GLfloat value, GLboolean invert) +{ + if (isContextLost()) + return; + webContext()->sampleCoverage(value, invert); +} + +void WebGLRenderingContextBase::scissor(GLint x, GLint y, GLsizei width, GLsizei height) +{ + if (isContextLost()) + return; + if (!validateSize("scissor", width, height)) + return; + webContext()->scissor(x, y, width, height); +} + +void WebGLRenderingContextBase::shaderSource(WebGLShader* shader, const String& string) +{ + if (isContextLost() || !validateWebGLObject("shaderSource", shader)) + return; + String stringWithoutComments = StripComments(string).result(); + if (!validateString("shaderSource", stringWithoutComments)) + return; + shader->setSource(string); + webContext()->shaderSource(objectOrZero(shader), stringWithoutComments.utf8().data()); +} + +void WebGLRenderingContextBase::stencilFunc(GLenum func, GLint ref, GLuint mask) +{ + if (isContextLost()) + return; + if (!validateStencilOrDepthFunc("stencilFunc", func)) + return; + m_stencilFuncRef = ref; + m_stencilFuncRefBack = ref; + m_stencilFuncMask = mask; + m_stencilFuncMaskBack = mask; + webContext()->stencilFunc(func, ref, mask); +} + +void WebGLRenderingContextBase::stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) +{ + if (isContextLost()) + return; + if (!validateStencilOrDepthFunc("stencilFuncSeparate", func)) + return; + switch (face) { + case GL_FRONT_AND_BACK: + m_stencilFuncRef = ref; + m_stencilFuncRefBack = ref; + m_stencilFuncMask = mask; + m_stencilFuncMaskBack = mask; + break; + case GL_FRONT: + m_stencilFuncRef = ref; + m_stencilFuncMask = mask; + break; + case GL_BACK: + m_stencilFuncRefBack = ref; + m_stencilFuncMaskBack = mask; + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "stencilFuncSeparate", "invalid face"); + return; + } + webContext()->stencilFuncSeparate(face, func, ref, mask); +} + +void WebGLRenderingContextBase::stencilMask(GLuint mask) +{ + if (isContextLost()) + return; + m_stencilMask = mask; + m_stencilMaskBack = mask; + webContext()->stencilMask(mask); +} + +void WebGLRenderingContextBase::stencilMaskSeparate(GLenum face, GLuint mask) +{ + if (isContextLost()) + return; + switch (face) { + case GL_FRONT_AND_BACK: + m_stencilMask = mask; + m_stencilMaskBack = mask; + break; + case GL_FRONT: + m_stencilMask = mask; + break; + case GL_BACK: + m_stencilMaskBack = mask; + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "stencilMaskSeparate", "invalid face"); + return; + } + webContext()->stencilMaskSeparate(face, mask); +} + +void WebGLRenderingContextBase::stencilOp(GLenum fail, GLenum zfail, GLenum zpass) +{ + if (isContextLost()) + return; + webContext()->stencilOp(fail, zfail, zpass); +} + +void WebGLRenderingContextBase::stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +{ + if (isContextLost()) + return; + webContext()->stencilOpSeparate(face, fail, zfail, zpass); +} + +GLenum WebGLRenderingContextBase::convertTexInternalFormat(GLenum internalformat, GLenum type) +{ + // Convert to sized internal formats that are renderable with GL_CHROMIUM_color_buffer_float_rgb(a). + if (type == GL_FLOAT && internalformat == GL_RGBA + && extensionsUtil()->isExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgba")) + return GL_RGBA32F_EXT; + if (type == GL_FLOAT && internalformat == GL_RGB + && extensionsUtil()->isExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgb")) + return GL_RGB32F_EXT; + return internalformat; +} + +void WebGLRenderingContextBase::texImage2DBase(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels, ExceptionState& exceptionState) +{ + // All calling functions check isContextLost, so a duplicate check is not needed here. + // FIXME: Handle errors. + 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)); + ASSERT(!pixels || validateSettableTexFormat("texImage2D", internalformat)); + webContext()->texImage2D(target, level, convertTexInternalFormat(internalformat, type), width, height, border, format, type, pixels); + tex->setLevelInfo(target, level, internalformat, width, height, type); +} + +void WebGLRenderingContextBase::texImage2DImpl(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, Image* image, WebGLImageConversion::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionState& exceptionState) +{ + // All calling functions check isContextLost, so a duplicate check is not needed here. + Vector<uint8_t> data; + WebGLImageConversion::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GL_NONE); + if (!imageExtractor.extractSucceeded()) { + synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "bad image data"); + return; + } + WebGLImageConversion::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat(); + WebGLImageConversion::AlphaOp alphaOp = imageExtractor.imageAlphaOp(); + const void* imagePixelData = imageExtractor.imagePixelData(); + + bool needConversion = true; + if (type == GL_UNSIGNED_BYTE && sourceDataFormat == WebGLImageConversion::DataFormatRGBA8 && format == GL_RGBA && alphaOp == WebGLImageConversion::AlphaDoNothing && !flipY) + needConversion = false; + else { + if (!WebGLImageConversion::packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) { + synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "packImage error"); + return; + } + } + + if (m_unpackAlignment != 1) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, 1); + texImage2DBase(target, level, internalformat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), 0, format, type, needConversion ? data.data() : imagePixelData, exceptionState); + if (m_unpackAlignment != 1) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); +} + +bool WebGLRenderingContextBase::validateTexFunc(const char* functionName, TexFuncValidationFunctionType functionType, TexFuncValidationSourceType sourceType, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLint xoffset, GLint 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 == NotTexSubImage2D) { + if (level && WebGLTexture::isNPOT(width, height)) { + synthesizeGLError(GL_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(GL_INVALID_VALUE, functionName, "bad dimensions"); + return false; + } + if (xoffset + width > texture->getWidth(target, level) || yoffset + height > texture->getHeight(target, level)) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "dimensions out of range"); + return false; + } + if (texture->getInternalFormat(target, level) != format || texture->getType(target, level) != type) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "type and format do not match texture"); + return false; + } + } + + return true; +} + +bool WebGLRenderingContextBase::validateValueFitNonNegInt32(const char* functionName, const char* paramName, long long value) +{ + if (value < 0) { + String errorMsg = String(paramName) + " < 0"; + synthesizeGLError(GL_INVALID_VALUE, functionName, errorMsg.ascii().data()); + return false; + } + if (value > static_cast<long long>(std::numeric_limits<int>::max())) { + String errorMsg = String(paramName) + " more than 32-bit"; + synthesizeGLError(GL_INVALID_OPERATION, functionName, errorMsg.ascii().data()); + return false; + } + return true; +} + +PassRefPtr<Image> WebGLRenderingContextBase::drawImageIntoBuffer(Image* image, int width, int height, const char* functionName) +{ + IntSize size(width, height); + ImageBuffer* buf = m_generatedImageCache.imageBuffer(size); + if (!buf) { + synthesizeGLError(GL_OUT_OF_MEMORY, functionName, "out of memory"); + return nullptr; + } + + IntRect srcRect(IntPoint(), image->size()); + IntRect destRect(0, 0, size.width(), size.height()); + buf->context()->drawImage(image, destRect, srcRect); + return buf->copyImage(ImageBuffer::fastCopyImageMode()); +} + +void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, ArrayBufferView* pixels, ExceptionState& exceptionState) +{ + 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 (!WebGLImageConversion::extractTextureData(width, height, format, type, m_unpackAlignment, m_unpackFlipY, m_unpackPremultiplyAlpha, data, tempData)) + return; + data = tempData.data(); + changeUnpackAlignment = true; + } + if (changeUnpackAlignment) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, 1); + texImage2DBase(target, level, internalformat, width, height, border, format, type, data, exceptionState); + if (changeUnpackAlignment) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); +} + +void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, ImageData* pixels, ExceptionState& exceptionState) +{ + 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 == GL_RGBA && type == GL_UNSIGNED_BYTE) + needConversion = false; + else { + if (!WebGLImageConversion::extractImageData(pixels->data()->data(), pixels->size(), format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) { + synthesizeGLError(GL_INVALID_VALUE, "texImage2D", "bad image data"); + return; + } + } + if (m_unpackAlignment != 1) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, 1); + texImage2DBase(target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, needConversion ? data.data() : pixels->data()->data(), exceptionState); + if (m_unpackAlignment != 1) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); +} + +void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, HTMLImageElement* image, ExceptionState& exceptionState) +{ + if (isContextLost() || !validateHTMLImageElement("texImage2D", image, exceptionState)) + return; + + RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer()); + if (imageForRender->isSVGImage()) + imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height(), "texImage2D"); + + 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(), WebGLImageConversion::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState); +} + +void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, HTMLCanvasElement* canvas, ExceptionState& exceptionState) +{ + if (isContextLost() || !validateHTMLCanvasElement("texImage2D", canvas, exceptionState) || !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. + if (GL_TEXTURE_2D == target && texture) { + ScopedTexture2DRestorer restorer(this); + + if (!canvas->is3D()) { + ImageBuffer* buffer = canvas->buffer(); + if (buffer && buffer->copyToPlatformTexture(webContext(), texture->object(), internalformat, type, + level, m_unpackPremultiplyAlpha, m_unpackFlipY)) { + texture->setLevelInfo(target, level, internalformat, canvas->width(), canvas->height(), type); + return; + } + } else { + WebGLRenderingContextBase* gl = toWebGLRenderingContextBase(canvas->renderingContext()); + ScopedTexture2DRestorer restorer(gl); + if (gl && gl->m_drawingBuffer->copyToPlatformTexture(webContext(), texture->object(), internalformat, type, + level, m_unpackPremultiplyAlpha, m_unpackFlipY)) { + texture->setLevelInfo(target, level, internalformat, canvas->width(), canvas->height(), type); + return; + } + } + } + + RefPtrWillBeRawPtr<ImageData> imageData = canvas->getImageData(); + if (imageData) + texImage2D(target, level, internalformat, format, type, imageData.get(), exceptionState); + else + texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(), WebGLImageConversion::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState); +} + +PassRefPtr<Image> WebGLRenderingContextBase::videoFrameToImage(HTMLVideoElement* video, BackingStoreCopy backingStoreCopy) +{ + IntSize size(video->videoWidth(), video->videoHeight()); + ImageBuffer* buf = m_generatedImageCache.imageBuffer(size); + if (!buf) { + synthesizeGLError(GL_OUT_OF_MEMORY, "texImage2D", "out of memory"); + return nullptr; + } + 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 WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, HTMLVideoElement* video, ExceptionState& exceptionState) +{ + if (isContextLost() || !validateHTMLVideoElement("texImage2D", video, exceptionState) + || !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. + WebGLTexture* texture = validateTextureBinding("texImage2D", target, true); + if (GL_TEXTURE_2D == target && texture) { + if (video->copyVideoTextureToPlatformTexture(webContext(), texture->object(), level, type, internalformat, m_unpackPremultiplyAlpha, m_unpackFlipY)) { + texture->setLevelInfo(target, level, internalformat, video->videoWidth(), video->videoHeight(), type); + return; + } + } + + // Normal pure SW path. + RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode()); + if (!image) + return; + texImage2DImpl(target, level, internalformat, format, type, image.get(), WebGLImageConversion::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState); +} + +void WebGLRenderingContextBase::texParameter(GLenum target, GLenum pname, GLfloat paramf, GLint parami, bool isFloat) +{ + if (isContextLost()) + return; + WebGLTexture* tex = validateTextureBinding("texParameter", target, false); + if (!tex) + return; + switch (pname) { + case GL_TEXTURE_MIN_FILTER: + case GL_TEXTURE_MAG_FILTER: + break; + case GL_TEXTURE_WRAP_S: + case GL_TEXTURE_WRAP_T: + if ((isFloat && paramf != GL_CLAMP_TO_EDGE && paramf != GL_MIRRORED_REPEAT && paramf != GL_REPEAT) + || (!isFloat && parami != GL_CLAMP_TO_EDGE && parami != GL_MIRRORED_REPEAT && parami != GL_REPEAT)) { + synthesizeGLError(GL_INVALID_ENUM, "texParameter", "invalid parameter"); + return; + } + break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic + if (!extensionEnabled(EXTTextureFilterAnisotropicName)) { + synthesizeGLError(GL_INVALID_ENUM, "texParameter", "invalid parameter, EXT_texture_filter_anisotropic not enabled"); + return; + } + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "texParameter", "invalid parameter name"); + return; + } + if (isFloat) { + tex->setParameterf(pname, paramf); + webContext()->texParameterf(target, pname, paramf); + } else { + tex->setParameteri(pname, parami); + webContext()->texParameteri(target, pname, parami); + } +} + +void WebGLRenderingContextBase::texParameterf(GLenum target, GLenum pname, GLfloat param) +{ + texParameter(target, pname, param, 0, true); +} + +void WebGLRenderingContextBase::texParameteri(GLenum target, GLenum pname, GLint param) +{ + texParameter(target, pname, 0, param, false); +} + +void WebGLRenderingContextBase::texSubImage2DBase(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels, ExceptionState& exceptionState) +{ + // FIXME: Handle errors. + 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); + webContext()->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); +} + +void WebGLRenderingContextBase::texSubImage2DImpl(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLenum format, GLenum type, Image* image, WebGLImageConversion::ImageHtmlDomSource domSource, bool flipY, bool premultiplyAlpha, ExceptionState& exceptionState) +{ + // All calling functions check isContextLost, so a duplicate check is not needed here. + Vector<uint8_t> data; + WebGLImageConversion::ImageExtractor imageExtractor(image, domSource, premultiplyAlpha, m_unpackColorspaceConversion == GL_NONE); + if (!imageExtractor.extractSucceeded()) { + synthesizeGLError(GL_INVALID_VALUE, "texSubImage2D", "bad image"); + return; + } + WebGLImageConversion::DataFormat sourceDataFormat = imageExtractor.imageSourceFormat(); + WebGLImageConversion::AlphaOp alphaOp = imageExtractor.imageAlphaOp(); + const void* imagePixelData = imageExtractor.imagePixelData(); + + bool needConversion = true; + if (type == GL_UNSIGNED_BYTE && sourceDataFormat == WebGLImageConversion::DataFormatRGBA8 && format == GL_RGBA && alphaOp == WebGLImageConversion::AlphaDoNothing && !flipY) + needConversion = false; + else { + if (!WebGLImageConversion::packImageData(image, imagePixelData, format, type, flipY, alphaOp, sourceDataFormat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), imageExtractor.imageSourceUnpackAlignment(), data)) { + synthesizeGLError(GL_INVALID_VALUE, "texSubImage2D", "bad image data"); + return; + } + } + + if (m_unpackAlignment != 1) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, 1); + texSubImage2DBase(target, level, xoffset, yoffset, imageExtractor.imageWidth(), imageExtractor.imageHeight(), format, type, needConversion ? data.data() : imagePixelData, exceptionState); + if (m_unpackAlignment != 1) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); +} + +void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, ArrayBufferView* pixels, ExceptionState& exceptionState) +{ + 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 (!WebGLImageConversion::extractTextureData(width, height, format, type, + m_unpackAlignment, + m_unpackFlipY, m_unpackPremultiplyAlpha, + data, + tempData)) + return; + data = tempData.data(); + changeUnpackAlignment = true; + } + if (changeUnpackAlignment) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, 1); + texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, type, data, exceptionState); + if (changeUnpackAlignment) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); +} + +void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, ImageData* pixels, ExceptionState& exceptionState) +{ + 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 == GL_RGBA && type == GL_UNSIGNED_BYTE && !m_unpackFlipY && !m_unpackPremultiplyAlpha) + needConversion = false; + else { + if (!WebGLImageConversion::extractImageData(pixels->data()->data(), pixels->size(), format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) { + synthesizeGLError(GL_INVALID_VALUE, "texSubImage2D", "bad image data"); + return; + } + } + if (m_unpackAlignment != 1) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, 1); + texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(), format, type, needConversion ? data.data() : pixels->data()->data(), exceptionState); + if (m_unpackAlignment != 1) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); +} + +void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, HTMLImageElement* image, ExceptionState& exceptionState) +{ + if (isContextLost() || !validateHTMLImageElement("texSubImage2D", image, exceptionState)) + return; + + RefPtr<Image> imageForRender = image->cachedImage()->imageForRenderer(image->renderer()); + if (imageForRender->isSVGImage()) + imageForRender = drawImageIntoBuffer(imageForRender.get(), image->width(), image->height(), "texSubImage2D"); + + 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(), WebGLImageConversion::HtmlDomImage, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState); +} + +void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, HTMLCanvasElement* canvas, ExceptionState& exceptionState) +{ + if (isContextLost() || !validateHTMLCanvasElement("texSubImage2D", canvas, exceptionState) + || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLCanvasElement, target, level, format, canvas->width(), canvas->height(), 0, format, type, xoffset, yoffset)) + return; + + RefPtrWillBeRawPtr<ImageData> imageData = canvas->getImageData(); + if (imageData) + texSubImage2D(target, level, xoffset, yoffset, format, type, imageData.get(), exceptionState); + else + texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), WebGLImageConversion::HtmlDomCanvas, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState); +} + +void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, HTMLVideoElement* video, ExceptionState& exceptionState) +{ + if (isContextLost() || !validateHTMLVideoElement("texSubImage2D", video, exceptionState) + || !validateTexFunc("texSubImage2D", TexSubImage2D, SourceHTMLVideoElement, target, level, format, video->videoWidth(), video->videoHeight(), 0, format, type, xoffset, yoffset)) + return; + + RefPtr<Image> image = videoFrameToImage(video, ImageBuffer::fastCopyImageMode()); + if (!image) + return; + texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), WebGLImageConversion::HtmlDomVideo, m_unpackFlipY, m_unpackPremultiplyAlpha, exceptionState); +} + +void WebGLRenderingContextBase::uniform1f(const WebGLUniformLocation* location, GLfloat x) +{ + if (isContextLost() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GL_INVALID_OPERATION, "uniform1f", "location not for current program"); + return; + } + + webContext()->uniform1f(location->location(), x); +} + +void WebGLRenderingContextBase::uniform1fv(const WebGLUniformLocation* location, Float32Array* v) +{ + if (isContextLost() || !validateUniformParameters("uniform1fv", location, v, 1)) + return; + + webContext()->uniform1fv(location->location(), v->length(), v->data()); +} + +void WebGLRenderingContextBase::uniform1fv(const WebGLUniformLocation* location, GLfloat* v, GLsizei size) +{ + if (isContextLost() || !validateUniformParameters("uniform1fv", location, v, size, 1)) + return; + + webContext()->uniform1fv(location->location(), size, v); +} + +void WebGLRenderingContextBase::uniform1i(const WebGLUniformLocation* location, GLint x) +{ + if (isContextLost() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GL_INVALID_OPERATION, "uniform1i", "location not for current program"); + return; + } + + webContext()->uniform1i(location->location(), x); +} + +void WebGLRenderingContextBase::uniform1iv(const WebGLUniformLocation* location, Int32Array* v) +{ + if (isContextLost() || !validateUniformParameters("uniform1iv", location, v, 1)) + return; + + webContext()->uniform1iv(location->location(), v->length(), v->data()); +} + +void WebGLRenderingContextBase::uniform1iv(const WebGLUniformLocation* location, GLint* v, GLsizei size) +{ + if (isContextLost() || !validateUniformParameters("uniform1iv", location, v, size, 1)) + return; + + webContext()->uniform1iv(location->location(), size, v); +} + +void WebGLRenderingContextBase::uniform2f(const WebGLUniformLocation* location, GLfloat x, GLfloat y) +{ + if (isContextLost() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GL_INVALID_OPERATION, "uniform2f", "location not for current program"); + return; + } + + webContext()->uniform2f(location->location(), x, y); +} + +void WebGLRenderingContextBase::uniform2fv(const WebGLUniformLocation* location, Float32Array* v) +{ + if (isContextLost() || !validateUniformParameters("uniform2fv", location, v, 2)) + return; + + webContext()->uniform2fv(location->location(), v->length() / 2, v->data()); +} + +void WebGLRenderingContextBase::uniform2fv(const WebGLUniformLocation* location, GLfloat* v, GLsizei size) +{ + if (isContextLost() || !validateUniformParameters("uniform2fv", location, v, size, 2)) + return; + + webContext()->uniform2fv(location->location(), size / 2, v); +} + +void WebGLRenderingContextBase::uniform2i(const WebGLUniformLocation* location, GLint x, GLint y) +{ + if (isContextLost() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GL_INVALID_OPERATION, "uniform2i", "location not for current program"); + return; + } + + webContext()->uniform2i(location->location(), x, y); +} + +void WebGLRenderingContextBase::uniform2iv(const WebGLUniformLocation* location, Int32Array* v) +{ + if (isContextLost() || !validateUniformParameters("uniform2iv", location, v, 2)) + return; + + webContext()->uniform2iv(location->location(), v->length() / 2, v->data()); +} + +void WebGLRenderingContextBase::uniform2iv(const WebGLUniformLocation* location, GLint* v, GLsizei size) +{ + if (isContextLost() || !validateUniformParameters("uniform2iv", location, v, size, 2)) + return; + + webContext()->uniform2iv(location->location(), size / 2, v); +} + +void WebGLRenderingContextBase::uniform3f(const WebGLUniformLocation* location, GLfloat x, GLfloat y, GLfloat z) +{ + if (isContextLost() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GL_INVALID_OPERATION, "uniform3f", "location not for current program"); + return; + } + + webContext()->uniform3f(location->location(), x, y, z); +} + +void WebGLRenderingContextBase::uniform3fv(const WebGLUniformLocation* location, Float32Array* v) +{ + if (isContextLost() || !validateUniformParameters("uniform3fv", location, v, 3)) + return; + + webContext()->uniform3fv(location->location(), v->length() / 3, v->data()); +} + +void WebGLRenderingContextBase::uniform3fv(const WebGLUniformLocation* location, GLfloat* v, GLsizei size) +{ + if (isContextLost() || !validateUniformParameters("uniform3fv", location, v, size, 3)) + return; + + webContext()->uniform3fv(location->location(), size / 3, v); +} + +void WebGLRenderingContextBase::uniform3i(const WebGLUniformLocation* location, GLint x, GLint y, GLint z) +{ + if (isContextLost() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GL_INVALID_OPERATION, "uniform3i", "location not for current program"); + return; + } + + webContext()->uniform3i(location->location(), x, y, z); +} + +void WebGLRenderingContextBase::uniform3iv(const WebGLUniformLocation* location, Int32Array* v) +{ + if (isContextLost() || !validateUniformParameters("uniform3iv", location, v, 3)) + return; + + webContext()->uniform3iv(location->location(), v->length() / 3, v->data()); +} + +void WebGLRenderingContextBase::uniform3iv(const WebGLUniformLocation* location, GLint* v, GLsizei size) +{ + if (isContextLost() || !validateUniformParameters("uniform3iv", location, v, size, 3)) + return; + + webContext()->uniform3iv(location->location(), size / 3, v); +} + +void WebGLRenderingContextBase::uniform4f(const WebGLUniformLocation* location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + if (isContextLost() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GL_INVALID_OPERATION, "uniform4f", "location not for current program"); + return; + } + + webContext()->uniform4f(location->location(), x, y, z, w); +} + +void WebGLRenderingContextBase::uniform4fv(const WebGLUniformLocation* location, Float32Array* v) +{ + if (isContextLost() || !validateUniformParameters("uniform4fv", location, v, 4)) + return; + + webContext()->uniform4fv(location->location(), v->length() / 4, v->data()); +} + +void WebGLRenderingContextBase::uniform4fv(const WebGLUniformLocation* location, GLfloat* v, GLsizei size) +{ + if (isContextLost() || !validateUniformParameters("uniform4fv", location, v, size, 4)) + return; + + webContext()->uniform4fv(location->location(), size / 4, v); +} + +void WebGLRenderingContextBase::uniform4i(const WebGLUniformLocation* location, GLint x, GLint y, GLint z, GLint w) +{ + if (isContextLost() || !location) + return; + + if (location->program() != m_currentProgram) { + synthesizeGLError(GL_INVALID_OPERATION, "uniform4i", "location not for current program"); + return; + } + + webContext()->uniform4i(location->location(), x, y, z, w); +} + +void WebGLRenderingContextBase::uniform4iv(const WebGLUniformLocation* location, Int32Array* v) +{ + if (isContextLost() || !validateUniformParameters("uniform4iv", location, v, 4)) + return; + + webContext()->uniform4iv(location->location(), v->length() / 4, v->data()); +} + +void WebGLRenderingContextBase::uniform4iv(const WebGLUniformLocation* location, GLint* v, GLsizei size) +{ + if (isContextLost() || !validateUniformParameters("uniform4iv", location, v, size, 4)) + return; + + webContext()->uniform4iv(location->location(), size / 4, v); +} + +void WebGLRenderingContextBase::uniformMatrix2fv(const WebGLUniformLocation* location, GLboolean transpose, Float32Array* v) +{ + if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, 4)) + return; + webContext()->uniformMatrix2fv(location->location(), v->length() / 4, transpose, v->data()); +} + +void WebGLRenderingContextBase::uniformMatrix2fv(const WebGLUniformLocation* location, GLboolean transpose, GLfloat* v, GLsizei size) +{ + if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix2fv", location, transpose, v, size, 4)) + return; + webContext()->uniformMatrix2fv(location->location(), size / 4, transpose, v); +} + +void WebGLRenderingContextBase::uniformMatrix3fv(const WebGLUniformLocation* location, GLboolean transpose, Float32Array* v) +{ + if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, 9)) + return; + webContext()->uniformMatrix3fv(location->location(), v->length() / 9, transpose, v->data()); +} + +void WebGLRenderingContextBase::uniformMatrix3fv(const WebGLUniformLocation* location, GLboolean transpose, GLfloat* v, GLsizei size) +{ + if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix3fv", location, transpose, v, size, 9)) + return; + webContext()->uniformMatrix3fv(location->location(), size / 9, transpose, v); +} + +void WebGLRenderingContextBase::uniformMatrix4fv(const WebGLUniformLocation* location, GLboolean transpose, Float32Array* v) +{ + if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, 16)) + return; + webContext()->uniformMatrix4fv(location->location(), v->length() / 16, transpose, v->data()); +} + +void WebGLRenderingContextBase::uniformMatrix4fv(const WebGLUniformLocation* location, GLboolean transpose, GLfloat* v, GLsizei size) +{ + if (isContextLost() || !validateUniformMatrixParameters("uniformMatrix4fv", location, transpose, v, size, 16)) + return; + webContext()->uniformMatrix4fv(location->location(), size / 16, transpose, v); +} + +void WebGLRenderingContextBase::useProgram(WebGLProgram* program) +{ + bool deleted; + if (!checkObjectToBeBound("useProgram", program, deleted)) + return; + if (deleted) + program = 0; + if (program && !program->linkStatus()) { + synthesizeGLError(GL_INVALID_OPERATION, "useProgram", "program not valid"); + return; + } + if (m_currentProgram != program) { + if (m_currentProgram) + m_currentProgram->onDetached(webContext()); + m_currentProgram = program; + webContext()->useProgram(objectOrZero(program)); + if (program) + program->onAttached(); + } +} + +void WebGLRenderingContextBase::validateProgram(WebGLProgram* program) +{ + if (isContextLost() || !validateWebGLObject("validateProgram", program)) + return; + webContext()->validateProgram(objectOrZero(program)); +} + +void WebGLRenderingContextBase::vertexAttrib1f(GLuint index, GLfloat v0) +{ + vertexAttribfImpl("vertexAttrib1f", index, 1, v0, 0.0f, 0.0f, 1.0f); +} + +void WebGLRenderingContextBase::vertexAttrib1fv(GLuint index, Float32Array* v) +{ + vertexAttribfvImpl("vertexAttrib1fv", index, v, 1); +} + +void WebGLRenderingContextBase::vertexAttrib1fv(GLuint index, GLfloat* v, GLsizei size) +{ + vertexAttribfvImpl("vertexAttrib1fv", index, v, size, 1); +} + +void WebGLRenderingContextBase::vertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) +{ + vertexAttribfImpl("vertexAttrib2f", index, 2, v0, v1, 0.0f, 1.0f); +} + +void WebGLRenderingContextBase::vertexAttrib2fv(GLuint index, Float32Array* v) +{ + vertexAttribfvImpl("vertexAttrib2fv", index, v, 2); +} + +void WebGLRenderingContextBase::vertexAttrib2fv(GLuint index, GLfloat* v, GLsizei size) +{ + vertexAttribfvImpl("vertexAttrib2fv", index, v, size, 2); +} + +void WebGLRenderingContextBase::vertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) +{ + vertexAttribfImpl("vertexAttrib3f", index, 3, v0, v1, v2, 1.0f); +} + +void WebGLRenderingContextBase::vertexAttrib3fv(GLuint index, Float32Array* v) +{ + vertexAttribfvImpl("vertexAttrib3fv", index, v, 3); +} + +void WebGLRenderingContextBase::vertexAttrib3fv(GLuint index, GLfloat* v, GLsizei size) +{ + vertexAttribfvImpl("vertexAttrib3fv", index, v, size, 3); +} + +void WebGLRenderingContextBase::vertexAttrib4f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) +{ + vertexAttribfImpl("vertexAttrib4f", index, 4, v0, v1, v2, v3); +} + +void WebGLRenderingContextBase::vertexAttrib4fv(GLuint index, Float32Array* v) +{ + vertexAttribfvImpl("vertexAttrib4fv", index, v, 4); +} + +void WebGLRenderingContextBase::vertexAttrib4fv(GLuint index, GLfloat* v, GLsizei size) +{ + vertexAttribfvImpl("vertexAttrib4fv", index, v, size, 4); +} + +void WebGLRenderingContextBase::vertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, long long offset) +{ + if (isContextLost()) + return; + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + case GL_SHORT: + case GL_UNSIGNED_SHORT: + case GL_FLOAT: + break; + default: + synthesizeGLError(GL_INVALID_ENUM, "vertexAttribPointer", "invalid type"); + return; + } + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GL_INVALID_VALUE, "vertexAttribPointer", "index out of range"); + return; + } + if (size < 1 || size > 4 || stride < 0 || stride > 255) { + synthesizeGLError(GL_INVALID_VALUE, "vertexAttribPointer", "bad size or stride"); + return; + } + if (!validateValueFitNonNegInt32("vertexAttribPointer", "offset", offset)) + return; + if (!m_boundArrayBuffer) { + synthesizeGLError(GL_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 typeSize = sizeInBytes(type); + if (!typeSize) { + synthesizeGLError(GL_INVALID_ENUM, "vertexAttribPointer", "invalid type"); + return; + } + if ((stride % typeSize) || (static_cast<GLintptr>(offset) % typeSize)) { + synthesizeGLError(GL_INVALID_OPERATION, "vertexAttribPointer", "stride or offset not valid for type"); + return; + } + GLsizei bytesPerElement = size * typeSize; + + m_boundVertexArrayObject->setVertexAttribState(index, bytesPerElement, size, type, normalized, stride, static_cast<GLintptr>(offset), m_boundArrayBuffer); + webContext()->vertexAttribPointer(index, size, type, normalized, stride, static_cast<GLintptr>(offset)); +} + +void WebGLRenderingContextBase::vertexAttribDivisorANGLE(GLuint index, GLuint divisor) +{ + if (isContextLost()) + return; + + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GL_INVALID_VALUE, "vertexAttribDivisorANGLE", "index out of range"); + return; + } + + m_boundVertexArrayObject->setVertexAttribDivisor(index, divisor); + webContext()->vertexAttribDivisorANGLE(index, divisor); +} + +void WebGLRenderingContextBase::viewport(GLint x, GLint y, GLsizei width, GLsizei height) +{ + if (isContextLost()) + return; + if (!validateSize("viewport", width, height)) + return; + webContext()->viewport(x, y, width, height); +} + +void WebGLRenderingContextBase::forceLostContext(WebGLRenderingContextBase::LostContextMode mode) +{ + if (isContextLost()) { + synthesizeGLError(GL_INVALID_OPERATION, "loseContext", "context already lost"); + return; + } + + m_contextGroup->loseContextGroup(mode); +} + +void WebGLRenderingContextBase::loseContextImpl(WebGLRenderingContextBase::LostContextMode mode) +{ +#ifndef NDEBUG + printWarningToConsole("loseContextImpl(): begin"); +#endif + + 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 (LocalFrame* frame = canvas()->document().frame()) + frame->loader().client()->didLoseWebGLContext(webContext()->getGraphicsResetStatusARB()); + } + + // Make absolutely sure we do not refer to an already-deleted texture or framebuffer. + m_drawingBuffer->setTexture2DBinding(0); + m_drawingBuffer->setFramebufferBinding(0); + + detachAndRemoveAllObjects(); + +#ifndef NDEBUG + printWarningToConsole("loseContextImpl(): after detachAndRemoveAllObjects()"); +#endif + + // Lose all the extensions. + for (size_t i = 0; i < m_extensions.size(); ++i) { + ExtensionTracker* tracker = m_extensions[i]; + tracker->loseExtension(); + } + + for (size_t i = 0; i < WebGLExtensionNameCount; ++i) + m_extensionEnabled[i] = false; + + removeAllCompressedTextureFormats(); + + if (mode != RealLostContext) + destroyContext(); + +#ifndef NDEBUG + printWarningToConsole("loseContextImpl(): after destroyContext()"); +#endif + + ConsoleDisplayPreference display = (mode == RealLostContext) ? DisplayInConsole: DontDisplayInConsole; + synthesizeGLError(GC3D_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, FROM_HERE); + +#ifndef NDEBUG + printWarningToConsole("loseContextImpl(): end"); +#endif +} + +void WebGLRenderingContextBase::forceRestoreContext() +{ + if (!isContextLost()) { + synthesizeGLError(GL_INVALID_OPERATION, "restoreContext", "context not lost"); + return; + } + + if (!m_restoreAllowed) { + if (m_contextLostMode == SyntheticLostContext) + synthesizeGLError(GL_INVALID_OPERATION, "restoreContext", "context restoration not allowed"); + return; + } + + if (!m_restoreTimer.isActive()) + m_restoreTimer.startOneShot(0, FROM_HERE); +} + +blink::WebLayer* WebGLRenderingContextBase::platformLayer() const +{ + return isContextLost() ? 0 : m_drawingBuffer->platformLayer(); +} + +Extensions3DUtil* WebGLRenderingContextBase::extensionsUtil() +{ + ASSERT(!isContextLost()); + if (!m_extensionsUtil) + m_extensionsUtil = Extensions3DUtil::create(webContext()); + return m_extensionsUtil.get(); +} + +void WebGLRenderingContextBase::removeSharedObject(WebGLSharedObject* object) +{ + m_contextGroup->removeObject(object); +} + +void WebGLRenderingContextBase::addSharedObject(WebGLSharedObject* object) +{ + ASSERT(!isContextLost()); + m_contextGroup->addObject(object); +} + +void WebGLRenderingContextBase::removeContextObject(WebGLContextObject* object) +{ + m_contextObjects.remove(object); +} + +void WebGLRenderingContextBase::addContextObject(WebGLContextObject* object) +{ + ASSERT(!isContextLost()); + m_contextObjects.add(object); +} + +void WebGLRenderingContextBase::detachAndRemoveAllObjects() +{ + 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()) { + forceLostContext(SyntheticLostContext); + destroyContext(); + } +} + +WebGLGetInfo WebGLRenderingContextBase::getBooleanParameter(GLenum pname) +{ + GLboolean value = 0; + if (!isContextLost()) + webContext()->getBooleanv(pname, &value); + return WebGLGetInfo(static_cast<bool>(value)); +} + +WebGLGetInfo WebGLRenderingContextBase::getBooleanArrayParameter(GLenum pname) +{ + if (pname != GL_COLOR_WRITEMASK) { + notImplemented(); + return WebGLGetInfo(0, 0); + } + GLboolean value[4] = {0}; + if (!isContextLost()) + webContext()->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 WebGLRenderingContextBase::getFloatParameter(GLenum pname) +{ + GLfloat value = 0; + if (!isContextLost()) + webContext()->getFloatv(pname, &value); + return WebGLGetInfo(value); +} + +WebGLGetInfo WebGLRenderingContextBase::getIntParameter(GLenum pname) +{ + GLint value = 0; + if (!isContextLost()) + webContext()->getIntegerv(pname, &value); + return WebGLGetInfo(value); +} + +WebGLGetInfo WebGLRenderingContextBase::getUnsignedIntParameter(GLenum pname) +{ + GLint value = 0; + if (!isContextLost()) + webContext()->getIntegerv(pname, &value); + return WebGLGetInfo(static_cast<unsigned>(value)); +} + +WebGLGetInfo WebGLRenderingContextBase::getWebGLFloatArrayParameter(GLenum pname) +{ + GLfloat value[4] = {0}; + if (!isContextLost()) + webContext()->getFloatv(pname, value); + unsigned length = 0; + switch (pname) { + case GL_ALIASED_POINT_SIZE_RANGE: + case GL_ALIASED_LINE_WIDTH_RANGE: + case GL_DEPTH_RANGE: + length = 2; + break; + case GL_BLEND_COLOR: + case GL_COLOR_CLEAR_VALUE: + length = 4; + break; + default: + notImplemented(); + } + return WebGLGetInfo(Float32Array::create(value, length)); +} + +WebGLGetInfo WebGLRenderingContextBase::getWebGLIntArrayParameter(GLenum pname) +{ + GLint value[4] = {0}; + if (!isContextLost()) + webContext()->getIntegerv(pname, value); + unsigned length = 0; + switch (pname) { + case GL_MAX_VIEWPORT_DIMS: + length = 2; + break; + case GL_SCISSOR_BOX: + case GL_VIEWPORT: + length = 4; + break; + default: + notImplemented(); + } + return WebGLGetInfo(Int32Array::create(value, length)); +} + +void WebGLRenderingContextBase::handleTextureCompleteness(const char* functionName, bool prepareToDraw) +{ + // All calling functions check isContextLost, so a duplicate check is not needed here. + bool resetActiveUnit = false; + WebGLTexture::TextureExtensionFlag flag = static_cast<WebGLTexture::TextureExtensionFlag>((extensionEnabled(OESTextureFloatLinearName) ? WebGLTexture::TextureFloatLinearExtensionEnabled : 0) + | (extensionEnabled(OESTextureHalfFloatLinearName) ? WebGLTexture::TextureHalfFloatLinearExtensionEnabled : 0)); + for (unsigned ii = 0; ii < m_onePlusMaxNonDefaultTextureUnit; ++ii) { + if ((m_textureUnits[ii].m_texture2DBinding.get() && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture(flag)) + || (m_textureUnits[ii].m_textureCubeMapBinding.get() && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture(flag))) { + if (ii != m_activeTextureUnit) { + webContext()->activeTexture(ii); + resetActiveUnit = true; + } else if (resetActiveUnit) { + webContext()->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 the texture is Float or Half Float type with linear filtering while OES_float_linear or OES_half_float_linear extension is not enabled."); + emitGLWarning(functionName, msg.utf8().data()); + tex2D = m_blackTexture2D.get(); + texCubeMap = m_blackTextureCubeMap.get(); + } else { + tex2D = m_textureUnits[ii].m_texture2DBinding.get(); + texCubeMap = m_textureUnits[ii].m_textureCubeMapBinding.get(); + } + if (m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture(flag)) + webContext()->bindTexture(GL_TEXTURE_2D, objectOrZero(tex2D)); + if (m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture(flag)) + webContext()->bindTexture(GL_TEXTURE_CUBE_MAP, objectOrZero(texCubeMap)); + } + } + if (resetActiveUnit) + webContext()->activeTexture(m_activeTextureUnit); +} + +void WebGLRenderingContextBase::createFallbackBlackTextures1x1() +{ + // All calling functions check isContextLost, so a duplicate check is not needed here. + unsigned char black[] = {0, 0, 0, 255}; + m_blackTexture2D = createTexture(); + webContext()->bindTexture(GL_TEXTURE_2D, m_blackTexture2D->object()); + webContext()->texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, black); + webContext()->bindTexture(GL_TEXTURE_2D, 0); + m_blackTextureCubeMap = createTexture(); + webContext()->bindTexture(GL_TEXTURE_CUBE_MAP, m_blackTextureCubeMap->object()); + webContext()->texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 1, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, black); + webContext()->texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 1, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, black); + webContext()->texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 1, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, black); + webContext()->texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 1, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, black); + webContext()->texImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 1, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, black); + webContext()->texImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 1, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, black); + webContext()->bindTexture(GL_TEXTURE_CUBE_MAP, 0); +} + +bool WebGLRenderingContextBase::isTexInternalFormatColorBufferCombinationValid(GLenum texInternalFormat, GLenum colorBufferFormat) +{ + unsigned need = WebGLImageConversion::getChannelBitsByFormat(texInternalFormat); + unsigned have = WebGLImageConversion::getChannelBitsByFormat(colorBufferFormat); + return (need & have) == need; +} + +GLenum WebGLRenderingContextBase::boundFramebufferColorFormat() +{ + if (m_framebufferBinding && m_framebufferBinding->object()) + return m_framebufferBinding->colorBufferFormat(); + if (m_requestedAttributes->alpha()) + return GL_RGBA; + return GL_RGB; +} + +WebGLTexture* WebGLRenderingContextBase::validateTextureBinding(const char* functionName, GLenum target, bool useSixEnumsForCubeMap) +{ + WebGLTexture* tex = 0; + switch (target) { + case GL_TEXTURE_2D: + tex = m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get(); + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + if (!useSixEnumsForCubeMap) { + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture target"); + return 0; + } + tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding.get(); + break; + case GL_TEXTURE_CUBE_MAP: + if (useSixEnumsForCubeMap) { + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture target"); + return 0; + } + tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding.get(); + break; + default: + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture target"); + return 0; + } + if (!tex) + synthesizeGLError(GL_INVALID_OPERATION, functionName, "no texture"); + return tex; +} + +bool WebGLRenderingContextBase::validateLocationLength(const char* functionName, const String& string) +{ + const unsigned maxWebGLLocationLength = 256; + if (string.length() > maxWebGLLocationLength) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "location length > 256"); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateSize(const char* functionName, GLint x, GLint y) +{ + if (x < 0 || y < 0) { + synthesizeGLError(GL_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(GL_INVALID_VALUE, functionName, "string not ASCII"); + return false; + } + } + return true; +} + +bool WebGLRenderingContextBase::validateTexFuncFormatAndType(const char* functionName, GLenum format, GLenum type, GLint level) +{ + switch (format) { + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + case GL_RGB: + case GL_RGBA: + break; + case GL_DEPTH_STENCIL_OES: + case GL_DEPTH_COMPONENT: + if (extensionEnabled(WebGLDepthTextureName)) + break; + synthesizeGLError(GL_INVALID_ENUM, functionName, "depth texture formats not enabled"); + return false; + default: + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture format"); + return false; + } + + switch (type) { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_5_5_5_1: + break; + case GL_FLOAT: + if (extensionEnabled(OESTextureFloatName)) + break; + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture type"); + return false; + case GL_HALF_FLOAT_OES: + if (extensionEnabled(OESTextureHalfFloatName)) + break; + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture type"); + return false; + case GL_UNSIGNED_INT: + case GL_UNSIGNED_INT_24_8_OES: + case GL_UNSIGNED_SHORT: + if (extensionEnabled(WebGLDepthTextureName)) + break; + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture type"); + return false; + default: + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid texture type"); + return false; + } + + // Verify that the combination of format and type is supported. + switch (format) { + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + if (type != GL_UNSIGNED_BYTE + && type != GL_FLOAT + && type != GL_HALF_FLOAT_OES) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "invalid type for format"); + return false; + } + break; + case GL_RGB: + if (type != GL_UNSIGNED_BYTE + && type != GL_UNSIGNED_SHORT_5_6_5 + && type != GL_FLOAT + && type != GL_HALF_FLOAT_OES) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "invalid type for RGB format"); + return false; + } + break; + case GL_RGBA: + if (type != GL_UNSIGNED_BYTE + && type != GL_UNSIGNED_SHORT_4_4_4_4 + && type != GL_UNSIGNED_SHORT_5_5_5_1 + && type != GL_FLOAT + && type != GL_HALF_FLOAT_OES) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "invalid type for RGBA format"); + return false; + } + break; + case GL_DEPTH_COMPONENT: + if (!extensionEnabled(WebGLDepthTextureName)) { + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid format. DEPTH_COMPONENT not enabled"); + return false; + } + if (type != GL_UNSIGNED_SHORT + && type != GL_UNSIGNED_INT) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "invalid type for DEPTH_COMPONENT format"); + return false; + } + if (level > 0) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "level must be 0 for DEPTH_COMPONENT format"); + return false; + } + break; + case GL_DEPTH_STENCIL_OES: + if (!extensionEnabled(WebGLDepthTextureName)) { + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid format. DEPTH_STENCIL not enabled"); + return false; + } + if (type != GL_UNSIGNED_INT_24_8_OES) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "invalid type for DEPTH_STENCIL format"); + return false; + } + if (level > 0) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "level must be 0 for DEPTH_STENCIL format"); + return false; + } + break; + default: + ASSERT_NOT_REACHED(); + } + + return true; +} + +bool WebGLRenderingContextBase::validateTexFuncLevel(const char* functionName, GLenum target, GLint level) +{ + if (level < 0) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "level < 0"); + return false; + } + switch (target) { + case GL_TEXTURE_2D: + if (level >= m_maxTextureLevel) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "level out of range"); + return false; + } + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + if (level >= m_maxCubeMapTextureLevel) { + synthesizeGLError(GL_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::validateTexFuncDimensions(const char* functionName, TexFuncValidationFunctionType functionType, + GLenum target, GLint level, GLsizei width, GLsizei height) +{ + if (width < 0 || height < 0) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "width or height < 0"); + return false; + } + + switch (target) { + case GL_TEXTURE_2D: + if (width > (m_maxTextureSize >> level) || height > (m_maxTextureSize >> level)) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "width or height out of range"); + return false; + } + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + if (functionType != TexSubImage2D && width != height) { + synthesizeGLError(GL_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 > (m_maxCubeMapTextureSize >> level)) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "width or height out of range for cube map"); + return false; + } + break; + default: + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid target"); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateTexFuncParameters(const char* functionName, TexFuncValidationFunctionType functionType, GLenum target, + GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum 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 (!validateTexFuncDimensions(functionName, functionType, target, level, width, height)) + return false; + + if (format != internalformat) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "format != internalformat"); + return false; + } + + if (border) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "border != 0"); + return false; + } + + return true; +} + +bool WebGLRenderingContextBase::validateTexFuncData(const char* functionName, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, ArrayBufferView* pixels, NullDisposition disposition) +{ + // All calling functions check isContextLost, so a duplicate check is not needed here. + if (!pixels) { + if (disposition == NullAllowed) + return true; + synthesizeGLError(GL_INVALID_VALUE, functionName, "no pixels"); + return false; + } + + if (!validateTexFuncFormatAndType(functionName, format, type, level)) + return false; + if (!validateSettableTexFormat(functionName, format)) + return false; + + switch (type) { + case GL_UNSIGNED_BYTE: + if (pixels->type() != ArrayBufferView::TypeUint8) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "type UNSIGNED_BYTE but ArrayBufferView not Uint8Array"); + return false; + } + break; + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_5_5_5_1: + if (pixels->type() != ArrayBufferView::TypeUint16) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "type UNSIGNED_SHORT but ArrayBufferView not Uint16Array"); + return false; + } + break; + case GL_FLOAT: // OES_texture_float + if (pixels->type() != ArrayBufferView::TypeFloat32) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "type FLOAT but ArrayBufferView not Float32Array"); + return false; + } + break; + case GL_HALF_FLOAT_OES: // OES_texture_half_float + // As per the specification, ArrayBufferView should be null or a Uint16Array when + // OES_texture_half_float is enabled. + if (pixels && pixels->type() != ArrayBufferView::TypeUint16) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "type HALF_FLOAT_OES but ArrayBufferView is not NULL and not Uint16Array"); + return false; + } + break; + default: + ASSERT_NOT_REACHED(); + } + + unsigned totalBytesRequired; + GLenum error = WebGLImageConversion::computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0); + if (error != GL_NO_ERROR) { + synthesizeGLError(error, functionName, "invalid texture dimensions"); + return false; + } + if (pixels->byteLength() < totalBytesRequired) { + if (m_unpackAlignment != 1) { + error = WebGLImageConversion::computeImageSizeInBytes(format, type, width, height, 1, &totalBytesRequired, 0); + if (pixels->byteLength() == totalBytesRequired) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request with UNPACK_ALIGNMENT > 1"); + return false; + } + } + synthesizeGLError(GL_INVALID_OPERATION, functionName, "ArrayBufferView not big enough for request"); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateCompressedTexFormat(GLenum format) +{ + return m_compressedTextureFormats.contains(format); +} + +bool WebGLRenderingContextBase::validateCompressedTexFuncData(const char* functionName, GLsizei width, GLsizei height, GLenum format, ArrayBufferView* pixels) +{ + if (!pixels) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "no pixels"); + return false; + } + if (width < 0 || height < 0) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "width or height < 0"); + return false; + } + + unsigned bytesRequired = 0; + + switch (format) { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + { + const int kBlockWidth = 4; + const int kBlockHeight = 4; + const int kBlockSize = 8; + int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth; + int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight; + int numBlocks = numBlocksAcross * numBlocksDown; + bytesRequired = numBlocks * kBlockSize; + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + { + const int kBlockWidth = 4; + const int kBlockHeight = 4; + const int kBlockSize = 16; + int numBlocksAcross = (width + kBlockWidth - 1) / kBlockWidth; + int numBlocksDown = (height + kBlockHeight - 1) / kBlockHeight; + int numBlocks = numBlocksAcross * numBlocksDown; + bytesRequired = numBlocks * kBlockSize; + } + break; + case GC3D_COMPRESSED_ATC_RGB_AMD: + case GL_ETC1_RGB8_OES: + { + bytesRequired = floor(static_cast<double>((width + 3) / 4)) * floor(static_cast<double>((height + 3) / 4)) * 8; + } + break; + case GC3D_COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD: + case GC3D_COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD: + { + bytesRequired = floor(static_cast<double>((width + 3) / 4)) * floor(static_cast<double>((height + 3) / 4)) * 16; + } + break; + case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG: + case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: + { + bytesRequired = (max(width, 8) * max(height, 8) * 4 + 7) / 8; + } + break; + case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG: + case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: + { + bytesRequired = (max(width, 16) * max(height, 8) * 2 + 7) / 8; + } + break; + default: + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid format"); + return false; + } + + if (pixels->byteLength() != bytesRequired) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "length of ArrayBufferView is not correct for dimensions"); + return false; + } + + return true; +} + +bool WebGLRenderingContextBase::validateCompressedTexDimensions(const char* functionName, TexFuncValidationFunctionType functionType, GLenum target, GLint level, GLsizei width, GLsizei height, GLenum format) +{ + if (!validateTexFuncDimensions(functionName, functionType, target, level, width, height)) + return false; + + bool widthValid = false; + bool heightValid = false; + + switch (format) { + case GC3D_COMPRESSED_ATC_RGB_AMD: + case GC3D_COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD: + case GC3D_COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD: + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: { + const int kBlockWidth = 4; + const int kBlockHeight = 4; + widthValid = (level && width == 1) || (level && width == 2) || !(width % kBlockWidth); + heightValid = (level && height == 1) || (level && height == 2) || !(height % kBlockHeight); + break; + } + case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG: + case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: + case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG: + case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: { + // Must be a power of two + widthValid = (width & (width - 1)) == 0; + heightValid = (height & (height - 1)) == 0; + break; + } + case GL_ETC1_RGB8_OES: { + widthValid = true; + heightValid = true; + break; + } + default: + return false; + } + + if (!widthValid || !heightValid) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "width or height invalid for level"); + return false; + } + + return true; +} + +bool WebGLRenderingContextBase::validateCompressedTexSubDimensions(const char* functionName, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, WebGLTexture* tex) +{ + if (xoffset < 0 || yoffset < 0) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "xoffset or yoffset < 0"); + return false; + } + + switch (format) { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: { + const int kBlockWidth = 4; + const int kBlockHeight = 4; + if ((xoffset % kBlockWidth) || (yoffset % kBlockHeight)) { + synthesizeGLError(GL_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(GL_INVALID_OPERATION, functionName, "dimensions out of range"); + return false; + } + return validateCompressedTexDimensions(functionName, TexSubImage2D, target, level, width, height, format); + } + case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG: + case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: + case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG: + case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: { + if ((xoffset != 0) || (yoffset != 0)) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "xoffset and yoffset must be zero"); + return false; + } + if (width != tex->getWidth(target, level) + || height != tex->getHeight(target, level)) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "dimensions must match existing level"); + return false; + } + return validateCompressedTexDimensions(functionName, TexSubImage2D, target, level, width, height, format); + } + case GC3D_COMPRESSED_ATC_RGB_AMD: + case GC3D_COMPRESSED_ATC_RGBA_EXPLICIT_ALPHA_AMD: + case GC3D_COMPRESSED_ATC_RGBA_INTERPOLATED_ALPHA_AMD: + case GL_ETC1_RGB8_OES: { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "unable to update sub-images with this format"); + return false; + } + default: + return false; + } +} + +bool WebGLRenderingContextBase::validateDrawMode(const char* functionName, GLenum mode) +{ + switch (mode) { + case GL_POINTS: + case GL_LINE_STRIP: + case GL_LINE_LOOP: + case GL_LINES: + case GL_TRIANGLE_STRIP: + case GL_TRIANGLE_FAN: + case GL_TRIANGLES: + return true; + default: + synthesizeGLError(GL_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(GL_INVALID_OPERATION, functionName, "front and back stencils settings do not match"); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateStencilOrDepthFunc(const char* functionName, GLenum func) +{ + switch (func) { + case GL_NEVER: + case GL_LESS: + case GL_LEQUAL: + case GL_GREATER: + case GL_GEQUAL: + case GL_EQUAL: + case GL_NOTEQUAL: + case GL_ALWAYS: + return true; + default: + synthesizeGLError(GL_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."); + + return; +} + +void WebGLRenderingContextBase::printWarningToConsole(const String& message) +{ + if (!canvas()) + return; + canvas()->document().addConsoleMessage(RenderingMessageSource, WarningMessageLevel, message); +} + +bool WebGLRenderingContextBase::validateFramebufferFuncParameters(const char* functionName, GLenum target, GLenum attachment) +{ + if (target != GL_FRAMEBUFFER) { + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid target"); + return false; + } + switch (attachment) { + case GL_COLOR_ATTACHMENT0: + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + case GC3D_DEPTH_STENCIL_ATTACHMENT_WEBGL: + break; + default: + if (extensionEnabled(WebGLDrawBuffersName) + && attachment > GL_COLOR_ATTACHMENT0 + && attachment < static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + maxColorAttachments())) + break; + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid attachment"); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateBlendEquation(const char* functionName, GLenum mode) +{ + switch (mode) { + case GL_FUNC_ADD: + case GL_FUNC_SUBTRACT: + case GL_FUNC_REVERSE_SUBTRACT: + return true; + case GL_MIN_EXT: + case GL_MAX_EXT: + if (extensionEnabled(EXTBlendMinMaxName)) + return true; + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid mode"); + return false; + default: + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid mode"); + return false; + } +} + +bool WebGLRenderingContextBase::validateBlendFuncFactors(const char* functionName, GLenum src, GLenum dst) +{ + if (((src == GL_CONSTANT_COLOR || src == GL_ONE_MINUS_CONSTANT_COLOR) + && (dst == GL_CONSTANT_ALPHA || dst == GL_ONE_MINUS_CONSTANT_ALPHA)) + || ((dst == GL_CONSTANT_COLOR || dst == GL_ONE_MINUS_CONSTANT_COLOR) + && (src == GL_CONSTANT_ALPHA || src == GL_ONE_MINUS_CONSTANT_ALPHA))) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "incompatible src and dst"); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateCapability(const char* functionName, GLenum cap) +{ + switch (cap) { + case GL_BLEND: + case GL_CULL_FACE: + case GL_DEPTH_TEST: + case GL_DITHER: + case GL_POLYGON_OFFSET_FILL: + case GL_SAMPLE_ALPHA_TO_COVERAGE: + case GL_SAMPLE_COVERAGE: + case GL_SCISSOR_TEST: + case GL_STENCIL_TEST: + return true; + default: + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid capability"); + return false; + } +} + +bool WebGLRenderingContextBase::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Float32Array* v, GLsizei requiredMinSize) +{ + if (!v) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "no array"); + return false; + } + return validateUniformMatrixParameters(functionName, location, false, v->data(), v->length(), requiredMinSize); +} + +bool WebGLRenderingContextBase::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, Int32Array* v, GLsizei requiredMinSize) +{ + if (!v) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "no array"); + return false; + } + return validateUniformMatrixParameters(functionName, location, false, v->data(), v->length(), requiredMinSize); +} + +bool WebGLRenderingContextBase::validateUniformParameters(const char* functionName, const WebGLUniformLocation* location, void* v, GLsizei size, GLsizei requiredMinSize) +{ + return validateUniformMatrixParameters(functionName, location, false, v, size, requiredMinSize); +} + +bool WebGLRenderingContextBase::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GLboolean transpose, Float32Array* v, GLsizei requiredMinSize) +{ + if (!v) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "no array"); + return false; + } + return validateUniformMatrixParameters(functionName, location, transpose, v->data(), v->length(), requiredMinSize); +} + +bool WebGLRenderingContextBase::validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation* location, GLboolean transpose, void* v, GLsizei size, GLsizei requiredMinSize) +{ + if (!location) + return false; + if (location->program() != m_currentProgram) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "location is not from current program"); + return false; + } + if (!v) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "no array"); + return false; + } + if (transpose) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "transpose not FALSE"); + return false; + } + if (size < requiredMinSize || (size % requiredMinSize)) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "invalid size"); + return false; + } + return true; +} + +WebGLBuffer* WebGLRenderingContextBase::validateBufferDataTarget(const char* functionName, GLenum target) +{ + WebGLBuffer* buffer = 0; + switch (target) { + case GL_ELEMENT_ARRAY_BUFFER: + buffer = m_boundVertexArrayObject->boundElementArrayBuffer().get(); + break; + case GL_ARRAY_BUFFER: + buffer = m_boundArrayBuffer.get(); + break; + default: + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid target"); + return 0; + } + if (!buffer) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "no buffer"); + return 0; + } + return buffer; +} + +bool WebGLRenderingContextBase::validateHTMLImageElement(const char* functionName, HTMLImageElement* image, ExceptionState& exceptionState) +{ + if (!image || !image->cachedImage()) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "no image"); + return false; + } + const KURL& url = image->cachedImage()->response().url(); + if (url.isNull() || url.isEmpty() || !url.isValid()) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "invalid image"); + return false; + } + + if (wouldTaintOrigin(image)) { + exceptionState.throwSecurityError("The cross-origin image at " + url.elidedString() + " may not be loaded."); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement* canvas, ExceptionState& exceptionState) +{ + if (!canvas || !canvas->buffer()) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "no canvas"); + return false; + } + if (wouldTaintOrigin(canvas)) { + exceptionState.throwSecurityError("Tainted canvases may not be loaded."); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateHTMLVideoElement(const char* functionName, HTMLVideoElement* video, ExceptionState& exceptionState) +{ + if (!video || !video->videoWidth() || !video->videoHeight()) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "no video"); + return false; + } + + if (wouldTaintOrigin(video)) { + exceptionState.throwSecurityError("The video element contains cross-origin data, and may not be loaded."); + return false; + } + return true; +} + +bool WebGLRenderingContextBase::validateDrawArrays(const char* functionName, GLenum mode, GLint first, GLsizei count) +{ + if (isContextLost() || !validateDrawMode(functionName, mode)) + return false; + + if (!validateStencilSettings(functionName)) + return false; + + if (first < 0 || count < 0) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "first or count < 0"); + return false; + } + + if (!count) { + markContextChanged(CanvasChanged); + return false; + } + + if (!validateRenderingState(functionName)) { + return false; + } + + const char* reason = "framebuffer incomplete"; + if (m_framebufferBinding && !m_framebufferBinding->onAccess(webContext(), &reason)) { + synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, functionName, reason); + return false; + } + + return true; +} + +bool WebGLRenderingContextBase::validateDrawElements(const char* functionName, GLenum mode, GLsizei count, GLenum type, long long offset) +{ + if (isContextLost() || !validateDrawMode(functionName, mode)) + return false; + + if (!validateStencilSettings(functionName)) + return false; + + switch (type) { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT: + break; + case GL_UNSIGNED_INT: + if (extensionEnabled(OESElementIndexUintName)) + break; + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid type"); + return false; + default: + synthesizeGLError(GL_INVALID_ENUM, functionName, "invalid type"); + return false; + } + + if (count < 0) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "count < 0"); + return false; + } + if (!validateValueFitNonNegInt32(functionName, "offset", offset)) + return false; + + if (!count) { + markContextChanged(CanvasChanged); + return false; + } + + if (!m_boundVertexArrayObject->boundElementArrayBuffer()) { + synthesizeGLError(GL_INVALID_OPERATION, functionName, "no ELEMENT_ARRAY_BUFFER bound"); + return false; + } + + if (!validateRenderingState(functionName)) { + return false; + } + + const char* reason = "framebuffer incomplete"; + if (m_framebufferBinding && !m_framebufferBinding->onAccess(webContext(), &reason)) { + synthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, functionName, reason); + return false; + } + + return true; +} + +// Helper function to validate draw*Instanced calls +bool WebGLRenderingContextBase::validateDrawInstanced(const char* functionName, GLsizei primcount) +{ + if (primcount < 0) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "primcount < 0"); + return false; + } + + // Ensure at least one enabled vertex attrib has a divisor of 0. + for (unsigned i = 0; i < m_onePlusMaxEnabledAttribIndex; ++i) { + const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(i); + if (state.enabled && !state.divisor) + return true; + } + + synthesizeGLError(GL_INVALID_OPERATION, functionName, "at least one enabled attribute must have a divisor of 0"); + return false; +} + +void WebGLRenderingContextBase::vertexAttribfImpl(const char* functionName, GLuint index, GLsizei expectedSize, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) +{ + if (isContextLost()) + return; + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "index out of range"); + return; + } + // In GL, we skip setting vertexAttrib0 values. + switch (expectedSize) { + case 1: + webContext()->vertexAttrib1f(index, v0); + break; + case 2: + webContext()->vertexAttrib2f(index, v0, v1); + break; + case 3: + webContext()->vertexAttrib3f(index, v0, v1, v2); + break; + case 4: + webContext()->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, GLuint index, Float32Array* v, GLsizei expectedSize) +{ + if (isContextLost()) + return; + if (!v) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "no array"); + return; + } + vertexAttribfvImpl(functionName, index, v->data(), v->length(), expectedSize); +} + +void WebGLRenderingContextBase::vertexAttribfvImpl(const char* functionName, GLuint index, GLfloat* v, GLsizei size, GLsizei expectedSize) +{ + if (isContextLost()) + return; + if (!v) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "no array"); + return; + } + if (size < expectedSize) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "invalid size"); + return; + } + if (index >= m_maxVertexAttribs) { + synthesizeGLError(GL_INVALID_VALUE, functionName, "index out of range"); + return; + } + // In GL, we skip setting vertexAttrib0 values. + switch (expectedSize) { + case 1: + webContext()->vertexAttrib1fv(index, v); + break; + case 2: + webContext()->vertexAttrib2fv(index, v); + break; + case 3: + webContext()->vertexAttrib3fv(index, v); + break; + case 4: + webContext()->vertexAttrib4fv(index, v); + break; + } + VertexAttribValue& attribValue = m_vertexAttribValue[index]; + attribValue.initValue(); + for (int ii = 0; ii < expectedSize; ++ii) + attribValue.value[ii] = v[ii]; +} + +void WebGLRenderingContextBase::dispatchContextLostEvent(Timer<WebGLRenderingContextBase>*) +{ + RefPtrWillBeRawPtr<WebGLContextEvent> event = WebGLContextEvent::create(EventTypeNames::webglcontextlost, false, true, ""); + canvas()->dispatchEvent(event); + m_restoreAllowed = event->defaultPrevented(); + deactivateContext(this, m_contextLostMode != RealLostContext && m_restoreAllowed); + if ((m_contextLostMode == RealLostContext || m_contextLostMode == AutoRecoverSyntheticLostContext) && m_restoreAllowed) + m_restoreTimer.startOneShot(0, FROM_HERE); +} + +void WebGLRenderingContextBase::maybeRestoreContext(Timer<WebGLRenderingContextBase>*) +{ +#ifndef NDEBUG + printWarningToConsole("maybeRestoreContext(): begin"); +#endif + ASSERT(isContextLost()); + + // 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; + + LocalFrame* frame = canvas()->document().frame(); + if (!frame) + return; + + Settings* settings = frame->settings(); + + if (!frame->loader().client()->allowWebGL(settings && settings->webGLEnabled())) + return; + + // If the context was lost due to RealLostContext, we need to destroy the old DrawingBuffer before creating new DrawingBuffer to ensure resource budget enough. + if (m_drawingBuffer) { + m_drawingBuffer->beginDestruction(); + m_drawingBuffer.clear(); + } +#ifndef NDEBUG + printWarningToConsole("maybeRestoreContext(): destroyed old DrawingBuffer"); +#endif + + blink::WebGraphicsContext3D::Attributes attributes = m_requestedAttributes->attributes(canvas()->document().topDocument().url().string(), settings); + OwnPtr<blink::WebGraphicsContext3D> context = adoptPtr(blink::Platform::current()->createOffscreenGraphicsContext3D(attributes, 0)); + RefPtr<DrawingBuffer> drawingBuffer; + // Even if a non-null WebGraphicsContext3D is created, until it's made current, it isn't known whether the context is still lost. + if (context) { + // Construct a new drawing buffer with the new WebGraphicsContext3D. + drawingBuffer = createDrawingBuffer(context.release()); + // If DrawingBuffer::create() fails to allocate a fbo, |drawingBuffer| is set to null. + } + if (!drawingBuffer) { + if (m_contextLostMode == RealLostContext) { + m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts, FROM_HERE); + } else { + // This likely shouldn't happen but is the best way to report it to the WebGL app. + synthesizeGLError(GL_INVALID_OPERATION, "", "error restoring context"); + } + return; + } +#ifndef NDEBUG + printWarningToConsole("maybeRestoreContext(): created new DrawingBuffer"); +#endif + + m_drawingBuffer = drawingBuffer.release(); + m_drawingBuffer->bind(); + m_lostContextErrors.clear(); + m_contextLost = false; + + setupFlags(); + initializeNewContext(); + markContextChanged(CanvasContextChanged); +#ifndef NDEBUG + printWarningToConsole("maybeRestoreContext(): before dispatchEvent"); +#endif + canvas()->dispatchEvent(WebGLContextEvent::create(EventTypeNames::webglcontextrestored, false, true, "")); +#ifndef NDEBUG + printWarningToConsole("maybeRestoreContext(): end"); +#endif +} + +String WebGLRenderingContextBase::ensureNotNull(const String& text) const +{ + if (text.isNull()) + return WTF::emptyString(); + return text; +} + +WebGLRenderingContextBase::LRUImageBufferCache::LRUImageBufferCache(int capacity) + : m_buffers(adoptArrayPtr(new OwnPtr<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->size() != size) + continue; + bubbleToFront(i); + return buf; + } + + OwnPtr<ImageBuffer> temp(ImageBuffer::create(size)); + if (!temp) + return 0; + i = std::min(m_capacity - 1, i); + m_buffers[i] = temp.release(); + + 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(GLenum error) + { + switch (error) { + case GL_INVALID_ENUM: + return "INVALID_ENUM"; + case GL_INVALID_VALUE: + return "INVALID_VALUE"; + case GL_INVALID_OPERATION: + return "INVALID_OPERATION"; + case GL_OUT_OF_MEMORY: + return "OUT_OF_MEMORY"; + case GL_INVALID_FRAMEBUFFER_OPERATION: + return "INVALID_FRAMEBUFFER_OPERATION"; + case GC3D_CONTEXT_LOST_WEBGL: + return "CONTEXT_LOST_WEBGL"; + default: + return String::format("WebGL ERROR(0x%04X)", error); + } + } + +} // namespace anonymous + +void WebGLRenderingContextBase::synthesizeGLError(GLenum error, const char* functionName, const char* description, ConsoleDisplayPreference display) +{ + String errorType = GetErrorString(error); + if (m_synthesizedErrorsToConsole && display == DisplayInConsole) { + String message = String("WebGL: ") + errorType + ": " + String(functionName) + ": " + String(description); + printGLErrorToConsole(message); + } + if (!isContextLost()) + webContext()->synthesizeGLError(error); + else { + if (m_lostContextErrors.find(error) == WTF::kNotFound) + m_lostContextErrors.append(error); + } + InspectorInstrumentation::didFireWebGLError(canvas(), errorType); +} + +void WebGLRenderingContextBase::emitGLWarning(const char* functionName, const char* description) +{ + if (m_synthesizedErrorsToConsole) { + String message = String("WebGL: ") + String(functionName) + ": " + String(description); + printGLErrorToConsole(message); + } + InspectorInstrumentation::didFireWebGLWarning(canvas()); +} + +void WebGLRenderingContextBase::applyStencilTest() +{ + bool haveStencilBuffer = false; + + if (m_framebufferBinding) + haveStencilBuffer = m_framebufferBinding->hasStencilBuffer(); + else { + RefPtr<WebGLContextAttributes> attributes = getContextAttributes(); + haveStencilBuffer = attributes->stencil(); + } + enableOrDisable(GL_STENCIL_TEST, + m_stencilEnabled && haveStencilBuffer); +} + +void WebGLRenderingContextBase::enableOrDisable(GLenum capability, bool enable) +{ + if (isContextLost()) + return; + if (enable) + webContext()->enable(capability); + else + webContext()->disable(capability); +} + +IntSize WebGLRenderingContextBase::clampedCanvasSize() +{ + return IntSize(clamp(canvas()->width(), 1, m_maxViewportDims[0]), + clamp(canvas()->height(), 1, m_maxViewportDims[1])); +} + +GLint WebGLRenderingContextBase::maxDrawBuffers() +{ + if (isContextLost() || !extensionEnabled(WebGLDrawBuffersName)) + return 0; + if (!m_maxDrawBuffers) + webContext()->getIntegerv(GL_MAX_DRAW_BUFFERS_EXT, &m_maxDrawBuffers); + if (!m_maxColorAttachments) + webContext()->getIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments); + // WEBGL_draw_buffers requires MAX_COLOR_ATTACHMENTS >= MAX_DRAW_BUFFERS. + return std::min(m_maxDrawBuffers, m_maxColorAttachments); +} + +GLint WebGLRenderingContextBase::maxColorAttachments() +{ + if (isContextLost() || !extensionEnabled(WebGLDrawBuffersName)) + return 0; + if (!m_maxColorAttachments) + webContext()->getIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &m_maxColorAttachments); + return m_maxColorAttachments; +} + +void WebGLRenderingContextBase::setBackDrawBuffer(GLenum buf) +{ + m_backDrawBuffer = buf; +} + +void WebGLRenderingContextBase::restoreCurrentFramebuffer() +{ + bindFramebuffer(GL_FRAMEBUFFER, m_framebufferBinding.get()); +} + +void WebGLRenderingContextBase::restoreCurrentTexture2D() +{ + bindTexture(GL_TEXTURE_2D, m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get()); +} + +void WebGLRenderingContextBase::multisamplingChanged(bool enabled) +{ + if (m_multisamplingAllowed != enabled) { + m_multisamplingAllowed = enabled; + forceLostContext(WebGLRenderingContextBase::AutoRecoverSyntheticLostContext); + } +} + +void WebGLRenderingContextBase::findNewMaxEnabledAttribIndex() +{ + // Trace backwards from the current max to find the new max enabled attrib index + int startIndex = m_onePlusMaxEnabledAttribIndex - 1; + for (int i = startIndex; i >= 0; --i) { + if (m_boundVertexArrayObject->getVertexAttribState(i).enabled) { + m_onePlusMaxEnabledAttribIndex = i + 1; + return; + } + } + m_onePlusMaxEnabledAttribIndex = 0; +} + +void WebGLRenderingContextBase::findNewMaxNonDefaultTextureUnit() +{ + // Trace backwards from the current max to find the new max non-default texture unit + int startIndex = m_onePlusMaxNonDefaultTextureUnit - 1; + for (int i = startIndex; i >= 0; --i) { + if (m_textureUnits[i].m_texture2DBinding + || m_textureUnits[i].m_textureCubeMapBinding) { + m_onePlusMaxNonDefaultTextureUnit = i + 1; + return; + } + } + m_onePlusMaxNonDefaultTextureUnit = 0; +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContextBase.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContextBase.h new file mode 100644 index 00000000000..ca08a621efc --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContextBase.h @@ -0,0 +1,914 @@ +/* + * Copyright (C) 2009 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 COMPUTER, 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 + * 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 WebGLRenderingContextBase_h +#define WebGLRenderingContextBase_h + +#include "core/dom/ActiveDOMObject.h" +#include "core/html/canvas/CanvasRenderingContext.h" +#include "core/html/canvas/WebGLExtensionName.h" +#include "core/html/canvas/WebGLGetInfo.h" +#include "core/page/Page.h" +#include "core/rendering/RenderBoxModelObject.h" +#include "platform/Timer.h" +#include "platform/graphics/GraphicsTypes3D.h" +#include "platform/graphics/ImageBuffer.h" +#include "platform/graphics/gpu/DrawingBuffer.h" +#include "platform/graphics/gpu/Extensions3DUtil.h" +#include "platform/graphics/gpu/WebGLImageConversion.h" +#include "public/platform/WebGraphicsContext3D.h" +#include "wtf/Float32Array.h" +#include "wtf/Int32Array.h" +#include "wtf/OwnPtr.h" +#include "wtf/text/WTFString.h" + +namespace blink { +class WebLayer; +} + +namespace WebCore { + +class ANGLEInstancedArrays; +class EXTBlendMinMax; +class EXTFragDepth; +class EXTShaderTextureLOD; +class EXTTextureFilterAnisotropic; +class ExceptionState; +class HTMLImageElement; +class HTMLVideoElement; +class ImageBuffer; +class ImageData; +class IntSize; +class OESElementIndexUint; +class OESStandardDerivatives; +class OESTextureFloat; +class OESTextureFloatLinear; +class OESTextureHalfFloat; +class OESTextureHalfFloatLinear; +class OESVertexArrayObject; +class WebGLActiveInfo; +class WebGLBuffer; +class WebGLCompressedTextureATC; +class WebGLCompressedTextureETC1; +class WebGLCompressedTexturePVRTC; +class WebGLCompressedTextureS3TC; +class WebGLContextAttributes; +class WebGLContextGroup; +class WebGLContextObject; +class WebGLDebugRendererInfo; +class WebGLDebugShaders; +class WebGLDepthTexture; +class WebGLDrawBuffers; +class WebGLExtension; +class WebGLFramebuffer; +class WebGLLoseContext; +class WebGLObject; +class WebGLProgram; +class WebGLRenderbuffer; +class WebGLShader; +class WebGLShaderPrecisionFormat; +class WebGLSharedObject; +class WebGLTexture; +class WebGLUniformLocation; +class WebGLVertexArrayObjectOES; + +class WebGLRenderingContextLostCallback; +class WebGLRenderingContextErrorMessageCallback; + +class WebGLRenderingContextBase: public CanvasRenderingContext, public ActiveDOMObject, public Page::MultisamplingChangedObserver { + WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(WebGLRenderingContextBase); +public: + virtual ~WebGLRenderingContextBase(); + + virtual bool is3d() const OVERRIDE { return true; } + virtual bool isAccelerated() const OVERRIDE { return true; } + virtual unsigned version() const = 0; + virtual String contextName() const = 0; + virtual void registerContextExtensions() = 0; + + static unsigned getWebGLVersion(const CanvasRenderingContext*); + + int drawingBufferWidth() const; + int drawingBufferHeight() const; + + void activeTexture(GLenum texture); + void attachShader(WebGLProgram*, WebGLShader*); + void bindAttribLocation(WebGLProgram*, GLuint index, const String& name); + void bindBuffer(GLenum target, WebGLBuffer*); + void bindFramebuffer(GLenum target, WebGLFramebuffer*); + void bindRenderbuffer(GLenum target, WebGLRenderbuffer*); + void bindTexture(GLenum target, WebGLTexture*); + void blendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat 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, long long size, GLenum usage); + void bufferData(GLenum target, ArrayBuffer* data, GLenum usage); + void bufferData(GLenum target, ArrayBufferView* data, GLenum usage); + void bufferSubData(GLenum target, long long offset, ArrayBuffer* data); + void bufferSubData(GLenum target, long long offset, ArrayBufferView* data); + + GLenum checkFramebufferStatus(GLenum target); + void clear(GLbitfield mask); + void clearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); + void clearDepth(GLfloat); + void clearStencil(GLint); + void colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); + void compileShader(WebGLShader*); + + 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); + + PassRefPtr<WebGLBuffer> createBuffer(); + PassRefPtr<WebGLFramebuffer> createFramebuffer(); + PassRefPtr<WebGLProgram> createProgram(); + PassRefPtr<WebGLRenderbuffer> createRenderbuffer(); + PassRefPtr<WebGLShader> createShader(GLenum type); + PassRefPtr<WebGLTexture> createTexture(); + + void cullFace(GLenum mode); + + void deleteBuffer(WebGLBuffer*); + void deleteFramebuffer(WebGLFramebuffer*); + void deleteProgram(WebGLProgram*); + void deleteRenderbuffer(WebGLRenderbuffer*); + void deleteShader(WebGLShader*); + void deleteTexture(WebGLTexture*); + + void depthFunc(GLenum); + void depthMask(GLboolean); + void depthRange(GLfloat zNear, GLfloat zFar); + void detachShader(WebGLProgram*, WebGLShader*); + void disable(GLenum cap); + void disableVertexAttribArray(GLuint index); + void drawArrays(GLenum mode, GLint first, GLsizei count); + void drawElements(GLenum mode, GLsizei count, GLenum type, long long offset); + + void drawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount); + void drawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, long long offset, GLsizei primcount); + + void enable(GLenum cap); + void enableVertexAttribArray(GLuint index); + void finish(); + void flush(); + void framebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, WebGLRenderbuffer*); + void framebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, WebGLTexture*, GLint level); + void frontFace(GLenum mode); + void generateMipmap(GLenum target); + + PassRefPtr<WebGLActiveInfo> getActiveAttrib(WebGLProgram*, GLuint index); + PassRefPtr<WebGLActiveInfo> getActiveUniform(WebGLProgram*, GLuint index); + bool getAttachedShaders(WebGLProgram*, Vector<RefPtr<WebGLShader> >&); + GLint getAttribLocation(WebGLProgram*, const String& name); + WebGLGetInfo getBufferParameter(GLenum target, GLenum pname); + PassRefPtr<WebGLContextAttributes> getContextAttributes(); + GLenum getError(); + PassRefPtr<WebGLExtension> getExtension(const String& name); + WebGLGetInfo getFramebufferAttachmentParameter(GLenum target, GLenum attachment, GLenum pname); + WebGLGetInfo getParameter(GLenum pname); + WebGLGetInfo getProgramParameter(WebGLProgram*, GLenum pname); + String getProgramInfoLog(WebGLProgram*); + WebGLGetInfo getRenderbufferParameter(GLenum target, GLenum pname); + WebGLGetInfo getShaderParameter(WebGLShader*, GLenum pname); + String getShaderInfoLog(WebGLShader*); + PassRefPtr<WebGLShaderPrecisionFormat> getShaderPrecisionFormat(GLenum shaderType, GLenum precisionType); + String getShaderSource(WebGLShader*); + Vector<String> getSupportedExtensions(); + WebGLGetInfo getTexParameter(GLenum target, GLenum pname); + WebGLGetInfo getUniform(WebGLProgram*, const WebGLUniformLocation*); + PassRefPtr<WebGLUniformLocation> getUniformLocation(WebGLProgram*, const String&); + WebGLGetInfo getVertexAttrib(GLuint index, GLenum pname); + long long getVertexAttribOffset(GLuint index, GLenum pname); + + void hint(GLenum target, GLenum mode); + GLboolean isBuffer(WebGLBuffer*); + bool isContextLost() const; + GLboolean isEnabled(GLenum cap); + GLboolean isFramebuffer(WebGLFramebuffer*); + GLboolean isProgram(WebGLProgram*); + GLboolean isRenderbuffer(WebGLRenderbuffer*); + GLboolean isShader(WebGLShader*); + GLboolean isTexture(WebGLTexture*); + + void lineWidth(GLfloat); + void linkProgram(WebGLProgram*); + 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 renderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + void sampleCoverage(GLfloat value, GLboolean invert); + void scissor(GLint x, GLint y, GLsizei width, GLsizei height); + void shaderSource(WebGLShader*, const String&); + void stencilFunc(GLenum func, GLint ref, GLuint mask); + void stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask); + void stencilMask(GLuint); + 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 texImage2D(GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, ArrayBufferView*, ExceptionState&); + void texImage2D(GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, ImageData*, ExceptionState&); + void texImage2D(GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, HTMLImageElement*, ExceptionState&); + void texImage2D(GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, HTMLCanvasElement*, ExceptionState&); + void texImage2D(GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, HTMLVideoElement*, ExceptionState&); + + void texParameterf(GLenum target, GLenum pname, GLfloat param); + void texParameteri(GLenum target, GLenum pname, GLint param); + + void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, ArrayBufferView*, ExceptionState&); + void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, ImageData*, ExceptionState&); + void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, HTMLImageElement*, ExceptionState&); + void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, HTMLCanvasElement*, ExceptionState&); + void texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, HTMLVideoElement*, ExceptionState&); + + void uniform1f(const WebGLUniformLocation*, GLfloat x); + void uniform1fv(const WebGLUniformLocation*, Float32Array* v); + void uniform1fv(const WebGLUniformLocation*, GLfloat* v, GLsizei); + void uniform1i(const WebGLUniformLocation*, GLint x); + void uniform1iv(const WebGLUniformLocation*, Int32Array* v); + void uniform1iv(const WebGLUniformLocation*, GLint* v, GLsizei); + void uniform2f(const WebGLUniformLocation*, GLfloat x, GLfloat y); + void uniform2fv(const WebGLUniformLocation*, Float32Array* v); + void uniform2fv(const WebGLUniformLocation*, GLfloat* v, GLsizei); + void uniform2i(const WebGLUniformLocation*, GLint x, GLint y); + void uniform2iv(const WebGLUniformLocation*, Int32Array* v); + void uniform2iv(const WebGLUniformLocation*, GLint* v, GLsizei); + void uniform3f(const WebGLUniformLocation*, GLfloat x, GLfloat y, GLfloat z); + void uniform3fv(const WebGLUniformLocation*, Float32Array* v); + void uniform3fv(const WebGLUniformLocation*, GLfloat* v, GLsizei); + void uniform3i(const WebGLUniformLocation*, GLint x, GLint y, GLint z); + void uniform3iv(const WebGLUniformLocation*, Int32Array* v); + void uniform3iv(const WebGLUniformLocation*, GLint* v, GLsizei); + void uniform4f(const WebGLUniformLocation*, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void uniform4fv(const WebGLUniformLocation*, Float32Array* v); + void uniform4fv(const WebGLUniformLocation*, GLfloat* v, GLsizei); + void uniform4i(const WebGLUniformLocation*, GLint x, GLint y, GLint z, GLint w); + void uniform4iv(const WebGLUniformLocation*, Int32Array* v); + void uniform4iv(const WebGLUniformLocation*, GLint* v, GLsizei); + void uniformMatrix2fv(const WebGLUniformLocation*, GLboolean transpose, Float32Array* value); + void uniformMatrix2fv(const WebGLUniformLocation*, GLboolean transpose, GLfloat* value, GLsizei); + void uniformMatrix3fv(const WebGLUniformLocation*, GLboolean transpose, Float32Array* value); + void uniformMatrix3fv(const WebGLUniformLocation*, GLboolean transpose, GLfloat* value, GLsizei); + void uniformMatrix4fv(const WebGLUniformLocation*, GLboolean transpose, Float32Array* value); + void uniformMatrix4fv(const WebGLUniformLocation*, GLboolean transpose, GLfloat* value, GLsizei); + + void useProgram(WebGLProgram*); + void validateProgram(WebGLProgram*); + + void vertexAttrib1f(GLuint index, GLfloat x); + void vertexAttrib1fv(GLuint index, Float32Array* values); + void vertexAttrib1fv(GLuint index, GLfloat* values, GLsizei); + void vertexAttrib2f(GLuint index, GLfloat x, GLfloat y); + void vertexAttrib2fv(GLuint index, Float32Array* values); + void vertexAttrib2fv(GLuint index, GLfloat* values, GLsizei); + void vertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z); + void vertexAttrib3fv(GLuint index, Float32Array* values); + void vertexAttrib3fv(GLuint index, GLfloat* values, GLsizei); + void vertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void vertexAttrib4fv(GLuint index, Float32Array* values); + void vertexAttrib4fv(GLuint index, GLfloat* values, GLsizei); + void vertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, + GLsizei stride, long long offset); + + void vertexAttribDivisorANGLE(GLuint index, GLuint divisor); + + void viewport(GLint x, GLint y, GLsizei width, GLsizei height); + + // WEBKIT_lose_context support + enum LostContextMode { + // Lost context occurred at the graphics system level. + RealLostContext, + + // Lost context provoked by WEBKIT_lose_context. + SyntheticLostContext, + + // A synthetic lost context that should attempt to recover automatically + AutoRecoverSyntheticLostContext + }; + void forceLostContext(LostContextMode); + void forceRestoreContext(); + void loseContextImpl(LostContextMode); + + blink::WebGraphicsContext3D* webContext() const { return m_drawingBuffer->context(); } + WebGLContextGroup* contextGroup() const { return m_contextGroup.get(); } + virtual blink::WebLayer* platformLayer() const OVERRIDE; + Extensions3DUtil* extensionsUtil(); + + void reshape(int width, int height); + + void markLayerComposited(); + virtual void paintRenderingResultsToCanvas() OVERRIDE; + PassRefPtrWillBeRawPtr<ImageData> paintRenderingResultsToImageData(); + + void removeSharedObject(WebGLSharedObject*); + void removeContextObject(WebGLContextObject*); + + unsigned maxVertexAttribs() const { return m_maxVertexAttribs; } + + // ActiveDOMObject notifications + virtual bool hasPendingActivity() const OVERRIDE; + virtual void stop() OVERRIDE; + + void setSavingImage(bool isSaving) { m_savingImage = isSaving; } +protected: + friend class WebGLDrawBuffers; + friend class WebGLFramebuffer; + friend class WebGLObject; + friend class OESVertexArrayObject; + friend class WebGLDebugShaders; + friend class WebGLCompressedTextureATC; + friend class WebGLCompressedTextureETC1; + friend class WebGLCompressedTexturePVRTC; + friend class WebGLCompressedTextureS3TC; + friend class WebGLRenderingContextErrorMessageCallback; + friend class WebGLVertexArrayObjectOES; + friend class ScopedTexture2DRestorer; + + WebGLRenderingContextBase(HTMLCanvasElement*, PassOwnPtr<blink::WebGraphicsContext3D>, WebGLContextAttributes*); + PassRefPtr<DrawingBuffer> createDrawingBuffer(PassOwnPtr<blink::WebGraphicsContext3D>); + void initializeNewContext(); + void setupFlags(); + + void addSharedObject(WebGLSharedObject*); + void addContextObject(WebGLContextObject*); + void detachAndRemoveAllObjects(); + + void destroyContext(); + void markContextChanged(ContentChangeType); + + // 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 sizeInBytes(GLenum type); + + // Check if each enabled vertex attribute is bound to a buffer. + bool validateRenderingState(const char*); + + bool validateWebGLObject(const char*, WebGLObject*); + + // Adds a compressed texture format. + void addCompressedTextureFormat(GLenum); + void removeAllCompressedTextureFormats(); + + PassRefPtr<Image> drawImageIntoBuffer(Image*, int width, int height, const char* functionName); + + PassRefPtr<Image> videoFrameToImage(HTMLVideoElement*, BackingStoreCopy); + + WebGLRenderbuffer* ensureEmulatedStencilBuffer(GLenum target, WebGLRenderbuffer*); + + // Structure for rendering to a DrawingBuffer, instead of directly + // to the back-buffer of m_context. + RefPtr<DrawingBuffer> m_drawingBuffer; + 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<WebGLRenderingContextBase> m_dispatchContextLostEventTimer; + bool m_restoreAllowed; + Timer<WebGLRenderingContextBase> m_restoreTimer; + + bool m_needsUpdate; + bool m_markedCanvasDirty; + HashSet<WebGLContextObject*> m_contextObjects; + + OwnPtr<WebGLRenderingContextLostCallback> m_contextLostCallbackAdapter; + OwnPtr<WebGLRenderingContextErrorMessageCallback> m_errorMessageCallbackAdapter; + + // 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; + } + + GLfloat value[4]; + }; + Vector<VertexAttribValue> m_vertexAttribValue; + unsigned m_maxVertexAttribs; + RefPtr<WebGLBuffer> m_vertexAttrib0Buffer; + long m_vertexAttrib0BufferSize; + GLfloat m_vertexAttrib0BufferValue[4]; + bool m_forceAttrib0BufferRefill; + bool m_vertexAttrib0UsedBefore; + + RefPtr<WebGLProgram> m_currentProgram; + RefPtr<WebGLFramebuffer> m_framebufferBinding; + RefPtr<WebGLRenderbuffer> m_renderbufferBinding; + class TextureUnitState { + public: + RefPtr<WebGLTexture> m_texture2DBinding; + RefPtr<WebGLTexture> m_textureCubeMapBinding; + }; + Vector<TextureUnitState> m_textureUnits; + unsigned long m_activeTextureUnit; + + RefPtr<WebGLTexture> m_blackTexture2D; + RefPtr<WebGLTexture> m_blackTextureCubeMap; + + Vector<GLenum> 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); + OwnPtr<OwnPtr<ImageBuffer>[]> m_buffers; + int m_capacity; + }; + LRUImageBufferCache m_generatedImageCache; + + GLint m_maxTextureSize; + GLint m_maxCubeMapTextureSize; + GLint m_maxRenderbufferSize; + GLint m_maxViewportDims[2]; + GLint m_maxTextureLevel; + GLint m_maxCubeMapTextureLevel; + + GLint m_maxDrawBuffers; + GLint m_maxColorAttachments; + GLenum m_backDrawBuffer; + bool m_drawBuffersWebGLRequirementsChecked; + bool m_drawBuffersSupported; + + GLint m_packAlignment; + GLint m_unpackAlignment; + bool m_unpackFlipY; + bool m_unpackPremultiplyAlpha; + GLenum m_unpackColorspaceConversion; + bool m_contextLost; + LostContextMode m_contextLostMode; + RefPtr<WebGLContextAttributes> m_requestedAttributes; + + bool m_layerCleared; + GLfloat m_clearColor[4]; + bool m_scissorEnabled; + GLfloat m_clearDepth; + GLint m_clearStencil; + GLboolean m_colorMask[4]; + GLboolean m_depthMask; + + bool m_stencilEnabled; + GLuint m_stencilMask, m_stencilMaskBack; + GLint m_stencilFuncRef, m_stencilFuncRefBack; // Note that these are the user specified values, not the internal clamped value. + GLuint m_stencilFuncMask, m_stencilFuncMaskBack; + + bool m_isGLES2NPOTStrict; + bool m_isDepthStencilSupported; + + bool m_synthesizedErrorsToConsole; + int m_numGLErrorsToConsoleAllowed; + + bool m_multisamplingAllowed; + bool m_multisamplingObserverRegistered; + + GLuint m_onePlusMaxEnabledAttribIndex; + unsigned long m_onePlusMaxNonDefaultTextureUnit; + + OwnPtr<Extensions3DUtil> m_extensionsUtil; + + bool m_savingImage; + + enum ExtensionFlags { + ApprovedExtension = 0x00, + // Extension that is behind the draft extensions runtime flag: + DraftExtension = 0x01, + // Extension that is still in draft state, but has been selectively enabled by default under a prefix. Do not use + // this for enabling new draft extensions; use the DraftExtension flag instead, and do not use vendor prefixes: + EnabledDraftExtension = 0x04, + }; + + class ExtensionTracker { + public: + ExtensionTracker(ExtensionFlags flags, const char* const* prefixes) + : m_draft(flags & DraftExtension) + , m_prefixes(prefixes) + { + } + + virtual ~ExtensionTracker() + { + } + + bool draft() const + { + return m_draft; + } + + const char* const* prefixes() const; + bool matchesNameWithPrefixes(const String&) const; + + virtual PassRefPtr<WebGLExtension> getExtension(WebGLRenderingContextBase*) = 0; + virtual bool supported(WebGLRenderingContextBase*) const = 0; + virtual const char* extensionName() const = 0; + virtual void loseExtension() = 0; + + private: + bool m_draft; + const char* const* m_prefixes; + }; + + template <typename T> + class TypedExtensionTracker FINAL : public ExtensionTracker { + public: + TypedExtensionTracker(RefPtr<T>& extensionField, ExtensionFlags flags, const char* const* prefixes) + : ExtensionTracker(flags, prefixes) + , m_extensionField(extensionField) + , m_extension(nullptr) + { + } + + virtual ~TypedExtensionTracker() + { + if (m_extension) { + m_extension->lose(true); + m_extension = nullptr; + } + } + + virtual PassRefPtr<WebGLExtension> getExtension(WebGLRenderingContextBase* context) OVERRIDE + { + if (!m_extension) { + m_extension = T::create(context); + m_extensionField = m_extension; + } + + return m_extension; + } + + virtual bool supported(WebGLRenderingContextBase* context) const OVERRIDE + { + return T::supported(context); + } + + virtual const char* extensionName() const OVERRIDE + { + return T::extensionName(); + } + + virtual void loseExtension() OVERRIDE + { + if (m_extension) { + m_extension->lose(false); + if (m_extension->isLost()) + m_extension = nullptr; + } + } + + private: + RefPtr<T>& m_extensionField; + // ExtensionTracker holds it's own reference to the extension to ensure + // that it is not deleted before this object's destructor is called + RefPtr<T> m_extension; + }; + + bool m_extensionEnabled[WebGLExtensionNameCount]; + Vector<ExtensionTracker*> m_extensions; + + template <typename T> + void registerExtension(RefPtr<T>& extensionPtr, ExtensionFlags flags = ApprovedExtension, const char* const* prefixes = 0) + { + m_extensions.append(new TypedExtensionTracker<T>(extensionPtr, flags, prefixes)); + } + + bool extensionSupportedAndAllowed(const ExtensionTracker*); + + inline bool extensionEnabled(WebGLExtensionName name) + { + return m_extensionEnabled[name]; + } + + // Errors raised by synthesizeGLError() while the context is lost. + Vector<GLenum> m_lostContextErrors; + + // Helpers for getParameter and others + WebGLGetInfo getBooleanParameter(GLenum); + WebGLGetInfo getBooleanArrayParameter(GLenum); + WebGLGetInfo getFloatParameter(GLenum); + WebGLGetInfo getIntParameter(GLenum); + WebGLGetInfo getUnsignedIntParameter(GLenum); + WebGLGetInfo getWebGLFloatArrayParameter(GLenum); + WebGLGetInfo getWebGLIntArrayParameter(GLenum); + + // 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(GLbitfield clearMask = 0); + + // Helper to restore state that clearing the framebuffer may destroy. + void restoreStateAfterClear(); + + // Convert texture internal format. + GLenum convertTexInternalFormat(GLenum internalformat, GLenum type); + + void texImage2DBase(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels, ExceptionState&); + void texImage2DImpl(GLenum target, GLint level, GLenum internalformat, GLenum format, GLenum type, Image*, WebGLImageConversion::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionState&); + void texSubImage2DBase(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels, ExceptionState&); + void texSubImage2DImpl(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLenum format, GLenum type, Image*, WebGLImageConversion::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha, ExceptionState&); + + void handleTextureCompleteness(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(GLenum texInternalFormat, GLenum colorBufferFormat); + + // Helper function to get the bound framebuffer's color buffer format. + GLenum boundFramebufferColorFormat(); + + // 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, GLint x, GLint 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, GLenum 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, GLenum format, GLenum type, GLint 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, GLenum target, GLint level); + + // Helper function to check if a 64-bit value is non-negative and can fit into a 32-bit integer. + // Generates GL error and returns false if not. + bool validateValueFitNonNegInt32(const char* functionName, const char* paramName, long long value); + + 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, GLenum target, GLint level, GLenum internalformat, GLsizei width, + GLsizei height, GLint border, GLenum format, GLenum type, GLint xoffset, GLint yoffset); + + // Helper function to check input width and height for functions {copy, compressed}Tex{Sub}Image. + // Generates GL error and returns false if width or height is invalid. + bool validateTexFuncDimensions(const char* functionName, TexFuncValidationFunctionType, GLenum target, GLint level, GLsizei width, GLsizei height); + + // 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, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum 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, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum 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, GLenum format); + + // Helper function to validate compressed texture data is correct size + // for the given format and dimensions. + bool validateCompressedTexFuncData(const char* functionName, GLsizei width, GLsizei height, GLenum format, ArrayBufferView* pixels); + + // Helper function for validating compressed texture formats. + bool validateCompressedTexFormat(GLenum format); + + // Helper function to validate compressed texture dimensions are valid for + // the given format. + bool validateCompressedTexDimensions(const char* functionName, TexFuncValidationFunctionType, GLenum target, GLint level, GLsizei width, GLsizei height, GLenum format); + + // Helper function to validate compressed texture dimensions are valid for + // the given format. + bool validateCompressedTexSubDimensions(const char* functionName, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, WebGLTexture*); + + // Helper function to validate mode for draw{Arrays/Elements}. + bool validateDrawMode(const char* functionName, GLenum); + + // Helper function to validate if front/back stencilMask and stencilFunc settings are the same. + bool validateStencilSettings(const char* functionName); + + // Helper function to validate stencil or depth func. + bool validateStencilOrDepthFunc(const char* functionName, GLenum); + + // Helper function for texParameterf and texParameteri. + void texParameter(GLenum target, GLenum pname, GLfloat parami, GLint paramf, bool isFloat); + + // Helper function to print GL errors to console. + void printGLErrorToConsole(const String&); + + // 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, GLenum target, GLenum attachment); + + // Helper function to validate blend equation mode. + bool validateBlendEquation(const char* functionName, GLenum); + + // Helper function to validate blend func factors. + bool validateBlendFuncFactors(const char* functionName, GLenum src, GLenum dst); + + // Helper function to validate a GL capability. + bool validateCapability(const char* functionName, GLenum); + + // Helper function to validate input parameters for uniform functions. + bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, Float32Array*, GLsizei mod); + bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, Int32Array*, GLsizei mod); + bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, void*, GLsizei, GLsizei mod); + bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GLboolean transpose, Float32Array*, GLsizei mod); + bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GLboolean transpose, void*, GLsizei, GLsizei mod); + + // Helper function to validate the target for bufferData. + // Return the current bound buffer to target, or 0 if the target is invalid. + WebGLBuffer* validateBufferDataTarget(const char* functionName, GLenum target); + + // Helper function for tex{Sub}Image2D to make sure image is ready and wouldn't taint Origin. + bool validateHTMLImageElement(const char* functionName, HTMLImageElement*, ExceptionState&); + + // Helper function for tex{Sub}Image2D to make sure canvas is ready and wouldn't taint Origin. + bool validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement*, ExceptionState&); + + // Helper function for tex{Sub}Image2D to make sure video is ready wouldn't taint Origin. + bool validateHTMLVideoElement(const char* functionName, HTMLVideoElement*, ExceptionState&); + + // Helper function to validate drawArrays(Instanced) calls + bool validateDrawArrays(const char* functionName, GLenum mode, GLint first, GLsizei count); + + // Helper function to validate drawElements(Instanced) calls + bool validateDrawElements(const char* functionName, GLenum mode, GLsizei count, GLenum type, long long offset); + + // Helper function to validate draw*Instanced calls + bool validateDrawInstanced(const char* functionName, GLsizei primcount); + + // Helper functions for vertexAttribNf{v}. + void vertexAttribfImpl(const char* functionName, GLuint index, GLsizei expectedSize, GLfloat, GLfloat, GLfloat, GLfloat); + void vertexAttribfvImpl(const char* functionName, GLuint index, Float32Array*, GLsizei expectedSize); + void vertexAttribfvImpl(const char* functionName, GLuint index, GLfloat*, GLsizei, GLsizei expectedSize); + + // Helper functions to bufferData() and bufferSubData(). + void bufferDataImpl(GLenum target, long long size, const void* data, GLenum usage); + void bufferSubDataImpl(GLenum target, long long offset, GLsizeiptr size, const void* data); + + // 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); + + void dispatchContextLostEvent(Timer<WebGLRenderingContextBase>*); + // Helper for restoration after context lost. + void maybeRestoreContext(Timer<WebGLRenderingContextBase>*); + + enum ConsoleDisplayPreference { + DisplayInConsole, + DontDisplayInConsole + }; + + // Wrapper for WebGraphicsContext3D::synthesizeGLError that sends a message + // to the JavaScript console. + void synthesizeGLError(GLenum, const char* functionName, const char* description, ConsoleDisplayPreference = DisplayInConsole); + void emitGLWarning(const char* function, const char* reason); + + 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(GLenum 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. + GLint maxDrawBuffers(); + GLint maxColorAttachments(); + + void setBackDrawBuffer(GLenum); + + void restoreCurrentFramebuffer(); + void restoreCurrentTexture2D(); + + virtual void multisamplingChanged(bool) OVERRIDE; + + void findNewMaxEnabledAttribIndex(); + void findNewMaxNonDefaultTextureUnit(); + + friend class WebGLStateRestorer; + friend class WebGLRenderingContextEvictionManager; + + static Vector<WebGLRenderingContextBase*>& activeContexts(); + static Vector<WebGLRenderingContextBase*>& forciblyEvictedContexts(); + + static void activateContext(WebGLRenderingContextBase*); + static void deactivateContext(WebGLRenderingContextBase*, bool addToInactiveList); + static void willDestroyContext(WebGLRenderingContextBase*); + static void forciblyLoseOldestContext(const String& reason); + // Return the least recently used context's position in the active context vector. + // If the vector is empty, return the maximum allowed active context number. + static size_t oldestContextIndex(); + static IntSize oldestContextSize(); +}; + +DEFINE_TYPE_CASTS(WebGLRenderingContextBase, CanvasRenderingContext, context, context->is3d(), context.is3d()); + +} // namespace WebCore + +#endif // WebGLRenderingContextBase_h diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContextBase.idl b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContextBase.idl new file mode 100644 index 00000000000..4f0de43de88 --- /dev/null +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLRenderingContextBase.idl @@ -0,0 +1,689 @@ +/* + * Copyright (C) 2009 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 COMPUTER, 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 + * 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. + */ + +// http://www.khronos.org/registry/webgl/specs/latest/1.0/#WebGLRenderingContextBase + +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; + +[ + // FIXME: [DoNotCheckConstants] and [TypeChecking=Interface|Nullable] should be applied + // to members and not need to be put on implementing interface + // DoNotCheckConstants, // need to put on implementing interface + NoInterfaceObject, // Always used on target of 'implements' + // TypeChecking=Interface|Nullable|Unrestricted, // need to put on implementing interface +] interface WebGLRenderingContextBase { + + 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); + // FIXME: should be union type + // https://www.khronos.org/bugzilla/show_bug.cgi?id=1172 + void bufferData(GLenum target, GLsizeiptr size, GLenum usage); + void bufferData(GLenum target, ArrayBufferView data, GLenum usage); + void bufferData(GLenum target, ArrayBuffer? data, GLenum usage); + void bufferSubData(GLenum target, GLintptr offset, ArrayBufferView data); + void bufferSubData(GLenum target, GLintptr offset, ArrayBuffer? 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); + + [Custom] void getAttachedShaders(WebGLProgram? program); + + GLint getAttribLocation(WebGLProgram? program, DOMString name); + + [Custom] any getBufferParameter(GLenum target, GLenum pname); + + WebGLContextAttributes getContextAttributes(); + + GLenum getError(); + + // object getExtension(DOMString name); + [Custom] any getExtension(DOMString name); + + [Custom] any getFramebufferAttachmentParameter(GLenum target, GLenum attachment, GLenum pname); + [Custom] any getParameter(GLenum pname); + [Custom] any getProgramParameter(WebGLProgram? program, GLenum pname); + [TreatReturnedNullStringAs=Null] DOMString getProgramInfoLog(WebGLProgram? program); + [Custom] any getRenderbufferParameter(GLenum target, GLenum pname); + [Custom] any getShaderParameter(WebGLShader? shader, GLenum pname); + + [TreatReturnedNullStringAs=Null] DOMString getShaderInfoLog(WebGLShader? shader); + + WebGLShaderPrecisionFormat getShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype); + + [TreatReturnedNullStringAs=Null] DOMString getShaderSource(WebGLShader? shader); + + [Custom] sequence<DOMString> getSupportedExtensions(); + + [Custom] any getTexParameter(GLenum target, GLenum pname); + + [Custom] any getUniform(WebGLProgram? program, WebGLUniformLocation location); + + WebGLUniformLocation getUniformLocation(WebGLProgram? program, DOMString name); + + [Custom] 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 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: + // FIXME: should be union type + // https://www.khronos.org/bugzilla/show_bug.cgi?id=1172 + [RaisesException] void texImage2D( + GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, ArrayBufferView? pixels); + [RaisesException] void texImage2D( + GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, ImageData? pixels); + [RaisesException] void texImage2D( + GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, HTMLImageElement image); + [RaisesException] void texImage2D( + GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, HTMLCanvasElement canvas); + [RaisesException] void texImage2D( + GLenum target, GLint level, GLenum internalformat, + GLenum format, GLenum type, HTMLVideoElement video); + + [RaisesException] void texSubImage2D( + GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, ArrayBufferView? pixels); + [RaisesException] void texSubImage2D( + GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, ImageData? pixels); + [RaisesException] void texSubImage2D( + GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, HTMLImageElement image); + [RaisesException] void texSubImage2D( + GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, HTMLCanvasElement canvas); + [RaisesException] void texSubImage2D( + GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLenum format, GLenum type, HTMLVideoElement video); + + void uniform1f(WebGLUniformLocation? location, GLfloat x); + [Custom] void uniform1fv(WebGLUniformLocation? location, Float32Array v); + void uniform1i(WebGLUniformLocation? location, GLint x); + [Custom] void uniform1iv(WebGLUniformLocation? location, Int32Array v); + void uniform2f(WebGLUniformLocation? location, GLfloat x, GLfloat y); + [Custom] void uniform2fv(WebGLUniformLocation? location, Float32Array v); + void uniform2i(WebGLUniformLocation? location, GLint x, GLint y); + [Custom] void uniform2iv(WebGLUniformLocation? location, Int32Array v); + void uniform3f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z); + [Custom] void uniform3fv(WebGLUniformLocation? location, Float32Array v); + void uniform3i(WebGLUniformLocation? location, GLint x, GLint y, GLint z); + [Custom] void uniform3iv(WebGLUniformLocation? location, Int32Array v); + void uniform4f(WebGLUniformLocation? location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + [Custom] void uniform4fv(WebGLUniformLocation? location, Float32Array v); + void uniform4i(WebGLUniformLocation? location, GLint x, GLint y, GLint z, GLint w); + [Custom] void uniform4iv(WebGLUniformLocation? location, Int32Array v); + + [Custom] void uniformMatrix2fv(WebGLUniformLocation? location, GLboolean transpose, Float32Array array); + [Custom] void uniformMatrix3fv(WebGLUniformLocation? location, GLboolean transpose, Float32Array array); + [Custom] void uniformMatrix4fv(WebGLUniformLocation? location, GLboolean transpose, Float32Array array); + + void useProgram(WebGLProgram? program); + void validateProgram(WebGLProgram? program); + + void vertexAttrib1f(GLuint indx, GLfloat x); + [Custom] void vertexAttrib1fv(GLuint indx, Float32Array values); + void vertexAttrib2f(GLuint indx, GLfloat x, GLfloat y); + [Custom] void vertexAttrib2fv(GLuint indx, Float32Array values); + void vertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z); + [Custom] void vertexAttrib3fv(GLuint indx, Float32Array values); + void vertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + [Custom] void vertexAttrib4fv(GLuint indx, Float32Array 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/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShader.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShader.cpp index 0920fc9043e..203041e85cf 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShader.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShader.cpp @@ -27,22 +27,22 @@ #include "core/html/canvas/WebGLShader.h" -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -PassRefPtr<WebGLShader> WebGLShader::create(WebGLRenderingContext* ctx, GC3Denum type) +PassRefPtr<WebGLShader> WebGLShader::create(WebGLRenderingContextBase* ctx, GLenum type) { return adoptRef(new WebGLShader(ctx, type)); } -WebGLShader::WebGLShader(WebGLRenderingContext* ctx, GC3Denum type) +WebGLShader::WebGLShader(WebGLRenderingContextBase* ctx, GLenum type) : WebGLSharedObject(ctx) , m_type(type) , m_source("") { ScriptWrappable::init(this); - setObject(ctx->graphicsContext3D()->createShader(type)); + setObject(ctx->webContext()->createShader(type)); } WebGLShader::~WebGLShader() @@ -50,7 +50,7 @@ WebGLShader::~WebGLShader() deleteObject(0); } -void WebGLShader::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object) +void WebGLShader::deleteObjectImpl(blink::WebGraphicsContext3D* context3d, Platform3DObject object) { context3d->deleteShader(object); } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShader.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShader.h index 6c776afc281..2d2fc23be20 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShader.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShader.h @@ -29,28 +29,29 @@ #include "bindings/v8/ScriptWrappable.h" #include "core/html/canvas/WebGLSharedObject.h" #include "wtf/PassRefPtr.h" +#include "wtf/text/WTFString.h" namespace WebCore { -class WebGLShader : public WebGLSharedObject, public ScriptWrappable { +class WebGLShader FINAL : public WebGLSharedObject, public ScriptWrappable { public: virtual ~WebGLShader(); - static PassRefPtr<WebGLShader> create(WebGLRenderingContext*, GC3Denum); + static PassRefPtr<WebGLShader> create(WebGLRenderingContextBase*, GLenum); - GC3Denum type() const { return m_type; } + GLenum type() const { return m_type; } const String& source() const { return m_source; } void setSource(const String& source) { m_source = source; } private: - WebGLShader(WebGLRenderingContext*, GC3Denum); + WebGLShader(WebGLRenderingContextBase*, GLenum); - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject); + virtual void deleteObjectImpl(blink::WebGraphicsContext3D*, Platform3DObject) OVERRIDE; - virtual bool isShader() const { return true; } + virtual bool isShader() const OVERRIDE { return true; } - GC3Denum m_type; + GLenum m_type; String m_source; }; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShaderPrecisionFormat.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShaderPrecisionFormat.cpp index 288468f37ce..8fb4bb1c9af 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShaderPrecisionFormat.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShaderPrecisionFormat.cpp @@ -31,27 +31,27 @@ namespace WebCore { // static -PassRefPtr<WebGLShaderPrecisionFormat> WebGLShaderPrecisionFormat::create(GC3Dint rangeMin, GC3Dint rangeMax, GC3Dint precision) +PassRefPtr<WebGLShaderPrecisionFormat> WebGLShaderPrecisionFormat::create(GLint rangeMin, GLint rangeMax, GLint precision) { return adoptRef(new WebGLShaderPrecisionFormat(rangeMin, rangeMax, precision)); } -GC3Dint WebGLShaderPrecisionFormat::rangeMin() const +GLint WebGLShaderPrecisionFormat::rangeMin() const { return m_rangeMin; } -GC3Dint WebGLShaderPrecisionFormat::rangeMax() const +GLint WebGLShaderPrecisionFormat::rangeMax() const { return m_rangeMax; } -GC3Dint WebGLShaderPrecisionFormat::precision() const +GLint WebGLShaderPrecisionFormat::precision() const { return m_precision; } -WebGLShaderPrecisionFormat::WebGLShaderPrecisionFormat(GC3Dint rangeMin, GC3Dint rangeMax, GC3Dint precision) +WebGLShaderPrecisionFormat::WebGLShaderPrecisionFormat(GLint rangeMin, GLint rangeMax, GLint precision) : m_rangeMin(rangeMin) , m_rangeMax(rangeMax) , m_precision(precision) diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShaderPrecisionFormat.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShaderPrecisionFormat.h index b59acc052a5..bd363bb232b 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShaderPrecisionFormat.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLShaderPrecisionFormat.h @@ -28,7 +28,7 @@ #define WebGLShaderPrecisionFormat_h #include "bindings/v8/ScriptWrappable.h" -#include "platform/graphics/GraphicsContext3D.h" +#include "platform/graphics/GraphicsTypes3D.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" @@ -36,18 +36,18 @@ namespace WebCore { class WebGLShaderPrecisionFormat : public RefCounted<WebGLShaderPrecisionFormat>, public ScriptWrappable { public: - static PassRefPtr<WebGLShaderPrecisionFormat> create(GC3Dint rangeMin, GC3Dint rangeMax, GC3Dint precision); + static PassRefPtr<WebGLShaderPrecisionFormat> create(GLint rangeMin, GLint rangeMax, GLint precision); - GC3Dint rangeMin() const; - GC3Dint rangeMax() const; - GC3Dint precision() const; + GLint rangeMin() const; + GLint rangeMax() const; + GLint precision() const; private: - WebGLShaderPrecisionFormat(GC3Dint rangeMin, GC3Dint rangeMax, GC3Dint precision); + WebGLShaderPrecisionFormat(GLint rangeMin, GLint rangeMax, GLint precision); - GC3Dint m_rangeMin; - GC3Dint m_rangeMax; - GC3Dint m_precision; + GLint m_rangeMin; + GLint m_rangeMax; + GLint m_precision; }; } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLSharedObject.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLSharedObject.cpp index f5d63651ff5..94f1db80baf 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLSharedObject.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLSharedObject.cpp @@ -28,11 +28,11 @@ #include "core/html/canvas/WebGLSharedObject.h" #include "core/html/canvas/WebGLContextGroup.h" -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -WebGLSharedObject::WebGLSharedObject(WebGLRenderingContext* context) +WebGLSharedObject::WebGLSharedObject(WebGLRenderingContextBase* context) : WebGLObject(context), m_contextGroup(context->contextGroup()) { @@ -54,9 +54,9 @@ void WebGLSharedObject::detachContextGroup() } } -GraphicsContext3D* WebGLSharedObject::getAGraphicsContext3D() const +blink::WebGraphicsContext3D* WebGLSharedObject::getAWebGraphicsContext3D() const { - return m_contextGroup ? m_contextGroup->getAGraphicsContext3D() : 0; + return m_contextGroup ? m_contextGroup->getAWebGraphicsContext3D() : 0; } } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLSharedObject.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLSharedObject.h index 6c33471ba7f..990c8ae1565 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLSharedObject.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLSharedObject.h @@ -30,9 +30,8 @@ namespace WebCore { -class GraphicsContext3D; class WebGLContextGroup; -class WebGLRenderingContext; +class WebGLRenderingContextBase; // WebGLSharedObject the base class for objects that can be shared by multiple // WebGLRenderingContexts. @@ -43,13 +42,12 @@ public: 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 + virtual bool validate(const WebGLContextGroup* contextGroup, const WebGLRenderingContextBase*) const OVERRIDE FINAL { return contextGroup == m_contextGroup; } @@ -57,14 +55,14 @@ public: void detachContextGroup(); protected: - WebGLSharedObject(WebGLRenderingContext*); + WebGLSharedObject(WebGLRenderingContextBase*); - virtual bool hasGroupOrContext() const + virtual bool hasGroupOrContext() const OVERRIDE FINAL { return m_contextGroup; } - virtual GraphicsContext3D* getAGraphicsContext3D() const; + virtual blink::WebGraphicsContext3D* getAWebGraphicsContext3D() const OVERRIDE FINAL; private: WebGLContextGroup* m_contextGroup; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLTexture.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLTexture.cpp index 804547e1b0e..292974230ea 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLTexture.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLTexture.cpp @@ -27,16 +27,16 @@ #include "core/html/canvas/WebGLTexture.h" -#include "core/html/canvas/WebGLRenderingContext.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -PassRefPtr<WebGLTexture> WebGLTexture::create(WebGLRenderingContext* ctx) +PassRefPtr<WebGLTexture> WebGLTexture::create(WebGLRenderingContextBase* ctx) { return adoptRef(new WebGLTexture(ctx)); } -WebGLTexture::WebGLTexture(WebGLRenderingContext* ctx) +WebGLTexture::WebGLTexture(WebGLRenderingContextBase* ctx) : WebGLSharedObject(ctx) , m_target(0) , m_minFilter(GL_NEAREST_MIPMAP_LINEAR) @@ -51,7 +51,7 @@ WebGLTexture::WebGLTexture(WebGLRenderingContext* ctx) , m_isHalfFloatType(false) { ScriptWrappable::init(this); - setObject(ctx->graphicsContext3D()->createTexture()); + setObject(ctx->webContext()->createTexture()); } WebGLTexture::~WebGLTexture() @@ -59,7 +59,7 @@ WebGLTexture::~WebGLTexture() deleteObject(0); } -void WebGLTexture::setTarget(GC3Denum target, GC3Dint maxLevel) +void WebGLTexture::setTarget(GLenum target, GLint maxLevel) { if (!object()) return; @@ -81,7 +81,7 @@ void WebGLTexture::setTarget(GC3Denum target, GC3Dint maxLevel) } } -void WebGLTexture::setParameteri(GC3Denum pname, GC3Dint param) +void WebGLTexture::setParameteri(GLenum pname, GLint param) { if (!object() || !m_target) return; @@ -130,15 +130,15 @@ void WebGLTexture::setParameteri(GC3Denum pname, GC3Dint param) update(); } -void WebGLTexture::setParameterf(GC3Denum pname, GC3Dfloat param) +void WebGLTexture::setParameterf(GLenum pname, GLfloat param) { if (!object() || !m_target) return; - GC3Dint iparam = static_cast<GC3Dint>(param); + GLint iparam = static_cast<GLint>(param); setParameteri(pname, iparam); } -void WebGLTexture::setLevelInfo(GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, GC3Denum type) +void WebGLTexture::setLevelInfo(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum type) { if (!object() || !m_target) return; @@ -160,10 +160,10 @@ void WebGLTexture::generateMipmapLevelInfo() if (!m_isComplete) { for (size_t ii = 0; ii < m_info.size(); ++ii) { const LevelInfo& info0 = m_info[ii][0]; - GC3Dsizei width = info0.width; - GC3Dsizei height = info0.height; - GC3Dint levelCount = computeLevelCount(width, height); - for (GC3Dint level = 1; level < levelCount; ++level) { + GLsizei width = info0.width; + GLsizei height = info0.height; + GLint levelCount = computeLevelCount(width, height); + for (GLint level = 1; level < levelCount; ++level) { width = std::max(1, width >> 1); height = std::max(1, height >> 1); LevelInfo& info = m_info[ii][level]; @@ -175,7 +175,7 @@ void WebGLTexture::generateMipmapLevelInfo() m_needToUseBlackTexture = false; } -GC3Denum WebGLTexture::getInternalFormat(GC3Denum target, GC3Dint level) const +GLenum WebGLTexture::getInternalFormat(GLenum target, GLint level) const { const LevelInfo* info = getLevelInfo(target, level); if (!info) @@ -183,7 +183,7 @@ GC3Denum WebGLTexture::getInternalFormat(GC3Denum target, GC3Dint level) const return info->internalFormat; } -GC3Denum WebGLTexture::getType(GC3Denum target, GC3Dint level) const +GLenum WebGLTexture::getType(GLenum target, GLint level) const { const LevelInfo* info = getLevelInfo(target, level); if (!info) @@ -191,7 +191,7 @@ GC3Denum WebGLTexture::getType(GC3Denum target, GC3Dint level) const return info->type; } -GC3Dsizei WebGLTexture::getWidth(GC3Denum target, GC3Dint level) const +GLsizei WebGLTexture::getWidth(GLenum target, GLint level) const { const LevelInfo* info = getLevelInfo(target, level); if (!info) @@ -199,7 +199,7 @@ GC3Dsizei WebGLTexture::getWidth(GC3Denum target, GC3Dint level) const return info->width; } -GC3Dsizei WebGLTexture::getHeight(GC3Denum target, GC3Dint level) const +GLsizei WebGLTexture::getHeight(GLenum target, GLint level) const { const LevelInfo* info = getLevelInfo(target, level); if (!info) @@ -207,7 +207,7 @@ GC3Dsizei WebGLTexture::getHeight(GC3Denum target, GC3Dint level) const return info->height; } -bool WebGLTexture::isValid(GC3Denum target, GC3Dint level) const +bool WebGLTexture::isValid(GLenum target, GLint level) const { const LevelInfo* info = getLevelInfo(target, level); if (!info) @@ -215,7 +215,7 @@ bool WebGLTexture::isValid(GC3Denum target, GC3Dint level) const return info->valid; } -bool WebGLTexture::isNPOT(GC3Dsizei width, GC3Dsizei height) +bool WebGLTexture::isNPOT(GLsizei width, GLsizei height) { ASSERT(width >= 0 && height >= 0); if (!width || !height) @@ -245,12 +245,12 @@ bool WebGLTexture::needToUseBlackTexture(TextureExtensionFlag flag) const return false; } -void WebGLTexture::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object) +void WebGLTexture::deleteObjectImpl(blink::WebGraphicsContext3D* context3d, Platform3DObject object) { context3d->deleteTexture(object); } -int WebGLTexture::mapTargetToIndex(GC3Denum target) const +int WebGLTexture::mapTargetToIndex(GLenum target) const { if (m_target == GL_TEXTURE_2D) { if (target == GL_TEXTURE_2D) @@ -290,17 +290,17 @@ bool WebGLTexture::canGenerateMipmaps() return true; } -GC3Dint WebGLTexture::computeLevelCount(GC3Dsizei width, GC3Dsizei height) +GLint WebGLTexture::computeLevelCount(GLsizei width, GLsizei height) { // return 1 + log2Floor(std::max(width, height)); - GC3Dsizei n = std::max(width, height); + GLsizei n = std::max(width, height); if (n <= 0) return 0; - GC3Dint log = 0; - GC3Dsizei value = n; + GLint log = 0; + GLsizei value = n; for (int ii = 4; ii >= 0; --ii) { int shift = (1 << ii); - GC3Dsizei x = (value >> shift); + GLsizei x = (value >> shift); if (x) { value = x; log += shift; @@ -322,7 +322,7 @@ void WebGLTexture::update() m_isComplete = true; m_isCubeComplete = true; const LevelInfo& first = m_info[0][0]; - GC3Dint levelCount = computeLevelCount(first.width, first.height); + GLint levelCount = computeLevelCount(first.width, first.height); if (levelCount < 1) m_isComplete = false; else { @@ -337,9 +337,9 @@ void WebGLTexture::update() m_isComplete = false; break; } - GC3Dsizei width = info0.width; - GC3Dsizei height = info0.height; - for (GC3Dint level = 1; level < levelCount; ++level) { + GLsizei width = info0.width; + GLsizei height = info0.height; + for (GLint level = 1; level < levelCount; ++level) { width = std::max(1, width >> 1); height = std::max(1, height >> 1); const LevelInfo& info = m_info[ii][level]; @@ -369,14 +369,14 @@ void WebGLTexture::update() m_needToUseBlackTexture = true; } -const WebGLTexture::LevelInfo* WebGLTexture::getLevelInfo(GC3Denum target, GC3Dint level) const +const WebGLTexture::LevelInfo* WebGLTexture::getLevelInfo(GLenum target, GLint level) const { if (!object() || !m_target) return 0; int targetIndex = mapTargetToIndex(target); if (targetIndex < 0 || targetIndex >= static_cast<int>(m_info.size())) return 0; - if (level < 0 || level >= static_cast<GC3Dint>(m_info[targetIndex].size())) + if (level < 0 || level >= static_cast<GLint>(m_info[targetIndex].size())) return 0; return &(m_info[targetIndex][level]); } diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLTexture.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLTexture.h index 67f1fdce86c..bb086c08a10 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLTexture.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLTexture.h @@ -33,7 +33,7 @@ namespace WebCore { -class WebGLTexture : public WebGLSharedObject, public ScriptWrappable { +class WebGLTexture FINAL : public WebGLSharedObject, public ScriptWrappable { public: enum TextureExtensionFlag { NoTextureExtensionEnabled = 0, @@ -42,30 +42,30 @@ public: }; virtual ~WebGLTexture(); - static PassRefPtr<WebGLTexture> create(WebGLRenderingContext*); + static PassRefPtr<WebGLTexture> create(WebGLRenderingContextBase*); - void setTarget(GC3Denum target, GC3Dint maxLevel); - void setParameteri(GC3Denum pname, GC3Dint param); - void setParameterf(GC3Denum pname, GC3Dfloat param); + void setTarget(GLenum target, GLint maxLevel); + void setParameteri(GLenum pname, GLint param); + void setParameterf(GLenum pname, GLfloat param); - GC3Denum getTarget() const { return m_target; } + GLenum getTarget() const { return m_target; } int getMinFilter() const { return m_minFilter; } - void setLevelInfo(GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, GC3Denum type); + void setLevelInfo(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLenum type); bool canGenerateMipmaps(); // Generate all level information. void generateMipmapLevelInfo(); - GC3Denum getInternalFormat(GC3Denum target, GC3Dint level) const; - GC3Denum getType(GC3Denum target, GC3Dint level) const; - GC3Dsizei getWidth(GC3Denum target, GC3Dint level) const; - GC3Dsizei getHeight(GC3Denum target, GC3Dint level) const; - bool isValid(GC3Denum target, GC3Dint level) const; + GLenum getInternalFormat(GLenum target, GLint level) const; + GLenum getType(GLenum target, GLint level) const; + GLsizei getWidth(GLenum target, GLint level) const; + GLsizei getHeight(GLenum target, GLint level) const; + bool isValid(GLenum target, GLint level) const; // Whether width/height is NotPowerOfTwo. - static bool isNPOT(GC3Dsizei, GC3Dsizei); + static bool isNPOT(GLsizei, GLsizei); bool isNPOT() const; // Determine if texture sampling should always return [0, 0, 0, 1] (OpenGL ES 2.0 Sec 3.8.2). @@ -73,12 +73,12 @@ public: bool hasEverBeenBound() const { return object() && m_target; } - static GC3Dint computeLevelCount(GC3Dsizei width, GC3Dsizei height); + static GLint computeLevelCount(GLsizei width, GLsizei height); protected: - WebGLTexture(WebGLRenderingContext*); + WebGLTexture(WebGLRenderingContextBase*); - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject); + virtual void deleteObjectImpl(blink::WebGraphicsContext3D*, Platform3DObject) OVERRIDE; private: class LevelInfo { @@ -92,7 +92,7 @@ private: { } - void setInfo(GC3Denum internalFmt, GC3Dsizei w, GC3Dsizei h, GC3Denum tp) + void setInfo(GLenum internalFmt, GLsizei w, GLsizei h, GLenum tp) { valid = true; internalFormat = internalFmt; @@ -102,26 +102,26 @@ private: } bool valid; - GC3Denum internalFormat; - GC3Dsizei width; - GC3Dsizei height; - GC3Denum type; + GLenum internalFormat; + GLsizei width; + GLsizei height; + GLenum type; }; - virtual bool isTexture() const { return true; } + virtual bool isTexture() const OVERRIDE { return true; } void update(); - int mapTargetToIndex(GC3Denum) const; + int mapTargetToIndex(GLenum) const; - const LevelInfo* getLevelInfo(GC3Denum target, GC3Dint level) const; + const LevelInfo* getLevelInfo(GLenum target, GLint level) const; - GC3Denum m_target; + GLenum m_target; - GC3Denum m_minFilter; - GC3Denum m_magFilter; - GC3Denum m_wrapS; - GC3Denum m_wrapT; + GLenum m_minFilter; + GLenum m_magFilter; + GLenum m_wrapS; + GLenum m_wrapT; Vector<Vector<LevelInfo> > m_info; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLUniformLocation.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLUniformLocation.cpp index 2790c7eb70c..cd1eb95593a 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLUniformLocation.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLUniformLocation.cpp @@ -30,12 +30,12 @@ namespace WebCore { -PassRefPtr<WebGLUniformLocation> WebGLUniformLocation::create(WebGLProgram* program, GC3Dint location) +PassRefPtr<WebGLUniformLocation> WebGLUniformLocation::create(WebGLProgram* program, GLint location) { return adoptRef(new WebGLUniformLocation(program, location)); } -WebGLUniformLocation::WebGLUniformLocation(WebGLProgram* program, GC3Dint location) +WebGLUniformLocation::WebGLUniformLocation(WebGLProgram* program, GLint location) : m_program(program) , m_location(location) { @@ -53,7 +53,7 @@ WebGLProgram* WebGLUniformLocation::program() const return m_program.get(); } -GC3Dint WebGLUniformLocation::location() const +GLint WebGLUniformLocation::location() const { // If the program has been linked again, then this UniformLocation is no // longer valid. diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLUniformLocation.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLUniformLocation.h index 34e0480c126..76e98b3e359 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLUniformLocation.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLUniformLocation.h @@ -36,18 +36,18 @@ namespace WebCore { class WebGLUniformLocation FINAL : public RefCounted<WebGLUniformLocation>, public ScriptWrappable { public: - static PassRefPtr<WebGLUniformLocation> create(WebGLProgram*, GC3Dint location); + static PassRefPtr<WebGLUniformLocation> create(WebGLProgram*, GLint location); WebGLProgram* program() const; - GC3Dint location() const; + GLint location() const; protected: - WebGLUniformLocation(WebGLProgram*, GC3Dint location); + WebGLUniformLocation(WebGLProgram*, GLint location); private: RefPtr<WebGLProgram> m_program; - GC3Dint m_location; + GLint m_location; unsigned m_linkCount; }; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLVertexArrayObjectOES.cpp b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLVertexArrayObjectOES.cpp index 1d54886af8a..6c12bccb704 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLVertexArrayObjectOES.cpp +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLVertexArrayObjectOES.cpp @@ -27,31 +27,29 @@ #include "core/html/canvas/WebGLVertexArrayObjectOES.h" -#include "core/html/canvas/WebGLRenderingContext.h" -#include "platform/graphics/Extensions3D.h" +#include "core/html/canvas/WebGLRenderingContextBase.h" namespace WebCore { -PassRefPtr<WebGLVertexArrayObjectOES> WebGLVertexArrayObjectOES::create(WebGLRenderingContext* ctx, VaoType type) +PassRefPtr<WebGLVertexArrayObjectOES> WebGLVertexArrayObjectOES::create(WebGLRenderingContextBase* ctx, VaoType type) { return adoptRef(new WebGLVertexArrayObjectOES(ctx, type)); } -WebGLVertexArrayObjectOES::WebGLVertexArrayObjectOES(WebGLRenderingContext* ctx, VaoType type) +WebGLVertexArrayObjectOES::WebGLVertexArrayObjectOES(WebGLRenderingContextBase* ctx, VaoType type) : WebGLContextObject(ctx) , m_type(type) , m_hasEverBeenBound(false) - , m_boundElementArrayBuffer(0) + , m_boundElementArrayBuffer(nullptr) { ScriptWrappable::init(this); m_vertexAttribState.resize(ctx->maxVertexAttribs()); - Extensions3D* extensions = context()->graphicsContext3D()->extensions(); switch (m_type) { case VaoTypeDefault: break; default: - setObject(extensions->createVertexArrayOES()); + setObject(context()->webContext()->createVertexArrayOES()); break; } } @@ -61,14 +59,13 @@ WebGLVertexArrayObjectOES::~WebGLVertexArrayObjectOES() deleteObject(0); } -void WebGLVertexArrayObjectOES::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject object) +void WebGLVertexArrayObjectOES::deleteObjectImpl(blink::WebGraphicsContext3D* context3d, Platform3DObject object) { - Extensions3D* extensions = context3d->extensions(); switch (m_type) { case VaoTypeDefault: break; default: - extensions->deleteVertexArrayOES(object); + context()->webContext()->deleteVertexArrayOES(object); break; } @@ -87,22 +84,22 @@ void WebGLVertexArrayObjectOES::setElementArrayBuffer(PassRefPtr<WebGLBuffer> bu if (buffer) buffer->onAttached(); if (m_boundElementArrayBuffer) - m_boundElementArrayBuffer->onDetached(context()->graphicsContext3D()); + m_boundElementArrayBuffer->onDetached(context()->webContext()); m_boundElementArrayBuffer = buffer; } void WebGLVertexArrayObjectOES::setVertexAttribState( - GC3Duint index, GC3Dsizei bytesPerElement, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, GC3Dintptr offset, PassRefPtr<WebGLBuffer> buffer) + GLuint index, GLsizei bytesPerElement, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLintptr offset, PassRefPtr<WebGLBuffer> buffer) { - GC3Dsizei validatedStride = stride ? stride : bytesPerElement; + GLsizei validatedStride = stride ? stride : bytesPerElement; VertexAttribState& state = m_vertexAttribState[index]; if (buffer) buffer->onAttached(); if (state.bufferBinding) - state.bufferBinding->onDetached(context()->graphicsContext3D()); + state.bufferBinding->onDetached(context()->webContext()); state.bufferBinding = buffer; state.bytesPerElement = bytesPerElement; @@ -117,20 +114,20 @@ void WebGLVertexArrayObjectOES::setVertexAttribState( void WebGLVertexArrayObjectOES::unbindBuffer(PassRefPtr<WebGLBuffer> buffer) { if (m_boundElementArrayBuffer == buffer) { - m_boundElementArrayBuffer->onDetached(context()->graphicsContext3D()); - m_boundElementArrayBuffer = 0; + m_boundElementArrayBuffer->onDetached(context()->webContext()); + m_boundElementArrayBuffer = nullptr; } for (size_t i = 0; i < m_vertexAttribState.size(); ++i) { VertexAttribState& state = m_vertexAttribState[i]; if (state.bufferBinding == buffer) { - buffer->onDetached(context()->graphicsContext3D()); - state.bufferBinding = 0; + buffer->onDetached(context()->webContext()); + state.bufferBinding = nullptr; } } } -void WebGLVertexArrayObjectOES::setVertexAttribDivisor(GC3Duint index, GC3Duint divisor) +void WebGLVertexArrayObjectOES::setVertexAttribDivisor(GLuint index, GLuint divisor) { VertexAttribState& state = m_vertexAttribState[index]; state.divisor = divisor; diff --git a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLVertexArrayObjectOES.h b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLVertexArrayObjectOES.h index 8b1fd6ee063..e54ef0a36a9 100644 --- a/chromium/third_party/WebKit/Source/core/html/canvas/WebGLVertexArrayObjectOES.h +++ b/chromium/third_party/WebKit/Source/core/html/canvas/WebGLVertexArrayObjectOES.h @@ -33,7 +33,7 @@ namespace WebCore { -class WebGLVertexArrayObjectOES : public WebGLContextObject, public ScriptWrappable { +class WebGLVertexArrayObjectOES FINAL : public WebGLContextObject, public ScriptWrappable { public: enum VaoType { VaoTypeDefault, @@ -42,7 +42,7 @@ public: virtual ~WebGLVertexArrayObjectOES(); - static PassRefPtr<WebGLVertexArrayObjectOES> create(WebGLRenderingContext*, VaoType); + static PassRefPtr<WebGLVertexArrayObjectOES> create(WebGLRenderingContextBase*, VaoType); // Cached values for vertex attrib range checks struct VertexAttribState { @@ -61,14 +61,14 @@ public: bool enabled; RefPtr<WebGLBuffer> bufferBinding; - GC3Dsizei bytesPerElement; - GC3Dint size; - GC3Denum type; + GLsizei bytesPerElement; + GLint size; + GLenum type; bool normalized; - GC3Dsizei stride; - GC3Dsizei originalStride; - GC3Dintptr offset; - GC3Duint divisor; + GLsizei stride; + GLsizei originalStride; + GLintptr offset; + GLuint divisor; }; bool isDefaultObject() const { return m_type == VaoTypeDefault; } @@ -80,16 +80,14 @@ public: void setElementArrayBuffer(PassRefPtr<WebGLBuffer>); VertexAttribState& getVertexAttribState(int index) { return m_vertexAttribState[index]; } - void setVertexAttribState(GC3Duint, GC3Dsizei, GC3Dint, GC3Denum, GC3Dboolean, GC3Dsizei, GC3Dintptr, PassRefPtr<WebGLBuffer>); + void setVertexAttribState(GLuint, GLsizei, GLint, GLenum, GLboolean, GLsizei, GLintptr, PassRefPtr<WebGLBuffer>); void unbindBuffer(PassRefPtr<WebGLBuffer>); - void setVertexAttribDivisor(GC3Duint index, GC3Duint divisor); + void setVertexAttribDivisor(GLuint index, GLuint divisor); private: - WebGLVertexArrayObjectOES(WebGLRenderingContext*, VaoType); + WebGLVertexArrayObjectOES(WebGLRenderingContextBase*, VaoType); - virtual void deleteObjectImpl(GraphicsContext3D*, Platform3DObject); - - virtual bool isVertexArray() const { return true; } + virtual void deleteObjectImpl(blink::WebGraphicsContext3D*, Platform3DObject) OVERRIDE; VaoType m_type; bool m_hasEverBeenBound; |