diff options
Diffstat (limited to 'Source/WebCore/html/canvas/WebGLRenderingContextBase.h')
-rw-r--r-- | Source/WebCore/html/canvas/WebGLRenderingContextBase.h | 848 |
1 files changed, 848 insertions, 0 deletions
diff --git a/Source/WebCore/html/canvas/WebGLRenderingContextBase.h b/Source/WebCore/html/canvas/WebGLRenderingContextBase.h new file mode 100644 index 000000000..31e5542e6 --- /dev/null +++ b/Source/WebCore/html/canvas/WebGLRenderingContextBase.h @@ -0,0 +1,848 @@ +/* + * Copyright (C) 2015-2017 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if ENABLE(WEBGL) + +#include "ActiveDOMObject.h" +#include "ActivityStateChangeObserver.h" +#include "CanvasRenderingContext.h" +#include "GraphicsContext3D.h" +#include "ImageBuffer.h" +#include "Timer.h" +#include "WebGLAny.h" +#include "WebGLBuffer.h" +#include "WebGLContextAttributes.h" +#include "WebGLFramebuffer.h" +#include "WebGLProgram.h" +#include "WebGLRenderbuffer.h" +#include "WebGLStateTracker.h" +#include "WebGLTexture.h" +#include "WebGLVertexArrayObjectOES.h" +#include <memory> + +#if ENABLE(WEBGL2) +#include "WebGLVertexArrayObject.h" +#endif + +namespace WebCore { + +class ANGLEInstancedArrays; +class EXTBlendMinMax; +class EXTTextureFilterAnisotropic; +class EXTShaderTextureLOD; +class EXTsRGB; +class EXTFragDepth; +class HTMLImageElement; +class HTMLVideoElement; +class ImageData; +class IntSize; +class OESStandardDerivatives; +class OESTextureFloat; +class OESTextureFloatLinear; +class OESTextureHalfFloat; +class OESTextureHalfFloatLinear; +class OESVertexArrayObject; +class OESElementIndexUint; +class WebGLActiveInfo; +class WebGLContextGroup; +class WebGLContextObject; +class WebGLCompressedTextureATC; +class WebGLCompressedTexturePVRTC; +class WebGLCompressedTextureS3TC; +class WebGLDebugRendererInfo; +class WebGLDebugShaders; +class WebGLDepthTexture; +class WebGLDrawBuffers; +class WebGLExtension; +class WebGLLoseContext; +class WebGLObject; +class WebGLShader; +class WebGLSharedObject; +class WebGLShaderPrecisionFormat; +class WebGLUniformLocation; + +inline void clip1D(GC3Dint start, GC3Dsizei range, GC3Dsizei sourceRange, GC3Dint* clippedStart, GC3Dsizei* clippedRange) +{ + ASSERT(clippedStart && clippedRange); + if (start < 0) { + range += start; + start = 0; + } + GC3Dint end = start + range; + if (end > sourceRange) + range -= end - sourceRange; + *clippedStart = start; + *clippedRange = range; +} + +// Returns false if no clipping is necessary, i.e., x, y, width, height stay the same. +inline bool clip2D(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, + GC3Dsizei sourceWidth, GC3Dsizei sourceHeight, + GC3Dint* clippedX, GC3Dint* clippedY, GC3Dsizei* clippedWidth, GC3Dsizei*clippedHeight) +{ + ASSERT(clippedX && clippedY && clippedWidth && clippedHeight); + clip1D(x, width, sourceWidth, clippedX, clippedWidth); + clip1D(y, height, sourceHeight, clippedY, clippedHeight); + return (*clippedX != x || *clippedY != y || *clippedWidth != width || *clippedHeight != height); +} + +class WebGLRenderingContextBase : public CanvasRenderingContext, private ActivityStateChangeObserver, public ActiveDOMObject { +public: + static std::unique_ptr<WebGLRenderingContextBase> create(HTMLCanvasElement&, WebGLContextAttributes&, const String&); + virtual ~WebGLRenderingContextBase(); + +#if PLATFORM(WIN) + // FIXME: Implement accelerated 3d canvas on Windows. + bool isAccelerated() const override { return false; } +#else + bool isAccelerated() const override { return true; } +#endif + + int drawingBufferWidth() const; + int drawingBufferHeight() const; + + void activeTexture(GC3Denum texture); + void attachShader(WebGLProgram*, WebGLShader*); + void bindAttribLocation(WebGLProgram*, GC3Duint index, const String& name); + void bindBuffer(GC3Denum target, WebGLBuffer*); + void bindFramebuffer(GC3Denum target, WebGLFramebuffer*); + void bindRenderbuffer(GC3Denum target, WebGLRenderbuffer*); + void bindTexture(GC3Denum target, WebGLTexture*); + void blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha); + void blendEquation(GC3Denum mode); + void blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha); + void blendFunc(GC3Denum sfactor, GC3Denum dfactor); + void blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha); + + using BufferDataSource = WTF::Variant<RefPtr<ArrayBuffer>, RefPtr<ArrayBufferView>>; + void bufferData(GC3Denum target, long long size, GC3Denum usage); + void bufferData(GC3Denum target, std::optional<BufferDataSource>&&, GC3Denum usage); + void bufferSubData(GC3Denum target, long long offset, std::optional<BufferDataSource>&&); + + GC3Denum checkFramebufferStatus(GC3Denum target); + virtual void clear(GC3Dbitfield mask) = 0; + void clearColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha); + void clearDepth(GC3Dfloat); + void clearStencil(GC3Dint); + void colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha); + void compileShader(WebGLShader*); + + void compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, ArrayBufferView& data); + void compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView& data); + + void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border); + void copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height); + + RefPtr<WebGLBuffer> createBuffer(); + RefPtr<WebGLFramebuffer> createFramebuffer(); + RefPtr<WebGLProgram> createProgram(); + RefPtr<WebGLRenderbuffer> createRenderbuffer(); + RefPtr<WebGLShader> createShader(GC3Denum type); + RefPtr<WebGLTexture> createTexture(); + + void cullFace(GC3Denum mode); + + void deleteBuffer(WebGLBuffer*); + void deleteFramebuffer(WebGLFramebuffer*); + void deleteProgram(WebGLProgram*); + void deleteRenderbuffer(WebGLRenderbuffer*); + void deleteShader(WebGLShader*); + void deleteTexture(WebGLTexture*); + + void depthFunc(GC3Denum); + void depthMask(GC3Dboolean); + void depthRange(GC3Dfloat zNear, GC3Dfloat zFar); + void detachShader(WebGLProgram*, WebGLShader*); + void disable(GC3Denum cap); + void disableVertexAttribArray(GC3Duint index); + void drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count); + void drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset); + + void enable(GC3Denum cap); + void enableVertexAttribArray(GC3Duint index); + void finish(); + void flush(); + void framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer*); + void framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture*, GC3Dint level); + void frontFace(GC3Denum mode); + void generateMipmap(GC3Denum target); + + RefPtr<WebGLActiveInfo> getActiveAttrib(WebGLProgram*, GC3Duint index); + RefPtr<WebGLActiveInfo> getActiveUniform(WebGLProgram*, GC3Duint index); + std::optional<Vector<RefPtr<WebGLShader>>> getAttachedShaders(WebGLProgram*); + GC3Dint getAttribLocation(WebGLProgram*, const String& name); + WebGLAny getBufferParameter(GC3Denum target, GC3Denum pname); + std::optional<WebGLContextAttributes> getContextAttributes(); + GC3Denum getError(); + virtual WebGLExtension* getExtension(const String& name) = 0; + virtual WebGLAny getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname) = 0; + virtual WebGLAny getParameter(GC3Denum pname) = 0; + WebGLAny getProgramParameter(WebGLProgram*, GC3Denum pname); + String getProgramInfoLog(WebGLProgram*); + WebGLAny getRenderbufferParameter(GC3Denum target, GC3Denum pname); + WebGLAny getShaderParameter(WebGLShader*, GC3Denum pname); + String getShaderInfoLog(WebGLShader*); + RefPtr<WebGLShaderPrecisionFormat> getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType); + String getShaderSource(WebGLShader*); + virtual std::optional<Vector<String>> getSupportedExtensions() = 0; + WebGLAny getTexParameter(GC3Denum target, GC3Denum pname); + WebGLAny getUniform(WebGLProgram*, const WebGLUniformLocation*); + RefPtr<WebGLUniformLocation> getUniformLocation(WebGLProgram*, const String&); + WebGLAny getVertexAttrib(GC3Duint index, GC3Denum pname); + long long getVertexAttribOffset(GC3Duint index, GC3Denum pname); + + virtual void hint(GC3Denum target, GC3Denum mode) = 0; + GC3Dboolean isBuffer(WebGLBuffer*); + bool isContextLost() const; + GC3Dboolean isEnabled(GC3Denum cap); + GC3Dboolean isFramebuffer(WebGLFramebuffer*); + GC3Dboolean isProgram(WebGLProgram*); + GC3Dboolean isRenderbuffer(WebGLRenderbuffer*); + GC3Dboolean isShader(WebGLShader*); + GC3Dboolean isTexture(WebGLTexture*); + + void lineWidth(GC3Dfloat); + void linkProgram(WebGLProgram*); + void pixelStorei(GC3Denum pname, GC3Dint param); + void polygonOffset(GC3Dfloat factor, GC3Dfloat units); + void readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView& pixels); + void releaseShaderCompiler(); + virtual void renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) = 0; + void sampleCoverage(GC3Dfloat value, GC3Dboolean invert); + void scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height); + void shaderSource(WebGLShader*, const String&); + void stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask); + void stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask); + void stencilMask(GC3Duint); + void stencilMaskSeparate(GC3Denum face, GC3Duint mask); + void stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass); + void stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass); + + void texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&&); + + using TexImageSource = WTF::Variant<RefPtr<ImageData>, RefPtr<HTMLImageElement>, RefPtr<HTMLCanvasElement>, RefPtr<HTMLVideoElement>>; + ExceptionOr<void> texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, std::optional<TexImageSource>); + + void texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param); + void texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param); + + void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, RefPtr<ArrayBufferView>&&); + ExceptionOr<void> texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, std::optional<TexImageSource>&&); + + template <class TypedArray, class DataType> + class TypedList { + public: + using VariantType = Variant<RefPtr<TypedArray>, Vector<DataType>>; + + TypedList(VariantType&& variant) + : m_variant(WTFMove(variant)) + { + } + + DataType* data() const + { + return WTF::switchOn(m_variant, + [] (const RefPtr<TypedArray>& typedArray) -> DataType* { return typedArray->data(); }, + [] (const Vector<DataType>& vector) -> DataType* { return const_cast<Vector<DataType>&>(vector).data(); } + ); + } + + GC3Dsizei length() const + { + return WTF::switchOn(m_variant, + [] (const RefPtr<TypedArray>& typedArray) -> GC3Dsizei { return typedArray->length(); }, + [] (const Vector<DataType>& vector) -> GC3Dsizei { return vector.size(); } + ); + } + + private: + VariantType m_variant; + }; + + using Float32List = TypedList<Float32Array, float>; + using Int32List = TypedList<Int32Array, int>; + + void uniform1f(const WebGLUniformLocation*, GC3Dfloat x); + void uniform2f(const WebGLUniformLocation*, GC3Dfloat x, GC3Dfloat y); + void uniform3f(const WebGLUniformLocation*, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z); + void uniform4f(const WebGLUniformLocation*, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w); + + void uniform1i(const WebGLUniformLocation*, GC3Dint x); + void uniform2i(const WebGLUniformLocation*, GC3Dint x, GC3Dint y); + void uniform3i(const WebGLUniformLocation*, GC3Dint x, GC3Dint y, GC3Dint z); + void uniform4i(const WebGLUniformLocation*, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w); + + void uniform1fv(const WebGLUniformLocation*, Float32List&&); + void uniform2fv(const WebGLUniformLocation*, Float32List&&); + void uniform3fv(const WebGLUniformLocation*, Float32List&&); + void uniform4fv(const WebGLUniformLocation*, Float32List&&); + + void uniform1iv(const WebGLUniformLocation*, Int32List&&); + void uniform2iv(const WebGLUniformLocation*, Int32List&&); + void uniform3iv(const WebGLUniformLocation*, Int32List&&); + void uniform4iv(const WebGLUniformLocation*, Int32List&&); + + void uniformMatrix2fv(const WebGLUniformLocation*, GC3Dboolean transpose, Float32List&&); + void uniformMatrix3fv(const WebGLUniformLocation*, GC3Dboolean transpose, Float32List&&); + void uniformMatrix4fv(const WebGLUniformLocation*, GC3Dboolean transpose, Float32List&&); + + void useProgram(WebGLProgram*); + void validateProgram(WebGLProgram*); + + void vertexAttrib1f(GC3Duint index, GC3Dfloat x); + void vertexAttrib2f(GC3Duint index, GC3Dfloat x, GC3Dfloat y); + void vertexAttrib3f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z); + void vertexAttrib4f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w); + + void vertexAttrib1fv(GC3Duint index, Float32List&&); + void vertexAttrib2fv(GC3Duint index, Float32List&&); + void vertexAttrib3fv(GC3Duint index, Float32List&&); + void vertexAttrib4fv(GC3Duint index, Float32List&&); + + void vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, + GC3Dsizei stride, long long offset); + + void viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height); + + // WEBKIT_lose_context support + enum LostContextMode { + // Lost context occurred at the graphics system level. + RealLostContext, + + // Lost context provoked by WEBKIT_lose_context. + SyntheticLostContext + }; + void forceLostContext(LostContextMode); + void recycleContext(); + void forceRestoreContext(); + void loseContextImpl(LostContextMode); + + GraphicsContext3D* graphicsContext3D() const { return m_context.get(); } + WebGLContextGroup* contextGroup() const { return m_contextGroup.get(); } + PlatformLayer* platformLayer() const override; + + void reshape(int width, int height); + + void markLayerComposited(); + void paintRenderingResultsToCanvas() override; + RefPtr<ImageData> paintRenderingResultsToImageData(); + + void removeSharedObject(WebGLSharedObject&); + void removeContextObject(WebGLContextObject&); + + unsigned getMaxVertexAttribs() const { return m_maxVertexAttribs; } + + // Instanced Array helper functions. + void drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount); + void drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount); + void vertexAttribDivisor(GC3Duint index, GC3Duint divisor); + +protected: + WebGLRenderingContextBase(HTMLCanvasElement&, WebGLContextAttributes); + WebGLRenderingContextBase(HTMLCanvasElement&, Ref<GraphicsContext3D>&&, WebGLContextAttributes); + + friend class WebGLDrawBuffers; + friend class WebGLFramebuffer; + friend class WebGLObject; + friend class OESVertexArrayObject; + friend class WebGLDebugShaders; + friend class WebGLCompressedTextureATC; + friend class WebGLCompressedTexturePVRTC; + friend class WebGLCompressedTextureS3TC; + friend class WebGLRenderingContextErrorMessageCallback; + friend class WebGLVertexArrayObjectOES; + friend class WebGLVertexArrayObject; + friend class WebGLVertexArrayObjectBase; + + virtual void initializeNewContext(); + virtual void initializeVertexArrayObjects() = 0; + void setupFlags(); + + // ActiveDOMObject + bool hasPendingActivity() const override; + void stop() override; + const char* activeDOMObjectName() const override; + bool canSuspendForDocumentSuspension() const override; + + void addSharedObject(WebGLSharedObject&); + void addContextObject(WebGLContextObject&); + void detachAndRemoveAllObjects(); + + void destroyGraphicsContext3D(); + void markContextChanged(); + + void addActivityStateChangeObserverIfNecessary(); + void removeActivityStateChangeObserver(); + + // Query whether it is built on top of compliant GLES2 implementation. + bool isGLES2Compliant() { return m_isGLES2Compliant; } + // Query if the GL implementation is NPOT strict. + bool isGLES2NPOTStrict() { return m_isGLES2NPOTStrict; } + // Query if depth_stencil buffer is supported. + bool isDepthStencilSupported() { return m_isDepthStencilSupported; } + + // Helper to return the size in bytes of OpenGL data types + // like GL_FLOAT, GL_INT, etc. + unsigned int sizeInBytes(GC3Denum type); + + // Basic validation of count and offset against number of elements in element array buffer + bool validateElementArraySize(GC3Dsizei count, GC3Denum type, GC3Dintptr offset); + + // Conservative but quick index validation + virtual bool validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired) = 0; + + // Precise but slow index validation -- only done if conservative checks fail + bool validateIndexArrayPrecise(GC3Dsizei count, GC3Denum type, GC3Dintptr offset, unsigned& numElementsRequired); + bool validateVertexAttributes(unsigned elementCount, unsigned primitiveCount = 0); + + bool validateWebGLObject(const char*, WebGLObject*); + + bool validateDrawArrays(const char* functionName, GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount); + bool validateDrawElements(const char* functionName, GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, unsigned& numElements, GC3Dsizei primcount); + bool validateNPOTTextureLevel(GC3Dsizei width, GC3Dsizei height, GC3Dint level, const char* functionName); + + // Adds a compressed texture format. + void addCompressedTextureFormat(GC3Denum); + + RefPtr<Image> drawImageIntoBuffer(Image&, int width, int height, int deviceScaleFactor); + +#if ENABLE(VIDEO) + RefPtr<Image> videoFrameToImage(HTMLVideoElement*, BackingStoreCopy); +#endif + + WebGLTexture::TextureExtensionFlag textureExtensionFlags() const; + + bool enableSupportedExtension(const char* extensionNameLiteral); + + RefPtr<GraphicsContext3D> m_context; + RefPtr<WebGLContextGroup> m_contextGroup; + + // Dispatches a context lost event once it is determined that one is needed. + // This is used both for synthetic and real context losses. For real ones, it's + // likely that there's no JavaScript on the stack, but that might be dependent + // on how exactly the platform discovers that the context was lost. For better + // portability we always defer the dispatch of the event. + Timer m_dispatchContextLostEventTimer; + bool m_restoreAllowed { false }; + Timer m_restoreTimer; + + bool m_needsUpdate; + bool m_markedCanvasDirty; + HashSet<WebGLContextObject*> m_contextObjects; + + // List of bound VBO's. Used to maintain info about sizes for ARRAY_BUFFER and stored values for ELEMENT_ARRAY_BUFFER + RefPtr<WebGLBuffer> m_boundArrayBuffer; + RefPtr<WebGLBuffer> m_boundCopyReadBuffer; + RefPtr<WebGLBuffer> m_boundCopyWriteBuffer; + RefPtr<WebGLBuffer> m_boundPixelPackBuffer; + RefPtr<WebGLBuffer> m_boundPixelUnpackBuffer; + RefPtr<WebGLBuffer> m_boundTransformFeedbackBuffer; + RefPtr<WebGLBuffer> m_boundUniformBuffer; + + RefPtr<WebGLVertexArrayObjectBase> m_defaultVertexArrayObject; + RefPtr<WebGLVertexArrayObjectBase> m_boundVertexArrayObject; + + void setBoundVertexArrayObject(WebGLVertexArrayObjectBase* arrayObject) + { + m_boundVertexArrayObject = arrayObject ? arrayObject : m_defaultVertexArrayObject; + } + + class VertexAttribValue { + public: + VertexAttribValue() + { + initValue(); + } + + void initValue() + { + value[0] = 0.0f; + value[1] = 0.0f; + value[2] = 0.0f; + value[3] = 1.0f; + } + + GC3Dfloat value[4]; + }; + Vector<VertexAttribValue> m_vertexAttribValue; + unsigned m_maxVertexAttribs; + RefPtr<WebGLBuffer> m_vertexAttrib0Buffer; + long m_vertexAttrib0BufferSize; + GC3Dfloat m_vertexAttrib0BufferValue[4]; + bool m_forceAttrib0BufferRefill; + bool m_vertexAttrib0UsedBefore; + + RefPtr<WebGLProgram> m_currentProgram; + RefPtr<WebGLFramebuffer> m_framebufferBinding; + RefPtr<WebGLRenderbuffer> m_renderbufferBinding; + struct TextureUnitState { + RefPtr<WebGLTexture> texture2DBinding; + RefPtr<WebGLTexture> textureCubeMapBinding; + }; + Vector<TextureUnitState> m_textureUnits; + HashSet<unsigned, DefaultHash<unsigned>::Hash, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> m_unrenderableTextureUnits; + + unsigned long m_activeTextureUnit; + + RefPtr<WebGLTexture> m_blackTexture2D; + RefPtr<WebGLTexture> m_blackTextureCubeMap; + + Vector<GC3Denum> m_compressedTextureFormats; + + // Fixed-size cache of reusable image buffers for video texImage2D calls. + class LRUImageBufferCache { + public: + LRUImageBufferCache(int capacity); + // The pointer returned is owned by the image buffer map. + ImageBuffer* imageBuffer(const IntSize& size); + private: + void bubbleToFront(int idx); + std::unique_ptr<std::unique_ptr<ImageBuffer>[]> m_buffers; + int m_capacity; + }; + LRUImageBufferCache m_generatedImageCache { 0 }; + + GC3Dint m_maxTextureSize; + GC3Dint m_maxCubeMapTextureSize; + GC3Dint m_maxRenderbufferSize; + GC3Dint m_maxViewportDims[2] { 0, 0 }; + GC3Dint m_maxTextureLevel; + GC3Dint m_maxCubeMapTextureLevel; + + GC3Dint m_maxDrawBuffers; + GC3Dint m_maxColorAttachments; + GC3Denum m_backDrawBuffer; + bool m_drawBuffersWebGLRequirementsChecked; + bool m_drawBuffersSupported; + + GC3Dint m_packAlignment; + GC3Dint m_unpackAlignment; + bool m_unpackFlipY; + bool m_unpackPremultiplyAlpha; + GC3Denum m_unpackColorspaceConversion; + bool m_contextLost { false }; + LostContextMode m_contextLostMode { SyntheticLostContext }; + WebGLContextAttributes m_attributes; + + bool m_layerCleared; + GC3Dfloat m_clearColor[4]; + bool m_scissorEnabled; + GC3Dfloat m_clearDepth; + GC3Dint m_clearStencil; + GC3Dboolean m_colorMask[4]; + GC3Dboolean m_depthMask; + + bool m_stencilEnabled; + GC3Duint m_stencilMask, m_stencilMaskBack; + GC3Dint m_stencilFuncRef, m_stencilFuncRefBack; // Note that these are the user specified values, not the internal clamped value. + GC3Duint m_stencilFuncMask, m_stencilFuncMaskBack; + + bool m_isGLES2Compliant; + bool m_isGLES2NPOTStrict; + bool m_isDepthStencilSupported; + bool m_isRobustnessEXTSupported; + + bool m_synthesizedErrorsToConsole { true }; + int m_numGLErrorsToConsoleAllowed; + + // A WebGLRenderingContext can be created in a state where it appears as + // a valid and active context, but will not execute any important operations + // until its load policy is completely resolved. + bool m_isPendingPolicyResolution { false }; + bool m_hasRequestedPolicyResolution { false }; + bool isContextLostOrPending(); + + // Enabled extension objects. + // FIXME: Move some of these to WebGLRenderingContext, the ones not needed for WebGL2 + std::unique_ptr<EXTFragDepth> m_extFragDepth; + std::unique_ptr<EXTBlendMinMax> m_extBlendMinMax; + std::unique_ptr<EXTsRGB> m_extsRGB; + std::unique_ptr<EXTTextureFilterAnisotropic> m_extTextureFilterAnisotropic; + std::unique_ptr<EXTShaderTextureLOD> m_extShaderTextureLOD; + std::unique_ptr<OESTextureFloat> m_oesTextureFloat; + std::unique_ptr<OESTextureFloatLinear> m_oesTextureFloatLinear; + std::unique_ptr<OESTextureHalfFloat> m_oesTextureHalfFloat; + std::unique_ptr<OESTextureHalfFloatLinear> m_oesTextureHalfFloatLinear; + std::unique_ptr<OESStandardDerivatives> m_oesStandardDerivatives; + std::unique_ptr<OESVertexArrayObject> m_oesVertexArrayObject; + std::unique_ptr<OESElementIndexUint> m_oesElementIndexUint; + std::unique_ptr<WebGLLoseContext> m_webglLoseContext; + std::unique_ptr<WebGLDebugRendererInfo> m_webglDebugRendererInfo; + std::unique_ptr<WebGLDebugShaders> m_webglDebugShaders; + std::unique_ptr<WebGLCompressedTextureATC> m_webglCompressedTextureATC; + std::unique_ptr<WebGLCompressedTexturePVRTC> m_webglCompressedTexturePVRTC; + std::unique_ptr<WebGLCompressedTextureS3TC> m_webglCompressedTextureS3TC; + std::unique_ptr<WebGLDepthTexture> m_webglDepthTexture; + std::unique_ptr<WebGLDrawBuffers> m_webglDrawBuffers; + std::unique_ptr<ANGLEInstancedArrays> m_angleInstancedArrays; + + // Helpers for getParameter and other similar functions. + bool getBooleanParameter(GC3Denum); + Vector<bool> getBooleanArrayParameter(GC3Denum); + float getFloatParameter(GC3Denum); + int getIntParameter(GC3Denum); + unsigned getUnsignedIntParameter(GC3Denum); + long long getInt64Parameter(GC3Denum); + RefPtr<Float32Array> getWebGLFloatArrayParameter(GC3Denum); + RefPtr<Int32Array> getWebGLIntArrayParameter(GC3Denum); + + // Clear the backbuffer if it was composited since the last operation. + // clearMask is set to the bitfield of any clear that would happen anyway at this time + // and the function returns true if that clear is now unnecessary. + bool clearIfComposited(GC3Dbitfield clearMask = 0); + + // Helper to restore state that clearing the framebuffer may destroy. + void restoreStateAfterClear(); + + void texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels); + void texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha); + void texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum internalformat, GC3Denum format, GC3Denum type, const void* pixels); + void texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Denum format, GC3Denum type, Image*, GraphicsContext3D::ImageHtmlDomSource, bool flipY, bool premultiplyAlpha); + + bool checkTextureCompleteness(const char*, bool); + + void createFallbackBlackTextures1x1(); + + // Helper function for copyTex{Sub}Image, check whether the internalformat + // and the color buffer format of the current bound framebuffer combination + // is valid. + bool isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat, + GC3Denum colorBufferFormat); + + // Helper function to get the bound framebuffer's color buffer format. + GC3Denum getBoundFramebufferColorFormat(); + + // Helper function to get the bound framebuffer's width. + int getBoundFramebufferWidth(); + + // Helper function to get the bound framebuffer's height. + int getBoundFramebufferHeight(); + + // Helper function to verify limits on the length of uniform and attribute locations. + bool validateLocationLength(const char* functionName, const String&); + + // Helper function to check if size is non-negative. + // Generate GL error and return false for negative inputs; otherwise, return true. + bool validateSize(const char* functionName, GC3Dint x, GC3Dint y); + + // Helper function to check if all characters in the string belong to the + // ASCII subset as defined in GLSL ES 1.0 spec section 3.1. + bool validateString(const char* functionName, const String&); + + // Helper function to check target and texture bound to the target. + // Generate GL errors and return 0 if target is invalid or texture bound is + // null. Otherwise, return the texture bound to the target. + WebGLTexture* validateTextureBinding(const char* functionName, GC3Denum target, bool useSixEnumsForCubeMap); + + // Helper function to check input format/type for functions {copy}Tex{Sub}Image. + // Generates GL error and returns false if parameters are invalid. + bool validateTexFuncFormatAndType(const char* functionName, GC3Denum internalformat, GC3Denum format, GC3Denum type, GC3Dint level); + + // Helper function to check input level for functions {copy}Tex{Sub}Image. + // Generates GL error and returns false if level is invalid. + bool validateTexFuncLevel(const char* functionName, GC3Denum target, GC3Dint level); + + enum TexFuncValidationFunctionType { + TexImage, + TexSubImage, + CopyTexImage + }; + + enum TexFuncValidationSourceType { + SourceArrayBufferView, + SourceImageData, + SourceHTMLImageElement, + SourceHTMLCanvasElement, + SourceHTMLVideoElement, + }; + + // Helper function for tex{Sub}Image2D to check if the input format/type/level/target/width/height/border/xoffset/yoffset are valid. + // Otherwise, it would return quickly without doing other work. + bool validateTexFunc(const char* functionName, TexFuncValidationFunctionType, TexFuncValidationSourceType, GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, + GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint xoffset, GC3Dint yoffset); + + // Helper function to check input parameters for functions {copy}Tex{Sub}Image. + // Generates GL error and returns false if parameters are invalid. + bool validateTexFuncParameters(const char* functionName, + TexFuncValidationFunctionType, + GC3Denum target, GC3Dint level, + GC3Denum internalformat, + GC3Dsizei width, GC3Dsizei height, GC3Dint border, + GC3Denum format, GC3Denum type); + + enum NullDisposition { + NullAllowed, + NullNotAllowed + }; + + // Helper function to validate that the given ArrayBufferView + // is of the correct type and contains enough data for the texImage call. + // Generates GL error and returns false if parameters are invalid. + bool validateTexFuncData(const char* functionName, GC3Dint level, + GC3Dsizei width, GC3Dsizei height, + GC3Denum internalformat, GC3Denum format, GC3Denum type, + ArrayBufferView* pixels, + NullDisposition); + + // Helper function to validate a given texture format is settable as in + // you can supply data to texImage2D, or call texImage2D, copyTexImage2D and + // copyTexSubImage2D. + // Generates GL error and returns false if the format is not settable. + bool validateSettableTexInternalFormat(const char* functionName, GC3Denum format); + + // Helper function to validate compressed texture data is correct size + // for the given format and dimensions. + bool validateCompressedTexFuncData(const char* functionName, GC3Dsizei width, GC3Dsizei height, GC3Denum format, ArrayBufferView& pixels); + + // Helper function for validating compressed texture formats. + bool validateCompressedTexFormat(GC3Denum format); + + // Helper function to validate compressed texture dimensions are valid for + // the given format. + bool validateCompressedTexDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dsizei width, GC3Dsizei height, GC3Denum format); + + // Helper function to validate compressed texture dimensions are valid for + // the given format. + bool validateCompressedTexSubDimensions(const char* functionName, GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, + GC3Dsizei width, GC3Dsizei height, GC3Denum format, WebGLTexture*); + + // Helper function to validate mode for draw{Arrays/Elements}. + bool validateDrawMode(const char* functionName, GC3Denum); + + // Helper function to validate if front/back stencilMask and stencilFunc settings are the same. + bool validateStencilSettings(const char* functionName); + + // Helper function to validate stencil func. + bool validateStencilFunc(const char* functionName, GC3Denum); + + // Helper function for texParameterf and texParameteri. + void texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat parami, GC3Dint paramf, bool isFloat); + + // Helper function to print GL errors to console. + void printGLErrorToConsole(const String&); + void printGLWarningToConsole(const char* function, const char* reason); + + // Helper function to print warnings to console. Currently + // used only to warn about use of obsolete functions. + void printWarningToConsole(const String&); + + // Helper function to validate input parameters for framebuffer functions. + // Generate GL error if parameters are illegal. + virtual bool validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment) = 0; + + // Helper function to validate blend equation mode. + virtual bool validateBlendEquation(const char* functionName, GC3Denum) = 0; + + // Helper function to validate blend func factors. + bool validateBlendFuncFactors(const char* functionName, GC3Denum src, GC3Denum dst); + + // Helper function to validate a GL capability. + virtual bool validateCapability(const char* functionName, GC3Denum) = 0; + + // Helper function to validate input parameters for uniform functions. + bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, const Float32List&, GC3Dsizei mod); + bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, const Int32List&, GC3Dsizei mod); + bool validateUniformParameters(const char* functionName, const WebGLUniformLocation*, void*, GC3Dsizei, GC3Dsizei mod); + bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GC3Dboolean transpose, const Float32List&, GC3Dsizei mod); + bool validateUniformMatrixParameters(const char* functionName, const WebGLUniformLocation*, GC3Dboolean transpose, void*, GC3Dsizei, GC3Dsizei mod); + + // Helper function to validate parameters for bufferData. + // Return the current bound buffer to target, or 0 if parameters are invalid. + WebGLBuffer* validateBufferDataParameters(const char* functionName, GC3Denum target, GC3Denum usage); + + // Helper function for tex{Sub}Image2D to make sure image is ready. + bool validateHTMLImageElement(const char* functionName, HTMLImageElement*, ExceptionCode&); + bool validateHTMLCanvasElement(const char* functionName, HTMLCanvasElement*, ExceptionCode&); +#if ENABLE(VIDEO) + bool validateHTMLVideoElement(const char* functionName, HTMLVideoElement*, ExceptionCode&); +#endif + + // Helper functions for vertexAttribNf{v}. + void vertexAttribfImpl(const char* functionName, GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat, GC3Dfloat, GC3Dfloat, GC3Dfloat); + void vertexAttribfvImpl(const char* functionName, GC3Duint index, Float32List&&, GC3Dsizei expectedSize); + + // Helper function for delete* (deleteBuffer, deleteProgram, etc) functions. + // Return false if caller should return without further processing. + bool deleteObject(WebGLObject*); + + // Helper function for bind* (bindBuffer, bindTexture, etc) and useProgram. + // If the object has already been deleted, set deleted to true upon return. + // Return false if caller should return without further processing. + bool checkObjectToBeBound(const char* functionName, WebGLObject*, bool& deleted); + + // Helpers for simulating vertexAttrib0. + void initVertexAttrib0(); + bool simulateVertexAttrib0(GC3Dsizei numVertex); + bool validateSimulatedVertexAttrib0(GC3Dsizei numVertex); + void restoreStatesAfterVertexAttrib0Simulation(); + + void dispatchContextLostEvent(); + // Helper for restoration after context lost. + void maybeRestoreContext(); + + // Wrapper for GraphicsContext3D::synthesizeGLError that sends a message to the JavaScript console. + enum ConsoleDisplayPreference { DisplayInConsole, DontDisplayInConsole }; + void synthesizeGLError(GC3Denum, const char* functionName, const char* description, ConsoleDisplayPreference = DisplayInConsole); + + String ensureNotNull(const String&) const; + + // Enable or disable stencil test based on user setting and whether the current FBO has a stencil buffer. + void applyStencilTest(); + + // Helper for enabling or disabling a capability. + void enableOrDisable(GC3Denum capability, bool enable); + + // Clamp the width and height to GL_MAX_VIEWPORT_DIMS. + IntSize clampedCanvasSize(); + + virtual GC3Dint getMaxDrawBuffers() = 0; + virtual GC3Dint getMaxColorAttachments() = 0; + + void setBackDrawBuffer(GC3Denum); + + void restoreCurrentFramebuffer(); + void restoreCurrentTexture2D(); + + // Check if EXT_draw_buffers extension is supported and if it satisfies the WebGL requirements. + bool supportsDrawBuffers(); + +private: + bool validateArrayBufferType(const char* functionName, GC3Denum type, std::optional<JSC::TypedArrayType>); + void registerWithWebGLStateTracker(); + void checkForContextLossHandling(); + + void activityStateDidChange(ActivityState::Flags oldActivityState, ActivityState::Flags newActivityState) override; + + WebGLStateTracker::Token m_trackerToken; + Timer m_checkForContextLossHandlingTimer; +}; + +} // namespace WebCore + +SPECIALIZE_TYPE_TRAITS_CANVASRENDERINGCONTEXT(WebCore::WebGLRenderingContextBase, is3d()) + +#endif |