summaryrefslogtreecommitdiff
path: root/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.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/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp')
-rw-r--r--Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp446
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)