summaryrefslogtreecommitdiff
path: root/Source/WebCore/html/canvas/WebGL2RenderingContext.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/html/canvas/WebGL2RenderingContext.cpp
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/html/canvas/WebGL2RenderingContext.cpp')
-rw-r--r--Source/WebCore/html/canvas/WebGL2RenderingContext.cpp1830
1 files changed, 1830 insertions, 0 deletions
diff --git a/Source/WebCore/html/canvas/WebGL2RenderingContext.cpp b/Source/WebCore/html/canvas/WebGL2RenderingContext.cpp
new file mode 100644
index 000000000..92eefac0c
--- /dev/null
+++ b/Source/WebCore/html/canvas/WebGL2RenderingContext.cpp
@@ -0,0 +1,1830 @@
+/*
+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebGL2RenderingContext.h"
+
+#if ENABLE(WEBGL2)
+
+#include "CachedImage.h"
+#include "EXTTextureFilterAnisotropic.h"
+#include "Extensions3D.h"
+#include "HTMLCanvasElement.h"
+#include "HTMLImageElement.h"
+#include "HTMLVideoElement.h"
+#include "ImageData.h"
+#include "OESTextureFloat.h"
+#include "OESTextureFloatLinear.h"
+#include "OESTextureHalfFloat.h"
+#include "OESTextureHalfFloatLinear.h"
+#include "RenderBox.h"
+#include "WebGLActiveInfo.h"
+#include "WebGLCompressedTextureATC.h"
+#include "WebGLCompressedTexturePVRTC.h"
+#include "WebGLCompressedTextureS3TC.h"
+#include "WebGLDebugRendererInfo.h"
+#include "WebGLDebugShaders.h"
+#include "WebGLDepthTexture.h"
+#include "WebGLLoseContext.h"
+#include "WebGLQuery.h"
+#include "WebGLSampler.h"
+#include "WebGLSync.h"
+#include "WebGLTransformFeedback.h"
+#include "WebGLVertexArrayObject.h"
+#include <JavaScriptCore/GenericTypedArrayViewInlines.h>
+#include <JavaScriptCore/JSGenericTypedArrayViewInlines.h>
+
+namespace WebCore {
+
+WebGL2RenderingContext::WebGL2RenderingContext(HTMLCanvasElement& passedCanvas, GraphicsContext3DAttributes attributes)
+ : WebGLRenderingContextBase(passedCanvas, attributes)
+{
+}
+
+WebGL2RenderingContext::WebGL2RenderingContext(HTMLCanvasElement& passedCanvas, Ref<GraphicsContext3D>&& context, GraphicsContext3DAttributes attributes)
+ : WebGLRenderingContextBase(passedCanvas, WTFMove(context), attributes)
+{
+ initializeShaderExtensions();
+ initializeVertexArrayObjects();
+}
+
+void WebGL2RenderingContext::initializeVertexArrayObjects()
+{
+ m_defaultVertexArrayObject = WebGLVertexArrayObject::create(*this, WebGLVertexArrayObject::Type::Default);
+ addContextObject(*m_defaultVertexArrayObject);
+ m_boundVertexArrayObject = m_defaultVertexArrayObject;
+ if (!isGLES2Compliant())
+ initVertexAttrib0();
+}
+
+void WebGL2RenderingContext::initializeShaderExtensions()
+{
+ m_context->getExtensions().ensureEnabled("GL_OES_standard_derivatives");
+ m_context->getExtensions().ensureEnabled("GL_EXT_draw_buffers");
+ m_context->getExtensions().ensureEnabled("GL_EXT_shader_texture_lod");
+ m_context->getExtensions().ensureEnabled("GL_EXT_frag_depth");
+}
+
+inline static std::optional<unsigned> arrayBufferViewElementSize(const ArrayBufferView& data)
+{
+ switch (data.getType()) {
+ case JSC::NotTypedArray:
+ case JSC::TypeDataView:
+ return std::nullopt;
+ case JSC::TypeInt8:
+ case JSC::TypeUint8:
+ case JSC::TypeUint8Clamped:
+ case JSC::TypeInt16:
+ case JSC::TypeUint16:
+ case JSC::TypeInt32:
+ case JSC::TypeUint32:
+ case JSC::TypeFloat32:
+ case JSC::TypeFloat64:
+ return elementSize(data.getType());
+ }
+}
+
+void WebGL2RenderingContext::bufferData(GC3Denum target, const ArrayBufferView& data, GC3Denum usage, GC3Duint srcOffset, GC3Duint length)
+{
+ auto optionalElementSize = arrayBufferViewElementSize(data);
+ if (!optionalElementSize) {
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bufferData", "Invalid type of Array Buffer View");
+ return;
+ }
+ auto elementSize = optionalElementSize.value();
+ Checked<GC3Duint, RecordOverflow> checkedElementSize(elementSize);
+
+ Checked<GC3Duint, RecordOverflow> checkedSrcOffset(srcOffset);
+ Checked<GC3Duint, RecordOverflow> checkedByteSrcOffset = checkedSrcOffset * checkedElementSize;
+ Checked<GC3Duint, RecordOverflow> checkedlength(length);
+ Checked<GC3Duint, RecordOverflow> checkedByteLength = checkedlength * checkedElementSize;
+
+ if (checkedByteSrcOffset.hasOverflowed()
+ || checkedByteLength.hasOverflowed()
+ || checkedByteSrcOffset.unsafeGet() > data.byteLength()
+ || checkedByteLength.unsafeGet() > data.byteLength() - checkedByteSrcOffset.unsafeGet()) {
+ synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferData", "srcOffset or length is out of bounds");
+ return;
+ }
+
+ auto slice = Uint8Array::create(data.possiblySharedBuffer(), data.byteOffset() + checkedByteSrcOffset.unsafeGet(), checkedByteLength.unsafeGet());
+ if (!slice) {
+ synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY, "bufferData", "Could not create intermediate ArrayBufferView");
+ return;
+ }
+ WebGLRenderingContextBase::bufferData(target, BufferDataSource(slice.get()), usage);
+}
+
+void WebGL2RenderingContext::bufferSubData(GC3Denum target, long long offset, const ArrayBufferView& data, GC3Duint srcOffset, GC3Duint length)
+{
+ auto optionalElementSize = arrayBufferViewElementSize(data);
+ if (!optionalElementSize) {
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "bufferSubData", "Invalid type of Array Buffer View");
+ return;
+ }
+ auto elementSize = optionalElementSize.value();
+ Checked<GC3Duint, RecordOverflow> checkedElementSize(elementSize);
+
+ Checked<GC3Duint, RecordOverflow> checkedSrcOffset(srcOffset);
+ Checked<GC3Duint, RecordOverflow> checkedByteSrcOffset = checkedSrcOffset * checkedElementSize;
+ Checked<GC3Duint, RecordOverflow> checkedlength(length);
+ Checked<GC3Duint, RecordOverflow> checkedByteLength = checkedlength * checkedElementSize;
+
+ if (checkedByteSrcOffset.hasOverflowed()
+ || checkedByteLength.hasOverflowed()
+ || checkedByteSrcOffset.unsafeGet() > data.byteLength()
+ || checkedByteLength.unsafeGet() > data.byteLength() - checkedByteSrcOffset.unsafeGet()) {
+ synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "bufferSubData", "srcOffset or length is out of bounds");
+ return;
+ }
+
+ auto slice = Uint8Array::create(data.possiblySharedBuffer(), data.byteOffset() + checkedByteSrcOffset.unsafeGet(), checkedByteLength.unsafeGet());
+ if (!slice) {
+ synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY, "bufferSubData", "Could not create intermediate ArrayBufferView");
+ return;
+ }
+
+ WebGLRenderingContextBase::bufferSubData(target, offset, BufferDataSource(slice.get()));
+}
+
+void WebGL2RenderingContext::copyBufferSubData(GC3Denum readTarget, GC3Denum writeTarget, GC3Dint64 readOffset, GC3Dint64 writeOffset, GC3Dint64 size)
+{
+ if (isContextLostOrPending())
+ return;
+ if ((readTarget == GraphicsContext3D::ELEMENT_ARRAY_BUFFER && writeTarget != GraphicsContext3D::ELEMENT_ARRAY_BUFFER)
+ || (writeTarget == GraphicsContext3D::ELEMENT_ARRAY_BUFFER && readTarget != GraphicsContext3D::ELEMENT_ARRAY_BUFFER)) {
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "copyBufferSubData", "Either both targets need to be ELEMENT_ARRAY_BUFFER or neither should be ELEMENT_ARRAY_BUFFER.");
+ return;
+ }
+ if (readOffset < 0 || writeOffset < 0 || size < 0) {
+ synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyBufferSubData", "offset < 0");
+ return;
+ }
+ WebGLBuffer* readBuffer = validateBufferDataParameters("copyBufferSubData", readTarget, GraphicsContext3D::STATIC_DRAW);
+ WebGLBuffer* writeBuffer = validateBufferDataParameters("copyBufferSubData", writeTarget, GraphicsContext3D::STATIC_DRAW);
+ if (!readBuffer || !writeBuffer) {
+ synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyBufferSubData", "Invalid readTarget or writeTarget");
+ return;
+ }
+
+ Checked<GC3Dintptr, RecordOverflow> checkedReadOffset(readOffset);
+ Checked<GC3Dintptr, RecordOverflow> checkedWriteOffset(writeOffset);
+ Checked<GC3Dsizeiptr, RecordOverflow> checkedSize(size);
+ if (checkedReadOffset.hasOverflowed() || checkedWriteOffset.hasOverflowed() || checkedSize.hasOverflowed()) {
+ synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyBufferSubData", "Offset or size is too big");
+ return;
+ }
+
+ if (!writeBuffer->associateCopyBufferSubData(*readBuffer, checkedReadOffset.unsafeGet(), checkedWriteOffset.unsafeGet(), checkedSize.unsafeGet())) {
+ this->synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "copyBufferSubData", "offset out of range");
+ return;
+ }
+
+ m_context->moveErrorsToSyntheticErrorList();
+#if PLATFORM(COCOA)
+ m_context->copyBufferSubData(readTarget, writeTarget, checkedReadOffset.unsafeGet(), checkedWriteOffset.unsafeGet(), checkedSize.unsafeGet());
+#endif
+ if (m_context->moveErrorsToSyntheticErrorList()) {
+ // The bufferSubData function failed. Tell the buffer it doesn't have the data it thinks it does.
+ writeBuffer->disassociateBufferData();
+ }
+}
+
+void WebGL2RenderingContext::getBufferSubData(GC3Denum target, long long srcByteOffset, RefPtr<ArrayBufferView>&& dstData, GC3Duint dstOffset, GC3Duint length)
+{
+ if (isContextLostOrPending())
+ return;
+ WebGLBuffer* buffer = validateBufferDataParameters("bufferSubData", target, GraphicsContext3D::STATIC_DRAW);
+ if (!buffer) {
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getBufferSubData", "No WebGLBuffer is bound to target");
+ return;
+ }
+
+ // FIXME: Implement "If target is TRANSFORM_FEEDBACK_BUFFER, and any transform feedback object is currently active, an INVALID_OPERATION error is generated."
+
+ if (!dstData) {
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getBufferSubData", "Null dstData");
+ return;
+ }
+
+ auto optionalElementSize = arrayBufferViewElementSize(*dstData);
+ if (!optionalElementSize) {
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getBufferSubData", "Invalid type of Array Buffer View");
+ return;
+ }
+ auto elementSize = optionalElementSize.value();
+ auto dstDataLength = dstData->byteLength() / elementSize;
+
+ if (dstOffset > dstDataLength) {
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getBufferSubData", "dstOffset is larger than the length of the destination buffer.");
+ return;
+ }
+
+ GC3Duint copyLength = length ? length : dstDataLength - dstOffset;
+
+ Checked<GC3Duint, RecordOverflow> checkedDstOffset(dstOffset);
+ Checked<GC3Duint, RecordOverflow> checkedCopyLength(copyLength);
+ auto checkedDestinationEnd = checkedDstOffset + checkedCopyLength;
+ if (checkedDestinationEnd.hasOverflowed()) {
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getBufferSubData", "dstOffset + copyLength is too high");
+ return;
+ }
+
+ if (checkedDestinationEnd.unsafeGet() > dstDataLength) {
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getBufferSubData", "end of written destination is past the end of the buffer");
+ return;
+ }
+
+ if (srcByteOffset < 0) {
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getBufferSubData", "srcByteOffset is less than 0");
+ return;
+ }
+
+ Checked<GC3Dintptr, RecordOverflow> checkedSrcByteOffset(srcByteOffset);
+ Checked<GC3Dintptr, RecordOverflow> checkedCopyLengthPtr(copyLength);
+ Checked<GC3Dintptr, RecordOverflow> checkedElementSize(elementSize);
+ auto checkedSourceEnd = checkedSrcByteOffset + checkedCopyLengthPtr * checkedElementSize;
+ if (checkedSourceEnd.hasOverflowed() || checkedSourceEnd.unsafeGet() > buffer->byteLength()) {
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getBufferSubData", "Parameters would read outside the bounds of the source buffer");
+ return;
+ }
+
+ m_context->moveErrorsToSyntheticErrorList();
+#if PLATFORM(COCOA)
+ // FIXME: Coalesce multiple getBufferSubData() calls to use a single map() call
+ void* ptr = m_context->mapBufferRange(target, checkedSrcByteOffset.unsafeGet(), static_cast<GC3Dsizeiptr>(checkedCopyLengthPtr.unsafeGet() * checkedElementSize.unsafeGet()), GraphicsContext3D::MAP_READ_BIT);
+ memcpy(static_cast<char*>(dstData->baseAddress()) + dstData->byteOffset() + dstOffset * elementSize, ptr, copyLength * elementSize);
+ bool success = m_context->unmapBuffer(target);
+ ASSERT_UNUSED(success, success);
+#endif
+ m_context->moveErrorsToSyntheticErrorList();
+}
+
+void WebGL2RenderingContext::blitFramebuffer(GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dbitfield, GC3Denum)
+{
+}
+
+void WebGL2RenderingContext::framebufferTextureLayer(GC3Denum, GC3Denum, GC3Duint, GC3Dint, GC3Dint)
+{
+}
+
+WebGLAny WebGL2RenderingContext::getInternalformatParameter(GC3Denum, GC3Denum, GC3Denum)
+{
+ return nullptr;
+}
+
+void WebGL2RenderingContext::invalidateFramebuffer(GC3Denum, const Vector<GC3Denum>&)
+{
+}
+
+void WebGL2RenderingContext::invalidateSubFramebuffer(GC3Denum, const Vector<GC3Denum>&, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei)
+{
+}
+
+void WebGL2RenderingContext::readBuffer(GC3Denum)
+{
+}
+
+void WebGL2RenderingContext::renderbufferStorageMultisample(GC3Denum, GC3Dsizei, GC3Denum, GC3Dsizei, GC3Dsizei)
+{
+}
+
+bool WebGL2RenderingContext::validateTexStorageFuncParameters(GC3Denum target, GC3Dsizei levels, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, const char* functionName)
+{
+ if (width < 0 || height < 0) {
+ synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width or height < 0");
+ return false;
+ }
+
+ if (width > m_maxTextureSize || height > m_maxTextureSize) {
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "texture dimensions are larger than the maximum texture size");
+ return false;
+ }
+
+ if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) {
+ if (width != height) {
+ synthesizeGLError(GraphicsContext3D::INVALID_VALUE, functionName, "width != height for cube map");
+ return false;
+ }
+ } else if (target != GraphicsContext3D::TEXTURE_2D) {
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
+ return false;
+ }
+
+ if (levels < 0 || levels > m_maxTextureLevel) {
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "number of levels is out of bounds");
+ return false;
+ }
+
+ switch (internalFormat) {
+ case GraphicsContext3D::R8:
+ case GraphicsContext3D::R8_SNORM:
+ case GraphicsContext3D::R16F:
+ case GraphicsContext3D::R32F:
+ case GraphicsContext3D::R8UI:
+ case GraphicsContext3D::R8I:
+ case GraphicsContext3D::R16UI:
+ case GraphicsContext3D::R16I:
+ case GraphicsContext3D::R32UI:
+ case GraphicsContext3D::R32I:
+ case GraphicsContext3D::RG8:
+ case GraphicsContext3D::RG8_SNORM:
+ case GraphicsContext3D::RG16F:
+ case GraphicsContext3D::RG32F:
+ case GraphicsContext3D::RG8UI:
+ case GraphicsContext3D::RG8I:
+ case GraphicsContext3D::RG16UI:
+ case GraphicsContext3D::RG16I:
+ case GraphicsContext3D::RG32UI:
+ case GraphicsContext3D::RG32I:
+ case GraphicsContext3D::RGB8:
+ case GraphicsContext3D::SRGB8:
+ case GraphicsContext3D::RGB565:
+ case GraphicsContext3D::RGB8_SNORM:
+ case GraphicsContext3D::R11F_G11F_B10F:
+ case GraphicsContext3D::RGB9_E5:
+ case GraphicsContext3D::RGB16F:
+ case GraphicsContext3D::RGB32F:
+ case GraphicsContext3D::RGB8UI:
+ case GraphicsContext3D::RGB8I:
+ case GraphicsContext3D::RGB16UI:
+ case GraphicsContext3D::RGB16I:
+ case GraphicsContext3D::RGB32UI:
+ case GraphicsContext3D::RGB32I:
+ case GraphicsContext3D::RGBA8:
+ case GraphicsContext3D::SRGB8_ALPHA8:
+ case GraphicsContext3D::RGBA8_SNORM:
+ case GraphicsContext3D::RGB5_A1:
+ case GraphicsContext3D::RGBA4:
+ case GraphicsContext3D::RGB10_A2:
+ case GraphicsContext3D::RGBA16F:
+ case GraphicsContext3D::RGBA32F:
+ case GraphicsContext3D::RGBA8UI:
+ case GraphicsContext3D::RGBA8I:
+ case GraphicsContext3D::RGB10_A2UI:
+ case GraphicsContext3D::RGBA16UI:
+ case GraphicsContext3D::RGBA16I:
+ case GraphicsContext3D::RGBA32I:
+ case GraphicsContext3D::RGBA32UI:
+ case GraphicsContext3D::DEPTH_COMPONENT16:
+ case GraphicsContext3D::DEPTH_COMPONENT24:
+ case GraphicsContext3D::DEPTH_COMPONENT32F:
+ case GraphicsContext3D::DEPTH24_STENCIL8:
+ case GraphicsContext3D::DEPTH32F_STENCIL8:
+ break;
+ default:
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "Unknown internalFormat");
+ return false;
+ }
+
+ return true;
+}
+
+void WebGL2RenderingContext::texStorage2D(GC3Denum target, GC3Dsizei levels, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height)
+{
+ if (isContextLostOrPending())
+ return;
+
+ auto* texture = validateTextureBinding("texStorage2D", target, false);
+ if (!texture)
+ return;
+
+ if (!validateTexStorageFuncParameters(target, levels, internalFormat, width, height, "texStorage2D"))
+ return;
+
+ if (!validateNPOTTextureLevel(width, height, levels, "texStorage2D"))
+ return;
+
+ if (texture->immutable()) {
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "texStorage2D", "texStorage2D already called on this texture");
+ return;
+ }
+ texture->setImmutable();
+
+ m_context->texStorage2D(target, levels, internalFormat, width, height);
+
+ {
+ GC3Denum format;
+ GC3Denum type;
+ if (!GraphicsContext3D::possibleFormatAndTypeForInternalFormat(internalFormat, format, type)) {
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "texStorage2D", "Texture has unknown internal format");
+ return;
+ }
+
+ GC3Dsizei levelWidth = width;
+ GC3Dsizei levelHeight = height;
+
+ unsigned size;
+ GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &size, nullptr);
+ if (error != GraphicsContext3D::NO_ERROR) {
+ synthesizeGLError(error, "texStorage2D", "bad dimensions");
+ return;
+ }
+
+ Vector<char> data(size);
+ memset(data.data(), 0, size);
+
+ for (GC3Dsizei level = 0; level < levels; ++level) {
+ if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) {
+ m_context->texSubImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X, level, 0, 0, levelWidth, levelHeight, format, type, data.data());
+ m_context->texSubImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X, level, 0, 0, levelWidth, levelHeight, format, type, data.data());
+ m_context->texSubImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y, level, 0, 0, levelWidth, levelHeight, format, type, data.data());
+ m_context->texSubImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y, level, 0, 0, levelWidth, levelHeight, format, type, data.data());
+ m_context->texSubImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z, level, 0, 0, levelWidth, levelHeight, format, type, data.data());
+ m_context->texSubImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z, level, 0, 0, levelWidth, levelHeight, format, type, data.data());
+ } else
+ m_context->texSubImage2D(target, level, 0, 0, levelWidth, levelHeight, format, type, data.data());
+ levelWidth = std::max(1, levelWidth / 2);
+ levelHeight = std::max(1, levelHeight / 2);
+ }
+ }
+
+ for (GC3Dsizei level = 0; level < levels; ++level) {
+ if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) {
+ texture->setLevelInfo(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
+ texture->setLevelInfo(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
+ texture->setLevelInfo(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
+ texture->setLevelInfo(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
+ texture->setLevelInfo(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
+ texture->setLevelInfo(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
+ } else
+ texture->setLevelInfo(target, level, internalFormat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
+ }
+}
+
+void WebGL2RenderingContext::texStorage3D(GC3Denum, GC3Dsizei, GC3Denum, GC3Dsizei, GC3Dsizei, GC3Dsizei)
+{
+}
+
+void WebGL2RenderingContext::texImage3D(GC3Denum, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei, GC3Dsizei, GC3Dint, GC3Denum, GC3Denum, RefPtr<ArrayBufferView>&&)
+{
+}
+
+void WebGL2RenderingContext::texSubImage3D(GC3Denum, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei, GC3Dsizei, GC3Denum, GC3Denum, RefPtr<ArrayBufferView>&&)
+{
+}
+
+void WebGL2RenderingContext::texSubImage3D(GC3Denum, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Denum, GC3Denum, TexImageSource&&)
+{
+}
+
+void WebGL2RenderingContext::copyTexSubImage3D(GC3Denum, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei)
+{
+}
+
+void WebGL2RenderingContext::compressedTexImage3D(GC3Denum, GC3Dint, GC3Denum, GC3Dsizei, GC3Dsizei, GC3Dsizei, GC3Dint, GC3Dsizei, RefPtr<ArrayBufferView>&&)
+{
+}
+
+void WebGL2RenderingContext::compressedTexSubImage3D(GC3Denum, GC3Dint, GC3Dint, GC3Dint, GC3Dint, GC3Dsizei, GC3Dsizei, GC3Dsizei, GC3Denum, GC3Dsizei, RefPtr<ArrayBufferView>&&)
+{
+}
+
+GC3Dint WebGL2RenderingContext::getFragDataLocation(WebGLProgram*, const String&)
+{
+ return 0;
+}
+
+void WebGL2RenderingContext::uniform1ui(WebGLUniformLocation*, GC3Duint)
+{
+}
+
+void WebGL2RenderingContext::uniform2ui(WebGLUniformLocation*, GC3Duint, GC3Duint)
+{
+}
+
+void WebGL2RenderingContext::uniform3ui(WebGLUniformLocation*, GC3Duint, GC3Duint, GC3Duint)
+{
+}
+
+void WebGL2RenderingContext::uniform4ui(WebGLUniformLocation*, GC3Duint, GC3Duint, GC3Duint, GC3Duint)
+{
+}
+
+void WebGL2RenderingContext::uniform1uiv(WebGLUniformLocation*, RefPtr<Uint32Array>&&)
+{
+}
+
+void WebGL2RenderingContext::uniform2uiv(WebGLUniformLocation*, RefPtr<Uint32Array>&&)
+{
+}
+
+void WebGL2RenderingContext::uniform3uiv(WebGLUniformLocation*, RefPtr<Uint32Array>&&)
+{
+}
+
+void WebGL2RenderingContext::uniform4uiv(WebGLUniformLocation*, RefPtr<Uint32Array>&&)
+{
+}
+
+void WebGL2RenderingContext::uniformMatrix2x3fv(WebGLUniformLocation*, GC3Dboolean, RefPtr<Float32Array>&&)
+{
+}
+
+void WebGL2RenderingContext::uniformMatrix3x2fv(WebGLUniformLocation*, GC3Dboolean, RefPtr<Float32Array>&&)
+{
+}
+
+void WebGL2RenderingContext::uniformMatrix2x4fv(WebGLUniformLocation*, GC3Dboolean, RefPtr<Float32Array>&&)
+{
+}
+
+void WebGL2RenderingContext::uniformMatrix4x2fv(WebGLUniformLocation*, GC3Dboolean, RefPtr<Float32Array>&&)
+{
+}
+
+void WebGL2RenderingContext::uniformMatrix3x4fv(WebGLUniformLocation*, GC3Dboolean, RefPtr<Float32Array>&&)
+{
+}
+
+void WebGL2RenderingContext::uniformMatrix4x3fv(WebGLUniformLocation*, GC3Dboolean, RefPtr<Float32Array>&&)
+{
+}
+
+void WebGL2RenderingContext::vertexAttribI4i(GC3Duint, GC3Dint, GC3Dint, GC3Dint, GC3Dint)
+{
+}
+
+void WebGL2RenderingContext::vertexAttribI4iv(GC3Duint, RefPtr<Int32Array>&&)
+{
+}
+
+void WebGL2RenderingContext::vertexAttribI4ui(GC3Duint, GC3Duint, GC3Duint, GC3Duint, GC3Duint)
+{
+}
+
+void WebGL2RenderingContext::vertexAttribI4uiv(GC3Duint, RefPtr<Uint32Array>&&)
+{
+}
+
+void WebGL2RenderingContext::vertexAttribIPointer(GC3Duint, GC3Dint, GC3Denum, GC3Dsizei, GC3Dint64)
+{
+}
+
+void WebGL2RenderingContext::clear(GC3Dbitfield mask)
+{
+ if (isContextLostOrPending())
+ return;
+ if (mask & ~(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) {
+ synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clear", "invalid mask");
+ return;
+ }
+ if (m_framebufferBinding && (mask & GraphicsContext3D::COLOR_BUFFER_BIT) && isIntegerFormat(m_framebufferBinding->getColorBufferFormat())) {
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "clear", "cannot clear an integer buffer");
+ return;
+ }
+ const char* reason = "framebuffer incomplete";
+ if (m_framebufferBinding && !m_framebufferBinding->onAccess(graphicsContext3D(), &reason)) {
+ synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION, "clear", reason);
+ return;
+ }
+ if (!clearIfComposited(mask))
+ m_context->clear(mask);
+ markContextChanged();
+}
+
+void WebGL2RenderingContext::vertexAttribDivisor(GC3Duint index, GC3Duint divisor)
+{
+ if (isContextLostOrPending())
+ return;
+
+ WebGLRenderingContextBase::vertexAttribDivisor(index, divisor);
+}
+
+void WebGL2RenderingContext::drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei instanceCount)
+{
+ if (isContextLostOrPending())
+ return;
+
+ WebGLRenderingContextBase::drawArraysInstanced(mode, first, count, instanceCount);
+}
+
+void WebGL2RenderingContext::drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dint64 offset, GC3Dsizei instanceCount)
+{
+ if (isContextLostOrPending())
+ return;
+
+ WebGLRenderingContextBase::drawElementsInstanced(mode, count, type, offset, instanceCount);
+}
+
+void WebGL2RenderingContext::drawRangeElements(GC3Denum, GC3Duint, GC3Duint, GC3Dsizei, GC3Denum, GC3Dint64)
+{
+}
+
+void WebGL2RenderingContext::drawBuffers(const Vector<GC3Denum>& buffers)
+{
+ if (isContextLost())
+ return;
+ GC3Dsizei n = buffers.size();
+ const GC3Denum* bufs = buffers.data();
+ if (!m_framebufferBinding) {
+ if (n != 1) {
+ synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "drawBuffers", "more than one buffer");
+ return;
+ }
+ if (bufs[0] != GraphicsContext3D::BACK && bufs[0] != GraphicsContext3D::NONE) {
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawBuffers", "BACK or NONE");
+ return;
+ }
+ // Because the backbuffer is simulated on all current WebKit ports, we need to change BACK to COLOR_ATTACHMENT0.
+ GC3Denum value = (bufs[0] == GraphicsContext3D::BACK) ? GraphicsContext3D::COLOR_ATTACHMENT0 : GraphicsContext3D::NONE;
+ graphicsContext3D()->getExtensions().drawBuffersEXT(1, &value);
+ setBackDrawBuffer(bufs[0]);
+ } else {
+ if (n > getMaxDrawBuffers()) {
+ synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "drawBuffers", "more than max draw buffers");
+ return;
+ }
+ for (GC3Dsizei i = 0; i < n; ++i) {
+ if (bufs[i] != GraphicsContext3D::NONE && bufs[i] != static_cast<GC3Denum>(GraphicsContext3D::COLOR_ATTACHMENT0 + i)) {
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "drawBuffers", "COLOR_ATTACHMENTi or NONE");
+ return;
+ }
+ }
+ m_framebufferBinding->drawBuffers(buffers);
+ }
+}
+
+void WebGL2RenderingContext::clearBufferiv(GC3Denum buffer, GC3Dint drawbuffer, RefPtr<Int32Array>&&)
+{
+ switch (buffer) {
+ case GraphicsContext3D::COLOR:
+ if (drawbuffer < 0 || drawbuffer >= getMaxDrawBuffers()) {
+ synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clearBufferiv", "buffer index out of range");
+ return;
+ }
+ // TODO: Call clearBufferiv, requires gl3.h and ES3/gl.h
+ break;
+ case GraphicsContext3D::STENCIL:
+ if (drawbuffer) {
+ synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clearBufferiv", "buffer index must be 0");
+ return;
+ }
+ // TODO: Call clearBufferiv, requires gl3.h and ES3/gl.h
+ break;
+ case GraphicsContext3D::DEPTH:
+ case GraphicsContext3D::DEPTH_STENCIL:
+ default:
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "clearBufferiv", "buffer argument must be COLOR or STENCIL");
+ break;
+ }
+}
+
+void WebGL2RenderingContext::clearBufferuiv(GC3Denum buffer, GC3Dint drawbuffer, RefPtr<Uint32Array>&&)
+{
+ switch (buffer) {
+ case GraphicsContext3D::COLOR:
+ if (drawbuffer < 0 || drawbuffer >= getMaxDrawBuffers()) {
+ synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clearBufferuiv", "buffer index out of range");
+ return;
+ }
+ // TODO: Call clearBufferuiv, requires gl3.h and ES3/gl.h
+ break;
+ case GraphicsContext3D::DEPTH:
+ case GraphicsContext3D::STENCIL:
+ case GraphicsContext3D::DEPTH_STENCIL:
+ default:
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "clearBufferuiv", "buffer argument must be COLOR");
+ break;
+ }
+}
+
+void WebGL2RenderingContext::clearBufferfv(GC3Denum buffer, GC3Dint drawbuffer, RefPtr<Float32Array>&&)
+{
+ switch (buffer) {
+ case GraphicsContext3D::COLOR:
+ if (drawbuffer < 0 || drawbuffer >= getMaxDrawBuffers()) {
+ synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clearBufferfv", "buffer index out of range");
+ return;
+ }
+ // TODO: Call clearBufferfv, requires gl3.h and ES3/gl.h
+ break;
+ case GraphicsContext3D::DEPTH:
+ if (drawbuffer) {
+ synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clearBufferfv", "buffer index must be 0");
+ return;
+ }
+ // TODO: Call clearBufferfv, requires gl3.h and ES3/gl.h
+ break;
+ case GraphicsContext3D::STENCIL:
+ case GraphicsContext3D::DEPTH_STENCIL:
+ default:
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "clearBufferfv", "buffer argument must be COLOR OR DEPTH");
+ break;
+ }
+}
+
+void WebGL2RenderingContext::clearBufferfi(GC3Denum buffer, GC3Dint drawbuffer, GC3Dfloat, GC3Dint)
+{
+ switch (buffer) {
+ case GraphicsContext3D::DEPTH_STENCIL:
+ if (drawbuffer) {
+ synthesizeGLError(GraphicsContext3D::INVALID_VALUE, "clearBufferfv", "buffer index must be 0");
+ return;
+ }
+ // TODO: Call clearBufferfi, requires gl3.h and ES3/gl.h
+ break;
+ case GraphicsContext3D::COLOR:
+ case GraphicsContext3D::DEPTH:
+ case GraphicsContext3D::STENCIL:
+ default:
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "clearBufferfv", "buffer argument must be DEPTH_STENCIL");
+ break;
+ }
+}
+
+RefPtr<WebGLQuery> WebGL2RenderingContext::createQuery()
+{
+ return nullptr;
+}
+
+void WebGL2RenderingContext::deleteQuery(WebGLQuery*)
+{
+}
+
+GC3Dboolean WebGL2RenderingContext::isQuery(WebGLQuery*)
+{
+ return false;
+}
+
+void WebGL2RenderingContext::beginQuery(GC3Denum, WebGLQuery*)
+{
+}
+
+void WebGL2RenderingContext::endQuery(GC3Denum)
+{
+}
+
+RefPtr<WebGLQuery> WebGL2RenderingContext::getQuery(GC3Denum, GC3Denum)
+{
+ return nullptr;
+}
+
+WebGLAny WebGL2RenderingContext::getQueryParameter(WebGLQuery*, GC3Denum)
+{
+ return nullptr;
+}
+
+RefPtr<WebGLSampler> WebGL2RenderingContext::createSampler()
+{
+ return nullptr;
+}
+
+void WebGL2RenderingContext::deleteSampler(WebGLSampler*)
+{
+}
+
+GC3Dboolean WebGL2RenderingContext::isSampler(WebGLSampler*)
+{
+ return false;
+}
+
+void WebGL2RenderingContext::bindSampler(GC3Duint, WebGLSampler*)
+{
+}
+
+void WebGL2RenderingContext::samplerParameteri(WebGLSampler*, GC3Denum, GC3Dint)
+{
+}
+
+void WebGL2RenderingContext::samplerParameterf(WebGLSampler*, GC3Denum, GC3Dfloat)
+{
+}
+
+WebGLAny WebGL2RenderingContext::getSamplerParameter(WebGLSampler*, GC3Denum)
+{
+ return nullptr;
+}
+
+RefPtr<WebGLSync> WebGL2RenderingContext::fenceSync(GC3Denum, GC3Dbitfield)
+{
+ return nullptr;
+}
+
+GC3Dboolean WebGL2RenderingContext::isSync(WebGLSync*)
+{
+ return false;
+}
+
+void WebGL2RenderingContext::deleteSync(WebGLSync*)
+{
+}
+
+GC3Denum WebGL2RenderingContext::clientWaitSync(WebGLSync*, GC3Dbitfield, GC3Duint64)
+{
+ return 0;
+}
+
+void WebGL2RenderingContext::waitSync(WebGLSync*, GC3Dbitfield, GC3Duint64)
+{
+}
+
+WebGLAny WebGL2RenderingContext::getSyncParameter(WebGLSync*, GC3Denum)
+{
+ return nullptr;
+}
+
+RefPtr<WebGLTransformFeedback> WebGL2RenderingContext::createTransformFeedback()
+{
+ return nullptr;
+}
+
+void WebGL2RenderingContext::deleteTransformFeedback(WebGLTransformFeedback*)
+{
+}
+
+GC3Dboolean WebGL2RenderingContext::isTransformFeedback(WebGLTransformFeedback*)
+{
+ return false;
+}
+
+void WebGL2RenderingContext::bindTransformFeedback(GC3Denum, WebGLTransformFeedback*)
+{
+}
+
+void WebGL2RenderingContext::beginTransformFeedback(GC3Denum)
+{
+}
+
+void WebGL2RenderingContext::endTransformFeedback()
+{
+}
+
+void WebGL2RenderingContext::transformFeedbackVaryings(WebGLProgram*, const Vector<String>&, GC3Denum)
+{
+}
+
+RefPtr<WebGLActiveInfo> WebGL2RenderingContext::getTransformFeedbackVarying(WebGLProgram*, GC3Duint)
+{
+ return nullptr;
+}
+
+void WebGL2RenderingContext::pauseTransformFeedback()
+{
+}
+
+void WebGL2RenderingContext::resumeTransformFeedback()
+{
+}
+
+void WebGL2RenderingContext::bindBufferBase(GC3Denum, GC3Duint, WebGLBuffer*)
+{
+}
+
+void WebGL2RenderingContext::bindBufferRange(GC3Denum, GC3Duint, WebGLBuffer*, GC3Dint64, GC3Dint64)
+{
+}
+
+WebGLAny WebGL2RenderingContext::getIndexedParameter(GC3Denum target, GC3Duint)
+{
+ switch (target) {
+ case GraphicsContext3D::TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ case GraphicsContext3D::TRANSFORM_FEEDBACK_BUFFER_SIZE:
+ case GraphicsContext3D::TRANSFORM_FEEDBACK_BUFFER_START:
+ case GraphicsContext3D::UNIFORM_BUFFER_BINDING:
+ case GraphicsContext3D::UNIFORM_BUFFER_SIZE:
+ case GraphicsContext3D::UNIFORM_BUFFER_START:
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getIndexedParameter", "parameter name not yet supported");
+ return nullptr;
+ default:
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getIndexedParameter", "invalid parameter name");
+ return nullptr;
+ }
+}
+
+Uint32Array* WebGL2RenderingContext::getUniformIndices(WebGLProgram*, const Vector<String>&)
+{
+ return nullptr;
+}
+
+Int32Array* WebGL2RenderingContext::getActiveUniforms(WebGLProgram*, RefPtr<Uint32Array>&&, GC3Denum)
+{
+ return nullptr;
+}
+
+GC3Duint WebGL2RenderingContext::getUniformBlockIndex(WebGLProgram*, const String&)
+{
+ return 0;
+}
+
+WebGLAny WebGL2RenderingContext::getActiveUniformBlockParameter(WebGLProgram*, GC3Duint, GC3Denum)
+{
+ return nullptr;
+}
+
+WebGLAny WebGL2RenderingContext::getActiveUniformBlockName(WebGLProgram*, GC3Duint)
+{
+ return nullptr;
+}
+
+void WebGL2RenderingContext::uniformBlockBinding(WebGLProgram*, GC3Duint, GC3Duint)
+{
+}
+
+RefPtr<WebGLVertexArrayObject> WebGL2RenderingContext::createVertexArray()
+{
+ if (isContextLost())
+ return nullptr;
+
+ auto object = WebGLVertexArrayObject::create(*this, WebGLVertexArrayObject::Type::User);
+ addContextObject(object.get());
+ return WTFMove(object);
+}
+
+void WebGL2RenderingContext::deleteVertexArray(WebGLVertexArrayObject* arrayObject)
+{
+ if (!arrayObject || isContextLost())
+ return;
+
+ if (arrayObject->isDeleted())
+ return;
+
+ if (!arrayObject->isDefaultObject() && arrayObject == m_boundVertexArrayObject)
+ setBoundVertexArrayObject(nullptr);
+
+ arrayObject->deleteObject(graphicsContext3D());
+}
+
+GC3Dboolean WebGL2RenderingContext::isVertexArray(WebGLVertexArrayObject* arrayObject)
+{
+ if (!arrayObject || isContextLost())
+ return false;
+
+ if (!arrayObject->hasEverBeenBound() || !arrayObject->validate(0, *this))
+ return false;
+
+ return m_context->isVertexArray(arrayObject->object());
+}
+
+void WebGL2RenderingContext::bindVertexArray(WebGLVertexArrayObject* arrayObject)
+{
+ if (isContextLost())
+ return;
+
+ if (arrayObject && (arrayObject->isDeleted() || !arrayObject->validate(0, *this) || !m_contextObjects.contains(arrayObject))) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return;
+ }
+ if (arrayObject && !arrayObject->isDefaultObject() && arrayObject->object()) {
+ m_context->bindVertexArray(arrayObject->object());
+
+ arrayObject->setHasEverBeenBound();
+ setBoundVertexArrayObject(arrayObject);
+ } else {
+ m_context->bindVertexArray(m_defaultVertexArrayObject->object());
+ setBoundVertexArrayObject(m_defaultVertexArrayObject.get());
+ }
+}
+
+WebGLExtension* WebGL2RenderingContext::getExtension(const String& name)
+{
+ if (isContextLostOrPending())
+ return nullptr;
+
+ if (equalIgnoringASCIICase(name, "EXT_texture_filter_anisotropic") || equalIgnoringASCIICase(name, "WEBKIT_EXT_texture_filter_anisotropic")) {
+ if (!m_extTextureFilterAnisotropic) {
+ m_extTextureFilterAnisotropic = enableSupportedExtension("GL_EXT_texture_filter_anisotropic")
+ ? std::make_unique<EXTTextureFilterAnisotropic>(*this) : nullptr;
+ }
+ return m_extTextureFilterAnisotropic.get();
+ }
+ if (equalIgnoringASCIICase(name, "OES_texture_float")) {
+ if (!m_oesTextureFloat) {
+ m_oesTextureFloat = enableSupportedExtension("GL_OES_texture_float")
+ ? std::make_unique<OESTextureFloat>(*this) : nullptr;
+ }
+ return m_oesTextureFloat.get();
+ }
+ if (equalIgnoringASCIICase(name, "OES_texture_float_linear")) {
+ if (!m_oesTextureFloatLinear) {
+ m_oesTextureFloatLinear = enableSupportedExtension("GL_OES_texture_float_linear")
+ ? std::make_unique<OESTextureFloatLinear>(*this) : nullptr;
+ }
+ return m_oesTextureFloatLinear.get();
+ }
+ if (equalIgnoringASCIICase(name, "OES_texture_half_float")) {
+ if (!m_oesTextureHalfFloat) {
+ m_oesTextureHalfFloat = enableSupportedExtension("GL_OES_texture_half_float")
+ ? std::make_unique<OESTextureHalfFloat>(*this) : nullptr;
+ }
+ return m_oesTextureHalfFloat.get();
+ }
+ if (equalIgnoringASCIICase(name, "OES_texture_half_float_linear")) {
+ if (!m_oesTextureHalfFloatLinear) {
+ m_oesTextureHalfFloatLinear = enableSupportedExtension("GL_OES_texture_half_float_linear")
+ ? std::make_unique<OESTextureHalfFloatLinear>(*this) : nullptr;
+ }
+ return m_oesTextureHalfFloatLinear.get();
+ }
+ if (equalIgnoringASCIICase(name, "WEBGL_lose_context")) {
+ if (!m_webglLoseContext)
+ m_webglLoseContext = std::make_unique<WebGLLoseContext>(*this);
+ return m_webglLoseContext.get();
+ }
+ if (equalIgnoringASCIICase(name, "WEBKIT_WEBGL_compressed_texture_atc")) {
+ if (!m_webglCompressedTextureATC) {
+ if (WebGLCompressedTextureATC::supported(*this))
+ m_webglCompressedTextureATC = std::make_unique<WebGLCompressedTextureATC>(*this);
+ }
+ return m_webglCompressedTextureATC.get();
+ }
+ if (equalIgnoringASCIICase(name, "WEBKIT_WEBGL_compressed_texture_pvrtc")) {
+ if (!m_webglCompressedTexturePVRTC) {
+ m_webglCompressedTexturePVRTC = WebGLCompressedTexturePVRTC::supported(*this)
+ ? std::make_unique<WebGLCompressedTexturePVRTC>(*this) : nullptr;
+ }
+ return m_webglCompressedTexturePVRTC.get();
+ }
+ if (equalIgnoringASCIICase(name, "WEBGL_compressed_texture_s3tc")) {
+ if (!m_webglCompressedTextureS3TC) {
+ m_webglCompressedTextureS3TC = WebGLCompressedTextureS3TC::supported(*this)
+ ? std::make_unique<WebGLCompressedTextureS3TC>(*this) : nullptr;
+ }
+ return m_webglCompressedTextureS3TC.get();
+ }
+ if (equalIgnoringASCIICase(name, "WEBGL_depth_texture")) {
+ if (!m_webglDepthTexture) {
+ m_webglDepthTexture = WebGLDepthTexture::supported(*graphicsContext3D())
+ ? std::make_unique<WebGLDepthTexture>(*this) : nullptr;
+ }
+ return m_webglDepthTexture.get();
+ }
+ if (equalIgnoringASCIICase(name, "WEBGL_debug_renderer_info")) {
+ if (!m_webglDebugRendererInfo)
+ m_webglDebugRendererInfo = std::make_unique<WebGLDebugRendererInfo>(*this);
+ return m_webglDebugRendererInfo.get();
+ }
+ if (equalIgnoringASCIICase(name, "WEBGL_debug_shaders")) {
+ if (!m_webglDebugShaders) {
+ m_webglDebugShaders = m_context->getExtensions().supports(ASCIILiteral { "GL_ANGLE_translated_shader_source" })
+ ? std::make_unique<WebGLDebugShaders>(*this) : nullptr;
+ }
+ return m_webglDebugShaders.get();
+ }
+
+ return nullptr;
+}
+
+std::optional<Vector<String>> WebGL2RenderingContext::getSupportedExtensions()
+{
+ if (isContextLost())
+ return std::nullopt;
+
+ Vector<String> result;
+
+ if (m_isPendingPolicyResolution)
+ return result;
+
+ auto& extensions = m_context->getExtensions();
+ if (extensions.supports(ASCIILiteral { "GL_OES_texture_float" }))
+ result.append(ASCIILiteral { "OES_texture_float" });
+ if (extensions.supports(ASCIILiteral { "GL_OES_texture_float_linear" }))
+ result.append(ASCIILiteral { "OES_texture_float_linear" });
+ if (extensions.supports(ASCIILiteral { "GL_OES_texture_half_float" }))
+ result.append(ASCIILiteral { "OES_texture_half_float" });
+ if (extensions.supports(ASCIILiteral { "GL_OES_texture_half_float_linear" }))
+ result.append(ASCIILiteral { "OES_texture_half_float_linear" });
+ if (extensions.supports(ASCIILiteral { "GL_EXT_texture_filter_anisotropic" }))
+ result.append(ASCIILiteral { "WEBKIT_EXT_texture_filter_anisotropic" });
+ if (WebGLCompressedTextureATC::supported(*this))
+ result.append(ASCIILiteral { "WEBKIT_WEBGL_compressed_texture_atc" });
+ if (WebGLCompressedTexturePVRTC::supported(*this))
+ result.append(ASCIILiteral { "WEBKIT_WEBGL_compressed_texture_pvrtc" });
+ if (WebGLCompressedTextureS3TC::supported(*this))
+ result.append(ASCIILiteral { "WEBGL_compressed_texture_s3tc" });
+ if (WebGLDepthTexture::supported(*graphicsContext3D()))
+ result.append(ASCIILiteral { "WEBGL_depth_texture" });
+ result.append(ASCIILiteral { "WEBGL_lose_context" });
+ if (extensions.supports(ASCIILiteral { "GL_ANGLE_translated_shader_source" }))
+ result.append(ASCIILiteral { "WEBGL_debug_shaders" });
+ result.append(ASCIILiteral { "WEBGL_debug_renderer_info" });
+
+ return result;
+}
+
+WebGLAny WebGL2RenderingContext::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname)
+{
+ if (isContextLostOrPending() || !validateFramebufferFuncParameters("getFramebufferAttachmentParameter", target, attachment))
+ return nullptr;
+
+ if (!m_framebufferBinding || !m_framebufferBinding->object()) {
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "getFramebufferAttachmentParameter", "no framebuffer bound");
+ return nullptr;
+ }
+
+ auto* object = m_framebufferBinding->getAttachmentObject(attachment);
+ if (!object) {
+ if (pname == GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)
+ return static_cast<unsigned>(GraphicsContext3D::NONE);
+ // OpenGL ES 2.0 specifies INVALID_ENUM in this case, while desktop GL specifies INVALID_OPERATION.
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name");
+ return nullptr;
+ }
+
+ if (object->isTexture()) {
+ switch (pname) {
+ case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+ return static_cast<unsigned>(GraphicsContext3D::TEXTURE);
+ case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+ return makeRefPtr(reinterpret_cast<WebGLTexture&>(*object));
+ case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
+ case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
+ case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: {
+ GC3Dint value = 0;
+ m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value);
+ return value;
+ }
+ default:
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for texture attachment");
+ return nullptr;
+ }
+ } else {
+ ASSERT(object->isRenderbuffer());
+ switch (pname) {
+ case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+ return static_cast<unsigned>(GraphicsContext3D::RENDERBUFFER);
+ case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+ return makeRefPtr(reinterpret_cast<WebGLRenderbuffer&>(*object));
+ case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING : {
+ auto& renderBuffer = reinterpret_cast<WebGLRenderbuffer&>(*object);
+ auto format = renderBuffer.getInternalFormat();
+ if (format == GraphicsContext3D::SRGB8_ALPHA8
+ || format == GraphicsContext3D::COMPRESSED_SRGB8_ETC2
+ || format == GraphicsContext3D::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
+ || format == GraphicsContext3D::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2) {
+ return static_cast<unsigned>(GraphicsContext3D::SRGB);
+ }
+ return static_cast<unsigned>(GraphicsContext3D::LINEAR);
+ }
+ default:
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getFramebufferAttachmentParameter", "invalid parameter name for renderbuffer attachment");
+ return nullptr;
+ }
+ }
+}
+
+bool WebGL2RenderingContext::validateFramebufferFuncParameters(const char* functionName, GC3Denum target, GC3Denum attachment)
+{
+ if (target != GraphicsContext3D::FRAMEBUFFER) {
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid target");
+ return false;
+ }
+ switch (attachment) {
+ case GraphicsContext3D::DEPTH_ATTACHMENT:
+ case GraphicsContext3D::STENCIL_ATTACHMENT:
+ case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
+ return true;
+ default:
+ if (attachment >= GraphicsContext3D::COLOR_ATTACHMENT0 && attachment < static_cast<GC3Denum>(GraphicsContext3D::COLOR_ATTACHMENT0 + getMaxColorAttachments()))
+ return true;
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid attachment");
+ return false;
+ }
+}
+
+GC3Dint WebGL2RenderingContext::getMaxDrawBuffers()
+{
+ if (!m_maxDrawBuffers)
+ m_context->getIntegerv(GraphicsContext3D::MAX_DRAW_BUFFERS, &m_maxDrawBuffers);
+ return m_maxDrawBuffers;
+}
+
+GC3Dint WebGL2RenderingContext::getMaxColorAttachments()
+{
+ // DrawBuffers requires MAX_COLOR_ATTACHMENTS == MAX_DRAW_BUFFERS
+ if (!m_maxColorAttachments)
+ m_context->getIntegerv(GraphicsContext3D::MAX_DRAW_BUFFERS, &m_maxColorAttachments);
+ return m_maxColorAttachments;
+}
+
+void WebGL2RenderingContext::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height)
+{
+ if (isContextLostOrPending())
+ return;
+ if (target != GraphicsContext3D::RENDERBUFFER) {
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid target");
+ return;
+ }
+ if (!m_renderbufferBinding || !m_renderbufferBinding->object()) {
+ synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "renderbufferStorage", "no bound renderbuffer");
+ return;
+ }
+ if (!validateSize("renderbufferStorage", width, height))
+ return;
+ switch (internalformat) {
+ case GraphicsContext3D::DEPTH_COMPONENT16:
+ case GraphicsContext3D::DEPTH_COMPONENT32F:
+ case GraphicsContext3D::DEPTH_COMPONENT24:
+ case GraphicsContext3D::RGBA32I:
+ case GraphicsContext3D::RGBA32UI:
+ case GraphicsContext3D::RGBA16I:
+ case GraphicsContext3D::RGBA16UI:
+ case GraphicsContext3D::RGBA8:
+ case GraphicsContext3D::RGBA8I:
+ case GraphicsContext3D::RGBA8UI:
+ case GraphicsContext3D::RGB10_A2:
+ case GraphicsContext3D::RGB10_A2UI:
+ case GraphicsContext3D::RGBA4:
+ case GraphicsContext3D::RG32I:
+ case GraphicsContext3D::RG32UI:
+ case GraphicsContext3D::RG16I:
+ case GraphicsContext3D::RG16UI:
+ case GraphicsContext3D::RG8:
+ case GraphicsContext3D::RG8I:
+ case GraphicsContext3D::RG8UI:
+ case GraphicsContext3D::R32I:
+ case GraphicsContext3D::R32UI:
+ case GraphicsContext3D::R16I:
+ case GraphicsContext3D::R16UI:
+ case GraphicsContext3D::R8:
+ case GraphicsContext3D::R8I:
+ case GraphicsContext3D::R8UI:
+ case GraphicsContext3D::RGB5_A1:
+ case GraphicsContext3D::RGB565:
+ case GraphicsContext3D::STENCIL_INDEX8:
+ case GraphicsContext3D::SRGB8_ALPHA8:
+ m_context->renderbufferStorage(target, internalformat, width, height);
+ m_renderbufferBinding->setInternalFormat(internalformat);
+ m_renderbufferBinding->setIsValid(true);
+ m_renderbufferBinding->setSize(width, height);
+ break;
+ case GraphicsContext3D::DEPTH32F_STENCIL8:
+ case GraphicsContext3D::DEPTH24_STENCIL8:
+ if (!isDepthStencilSupported()) {
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid internalformat");
+ return;
+ }
+ m_context->renderbufferStorage(target, internalformat, width, height);
+ m_renderbufferBinding->setSize(width, height);
+ m_renderbufferBinding->setIsValid(isDepthStencilSupported());
+ m_renderbufferBinding->setInternalFormat(internalformat);
+ break;
+ default:
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "renderbufferStorage", "invalid internalformat");
+ return;
+ }
+ applyStencilTest();
+}
+
+void WebGL2RenderingContext::hint(GC3Denum target, GC3Denum mode)
+{
+ if (isContextLostOrPending())
+ return;
+ bool isValid = false;
+ switch (target) {
+ case GraphicsContext3D::GENERATE_MIPMAP_HINT:
+ case GraphicsContext3D::FRAGMENT_SHADER_DERIVATIVE_HINT:
+ isValid = true;
+ break;
+ }
+ if (!isValid) {
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "hint", "invalid target");
+ return;
+ }
+ m_context->hint(target, mode);
+}
+
+GC3Denum WebGL2RenderingContext::baseInternalFormatFromInternalFormat(GC3Denum internalformat)
+{
+ // Handles sized, unsized, and compressed internal formats.
+ switch (internalformat) {
+ case GraphicsContext3D::R8:
+ case GraphicsContext3D::R8_SNORM:
+ case GraphicsContext3D::R16F:
+ case GraphicsContext3D::R32F:
+ case GraphicsContext3D::R8I:
+ case GraphicsContext3D::R8UI:
+ case GraphicsContext3D::R16I:
+ case GraphicsContext3D::R16UI:
+ case GraphicsContext3D::R32I:
+ case GraphicsContext3D::R32UI:
+ case GraphicsContext3D::COMPRESSED_R11_EAC:
+ case GraphicsContext3D::COMPRESSED_SIGNED_R11_EAC:
+ return GraphicsContext3D::RED;
+ case GraphicsContext3D::RG8:
+ case GraphicsContext3D::RG8_SNORM:
+ case GraphicsContext3D::RG16F:
+ case GraphicsContext3D::RG32F:
+ case GraphicsContext3D::RG8I:
+ case GraphicsContext3D::RG8UI:
+ case GraphicsContext3D::RG16I:
+ case GraphicsContext3D::RG16UI:
+ case GraphicsContext3D::RG32I:
+ case GraphicsContext3D::RG32UI:
+ case GraphicsContext3D::COMPRESSED_RG11_EAC:
+ case GraphicsContext3D::COMPRESSED_SIGNED_RG11_EAC:
+ return GraphicsContext3D::RG;
+ case GraphicsContext3D::RGB8:
+ case GraphicsContext3D::RGB8_SNORM:
+ case GraphicsContext3D::RGB565:
+ case GraphicsContext3D::SRGB8:
+ case GraphicsContext3D::RGB16F:
+ case GraphicsContext3D::RGB32F:
+ case GraphicsContext3D::RGB8I:
+ case GraphicsContext3D::RGB8UI:
+ case GraphicsContext3D::RGB16I:
+ case GraphicsContext3D::RGB16UI:
+ case GraphicsContext3D::RGB32I:
+ case GraphicsContext3D::RGB32UI:
+ case GraphicsContext3D::RGB:
+ case GraphicsContext3D::COMPRESSED_RGB8_ETC2:
+ case GraphicsContext3D::COMPRESSED_SRGB8_ETC2:
+ return GraphicsContext3D::RGB;
+ case GraphicsContext3D::RGBA4:
+ case GraphicsContext3D::RGB5_A1:
+ case GraphicsContext3D::RGBA8:
+ case GraphicsContext3D::RGBA8_SNORM:
+ case GraphicsContext3D::RGB10_A2:
+ case GraphicsContext3D::RGB10_A2UI:
+ case GraphicsContext3D::SRGB8_ALPHA8:
+ case GraphicsContext3D::RGBA16F:
+ case GraphicsContext3D::RGBA32F:
+ case GraphicsContext3D::RGBA8I:
+ case GraphicsContext3D::RGBA8UI:
+ case GraphicsContext3D::RGBA16I:
+ case GraphicsContext3D::RGBA16UI:
+ case GraphicsContext3D::RGBA32I:
+ case GraphicsContext3D::RGBA32UI:
+ case GraphicsContext3D::RGBA:
+ case GraphicsContext3D::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ case GraphicsContext3D::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ case GraphicsContext3D::COMPRESSED_RGBA8_ETC2_EAC:
+ case GraphicsContext3D::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+ return GraphicsContext3D::RGBA;
+ case GraphicsContext3D::DEPTH_COMPONENT16:
+ case GraphicsContext3D::DEPTH_COMPONENT24:
+ case GraphicsContext3D::DEPTH_COMPONENT32F:
+ return GraphicsContext3D::DEPTH_COMPONENT;
+ case GraphicsContext3D::DEPTH24_STENCIL8:
+ case GraphicsContext3D::DEPTH32F_STENCIL8:
+ return GraphicsContext3D::DEPTH_STENCIL;
+ case GraphicsContext3D::LUMINANCE:
+ case GraphicsContext3D::LUMINANCE_ALPHA:
+ case GraphicsContext3D::ALPHA:
+ return internalformat;
+ default:
+ ASSERT_NOT_REACHED();
+ return GraphicsContext3D::NONE;
+ }
+}
+
+bool WebGL2RenderingContext::isIntegerFormat(GC3Denum internalformat)
+{
+ // FIXME: baseInternalFormatFromInternalFormat() never returns any of these enums.
+ // Because of that, this function erroneously always returns false!
+ switch (baseInternalFormatFromInternalFormat(internalformat)) {
+ case GraphicsContext3D::RED_INTEGER:
+ case GraphicsContext3D::RG_INTEGER:
+ case GraphicsContext3D::RGB_INTEGER:
+ case GraphicsContext3D::RGBA_INTEGER:
+ return true;
+ }
+ return false;
+}
+
+WebGLAny WebGL2RenderingContext::getParameter(GC3Denum pname)
+{
+ if (isContextLostOrPending())
+ return nullptr;
+ switch (pname) {
+ case GraphicsContext3D::ACTIVE_TEXTURE:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
+ return getWebGLFloatArrayParameter(pname);
+ case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
+ return getWebGLFloatArrayParameter(pname);
+ case GraphicsContext3D::ALPHA_BITS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::ARRAY_BUFFER_BINDING:
+ return m_boundArrayBuffer;
+ case GraphicsContext3D::BLEND:
+ return getBooleanParameter(pname);
+ case GraphicsContext3D::BLEND_COLOR:
+ return getWebGLFloatArrayParameter(pname);
+ case GraphicsContext3D::BLEND_DST_ALPHA:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::BLEND_DST_RGB:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::BLEND_EQUATION_ALPHA:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::BLEND_EQUATION_RGB:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::BLEND_SRC_ALPHA:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::BLEND_SRC_RGB:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::BLUE_BITS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::COLOR_CLEAR_VALUE:
+ return getWebGLFloatArrayParameter(pname);
+ case GraphicsContext3D::COLOR_WRITEMASK:
+ return getBooleanArrayParameter(pname);
+ case GraphicsContext3D::COMPRESSED_TEXTURE_FORMATS:
+ return Uint32Array::create(m_compressedTextureFormats.data(), m_compressedTextureFormats.size());
+ case GraphicsContext3D::CULL_FACE:
+ return getBooleanParameter(pname);
+ case GraphicsContext3D::CULL_FACE_MODE:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::CURRENT_PROGRAM:
+ return m_currentProgram;
+ case GraphicsContext3D::DEPTH_BITS:
+ if (!m_framebufferBinding && !m_attributes.depth)
+ return 0;
+ return getIntParameter(pname);
+ case GraphicsContext3D::DEPTH_CLEAR_VALUE:
+ return getFloatParameter(pname);
+ case GraphicsContext3D::DEPTH_FUNC:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::DEPTH_RANGE:
+ return getWebGLFloatArrayParameter(pname);
+ case GraphicsContext3D::DEPTH_TEST:
+ return getBooleanParameter(pname);
+ case GraphicsContext3D::DEPTH_WRITEMASK:
+ return getBooleanParameter(pname);
+ case GraphicsContext3D::DITHER:
+ return getBooleanParameter(pname);
+ case GraphicsContext3D::ELEMENT_ARRAY_BUFFER_BINDING:
+ return makeRefPtr(m_boundVertexArrayObject->getElementArrayBuffer());
+ case GraphicsContext3D::FRAMEBUFFER_BINDING:
+ return m_framebufferBinding;
+ case GraphicsContext3D::FRONT_FACE:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::GENERATE_MIPMAP_HINT:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::GREEN_BITS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::IMPLEMENTATION_COLOR_READ_FORMAT:
+ return getIntParameter(pname);
+ case GraphicsContext3D::IMPLEMENTATION_COLOR_READ_TYPE:
+ return getIntParameter(pname);
+ case GraphicsContext3D::LINE_WIDTH:
+ return getFloatParameter(pname);
+ case GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_RENDERBUFFER_SIZE:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_TEXTURE_SIZE:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_VARYING_VECTORS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_VERTEX_ATTRIBS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_VIEWPORT_DIMS:
+ return getWebGLIntArrayParameter(pname);
+ case GraphicsContext3D::NUM_SHADER_BINARY_FORMATS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::PACK_ALIGNMENT:
+ return getIntParameter(pname);
+ case GraphicsContext3D::POLYGON_OFFSET_FACTOR:
+ return getFloatParameter(pname);
+ case GraphicsContext3D::POLYGON_OFFSET_FILL:
+ return getBooleanParameter(pname);
+ case GraphicsContext3D::POLYGON_OFFSET_UNITS:
+ return getFloatParameter(pname);
+ case GraphicsContext3D::RED_BITS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::RENDERBUFFER_BINDING:
+ return m_renderbufferBinding;
+ case GraphicsContext3D::RENDERER:
+ return String { ASCIILiteral { "WebKit WebGL" } };
+ case GraphicsContext3D::SAMPLE_BUFFERS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::SAMPLE_COVERAGE_INVERT:
+ return getBooleanParameter(pname);
+ case GraphicsContext3D::SAMPLE_COVERAGE_VALUE:
+ return getFloatParameter(pname);
+ case GraphicsContext3D::SAMPLES:
+ return getIntParameter(pname);
+ case GraphicsContext3D::SCISSOR_BOX:
+ return getWebGLIntArrayParameter(pname);
+ case GraphicsContext3D::SCISSOR_TEST:
+ return getBooleanParameter(pname);
+ case GraphicsContext3D::SHADING_LANGUAGE_VERSION:
+ return "WebGL GLSL ES 1.0 (" + m_context->getString(GraphicsContext3D::SHADING_LANGUAGE_VERSION) + ")";
+ case GraphicsContext3D::STENCIL_BACK_FAIL:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::STENCIL_BACK_FUNC:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_FAIL:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_PASS:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::STENCIL_BACK_REF:
+ return getIntParameter(pname);
+ case GraphicsContext3D::STENCIL_BACK_VALUE_MASK:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::STENCIL_BACK_WRITEMASK:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::STENCIL_BITS:
+ if (!m_framebufferBinding && !m_attributes.stencil)
+ return 0;
+ return getIntParameter(pname);
+ case GraphicsContext3D::STENCIL_CLEAR_VALUE:
+ return getIntParameter(pname);
+ case GraphicsContext3D::STENCIL_FAIL:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::STENCIL_FUNC:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::STENCIL_PASS_DEPTH_FAIL:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::STENCIL_PASS_DEPTH_PASS:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::STENCIL_REF:
+ return getIntParameter(pname);
+ case GraphicsContext3D::STENCIL_TEST:
+ return getBooleanParameter(pname);
+ case GraphicsContext3D::STENCIL_VALUE_MASK:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::STENCIL_WRITEMASK:
+ return getUnsignedIntParameter(pname);
+ case GraphicsContext3D::SUBPIXEL_BITS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::TEXTURE_BINDING_2D:
+ return m_textureUnits[m_activeTextureUnit].texture2DBinding;
+ case GraphicsContext3D::TEXTURE_BINDING_CUBE_MAP:
+ return m_textureUnits[m_activeTextureUnit].textureCubeMapBinding;
+ case GraphicsContext3D::UNPACK_ALIGNMENT:
+ return getIntParameter(pname);
+ case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL:
+ return m_unpackFlipY;
+ case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL:
+ return m_unpackPremultiplyAlpha;
+ case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL:
+ return m_unpackColorspaceConversion;
+ case GraphicsContext3D::VENDOR:
+ return String { ASCIILiteral { "WebKit" } };
+ case GraphicsContext3D::VERSION:
+ return "WebGL 2.0 (" + m_context->getString(GraphicsContext3D::VERSION) + ")";
+ case GraphicsContext3D::VIEWPORT:
+ return getWebGLIntArrayParameter(pname);
+ case WebGLDebugRendererInfo::UNMASKED_RENDERER_WEBGL:
+ if (m_webglDebugRendererInfo)
+ return m_context->getString(GraphicsContext3D::RENDERER);
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled");
+ return nullptr;
+ case WebGLDebugRendererInfo::UNMASKED_VENDOR_WEBGL:
+ if (m_webglDebugRendererInfo)
+ return m_context->getString(GraphicsContext3D::VENDOR);
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, WEBGL_debug_renderer_info not enabled");
+ return nullptr;
+ case Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT: // EXT_texture_filter_anisotropic
+ if (m_extTextureFilterAnisotropic)
+ return getUnsignedIntParameter(Extensions3D::MAX_TEXTURE_MAX_ANISOTROPY_EXT);
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name, EXT_texture_filter_anisotropic not enabled");
+ return nullptr;
+ case GraphicsContext3D::FRAGMENT_SHADER_DERIVATIVE_HINT:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_3D_TEXTURE_SIZE:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_ARRAY_TEXTURE_LAYERS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_COLOR_ATTACHMENTS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS:
+ return getInt64Parameter(pname);
+ case GraphicsContext3D::MAX_COMBINED_UNIFORM_BLOCKS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS:
+ return getInt64Parameter(pname);
+ case GraphicsContext3D::MAX_DRAW_BUFFERS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_ELEMENT_INDEX:
+ return getInt64Parameter(pname);
+ case GraphicsContext3D::MAX_ELEMENTS_INDICES:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_ELEMENTS_VERTICES:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_FRAGMENT_UNIFORM_COMPONENTS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_FRAGMENT_UNIFORM_BLOCKS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_PROGRAM_TEXEL_OFFSET:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_SAMPLES:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_SERVER_WAIT_TIMEOUT:
+ return getInt64Parameter(pname);
+ case GraphicsContext3D::MAX_TEXTURE_LOD_BIAS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_UNIFORM_BLOCK_SIZE:
+ return getInt64Parameter(pname);
+ case GraphicsContext3D::MAX_UNIFORM_BUFFER_BINDINGS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_VARYING_COMPONENTS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_VERTEX_OUTPUT_COMPONENTS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_VERTEX_UNIFORM_BLOCKS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MAX_VERTEX_UNIFORM_COMPONENTS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::MIN_PROGRAM_TEXEL_OFFSET:
+ return getIntParameter(pname);
+ case GraphicsContext3D::PACK_ROW_LENGTH:
+ return getIntParameter(pname);
+ case GraphicsContext3D::PACK_SKIP_PIXELS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::PACK_SKIP_ROWS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::UNPACK_IMAGE_HEIGHT:
+ return getIntParameter(pname);
+ case GraphicsContext3D::UNPACK_ROW_LENGTH:
+ return getIntParameter(pname);
+ case GraphicsContext3D::UNPACK_SKIP_IMAGES:
+ return getIntParameter(pname);
+ case GraphicsContext3D::UNPACK_SKIP_PIXELS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::UNPACK_SKIP_ROWS:
+ return getIntParameter(pname);
+ case GraphicsContext3D::RASTERIZER_DISCARD:
+ return getBooleanParameter(pname);
+ case GraphicsContext3D::SAMPLE_ALPHA_TO_COVERAGE:
+ return getBooleanParameter(pname);
+ case GraphicsContext3D::SAMPLE_COVERAGE:
+ return getBooleanParameter(pname);
+ case GraphicsContext3D::TRANSFORM_FEEDBACK_ACTIVE:
+ return getBooleanParameter(pname);
+ case GraphicsContext3D::TRANSFORM_FEEDBACK_PAUSED:
+ return getBooleanParameter(pname);
+ case GraphicsContext3D::UNIFORM_BUFFER_OFFSET_ALIGNMENT:
+ return getIntParameter(pname);
+ case GraphicsContext3D::VERTEX_ARRAY_BINDING:
+ if (m_boundVertexArrayObject->isDefaultObject())
+ return nullptr;
+ return makeRefPtr(static_cast<WebGLVertexArrayObject&>(*m_boundVertexArrayObject));
+ case GraphicsContext3D::DRAW_BUFFER0:
+ case GraphicsContext3D::DRAW_BUFFER1:
+ case GraphicsContext3D::DRAW_BUFFER2:
+ case GraphicsContext3D::DRAW_BUFFER3:
+ case GraphicsContext3D::DRAW_BUFFER4:
+ case GraphicsContext3D::DRAW_BUFFER5:
+ case GraphicsContext3D::DRAW_BUFFER6:
+ case GraphicsContext3D::DRAW_BUFFER7:
+ case GraphicsContext3D::DRAW_BUFFER8:
+ case GraphicsContext3D::DRAW_BUFFER9:
+ case GraphicsContext3D::DRAW_BUFFER10:
+ case GraphicsContext3D::DRAW_BUFFER11:
+ case GraphicsContext3D::DRAW_BUFFER12:
+ case GraphicsContext3D::DRAW_BUFFER13:
+ case GraphicsContext3D::DRAW_BUFFER14:
+ case GraphicsContext3D::DRAW_BUFFER15:
+ if (m_framebufferBinding)
+ return m_framebufferBinding->getDrawBuffer(pname);
+ return m_backDrawBuffer; // emulated backbuffer
+ case GraphicsContext3D::COPY_READ_BUFFER:
+ case GraphicsContext3D::COPY_WRITE_BUFFER:
+ case GraphicsContext3D::PIXEL_PACK_BUFFER_BINDING:
+ case GraphicsContext3D::PIXEL_UNPACK_BUFFER_BINDING:
+ case GraphicsContext3D::READ_BUFFER:
+ case GraphicsContext3D::SAMPLER_BINDING:
+ case GraphicsContext3D::TEXTURE_BINDING_2D_ARRAY:
+ case GraphicsContext3D::TEXTURE_BINDING_3D:
+ case GraphicsContext3D::READ_FRAMEBUFFER_BINDING:
+ case GraphicsContext3D::TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ case GraphicsContext3D::UNIFORM_BUFFER_BINDING:
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "parameter name not yet supported");
+ return nullptr;
+ default:
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "getParameter", "invalid parameter name");
+ return nullptr;
+ }
+}
+
+bool WebGL2RenderingContext::validateIndexArrayConservative(GC3Denum type, unsigned& numElementsRequired)
+{
+ // Performs conservative validation by caching a maximum index of
+ // the given type per element array buffer. If all of the bound
+ // array buffers have enough elements to satisfy that maximum
+ // index, skips the expensive per-draw-call iteration in
+ // validateIndexArrayPrecise.
+
+ RefPtr<WebGLBuffer> elementArrayBuffer = m_boundVertexArrayObject->getElementArrayBuffer();
+
+ if (!elementArrayBuffer)
+ return false;
+
+ GC3Dsizeiptr numElements = elementArrayBuffer->byteLength();
+ // The case count==0 is already dealt with in drawElements before validateIndexArrayConservative.
+ if (!numElements)
+ return false;
+ auto* buffer = elementArrayBuffer->elementArrayBuffer();
+ ASSERT(buffer);
+
+ std::optional<unsigned> maxIndex = elementArrayBuffer->getCachedMaxIndex(type);
+ if (!maxIndex) {
+ // Compute the maximum index in the entire buffer for the given type of index.
+ switch (type) {
+ case GraphicsContext3D::UNSIGNED_BYTE: {
+ const GC3Dubyte* p = static_cast<const GC3Dubyte*>(buffer->data());
+ for (GC3Dsizeiptr i = 0; i < numElements; i++)
+ maxIndex = maxIndex ? std::max(maxIndex.value(), static_cast<unsigned>(p[i])) : static_cast<unsigned>(p[i]);
+ break;
+ }
+ case GraphicsContext3D::UNSIGNED_SHORT: {
+ numElements /= sizeof(GC3Dushort);
+ const GC3Dushort* p = static_cast<const GC3Dushort*>(buffer->data());
+ for (GC3Dsizeiptr i = 0; i < numElements; i++)
+ maxIndex = maxIndex ? std::max(maxIndex.value(), static_cast<unsigned>(p[i])) : static_cast<unsigned>(p[i]);
+ break;
+ }
+ case GraphicsContext3D::UNSIGNED_INT: {
+ numElements /= sizeof(GC3Duint);
+ const GC3Duint* p = static_cast<const GC3Duint*>(buffer->data());
+ for (GC3Dsizeiptr i = 0; i < numElements; i++)
+ maxIndex = maxIndex ? std::max(maxIndex.value(), static_cast<unsigned>(p[i])) : static_cast<unsigned>(p[i]);
+ break;
+ }
+ default:
+ return false;
+ }
+ if (maxIndex)
+ elementArrayBuffer->setCachedMaxIndex(type, maxIndex.value());
+ }
+
+ if (!maxIndex)
+ return false;
+
+ // The number of required elements is one more than the maximum
+ // index that will be accessed.
+ numElementsRequired = maxIndex.value() + 1;
+
+ // Check for overflow.
+ return numElementsRequired > 0;
+}
+
+bool WebGL2RenderingContext::validateBlendEquation(const char* functionName, GC3Denum mode)
+{
+ switch (mode) {
+ case GraphicsContext3D::FUNC_ADD:
+ case GraphicsContext3D::FUNC_SUBTRACT:
+ case GraphicsContext3D::FUNC_REVERSE_SUBTRACT:
+ case GraphicsContext3D::MIN:
+ case GraphicsContext3D::MAX:
+ return true;
+ default:
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid mode");
+ return false;
+ }
+}
+
+bool WebGL2RenderingContext::validateCapability(const char* functionName, GC3Denum cap)
+{
+ switch (cap) {
+ case GraphicsContext3D::BLEND:
+ case GraphicsContext3D::CULL_FACE:
+ case GraphicsContext3D::DEPTH_TEST:
+ case GraphicsContext3D::DITHER:
+ case GraphicsContext3D::POLYGON_OFFSET_FILL:
+ case GraphicsContext3D::SAMPLE_ALPHA_TO_COVERAGE:
+ case GraphicsContext3D::SAMPLE_COVERAGE:
+ case GraphicsContext3D::SCISSOR_TEST:
+ case GraphicsContext3D::STENCIL_TEST:
+ case GraphicsContext3D::RASTERIZER_DISCARD:
+ return true;
+ default:
+ synthesizeGLError(GraphicsContext3D::INVALID_ENUM, functionName, "invalid capability");
+ return false;
+ }
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBGL)