diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp')
-rw-r--r-- | Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp | 446 |
1 files changed, 366 insertions, 80 deletions
diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp index c1356a0e9..1536faf42 100644 --- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp +++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp @@ -13,10 +13,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -28,7 +28,7 @@ #include "config.h" -#if USE(3D_GRAPHICS) +#if ENABLE(GRAPHICS_CONTEXT_3D) #include "GraphicsContext3D.h" #if PLATFORM(IOS) @@ -40,26 +40,26 @@ #else #include "Extensions3DOpenGL.h" #endif +#include "ANGLEWebKitBridge.h" #include "GraphicsContext.h" #include "ImageBuffer.h" #include "ImageData.h" #include "IntRect.h" #include "IntSize.h" #include "Logging.h" -#include "NotImplemented.h" #include "TemporaryOpenGLSetting.h" +#include "WebGLRenderingContextBase.h" #include <cstring> -#include <runtime/ArrayBuffer.h> -#include <runtime/ArrayBufferView.h> -#include <runtime/Float32Array.h> -#include <runtime/Int32Array.h> -#include <runtime/Uint8Array.h> +#include <wtf/HexNumber.h> #include <wtf/MainThread.h> +#include <wtf/ThreadSpecific.h> #include <wtf/text/CString.h> +#include <wtf/text/StringBuilder.h> #include <yarr/RegularExpression.h> #if PLATFORM(IOS) #import <OpenGLES/ES2/glext.h> +#import <OpenGLES/ES3/gl.h> // From <OpenGLES/glext.h> #define GL_RGBA32F_ARB 0x8814 #define GL_RGB32F_ARB 0x8815 @@ -67,15 +67,35 @@ #if USE(OPENGL_ES_2) #include "OpenGLESShims.h" #elif PLATFORM(MAC) +#define GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED #include <OpenGL/gl.h> -#elif PLATFORM(GTK) || PLATFORM(EFL) || PLATFORM(WIN) +#include <OpenGL/gl3.h> +#include <OpenGL/gl3ext.h> +#undef GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED +#elif PLATFORM(GTK) || PLATFORM(WIN) #include "OpenGLShims.h" #endif #endif +using namespace WTF; + namespace WebCore { -static ShaderNameHash* currentNameHashMapForShader; +static ThreadSpecific<ShaderNameHash*>& getCurrentNameHashMapForShader() +{ + static std::once_flag onceFlag; + static ThreadSpecific<ShaderNameHash*>* sharedNameHash; + std::call_once(onceFlag, [] { + sharedNameHash = new ThreadSpecific<ShaderNameHash*>; + }); + + return *sharedNameHash; +} + +static void setCurrentNameHashMapForShader(ShaderNameHash* shaderNameHash) +{ + *getCurrentNameHashMapForShader() = shaderNameHash; +} // Hash function used by the ANGLE translator/compiler to do // symbol name mangling. Since this is a static method, before @@ -90,11 +110,10 @@ static uint64_t nameHashForShader(const char* name, size_t length) CString nameAsCString = CString(name); // Look up name in our local map. - if (currentNameHashMapForShader) { - ShaderNameHash::iterator result = currentNameHashMapForShader->find(nameAsCString); - if (result != currentNameHashMapForShader->end()) - return result->value; - } + ShaderNameHash*& currentNameHashMapForShader = *getCurrentNameHashMapForShader(); + ShaderNameHash::iterator findResult = currentNameHashMapForShader->find(nameAsCString); + if (findResult != currentNameHashMapForShader->end()) + return findResult->value; unsigned hashValue = nameAsCString.hash(); @@ -111,37 +130,39 @@ static uint64_t nameHashForShader(const char* name, size_t length) return result; } -PassRefPtr<GraphicsContext3D> GraphicsContext3D::createForCurrentGLContext() +RefPtr<GraphicsContext3D> GraphicsContext3D::createForCurrentGLContext() { - RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(Attributes(), 0, GraphicsContext3D::RenderToCurrentGLContext)); - return context->m_private ? context.release() : 0; + auto context = adoptRef(*new GraphicsContext3D({ }, 0, GraphicsContext3D::RenderToCurrentGLContext)); +#if USE(TEXTURE_MAPPER) + if (!context->m_texmapLayer) + return nullptr; +#else + if (!context->m_private) + return nullptr; +#endif + return WTFMove(context); } void GraphicsContext3D::validateDepthStencil(const char* packedDepthStencilExtension) { - Extensions3D* extensions = getExtensions(); + Extensions3D& extensions = getExtensions(); if (m_attrs.stencil) { - if (extensions->supports(packedDepthStencilExtension)) { - extensions->ensureEnabled(packedDepthStencilExtension); + if (extensions.supports(packedDepthStencilExtension)) { + extensions.ensureEnabled(packedDepthStencilExtension); // Force depth if stencil is true. m_attrs.depth = true; } else m_attrs.stencil = false; } if (m_attrs.antialias) { - if (!extensions->maySupportMultisampling() || !extensions->supports("GL_ANGLE_framebuffer_multisample") || isGLES2Compliant()) + if (!extensions.supports("GL_ANGLE_framebuffer_multisample") || isGLES2Compliant()) m_attrs.antialias = false; else - extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample"); + extensions.ensureEnabled("GL_ANGLE_framebuffer_multisample"); } } -bool GraphicsContext3D::isResourceSafe() -{ - return false; -} - -void GraphicsContext3D::paintRenderingResultsToCanvas(ImageBuffer* imageBuffer, DrawingBuffer*) +void GraphicsContext3D::paintRenderingResultsToCanvas(ImageBuffer* imageBuffer) { int rowBytes = m_currentWidth * 4; int totalBytes = rowBytes * m_currentHeight; @@ -165,8 +186,7 @@ void GraphicsContext3D::paintRenderingResultsToCanvas(ImageBuffer* imageBuffer, paintToCanvas(pixels.get(), m_currentWidth, m_currentHeight, imageBuffer->internalSize().width(), imageBuffer->internalSize().height(), imageBuffer->context()); #else - paintToCanvas(pixels.get(), m_currentWidth, m_currentHeight, - imageBuffer->internalSize().width(), imageBuffer->internalSize().height(), imageBuffer->context()->platformContext()); + paintToCanvas(pixels.get(), m_currentWidth, m_currentHeight, imageBuffer->internalSize().width(), imageBuffer->internalSize().height(), imageBuffer->context().platformContext()); #endif #if PLATFORM(IOS) @@ -180,14 +200,14 @@ bool GraphicsContext3D::paintCompositedResultsToCanvas(ImageBuffer*) return false; } -PassRefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData(DrawingBuffer*) +RefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData() { // Reading premultiplied alpha would involve unpremultiplying, which is // lossy. if (m_attrs.premultipliedAlpha) - return 0; + return nullptr; - RefPtr<ImageData> imageData = ImageData::create(IntSize(m_currentWidth, m_currentHeight)); + auto imageData = ImageData::create(IntSize(m_currentWidth, m_currentHeight)); unsigned char* pixels = imageData->data()->data(); int totalBytes = 4 * m_currentWidth * m_currentHeight; @@ -197,7 +217,7 @@ PassRefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData(Drawin for (int i = 0; i < totalBytes; i += 4) std::swap(pixels[i], pixels[i + 2]); - return imageData.release(); + return imageData; } void GraphicsContext3D::prepareTexture() @@ -207,12 +227,28 @@ void GraphicsContext3D::prepareTexture() makeContextCurrent(); +#if !USE(COORDINATED_GRAPHICS_THREADED) TemporaryOpenGLSetting scopedScissor(GL_SCISSOR_TEST, GL_FALSE); TemporaryOpenGLSetting scopedDither(GL_DITHER, GL_FALSE); - +#endif + if (m_attrs.antialias) resolveMultisamplingIfNecessary(); +#if USE(COORDINATED_GRAPHICS_THREADED) + std::swap(m_texture, m_compositorTexture); + std::swap(m_texture, m_intermediateTexture); + ::glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); + ::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0); + glFlush(); + + if (m_state.boundFBO != m_fbo) + ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_state.boundFBO); + else + ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo); + return; +#endif + ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo); ::glActiveTexture(GL_TEXTURE0); ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture); @@ -221,8 +257,7 @@ void GraphicsContext3D::prepareTexture() ::glActiveTexture(m_state.activeTexture); if (m_state.boundFBO != m_fbo) ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_state.boundFBO); - ::glFinish(); - m_layerComposited = true; + ::glFlush(); } void GraphicsContext3D::readRenderingResults(unsigned char *pixels, int pixelsSize) @@ -271,11 +306,6 @@ void GraphicsContext3D::reshape(int width, int height) markContextChanged(); -#if PLATFORM(EFL) && USE(GRAPHICS_SURFACE) - ::glFlush(); // Make sure all GL calls have been committed before resizing. - createGraphicsSurfaces(IntSize(width, height)); -#endif - m_currentWidth = width; m_currentHeight = height; @@ -334,6 +364,49 @@ void GraphicsContext3D::reshape(int width, int height) ::glFlush(); } +bool GraphicsContext3D::checkVaryingsPacking(Platform3DObject vertexShader, Platform3DObject fragmentShader) const +{ + ASSERT(m_shaderSourceMap.contains(vertexShader)); + ASSERT(m_shaderSourceMap.contains(fragmentShader)); + const auto& vertexEntry = m_shaderSourceMap.find(vertexShader)->value; + const auto& fragmentEntry = m_shaderSourceMap.find(fragmentShader)->value; + + HashMap<String, sh::ShaderVariable> combinedVaryings; + for (const auto& vertexSymbol : vertexEntry.varyingMap) { + const String& symbolName = vertexSymbol.key; + // The varying map includes variables for each index of an array variable. + // We only want a single variable to represent the array. + if (symbolName.endsWith("]")) + continue; + + // Don't count built in varyings. + if (symbolName == "gl_FragCoord" || symbolName == "gl_FrontFacing" || symbolName == "gl_PointCoord") + continue; + + const auto& fragmentSymbol = fragmentEntry.varyingMap.find(symbolName); + if (fragmentSymbol != fragmentEntry.varyingMap.end()) + combinedVaryings.add(symbolName, fragmentSymbol->value); + } + + size_t numVaryings = combinedVaryings.size(); + if (!numVaryings) + return true; + + std::vector<sh::ShaderVariable> variables; + variables.reserve(combinedVaryings.size()); + for (const auto& varyingSymbol : combinedVaryings.values()) + variables.push_back(varyingSymbol); + + GC3Dint maxVaryingVectors = 0; +#if !PLATFORM(IOS) && !((PLATFORM(WIN) || PLATFORM(GTK)) && USE(OPENGL_ES_2)) + GC3Dint maxVaryingFloats = 0; + ::glGetIntegerv(GL_MAX_VARYING_FLOATS, &maxVaryingFloats); + maxVaryingVectors = maxVaryingFloats / 4; +#else + ::glGetIntegerv(MAX_VARYING_VECTORS, &maxVaryingVectors); +#endif + return ShCheckVariablesWithinPackingLimits(maxVaryingVectors, variables); +} bool GraphicsContext3D::precisionsMatch(Platform3DObject vertexShader, Platform3DObject fragmentShader) const { @@ -342,13 +415,16 @@ bool GraphicsContext3D::precisionsMatch(Platform3DObject vertexShader, Platform3 const auto& vertexEntry = m_shaderSourceMap.find(vertexShader)->value; const auto& fragmentEntry = m_shaderSourceMap.find(fragmentShader)->value; - HashMap<String, ShPrecisionType> vertexSymbolPrecisionMap; + HashMap<String, sh::GLenum> vertexSymbolPrecisionMap; - for (const auto& entry : vertexEntry.uniformMap) - vertexSymbolPrecisionMap.add(entry.value.mappedName, entry.value.precision); + for (const auto& entry : vertexEntry.uniformMap) { + const std::string& mappedName = entry.value.mappedName; + vertexSymbolPrecisionMap.add(String(mappedName.c_str(), mappedName.length()), entry.value.precision); + } for (const auto& entry : fragmentEntry.uniformMap) { - const auto& vertexSymbol = vertexSymbolPrecisionMap.find(entry.value.mappedName); + const std::string& mappedName = entry.value.mappedName; + const auto& vertexSymbol = vertexSymbolPrecisionMap.find(String(mappedName.c_str(), mappedName.length())); if (vertexSymbol != vertexSymbolPrecisionMap.end() && vertexSymbol->value != entry.value.precision) return false; } @@ -373,6 +449,7 @@ void GraphicsContext3D::attachShader(Platform3DObject program, Platform3DObject ASSERT(program); ASSERT(shader); makeContextCurrent(); + m_shaderProgramSymbolCountMap.remove(program); ::glAttachShader(program, shader); } @@ -470,6 +547,38 @@ void GraphicsContext3D::bufferSubData(GC3Denum target, GC3Dintptr offset, GC3Dsi ::glBufferSubData(target, offset, size, data); } +#if PLATFORM(MAC) || PLATFORM(IOS) +void* GraphicsContext3D::mapBufferRange(GC3Denum target, GC3Dintptr offset, GC3Dsizeiptr length, GC3Dbitfield access) +{ + makeContextCurrent(); + return ::glMapBufferRange(target, offset, length, access); +} + +GC3Dboolean GraphicsContext3D::unmapBuffer(GC3Denum target) +{ + makeContextCurrent(); + return ::glUnmapBuffer(target); +} + +void GraphicsContext3D::copyBufferSubData(GC3Denum readTarget, GC3Denum writeTarget, GC3Dintptr readOffset, GC3Dintptr writeOffset, GC3Dsizeiptr size) +{ + makeContextCurrent(); + ::glCopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size); +} + +void GraphicsContext3D::texStorage2D(GC3Denum target, GC3Dsizei levels, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) +{ + makeContextCurrent(); + ::glTexStorage2D(target, levels, internalformat, width, height); +} + +void GraphicsContext3D::texStorage3D(GC3Denum target, GC3Dsizei levels, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dsizei depth) +{ + makeContextCurrent(); + ::glTexStorage3D(target, levels, internalformat, width, height, depth); +} +#endif + GC3Denum GraphicsContext3D::checkFramebufferStatus(GC3Denum target) { makeContextCurrent(); @@ -512,15 +621,15 @@ void GraphicsContext3D::compileShader(Platform3DObject shader) ANGLEResources.HashFunction = nameHashForShader; if (!nameHashMapForShaders) - nameHashMapForShaders = adoptPtr(new ShaderNameHash); - currentNameHashMapForShader = nameHashMapForShaders.get(); + nameHashMapForShaders = std::make_unique<ShaderNameHash>(); + setCurrentNameHashMapForShader(nameHashMapForShaders.get()); m_compiler.setResources(ANGLEResources); String translatedShaderSource = m_extensions->getTranslatedShaderSourceANGLE(shader); ANGLEResources.HashFunction = previousHashFunction; m_compiler.setResources(ANGLEResources); - currentNameHashMapForShader = nullptr; + setCurrentNameHashMapForShader(nullptr); if (!translatedShaderSource.length()) return; @@ -560,8 +669,6 @@ void GraphicsContext3D::compileShader(Platform3DObject shader) entry.isValid = false; LOG(WebGL, "Error: shader translator produced a shader that OpenGL would not compile."); } - - m_shaderSymbolCount = nullptr; } void GraphicsContext3D::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) @@ -611,6 +718,7 @@ void GraphicsContext3D::detachShader(Platform3DObject program, Platform3DObject ASSERT(program); ASSERT(shader); makeContextCurrent(); + m_shaderProgramSymbolCountMap.remove(program); ::glDetachShader(program, shader); } @@ -630,12 +738,14 @@ void GraphicsContext3D::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count { makeContextCurrent(); ::glDrawArrays(mode, first, count); + checkGPUStatusIfNecessary(); } void GraphicsContext3D::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset) { makeContextCurrent(); ::glDrawElements(mode, count, type, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset))); + checkGPUStatusIfNecessary(); } void GraphicsContext3D::enable(GC3Denum cap) @@ -718,8 +828,15 @@ bool GraphicsContext3D::getActiveAttribImpl(Platform3DObject program, GC3Duint i bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo& info) { - ASSERT(!m_shaderSymbolCount || index < m_shaderSymbolCount->filteredToActualAttributeIndexMap.size()); - GC3Duint rawIndex = (m_shaderSymbolCount) ? m_shaderSymbolCount->filteredToActualAttributeIndexMap[index] : index; + GC3Dint symbolCount; + auto result = m_shaderProgramSymbolCountMap.find(program); + if (result == m_shaderProgramSymbolCountMap.end()) { + getNonBuiltInActiveSymbolCount(program, GraphicsContext3D::ACTIVE_ATTRIBUTES, &symbolCount); + result = m_shaderProgramSymbolCountMap.find(program); + } + + ActiveShaderSymbolCounts& symbolCounts = result->value; + GC3Duint rawIndex = (index < symbolCounts.filteredToActualAttributeIndexMap.size()) ? symbolCounts.filteredToActualAttributeIndexMap[index] : -1; return getActiveAttribImpl(program, rawIndex, info); } @@ -758,8 +875,15 @@ bool GraphicsContext3D::getActiveUniformImpl(Platform3DObject program, GC3Duint bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info) { - ASSERT(!m_shaderSymbolCount || index < m_shaderSymbolCount->filteredToActualUniformIndexMap.size()); - GC3Duint rawIndex = (m_shaderSymbolCount) ? m_shaderSymbolCount->filteredToActualUniformIndexMap[index] : index; + GC3Dint symbolCount; + auto result = m_shaderProgramSymbolCountMap.find(program); + if (result == m_shaderProgramSymbolCountMap.end()) { + getNonBuiltInActiveSymbolCount(program, GraphicsContext3D::ACTIVE_UNIFORMS, &symbolCount); + result = m_shaderProgramSymbolCountMap.find(program); + } + + ActiveShaderSymbolCounts& symbolCounts = result->value; + GC3Duint rawIndex = (index < symbolCounts.filteredToActualUniformIndexMap.size()) ? symbolCounts.filteredToActualUniformIndexMap[index] : -1; return getActiveUniformImpl(program, rawIndex, info); } @@ -774,10 +898,21 @@ void GraphicsContext3D::getAttachedShaders(Platform3DObject program, GC3Dsizei m ::glGetAttachedShaders(program, maxCount, count, shaders); } +static String generateHashedName(const String& name) +{ + if (name.isEmpty()) + return name; + uint64_t number = nameHashForShader(name.utf8().data(), name.length()); + StringBuilder builder; + builder.appendLiteral("webgl_"); + appendUnsigned64AsHex(number, builder, Lowercase); + return builder.toString(); +} + String GraphicsContext3D::mappedSymbolName(Platform3DObject program, ANGLEShaderSymbolType symbolType, const String& name) { - GC3Dsizei count; - Platform3DObject shaders[2]; + GC3Dsizei count = 0; + Platform3DObject shaders[2] = { }; getAttachedShaders(program, 2, &count, shaders); for (GC3Dsizei i = 0; i < count; ++i) { @@ -787,9 +922,28 @@ String GraphicsContext3D::mappedSymbolName(Platform3DObject program, ANGLEShader const ShaderSymbolMap& symbolMap = result->value.symbolMap(symbolType); ShaderSymbolMap::const_iterator symbolEntry = symbolMap.find(name); - if (symbolEntry != symbolMap.end()) - return symbolEntry->value.mappedName; + if (symbolEntry != symbolMap.end()) { + const std::string& mappedName = symbolEntry->value.mappedName; + return String(mappedName.c_str(), mappedName.length()); + } } + + if (symbolType == SHADER_SYMBOL_TYPE_ATTRIBUTE && !name.isEmpty()) { + // Attributes are a special case: they may be requested before any shaders have been compiled, + // and aren't even required to be used in any shader program. + if (!nameHashMapForShaders) + nameHashMapForShaders = std::make_unique<ShaderNameHash>(); + setCurrentNameHashMapForShader(nameHashMapForShaders.get()); + + String generatedName = generateHashedName(name); + + setCurrentNameHashMapForShader(nullptr); + + m_possiblyUnusedAttributeMap.set(generatedName, name); + + return generatedName; + } + return name; } @@ -806,10 +960,20 @@ String GraphicsContext3D::originalSymbolName(Platform3DObject program, ANGLEShad const ShaderSymbolMap& symbolMap = result->value.symbolMap(symbolType); for (const auto& symbolEntry : symbolMap) { - if (symbolEntry.value.mappedName == name) + if (name == symbolEntry.value.mappedName.c_str()) return symbolEntry.key; } } + + if (symbolType == SHADER_SYMBOL_TYPE_ATTRIBUTE && !name.isEmpty()) { + // Attributes are a special case: they may be requested before any shaders have been compiled, + // and aren't even required to be used in any shader program. + + const auto& cached = m_possiblyUnusedAttributeMap.find(name); + if (cached != m_possiblyUnusedAttributeMap.end()) + return cached->value; + } + return name; } @@ -823,7 +987,7 @@ String GraphicsContext3D::mappedSymbolName(Platform3DObject shaders[2], size_t c const ShaderSymbolMap& symbolMap = result->value.symbolMap(static_cast<enum ANGLEShaderSymbolType>(symbolType)); for (const auto& symbolEntry : symbolMap) { - if (symbolEntry.value.mappedName == name) + if (name == symbolEntry.value.mappedName.c_str()) return symbolEntry.key; } } @@ -843,18 +1007,38 @@ int GraphicsContext3D::getAttribLocation(Platform3DObject program, const String& return ::glGetAttribLocation(program, mappedName.utf8().data()); } -GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes() +GraphicsContext3DAttributes GraphicsContext3D::getContextAttributes() { return m_attrs; } +bool GraphicsContext3D::moveErrorsToSyntheticErrorList() +{ + makeContextCurrent(); + bool movedAnError = false; + + // Set an arbitrary limit of 100 here to avoid creating a hang if + // a problem driver has a bug that causes it to never clear the error. + // Otherwise, we would just loop until we got NO_ERROR. + for (unsigned i = 0; i < 100; ++i) { + GC3Denum error = glGetError(); + if (error == NO_ERROR) + break; + m_syntheticErrors.add(error); + movedAnError = true; + } + + return movedAnError; +} + GC3Denum GraphicsContext3D::getError() { - if (m_syntheticErrors.size() > 0) { - ListHashSet<GC3Denum>::iterator iter = m_syntheticErrors.begin(); - GC3Denum err = *iter; - m_syntheticErrors.remove(iter); - return err; + if (!m_syntheticErrors.isEmpty()) { + // Need to move the current errors to the synthetic error list in case + // that error is already there, since the expected behavior of both + // glGetError and getError is to only report each error code once. + moveErrorsToSyntheticErrorList(); + return m_syntheticErrors.takeFirst(); } makeContextCurrent(); @@ -1228,6 +1412,57 @@ void GraphicsContext3D::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsize ::glViewport(x, y, width, height); } +Platform3DObject GraphicsContext3D::createVertexArray() +{ + makeContextCurrent(); + GLuint array = 0; +#if !USE(OPENGL_ES_2) && (PLATFORM(GTK) || PLATFORM(WIN) || PLATFORM(IOS)) + glGenVertexArrays(1, &array); +#elif defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object + glGenVertexArraysAPPLE(1, &array); +#endif + return array; +} + +void GraphicsContext3D::deleteVertexArray(Platform3DObject array) +{ + if (!array) + return; + + makeContextCurrent(); +#if !USE(OPENGL_ES_2) && (PLATFORM(GTK) || PLATFORM(WIN) || PLATFORM(IOS)) + glDeleteVertexArrays(1, &array); +#elif defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object + glDeleteVertexArraysAPPLE(1, &array); +#endif +} + +GC3Dboolean GraphicsContext3D::isVertexArray(Platform3DObject array) +{ + if (!array) + return GL_FALSE; + + makeContextCurrent(); +#if !USE(OPENGL_ES_2) && (PLATFORM(GTK) || PLATFORM(WIN) || PLATFORM(IOS)) + return glIsVertexArray(array); +#elif defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object + return glIsVertexArrayAPPLE(array); +#endif + return GL_FALSE; +} + +void GraphicsContext3D::bindVertexArray(Platform3DObject array) +{ + makeContextCurrent(); +#if !USE(OPENGL_ES_2) && (PLATFORM(GTK) || PLATFORM(WIN) || PLATFORM(IOS)) + glBindVertexArray(array); +#elif defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object + glBindVertexArrayAPPLE(array); +#else + UNUSED_PARAM(array); +#endif +} + void GraphicsContext3D::getBooleanv(GC3Denum pname, GC3Dboolean* value) { makeContextCurrent(); @@ -1245,6 +1480,15 @@ void GraphicsContext3D::getFloatv(GC3Denum pname, GC3Dfloat* value) makeContextCurrent(); ::glGetFloatv(pname, value); } + +void GraphicsContext3D::getInteger64v(GC3Denum pname, GC3Dint64* value) +{ + UNUSED_PARAM(pname); + makeContextCurrent(); + *value = 0; + // FIXME 141178: Before enabling this we must first switch over to using gl3.h and creating and initialing the WebGL2 context using OpenGL ES 3.0. + // ::glGetInteger64v(pname, value); +} void GraphicsContext3D::getFramebufferAttachmentParameteriv(GC3Denum target, GC3Denum attachment, GC3Denum pname, GC3Dint* value) { @@ -1267,13 +1511,14 @@ void GraphicsContext3D::getNonBuiltInActiveSymbolCount(Platform3DObject program, return; makeContextCurrent(); - - if (m_shaderSymbolCount) { - *value = m_shaderSymbolCount->countForType(pname); + const auto& result = m_shaderProgramSymbolCountMap.find(program); + if (result != m_shaderProgramSymbolCountMap.end()) { + *value = result->value.countForType(pname); return; } - m_shaderSymbolCount = std::make_unique<ActiveShaderSymbolCounts>(); + m_shaderProgramSymbolCountMap.set(program, ActiveShaderSymbolCounts()); + ActiveShaderSymbolCounts& symbolCounts = m_shaderProgramSymbolCountMap.find(program)->value; // Retrieve the active attributes, build a filtered count, and a mapping of // our internal attributes indexes to the real unfiltered indexes inside OpenGL. @@ -1285,7 +1530,7 @@ void GraphicsContext3D::getNonBuiltInActiveSymbolCount(Platform3DObject program, if (info.name.startsWith("gl_")) continue; - m_shaderSymbolCount->filteredToActualAttributeIndexMap.append(i); + symbolCounts.filteredToActualAttributeIndexMap.append(i); } // Do the same for uniforms. @@ -1297,10 +1542,10 @@ void GraphicsContext3D::getNonBuiltInActiveSymbolCount(Platform3DObject program, if (info.name.startsWith("gl_")) continue; - m_shaderSymbolCount->filteredToActualUniformIndexMap.append(i); + symbolCounts.filteredToActualUniformIndexMap.append(i); } - *value = m_shaderSymbolCount->countForType(pname); + *value = symbolCounts.countForType(pname); } String GraphicsContext3D::getUnmangledInfoLog(Platform3DObject shaders[2], GC3Dsizei count, const String& log) @@ -1309,7 +1554,7 @@ String GraphicsContext3D::getUnmangledInfoLog(Platform3DObject shaders[2], GC3Ds JSC::Yarr::RegularExpression regExp("webgl_[0123456789abcdefABCDEF]+", TextCaseSensitive); - String processedLog; + StringBuilder processedLog; int startFrom = 0; int matchedLength = 0; @@ -1329,8 +1574,8 @@ String GraphicsContext3D::getUnmangledInfoLog(Platform3DObject shaders[2], GC3Ds processedLog.append(log.substring(startFrom, log.length() - startFrom)); - LOG(WebGL, "-->: %s", processedLog.utf8().data()); - return processedLog; + LOG(WebGL, "-->: %s", processedLog.toString().utf8().data()); + return processedLog.toString(); } String GraphicsContext3D::getProgramInfoLog(Platform3DObject program) @@ -1501,6 +1746,12 @@ void GraphicsContext3D::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xo type = GL_HALF_FLOAT_ARB; #endif + if (m_usingCoreProfile && format == ALPHA) { + // We are using a core profile. This means that GL_ALPHA, which is a valid format in WebGL for texSubImage2D + // is not supported in OpenGL. We are using GL_RED to back GL_ALPHA, so do it here as well. + format = RED; + } + // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size. ::glTexSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels); } @@ -1606,6 +1857,10 @@ void GraphicsContext3D::deleteTexture(Platform3DObject texture) void GraphicsContext3D::synthesizeGLError(GC3Denum error) { + // Need to move the current errors to the synthetic error list to + // preserve the order of errors, so a caller to getError will get + // any errors from glError before the error we are synthesizing. + moveErrorsToSyntheticErrorList(); m_syntheticErrors.add(error); } @@ -1624,12 +1879,43 @@ bool GraphicsContext3D::layerComposited() const return m_layerComposited; } +void GraphicsContext3D::forceContextLost() +{ +#if ENABLE(WEBGL) + if (m_webglContext) + m_webglContext->forceLostContext(WebGLRenderingContextBase::RealLostContext); +#endif +} + +void GraphicsContext3D::recycleContext() +{ +#if ENABLE(WEBGL) + if (m_webglContext) + m_webglContext->recycleContext(); +#endif +} + void GraphicsContext3D::texImage2DDirect(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels) { makeContextCurrent(); ::glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels); } +void GraphicsContext3D::drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount) +{ + getExtensions().drawArraysInstanced(mode, first, count, primcount); +} + +void GraphicsContext3D::drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset, GC3Dsizei primcount) +{ + getExtensions().drawElementsInstanced(mode, count, type, offset, primcount); +} + +void GraphicsContext3D::vertexAttribDivisor(GC3Duint index, GC3Duint divisor) +{ + getExtensions().vertexAttribDivisor(index, divisor); +} + } -#endif // USE(3D_GRAPHICS) +#endif // ENABLE(GRAPHICS_CONTEXT_3D) |