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 | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/platform/graphics/opengl')
15 files changed, 1534 insertions, 332 deletions
diff --git a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp index f8321cac0..5da632035 100644 --- a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp +++ b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp @@ -25,20 +25,17 @@ #include "config.h" -#if USE(3D_GRAPHICS) +#if ENABLE(GRAPHICS_CONTEXT_3D) #include "Extensions3DOpenGL.h" #include "GraphicsContext3D.h" -#include <wtf/Vector.h> #if PLATFORM(IOS) -#include "ANGLE/ShaderLang.h" #include <OpenGLES/ES2/glext.h> #elif PLATFORM(MAC) -#include "ANGLE/ShaderLang.h" #include <OpenGL/gl.h> -#elif PLATFORM(GTK) || PLATFORM(EFL) || PLATFORM(WIN) +#elif PLATFORM(GTK) || PLATFORM(WIN) #include "OpenGLShims.h" #endif @@ -48,8 +45,8 @@ namespace WebCore { -Extensions3DOpenGL::Extensions3DOpenGL(GraphicsContext3D* context) - : Extensions3DOpenGLCommon(context) +Extensions3DOpenGL::Extensions3DOpenGL(GraphicsContext3D* context, bool useIndexedGetString) + : Extensions3DOpenGLCommon(context, useIndexedGetString) { } @@ -86,7 +83,7 @@ Platform3DObject Extensions3DOpenGL::createVertexArrayOES() { m_context->makeContextCurrent(); GLuint array = 0; -#if (PLATFORM(GTK) || PLATFORM(EFL) || PLATFORM(WIN)) +#if (PLATFORM(GTK) || PLATFORM(WIN) || PLATFORM(IOS)) if (isVertexArrayObjectSupported()) glGenVertexArrays(1, &array); #elif defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object @@ -101,7 +98,7 @@ void Extensions3DOpenGL::deleteVertexArrayOES(Platform3DObject array) return; m_context->makeContextCurrent(); -#if (PLATFORM(GTK) || PLATFORM(EFL) || PLATFORM(WIN)) +#if (PLATFORM(GTK) || PLATFORM(WIN) || PLATFORM(IOS)) if (isVertexArrayObjectSupported()) glDeleteVertexArrays(1, &array); #elif defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object @@ -115,7 +112,7 @@ GC3Dboolean Extensions3DOpenGL::isVertexArrayOES(Platform3DObject array) return GL_FALSE; m_context->makeContextCurrent(); -#if (PLATFORM(GTK) || PLATFORM(EFL) || PLATFORM(WIN)) +#if (PLATFORM(GTK) || PLATFORM(WIN) || PLATFORM(IOS)) if (isVertexArrayObjectSupported()) return glIsVertexArray(array); #elif defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object @@ -126,12 +123,8 @@ GC3Dboolean Extensions3DOpenGL::isVertexArrayOES(Platform3DObject array) void Extensions3DOpenGL::bindVertexArrayOES(Platform3DObject array) { -#if PLATFORM(IOS) - UNUSED_PARAM(array); -#endif - m_context->makeContextCurrent(); -#if (PLATFORM(GTK) || PLATFORM(EFL) || PLATFORM(WIN)) +#if (PLATFORM(GTK) || PLATFORM(WIN) || PLATFORM(IOS)) if (isVertexArrayObjectSupported()) glBindVertexArray(array); #elif defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object @@ -141,12 +134,6 @@ void Extensions3DOpenGL::bindVertexArrayOES(Platform3DObject array) #endif } -void Extensions3DOpenGL::copyTextureCHROMIUM(GC3Denum, Platform3DObject, Platform3DObject, GC3Dint, GC3Denum) -{ - // FIXME: implement this function and add GL_CHROMIUM_copy_texture in supports(). - return; -} - void Extensions3DOpenGL::insertEventMarkerEXT(const String&) { // FIXME: implement this function and add GL_EXT_debug_marker in supports(). @@ -168,25 +155,50 @@ void Extensions3DOpenGL::popGroupMarkerEXT(void) bool Extensions3DOpenGL::supportsExtension(const String& name) { // GL_ANGLE_framebuffer_blit and GL_ANGLE_framebuffer_multisample are "fake". They are implemented using other - // extensions. In particular GL_EXT_framebuffer_blit and GL_EXT_framebuffer_multisample + // extensions. In particular GL_EXT_framebuffer_blit and GL_EXT_framebuffer_multisample/GL_APPLE_framebuffer_multisample. if (name == "GL_ANGLE_framebuffer_blit") return m_availableExtensions.contains("GL_EXT_framebuffer_blit"); if (name == "GL_ANGLE_framebuffer_multisample") +#if PLATFORM(IOS) + return m_availableExtensions.contains("GL_APPLE_framebuffer_multisample"); +#else return m_availableExtensions.contains("GL_EXT_framebuffer_multisample"); +#endif + + if (name == "GL_ANGLE_instanced_arrays") { + return (m_availableExtensions.contains("GL_ARB_instanced_arrays") || m_availableExtensions.contains("GL_EXT_instanced_arrays")) + && (m_availableExtensions.contains("GL_ARB_draw_instanced") || m_availableExtensions.contains("GL_EXT_draw_instanced")); + } + + if (name == "GL_EXT_sRGB") +#if PLATFORM(IOS) + return m_availableExtensions.contains("GL_EXT_sRGB"); +#else + return m_availableExtensions.contains("GL_EXT_texture_sRGB") && (m_availableExtensions.contains("GL_EXT_framebuffer_sRGB") || m_availableExtensions.contains("GL_ARB_framebuffer_sRGB")); +#endif + + if (name == "GL_EXT_frag_depth") +#if PLATFORM(MAC) + return true; +#else + return m_availableExtensions.contains("GL_EXT_frag_depth"); +#endif // Desktop GL always supports GL_OES_rgb8_rgba8. if (name == "GL_OES_rgb8_rgba8") return true; - // If GL_ARB_texture_float is available then we report GL_OES_texture_float, + // If GL_ARB_texture_float or GL_OES_texture_float is available then we report // GL_OES_texture_half_float, GL_OES_texture_float_linear and GL_OES_texture_half_float_linear as available. if (name == "GL_OES_texture_float" || name == "GL_OES_texture_half_float" || name == "GL_OES_texture_float_linear" || name == "GL_OES_texture_half_float_linear") - return m_availableExtensions.contains("GL_ARB_texture_float"); + return m_availableExtensions.contains("GL_ARB_texture_float") || m_availableExtensions.contains("GL_OES_texture_float"); // GL_OES_vertex_array_object if (name == "GL_OES_vertex_array_object") { -#if (PLATFORM(GTK) || PLATFORM(EFL)) +#if (PLATFORM(GTK)) return m_availableExtensions.contains("GL_ARB_vertex_array_object"); +#elif PLATFORM(IOS) + return m_availableExtensions.contains("GL_OES_vertex_array_object"); #else return m_availableExtensions.contains("GL_APPLE_vertex_array_object"); #endif @@ -199,12 +211,17 @@ bool Extensions3DOpenGL::supportsExtension(const String& name) // Desktop GL always supports UNSIGNED_INT indices if (name == "GL_OES_element_index_uint") return true; - + + if (name == "GL_EXT_shader_texture_lod") + return m_availableExtensions.contains("GL_EXT_shader_texture_lod"); + if (name == "GL_EXT_texture_filter_anisotropic") return m_availableExtensions.contains("GL_EXT_texture_filter_anisotropic"); if (name == "GL_EXT_draw_buffers") { -#if PLATFORM(MAC) +#if PLATFORM(IOS) + return m_availableExtensions.contains(name); +#elif PLATFORM(MAC) || PLATFORM(GTK) return m_availableExtensions.contains("GL_ARB_draw_buffers"); #else // FIXME: implement support for other platforms. @@ -223,20 +240,67 @@ bool Extensions3DOpenGL::supportsExtension(const String& name) void Extensions3DOpenGL::drawBuffersEXT(GC3Dsizei n, const GC3Denum* bufs) { // FIXME: implement support for other platforms. -#if PLATFORM(MAC) && !PLATFORM(IOS) +#if PLATFORM(MAC) ::glDrawBuffersARB(n, bufs); +#elif PLATFORM(GTK) + ::glDrawBuffers(n, bufs); #else UNUSED_PARAM(n); UNUSED_PARAM(bufs); #endif } +void Extensions3DOpenGL::drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount) +{ + m_context->makeContextCurrent(); +#if PLATFORM(GTK) + ::glDrawArraysInstanced(mode, first, count, primcount); +#elif PLATFORM(COCOA) + ::glDrawArraysInstancedARB(mode, first, count, primcount); +#else + UNUSED_PARAM(mode); + UNUSED_PARAM(first); + UNUSED_PARAM(count); + UNUSED_PARAM(primcount); +#endif +} + +void Extensions3DOpenGL::drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount) +{ + m_context->makeContextCurrent(); +#if PLATFORM(GTK) + ::glDrawElementsInstanced(mode, count, type, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset)), primcount); +#elif PLATFORM(COCOA) + ::glDrawElementsInstancedARB(mode, count, type, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset)), primcount); +#else + UNUSED_PARAM(mode); + UNUSED_PARAM(count); + UNUSED_PARAM(type); + UNUSED_PARAM(offset); + UNUSED_PARAM(primcount); +#endif +} + +void Extensions3DOpenGL::vertexAttribDivisor(GC3Duint index, GC3Duint divisor) +{ + m_context->makeContextCurrent(); +#if PLATFORM(GTK) + ::glVertexAttribDivisor(index, divisor); +#elif PLATFORM(COCOA) + ::glVertexAttribDivisorARB(index, divisor); +#else + UNUSED_PARAM(index); + UNUSED_PARAM(divisor); +#endif +} + String Extensions3DOpenGL::getExtensions() { + ASSERT(!m_useIndexedGetString); return String(reinterpret_cast<const char*>(::glGetString(GL_EXTENSIONS))); } -#if (PLATFORM(GTK) || PLATFORM(EFL) || PLATFORM(WIN)) +#if (PLATFORM(GTK) || PLATFORM(WIN) || PLATFORM(IOS)) bool Extensions3DOpenGL::isVertexArrayObjectSupported() { static const bool supportsVertexArrayObject = supports("GL_OES_vertex_array_object"); @@ -246,4 +310,4 @@ bool Extensions3DOpenGL::isVertexArrayObjectSupported() } // namespace WebCore -#endif // USE(3D_GRAPHICS) +#endif // ENABLE(GRAPHICS_CONTEXT_3D) diff --git a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h index 81c5e49d5..c3fe83eb5 100644 --- a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h +++ b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h @@ -23,8 +23,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef Extensions3DOpenGL_h -#define Extensions3DOpenGL_h +#pragma once #include "Extensions3DOpenGLCommon.h" @@ -37,35 +36,35 @@ namespace WebCore { class Extensions3DOpenGL : public Extensions3DOpenGLCommon { WTF_MAKE_FAST_ALLOCATED; public: + // This class only needs to be instantiated by GraphicsContext3D implementations. + Extensions3DOpenGL(GraphicsContext3D*, bool useIndexedGetString); virtual ~Extensions3DOpenGL(); // Extensions3D methods. - virtual void blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter); - virtual void renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height); + void blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter) override; + void renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height) override; + + Platform3DObject createVertexArrayOES() override; + void deleteVertexArrayOES(Platform3DObject) override; + GC3Dboolean isVertexArrayOES(Platform3DObject) override; + void bindVertexArrayOES(Platform3DObject) override; + void insertEventMarkerEXT(const String&) override; + void pushGroupMarkerEXT(const String&) override; + void popGroupMarkerEXT(void) override; + void drawBuffersEXT(GC3Dsizei, const GC3Denum*) override; - virtual Platform3DObject createVertexArrayOES(); - virtual void deleteVertexArrayOES(Platform3DObject); - virtual GC3Dboolean isVertexArrayOES(Platform3DObject); - virtual void bindVertexArrayOES(Platform3DObject); - virtual void copyTextureCHROMIUM(GC3Denum, Platform3DObject, Platform3DObject, GC3Dint, GC3Denum); - virtual void insertEventMarkerEXT(const String&); - virtual void pushGroupMarkerEXT(const String&); - virtual void popGroupMarkerEXT(void); - virtual void drawBuffersEXT(GC3Dsizei, const GC3Denum*); + void drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount) override; + void drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount) override; + void vertexAttribDivisor(GC3Duint index, GC3Duint divisor) override; protected: - // This class only needs to be instantiated by GraphicsContext3D implementations. - friend class GraphicsContext3D; - Extensions3DOpenGL(GraphicsContext3D*); + bool supportsExtension(const WTF::String&) override; + String getExtensions() override; - virtual bool supportsExtension(const WTF::String&); - virtual String getExtensions(); -#if (PLATFORM(GTK) || PLATFORM(EFL) || PLATFORM(WIN)) private: +#if (PLATFORM(GTK) || PLATFORM(WIN) || PLATFORM(IOS)) bool isVertexArrayObjectSupported(); #endif }; } // namespace WebCore - -#endif // Extensions3DOpenGL_h diff --git a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp index 9b7c5ab65..d28d765df 100644 --- a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp +++ b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp @@ -26,7 +26,7 @@ #include "config.h" -#if USE(3D_GRAPHICS) +#if ENABLE(GRAPHICS_CONTEXT_3D) #include "Extensions3DOpenGLCommon.h" #include "ANGLEWebKitBridge.h" @@ -34,14 +34,18 @@ #if PLATFORM(IOS) #include <OpenGLES/ES2/glext.h> +#include <OpenGLES/ES3/gl.h> #else #if USE(OPENGL_ES_2) #include "OpenGLESShims.h" #include <GLES2/gl2.h> #include <GLES2/gl2ext.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> +#undef GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED +#elif PLATFORM(GTK) || PLATFORM(WIN) #include "OpenGLShims.h" #endif #endif @@ -49,54 +53,39 @@ #include <wtf/MainThread.h> #include <wtf/Vector.h> -#if PLATFORM(WIN) || (PLATFORM(GTK) && OS(WINDOWS)) -#undef NO_ERROR -#endif - namespace WebCore { -Extensions3DOpenGLCommon::Extensions3DOpenGLCommon(GraphicsContext3D* context) +Extensions3DOpenGLCommon::Extensions3DOpenGLCommon(GraphicsContext3D* context, bool useIndexedGetString) : m_initializedAvailableExtensions(false) , m_context(context) , m_isNVIDIA(false) , m_isAMD(false) , m_isIntel(false) - , m_maySupportMultisampling(true) + , m_isImagination(false) , m_requiresBuiltInFunctionEmulation(false) + , m_requiresRestrictedMaximumTextureSize(false) + , m_useIndexedGetString(useIndexedGetString) { m_vendor = String(reinterpret_cast<const char*>(::glGetString(GL_VENDOR))); + m_renderer = String(reinterpret_cast<const char*>(::glGetString(GL_RENDERER))); Vector<String> vendorComponents; - m_vendor.lower().split(' ', vendorComponents); + m_vendor.convertToASCIILowercase().split(' ', vendorComponents); if (vendorComponents.contains("nvidia")) m_isNVIDIA = true; if (vendorComponents.contains("ati") || vendorComponents.contains("amd")) m_isAMD = true; if (vendorComponents.contains("intel")) m_isIntel = true; + if (vendorComponents.contains("imagination")) + m_isImagination = true; -#if PLATFORM(MAC) && !PLATFORM(IOS) +#if PLATFORM(MAC) if (m_isAMD || m_isIntel) m_requiresBuiltInFunctionEmulation = true; - // Currently in Mac we only allow multisampling if the vendor is NVIDIA, - // or if the vendor is AMD/ATI and the system is 10.7.2 and above. - - bool systemSupportsMultisampling = true; -#if !PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED < 1080 - ASSERT(isMainThread()); - static SInt32 version; - if (!version) { - if (Gestalt(gestaltSystemVersion, &version) != noErr) - systemSupportsMultisampling = false; - } - // See https://bugs.webkit.org/show_bug.cgi?id=77922 for more details - if (systemSupportsMultisampling) - systemSupportsMultisampling = version >= 0x1072; -#endif // SNOW_LEOPARD and LION - - if (m_isAMD && !systemSupportsMultisampling) - m_maySupportMultisampling = false; + // Intel HD 3000 devices have problems with large textures. <rdar://problem/16649140> + m_requiresRestrictedMaximumTextureSize = m_renderer.startsWith("Intel HD Graphics 3000"); #endif } @@ -109,6 +98,12 @@ bool Extensions3DOpenGLCommon::supports(const String& name) if (!m_initializedAvailableExtensions) initializeAvailableExtensions(); + // We explicitly do not support this extension until + // we fix the following bug: + // https://bugs.webkit.org/show_bug.cgi?id=149734 + if (name == "GL_ANGLE_translated_shader_source") + return false; + return supportsExtension(name); } @@ -131,6 +126,22 @@ void Extensions3DOpenGLCommon::ensureEnabled(const String& name) m_context->getIntegerv(Extensions3D::MAX_DRAW_BUFFERS_EXT, &ANGLEResources.MaxDrawBuffers); compiler.setResources(ANGLEResources); } + } else if (name == "GL_EXT_shader_texture_lod") { + // Enable support in ANGLE (if not enabled already) + ANGLEWebKitBridge& compiler = m_context->m_compiler; + ShBuiltInResources ANGLEResources = compiler.getResources(); + if (!ANGLEResources.EXT_shader_texture_lod) { + ANGLEResources.EXT_shader_texture_lod = 1; + compiler.setResources(ANGLEResources); + } + } else if (name == "GL_EXT_frag_depth") { + // Enable support in ANGLE (if not enabled already) + ANGLEWebKitBridge& compiler = m_context->m_compiler; + ShBuiltInResources ANGLEResources = compiler.getResources(); + if (!ANGLEResources.EXT_frag_depth) { + ANGLEResources.EXT_frag_depth = 1; + compiler.setResources(ANGLEResources); + } } } @@ -174,22 +185,20 @@ String Extensions3DOpenGLCommon::getTranslatedShaderSourceANGLE(Platform3DObject String translatedShaderSource; String shaderInfoLog; - int extraCompileOptions = SH_MAP_LONG_VARIABLE_NAMES | SH_CLAMP_INDIRECT_ARRAY_BOUNDS | SH_UNFOLD_SHORT_CIRCUIT | SH_ENFORCE_PACKING_RESTRICTIONS; + int extraCompileOptions = SH_CLAMP_INDIRECT_ARRAY_BOUNDS | SH_UNFOLD_SHORT_CIRCUIT | SH_INIT_OUTPUT_VARIABLES | SH_ENFORCE_PACKING_RESTRICTIONS | SH_LIMIT_EXPRESSION_COMPLEXITY | SH_LIMIT_CALL_STACK_DEPTH; if (m_requiresBuiltInFunctionEmulation) - extraCompileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS; + extraCompileOptions |= SH_EMULATE_ABS_INT_FUNCTION; - Vector<ANGLEShaderSymbol> symbols; + Vector<std::pair<ANGLEShaderSymbolType, sh::ShaderVariable>> symbols; bool isValid = compiler.compileShaderSource(entry.source.utf8().data(), shaderType, translatedShaderSource, shaderInfoLog, symbols, extraCompileOptions); entry.log = shaderInfoLog; entry.isValid = isValid; - size_t numSymbols = symbols.size(); - for (size_t i = 0; i < numSymbols; ++i) { - ANGLEShaderSymbol shaderSymbol = symbols[i]; - GraphicsContext3D::SymbolInfo symbolInfo(shaderSymbol.dataType, shaderSymbol.size, shaderSymbol.mappedName, shaderSymbol.precision, shaderSymbol.staticUse); - entry.symbolMap(shaderSymbol.symbolType).set(shaderSymbol.name, symbolInfo); + for (const std::pair<ANGLEShaderSymbolType, sh::ShaderVariable>& pair : symbols) { + const std::string& name = pair.second.name; + entry.symbolMap(pair.first).set(String(name.c_str(), name.length()), pair.second); } if (!isValid) @@ -200,11 +209,30 @@ String Extensions3DOpenGLCommon::getTranslatedShaderSourceANGLE(Platform3DObject void Extensions3DOpenGLCommon::initializeAvailableExtensions() { - String extensionsString = getExtensions(); - Vector<String> availableExtensions; - extensionsString.split(" ", availableExtensions); - for (size_t i = 0; i < availableExtensions.size(); ++i) - m_availableExtensions.add(availableExtensions[i]); +#if PLATFORM(MAC) || (PLATFORM(GTK) && !USE(OPENGL_ES_2)) + if (m_useIndexedGetString) { + GLint numExtensions = 0; + ::glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions); + for (GLint i = 0; i < numExtensions; ++i) + m_availableExtensions.add(glGetStringi(GL_EXTENSIONS, i)); + + if (!m_availableExtensions.contains(ASCIILiteral("GL_ARB_texture_storage"))) { + GLint majorVersion; + glGetIntegerv(GL_MAJOR_VERSION, &majorVersion); + GLint minorVersion; + glGetIntegerv(GL_MINOR_VERSION, &minorVersion); + if (majorVersion > 4 || (majorVersion == 4 && minorVersion >= 2)) + m_availableExtensions.add(ASCIILiteral("GL_ARB_texture_storage")); + } + } else +#endif + { + String extensionsString = getExtensions(); + Vector<String> availableExtensions; + extensionsString.split(' ', availableExtensions); + for (size_t i = 0; i < availableExtensions.size(); ++i) + m_availableExtensions.add(availableExtensions[i]); + } m_initializedAvailableExtensions = true; } @@ -225,4 +253,4 @@ void Extensions3DOpenGLCommon::getnUniformivEXT(GC3Duint, int, GC3Dsizei, int *) } // namespace WebCore -#endif // USE(3D_GRAPHICS) +#endif // ENABLE(GRAPHICS_CONTEXT_3D) diff --git a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.h b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.h index 4cc8dbac1..7c614fb40 100644 --- a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.h +++ b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.h @@ -24,8 +24,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef Extensions3DOpenGLCommon_h -#define Extensions3DOpenGLCommon_h +#pragma once #include "Extensions3D.h" @@ -40,36 +39,37 @@ public: virtual ~Extensions3DOpenGLCommon(); // Extensions3D methods. - virtual bool supports(const String&); - virtual void ensureEnabled(const String&); - virtual bool isEnabled(const String&); - virtual int getGraphicsResetStatusARB(); + bool supports(const String&) override; + void ensureEnabled(const String&) override; + bool isEnabled(const String&) override; + int getGraphicsResetStatusARB() override; - virtual Platform3DObject createVertexArrayOES() = 0; - virtual void deleteVertexArrayOES(Platform3DObject) = 0; - virtual GC3Dboolean isVertexArrayOES(Platform3DObject) = 0; - virtual void bindVertexArrayOES(Platform3DObject) = 0; + Platform3DObject createVertexArrayOES() override = 0; + void deleteVertexArrayOES(Platform3DObject) override = 0; + GC3Dboolean isVertexArrayOES(Platform3DObject) override = 0; + void bindVertexArrayOES(Platform3DObject) override = 0; - virtual void drawBuffersEXT(GC3Dsizei, const GC3Denum*) = 0; + void drawBuffersEXT(GC3Dsizei, const GC3Denum*) override = 0; - virtual String getTranslatedShaderSourceANGLE(Platform3DObject); + String getTranslatedShaderSourceANGLE(Platform3DObject) override; // EXT Robustness - uses getGraphicsResetStatusARB() - virtual void readnPixelsEXT(int x, int y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, GC3Dsizei bufSize, void *data); - virtual void getnUniformfvEXT(GC3Duint program, int location, GC3Dsizei bufSize, float *params); - virtual void getnUniformivEXT(GC3Duint program, int location, GC3Dsizei bufSize, int *params); + void readnPixelsEXT(int x, int y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, GC3Dsizei bufSize, void *data) override; + void getnUniformfvEXT(GC3Duint program, int location, GC3Dsizei bufSize, float *params) override; + void getnUniformivEXT(GC3Duint program, int location, GC3Dsizei bufSize, int *params) override; - virtual bool isNVIDIA() { return m_isNVIDIA; } - virtual bool isAMD() { return m_isAMD; } - virtual bool isIntel() { return m_isIntel; } - virtual String vendor() { return m_vendor; } + bool isNVIDIA() override { return m_isNVIDIA; } + bool isAMD() override { return m_isAMD; } + bool isIntel() override { return m_isIntel; } + bool isImagination() override { return m_isImagination; } + String vendor() override { return m_vendor; } - virtual bool maySupportMultisampling() { return m_maySupportMultisampling; } - virtual bool requiresBuiltInFunctionEmulation() { return m_requiresBuiltInFunctionEmulation; } + bool requiresBuiltInFunctionEmulation() override { return m_requiresBuiltInFunctionEmulation; } + bool requiresRestrictedMaximumTextureSize() override { return m_requiresRestrictedMaximumTextureSize; } protected: friend class Extensions3DOpenGLES; - Extensions3DOpenGLCommon(GraphicsContext3D*); + Extensions3DOpenGLCommon(GraphicsContext3D*, bool useIndexedGetString); virtual bool supportsExtension(const String&) = 0; virtual String getExtensions() = 0; @@ -84,12 +84,14 @@ protected: bool m_isNVIDIA; bool m_isAMD; bool m_isIntel; - bool m_maySupportMultisampling; + bool m_isImagination; bool m_requiresBuiltInFunctionEmulation; + bool m_requiresRestrictedMaximumTextureSize; + + bool m_useIndexedGetString { false }; String m_vendor; + String m_renderer; }; } // namespace WebCore - -#endif // Extensions3DOpenGLCommon_h diff --git a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLES.cpp b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLES.cpp index dc9e59252..958e09383 100644 --- a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLES.cpp +++ b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLES.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2011 Google Inc. All rights reserved. * Copyright (C) 2012 Research In Motion Limited. All rights reserved. + * Copyright (C) 2014 Collabora Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,21 +26,23 @@ */ #include "config.h" -#if USE(3D_GRAPHICS) + +#if USE(OPENGL_ES_2) #include "Extensions3DOpenGLES.h" +#if ENABLE(GRAPHICS_CONTEXT_3D) #include "GraphicsContext3D.h" #include "NotImplemented.h" #include <EGL/egl.h> -#include <wtf/Vector.h> namespace WebCore { -Extensions3DOpenGLES::Extensions3DOpenGLES(GraphicsContext3D* context) - : Extensions3DOpenGLCommon(context) +Extensions3DOpenGLES::Extensions3DOpenGLES(GraphicsContext3D* context, bool useIndexedGetString) + : Extensions3DOpenGLCommon(context, useIndexedGetString) , m_contextResetStatus(GL_NO_ERROR) , m_supportsOESvertexArrayObject(false) , m_supportsIMGMultisampledRenderToTexture(false) + , m_supportsANGLEinstancedArrays(false) , m_glFramebufferTexture2DMultisampleIMG(0) , m_glRenderbufferStorageMultisampleIMG(0) , m_glBindVertexArrayOES(0) @@ -50,6 +53,9 @@ Extensions3DOpenGLES::Extensions3DOpenGLES(GraphicsContext3D* context) , m_glReadnPixelsEXT(0) , m_glGetnUniformfvEXT(0) , m_glGetnUniformivEXT(0) + , m_glVertexAttribDivisorANGLE(nullptr) + , m_glDrawArraysInstancedANGLE(nullptr) + , m_glDrawElementsInstancedANGLE(nullptr) { } @@ -73,7 +79,7 @@ void Extensions3DOpenGLES::renderbufferStorageMultisampleIMG(unsigned long targe m_context->synthesizeGLError(GL_INVALID_OPERATION); } -void Extensions3DOpenGLES::blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter) +void Extensions3DOpenGLES::blitFramebuffer(long /* srcX0 */, long /* srcY0 */, long /* srcX1 */, long /* srcY1 */, long /* dstX0 */, long /* dstY0 */, long /* dstX1 */, long /* dstY1 */, unsigned long /* mask */, unsigned long /* filter */) { notImplemented(); } @@ -86,11 +92,6 @@ void Extensions3DOpenGLES::renderbufferStorageMultisample(unsigned long target, notImplemented(); } -void Extensions3DOpenGLES::copyTextureCHROMIUM(GC3Denum, Platform3DObject, Platform3DObject, GC3Dint, GC3Denum) -{ - notImplemented(); -} - void Extensions3DOpenGLES::insertEventMarkerEXT(const String&) { notImplemented(); @@ -156,9 +157,10 @@ void Extensions3DOpenGLES::bindVertexArrayOES(Platform3DObject array) m_context->synthesizeGLError(GL_INVALID_OPERATION); } -void Extensions3DOpenGLES::drawBuffersEXT(GC3Dsizei n, const GC3Denum* bufs) +void Extensions3DOpenGLES::drawBuffersEXT(GC3Dsizei /* n */, const GC3Denum* /* bufs */) { // FIXME: implement the support. + notImplemented(); } int Extensions3DOpenGLES::getGraphicsResetStatusARB() @@ -184,9 +186,9 @@ int Extensions3DOpenGLES::getGraphicsResetStatusARB() return false; } -void Extensions3DOpenGLES::setEXTContextLostCallback(PassOwnPtr<GraphicsContext3D::ContextLostCallback> callback) +void Extensions3DOpenGLES::setEXTContextLostCallback(std::unique_ptr<GraphicsContext3D::ContextLostCallback> callback) { - m_contextLostCallback = callback; + m_contextLostCallback = WTFMove(callback); } void Extensions3DOpenGLES::readnPixelsEXT(int x, int y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, GC3Dsizei bufSize, void *data) @@ -228,6 +230,39 @@ void Extensions3DOpenGLES::getnUniformivEXT(GC3Duint program, int location, GC3D m_context->synthesizeGLError(GL_INVALID_OPERATION); } +void Extensions3DOpenGLES::drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount) +{ + if (!m_glDrawArraysInstancedANGLE) { + m_context->synthesizeGLError(GL_INVALID_OPERATION); + return; + } + + m_context->makeContextCurrent(); + m_glDrawArraysInstancedANGLE(mode, first, count, primcount); +} + +void Extensions3DOpenGLES::drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount) +{ + if (!m_glDrawElementsInstancedANGLE) { + m_context->synthesizeGLError(GL_INVALID_OPERATION); + return; + } + + m_context->makeContextCurrent(); + m_glDrawElementsInstancedANGLE(mode, count, type, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset)), primcount); +} + +void Extensions3DOpenGLES::vertexAttribDivisor(GC3Duint index, GC3Duint divisor) +{ + if (!m_glVertexAttribDivisorANGLE) { + m_context->synthesizeGLError(GL_INVALID_OPERATION); + return; + } + + m_context->makeContextCurrent(); + m_glVertexAttribDivisorANGLE(index, divisor); +} + bool Extensions3DOpenGLES::supportsExtension(const String& name) { if (m_availableExtensions.contains(name)) { @@ -238,14 +273,19 @@ bool Extensions3DOpenGLES::supportsExtension(const String& name) m_glIsVertexArrayOES = reinterpret_cast<PFNGLISVERTEXARRAYOESPROC>(eglGetProcAddress("glIsVertexArrayOES")); m_supportsOESvertexArrayObject = true; } else if (!m_supportsIMGMultisampledRenderToTexture && name == "GL_IMG_multisampled_render_to_texture") { - m_glFramebufferTexture2DMultisampleIMG = reinterpret_cast<PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMG>(eglGetProcAddress("glFramebufferTexture2DMultisampleIMG")); - m_glRenderbufferStorageMultisampleIMG = reinterpret_cast<PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMG>(eglGetProcAddress("glRenderbufferStorageMultisampleIMG")); + m_glFramebufferTexture2DMultisampleIMG = reinterpret_cast<PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC>(eglGetProcAddress("glFramebufferTexture2DMultisampleIMG")); + m_glRenderbufferStorageMultisampleIMG = reinterpret_cast<PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC>(eglGetProcAddress("glRenderbufferStorageMultisampleIMG")); m_supportsIMGMultisampledRenderToTexture = true; } else if (!m_glGetGraphicsResetStatusEXT && name == "GL_EXT_robustness") { m_glGetGraphicsResetStatusEXT = reinterpret_cast<PFNGLGETGRAPHICSRESETSTATUSEXTPROC>(eglGetProcAddress("glGetGraphicsResetStatusEXT")); m_glReadnPixelsEXT = reinterpret_cast<PFNGLREADNPIXELSEXTPROC>(eglGetProcAddress("glReadnPixelsEXT")); m_glGetnUniformfvEXT = reinterpret_cast<PFNGLGETNUNIFORMFVEXTPROC>(eglGetProcAddress("glGetnUniformfvEXT")); m_glGetnUniformivEXT = reinterpret_cast<PFNGLGETNUNIFORMIVEXTPROC>(eglGetProcAddress("glGetnUniformivEXT")); + } else if (!m_supportsANGLEinstancedArrays && name == "GL_ANGLE_instanced_arrays") { + m_glVertexAttribDivisorANGLE = reinterpret_cast<PFNGLVERTEXATTRIBDIVISORANGLEPROC>(eglGetProcAddress("glVertexAttribDivisorANGLE")); + m_glDrawArraysInstancedANGLE = reinterpret_cast<PFNGLDRAWARRAYSINSTANCEDANGLEPROC >(eglGetProcAddress("glDrawArraysInstancedANGLE")); + m_glDrawElementsInstancedANGLE = reinterpret_cast<PFNGLDRAWELEMENTSINSTANCEDANGLEPROC >(eglGetProcAddress("glDrawElementsInstancedANGLE")); + m_supportsANGLEinstancedArrays = true; } else if (name == "GL_EXT_draw_buffers") { // FIXME: implement the support. return false; @@ -263,4 +303,6 @@ String Extensions3DOpenGLES::getExtensions() } // namespace WebCore -#endif // USE(3D_GRAPHICS) +#endif // ENABLE(GRAPHICS_CONTEXT_3D) + +#endif // USE(OPENGL_ES_2) diff --git a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLES.h b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLES.h index 7c40566e9..316e5e9b5 100644 --- a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLES.h +++ b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLES.h @@ -24,11 +24,12 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef Extensions3DOpenGLES_h -#define Extensions3DOpenGLES_h +#pragma once #include "Extensions3DOpenGLCommon.h" +#if USE(OPENGL_ES_2) + #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> @@ -61,6 +62,8 @@ namespace WebCore { class Extensions3DOpenGLES : public Extensions3DOpenGLCommon { public: + // This class only needs to be instantiated by GraphicsContext3D implementations. + Extensions3DOpenGLES(GraphicsContext3D*, bool useIndexedGetString); virtual ~Extensions3DOpenGLES(); virtual void framebufferTexture2DMultisampleIMG(unsigned long target, unsigned long attachment, unsigned long textarget, unsigned int texture, int level, unsigned long samples); @@ -69,7 +72,6 @@ public: // Extension3D methods virtual void blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter); virtual void renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height); - virtual void copyTextureCHROMIUM(GC3Denum, Platform3DObject, Platform3DObject, GC3Dint, GC3Denum); virtual void insertEventMarkerEXT(const String&); virtual void pushGroupMarkerEXT(const String&); virtual void popGroupMarkerEXT(void); @@ -80,9 +82,13 @@ public: virtual void bindVertexArrayOES(Platform3DObject); virtual void drawBuffersEXT(GC3Dsizei, const GC3Denum*); + virtual void drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount); + virtual void drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, long long offset, GC3Dsizei primcount); + virtual void vertexAttribDivisor(GC3Duint index, GC3Duint divisor); + // EXT Robustness - reset virtual int getGraphicsResetStatusARB(); - void setEXTContextLostCallback(PassOwnPtr<GraphicsContext3D::ContextLostCallback>); + void setEXTContextLostCallback(std::unique_ptr<GraphicsContext3D::ContextLostCallback>); // EXT Robustness - etc virtual void readnPixelsEXT(int x, int y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, GC3Dsizei bufSize, void *data); @@ -90,10 +96,6 @@ public: virtual void getnUniformivEXT(GC3Duint program, int location, GC3Dsizei bufSize, int *params); protected: - // This class only needs to be instantiated by GraphicsContext3D implementations. - friend class GraphicsContext3D; - Extensions3DOpenGLES(GraphicsContext3D*); - virtual bool supportsExtension(const String&); virtual String getExtensions(); @@ -101,9 +103,10 @@ protected: bool m_supportsOESvertexArrayObject; bool m_supportsIMGMultisampledRenderToTexture; + bool m_supportsANGLEinstancedArrays; - PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMG m_glFramebufferTexture2DMultisampleIMG; - PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMG m_glRenderbufferStorageMultisampleIMG; + PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC m_glFramebufferTexture2DMultisampleIMG; + PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC m_glRenderbufferStorageMultisampleIMG; PFNGLBINDVERTEXARRAYOESPROC m_glBindVertexArrayOES; PFNGLDELETEVERTEXARRAYSOESPROC m_glDeleteVertexArraysOES; PFNGLGENVERTEXARRAYSOESPROC m_glGenVertexArraysOES; @@ -112,10 +115,13 @@ protected: PFNGLREADNPIXELSEXTPROC m_glReadnPixelsEXT; PFNGLGETNUNIFORMFVEXTPROC m_glGetnUniformfvEXT; PFNGLGETNUNIFORMIVEXTPROC m_glGetnUniformivEXT; + PFNGLVERTEXATTRIBDIVISORANGLEPROC m_glVertexAttribDivisorANGLE; + PFNGLDRAWARRAYSINSTANCEDANGLEPROC m_glDrawArraysInstancedANGLE; + PFNGLDRAWELEMENTSINSTANCEDANGLEPROC m_glDrawElementsInstancedANGLE; - OwnPtr<GraphicsContext3D::ContextLostCallback> m_contextLostCallback; + std::unique_ptr<GraphicsContext3D::ContextLostCallback> m_contextLostCallback; }; } // namespace WebCore -#endif // Extensions3DOpenGLES_h +#endif // USE(OPENGL_ES_2) diff --git a/Source/WebCore/platform/graphics/opengl/GLDefs.h b/Source/WebCore/platform/graphics/opengl/GLDefs.h new file mode 100644 index 000000000..9a2c2fffd --- /dev/null +++ b/Source/WebCore/platform/graphics/opengl/GLDefs.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2012 Intel Corporation. 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. AND ITS CONTRIBUTORS ``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 ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GLDefs_h +#define GLDefs_h + +#define GL_GLEXT_PROTOTYPES 1 + +#if USE(OPENGL_ES_2) +#include "Extensions3DOpenGLES.h" +#include "OpenGLESShims.h" +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> +#else +#include "Extensions3DOpenGL.h" +#include "OpenGLShims.h" +#include <GL/gl.h> +#include <GL/glext.h> +#if USE(GLX) +#define GLX_GLXEXT_PROTOTYPES 1 +#include <GL/glx.h> +#include <GL/glxext.h> +#endif +#endif + +#if USE(EGL) +#define EGL_EGLEXT_PROTOTYPES 1 +#include <EGL/egl.h> +#include <EGL/eglext.h> +#endif + +namespace WebCore { + +typedef uint32_t PlatformBufferHandle; + +#if USE(GLX) +typedef GLXContext PlatformContext; +typedef GLXFBConfig PlatformSurfaceConfig; +typedef GLXDrawable PlatformDrawable; +#elif USE(EGL) +typedef EGLContext PlatformContext; +typedef EGLConfig PlatformSurfaceConfig; +typedef EGLSurface PlatformDrawable; +#else +typedef void* PlatformContext; +typedef void* PlatformSurfaceConfig; +typedef void* PlatformDrawable; +#endif + +} + +#endif diff --git a/Source/WebCore/platform/graphics/opengl/GLPlatformContext.cpp b/Source/WebCore/platform/graphics/opengl/GLPlatformContext.cpp new file mode 100644 index 000000000..5219a2391 --- /dev/null +++ b/Source/WebCore/platform/graphics/opengl/GLPlatformContext.cpp @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2012 Intel Corporation. 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. AND ITS CONTRIBUTORS ``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 ITS 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" + +#if ENABLE(GRAPHICS_CONTEXT_3D) +#include "GLPlatformContext.h" + +#if USE(GLX) +#include "GLXContext.h" +#elif USE(EGL) +#include "EGLContext.h" +#endif + +#include "NotImplemented.h" + +namespace WebCore { + +#if USE(OPENGL_ES_2) +static PFNGLGETGRAPHICSRESETSTATUSEXTPROC glGetGraphicsResetStatus = 0; +#else +static PFNGLGETGRAPHICSRESETSTATUSARBPROC glGetGraphicsResetStatus = 0; +#endif + +class GLCurrentContextWrapper : public GLPlatformContext { + +public: + GLCurrentContextWrapper() + : GLPlatformContext() + { +#if USE(GLX) + m_contextHandle = glXGetCurrentContext(); +#elif USE(EGL) + m_contextHandle = eglGetCurrentContext(); +#endif + } + + virtual ~GLCurrentContextWrapper() { } + + bool isCurrentContext() const override + { + return true; + } +}; + +static std::unique_ptr<GLPlatformContext> createOffScreenContext() +{ +#if USE(GLX) + return std::make_unique<GLXOffScreenContext>(); +#elif USE(EGL) + return std::make_unique<EGLOffScreenContext>(); +#else + return nullptr; +#endif +} + +static HashSet<String> parseExtensions(const String& extensionsString) +{ + Vector<String> extNames; + extensionsString.split(' ', extNames); + HashSet<String> splitExtNames; + unsigned size = extNames.size(); + for (unsigned i = 0; i < size; ++i) + splitExtNames.add(extNames[i]); + extNames.clear(); + + return splitExtNames; +} + +static void resolveResetStatusExtension() +{ + static bool resolvedRobustnessExtension = false; + if (!resolvedRobustnessExtension) { + resolvedRobustnessExtension = true; +#if USE(OPENGL_ES_2) + glGetGraphicsResetStatus = reinterpret_cast<PFNGLGETGRAPHICSRESETSTATUSEXTPROC>(eglGetProcAddress("glGetGraphicsResetStatusEXT")); +#elif USE(EGL) + glGetGraphicsResetStatus = reinterpret_cast<PFNGLGETGRAPHICSRESETSTATUSARBPROC>(eglGetProcAddress("glGetGraphicsResetStatusARB")); +#elif USE(GLX) + glGetGraphicsResetStatus = reinterpret_cast<PFNGLGETGRAPHICSRESETSTATUSARBPROC>(glXGetProcAddressARB(reinterpret_cast<const GLubyte*>("glGetGraphicsResetStatusARB"))); +#endif + } +} + +std::unique_ptr<GLPlatformContext> GLPlatformContext::createContext(GraphicsContext3D::RenderStyle renderStyle) +{ +#if !USE(OPENGL_ES_2) + if (!initializeOpenGLShims()) + return nullptr; +#endif + + switch (renderStyle) { + case GraphicsContext3D::RenderOffscreen: + return createOffScreenContext(); + case GraphicsContext3D::RenderToCurrentGLContext: + return std::make_unique<GLCurrentContextWrapper>(); + case GraphicsContext3D::RenderDirectlyToHostWindow: + ASSERT_NOT_REACHED(); + break; + } + + return nullptr; +} + +bool GLPlatformContext::supportsGLExtension(const String& name) +{ + static HashSet<String> supportedExtensions; + + if (!supportedExtensions.size()) { + String rawExtensions = reinterpret_cast<const char*>(::glGetString(GL_EXTENSIONS)); + supportedExtensions = parseExtensions(rawExtensions); + } + + if (supportedExtensions.contains(name)) + return true; + + return false; +} + +#if USE(EGL) +bool GLPlatformContext::supportsEGLExtension(EGLDisplay display, const String& name) +{ + static HashSet<String> supportedExtensions; + + if (!supportedExtensions.size()) { + if (display == EGL_NO_DISPLAY) + return false; + + String rawExtensions = reinterpret_cast<const char*>(eglQueryString(display, EGL_EXTENSIONS)); + supportedExtensions = parseExtensions(rawExtensions); + } + + if (supportedExtensions.contains(name)) + return true; + + return false; +} +#endif + +#if USE(GLX) +bool GLPlatformContext::supportsGLXExtension(Display* display, const String& name) +{ + static HashSet<String> supportedExtensions; + + if (!supportedExtensions.size()) { + if (!display) + return false; + + String rawExtensions = glXQueryExtensionsString(display, DefaultScreen(display)); + supportedExtensions = parseExtensions(rawExtensions); + } + + if (supportedExtensions.contains(name)) + return true; + + return false; +} +#endif + +GLPlatformContext::GLPlatformContext() + : m_contextHandle(0) + , m_resetLostContext(false) +{ +} + +GLPlatformContext::~GLPlatformContext() +{ +} + +bool GLPlatformContext::makeCurrent(GLPlatformSurface* surface) +{ + m_contextLost = false; + + if (isCurrentContext() && (!surface || surface->isCurrentDrawable())) + return true; + + GLPlatformContext* currentContext = 0; + + if (!surface || (surface && !surface->drawable())) + platformReleaseCurrent(); + else if (platformMakeCurrent(surface)) { + currentContext = this; + surface->onMakeCurrent(); + } + + if (m_resetLostContext) { + resolveResetStatusExtension(); + + if (glGetGraphicsResetStatus) { + GLenum status = glGetGraphicsResetStatus(); + + switch (status) { + case PLATFORMCONTEXT_NO_ERROR: + break; + case PLATFORMCONTEXT_GUILTY_CONTEXT_RESET: + m_contextLost = true; + break; + case PLATFORMCONTEXT_INNOCENT_CONTEXT_RESET: + break; + case PLATFORMCONTEXT_UNKNOWN_CONTEXT_RESET: + m_contextLost = true; + break; + default: + break; + } + } + } + + return currentContext; +} + +bool GLPlatformContext::isValid() const +{ + return !m_contextLost; +} + +void GLPlatformContext::releaseCurrent() +{ + if (isCurrentContext()) + platformReleaseCurrent(); +} + +PlatformContext GLPlatformContext::handle() const +{ + return m_contextHandle; +} + +bool GLPlatformContext::initialize(GLPlatformSurface*, PlatformContext) +{ + return true; +} + +bool GLPlatformContext::platformMakeCurrent(GLPlatformSurface*) +{ + return true; +} + +void GLPlatformContext::platformReleaseCurrent() +{ + notImplemented(); +} + +void GLPlatformContext::destroy() +{ + m_contextHandle = 0; + m_resetLostContext = false; +} + +} // namespace WebCore + +#endif diff --git a/Source/WebCore/platform/graphics/opengl/GLPlatformContext.h b/Source/WebCore/platform/graphics/opengl/GLPlatformContext.h new file mode 100644 index 000000000..a999cc0cf --- /dev/null +++ b/Source/WebCore/platform/graphics/opengl/GLPlatformContext.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2012 Intel Corporation. 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. AND ITS CONTRIBUTORS ``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 ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GLPlatformContext_h +#define GLPlatformContext_h + +#include "GLDefs.h" +#include "GLPlatformSurface.h" +#include "GraphicsContext3D.h" +#include <wtf/Noncopyable.h> + +// Encapsulates an OpenGL context, hiding platform specific management. +namespace WebCore { + +class GLPlatformContext { + WTF_MAKE_NONCOPYABLE(GLPlatformContext); + +public: + // From http://www.khronos.org/registry/gles/extensions/EXT/EXT_robustness.txt + enum PlatformContextReset { + PLATFORMCONTEXT_NO_ERROR = 0x0000, + PLATFORMCONTEXT_GUILTY_CONTEXT_RESET = 0x8253, + PLATFORMCONTEXT_INNOCENT_CONTEXT_RESET = 0x8254, + PLATFORMCONTEXT_UNKNOWN_CONTEXT_RESET = 0x8255, + }; + + static std::unique_ptr<GLPlatformContext> createContext(GraphicsContext3D::RenderStyle); + + static bool supportsGLExtension(const String&); + +#if USE(EGL) + static bool supportsEGLExtension(EGLDisplay, const String&); +#endif + +#if USE(GLX) + static bool supportsGLXExtension(Display*, const String&); +#endif + + virtual ~GLPlatformContext(); + + virtual bool initialize(GLPlatformSurface*, PlatformContext = 0); + + // Makes this and surface as current context and drawable. + // Calling this function with no surface is same as calling releaseCurrent. + // Does nothing if this is already current Context. + bool makeCurrent(GLPlatformSurface* = 0); + + // Sets Current Context and Drawable as Null. + // Doesn't have any effect if this is not the current Context. + void releaseCurrent(); + + virtual PlatformContext handle() const; + + virtual bool isCurrentContext() const = 0; + + bool isValid() const; + + // Destroys any GL resources associated with this context. + virtual void destroy(); + +protected: + GLPlatformContext(); + virtual bool platformMakeCurrent(GLPlatformSurface*); + virtual void platformReleaseCurrent(); + PlatformContext m_contextHandle; + bool m_resetLostContext; + bool m_contextLost; +}; + +} // namespace WebCore + +#endif // GLNativeContext_H diff --git a/Source/WebCore/platform/graphics/opengl/GLPlatformSurface.h b/Source/WebCore/platform/graphics/opengl/GLPlatformSurface.h new file mode 100644 index 000000000..2d99d6f2d --- /dev/null +++ b/Source/WebCore/platform/graphics/opengl/GLPlatformSurface.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2012 Intel Corporation. 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. AND ITS CONTRIBUTORS ``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 ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GLPlatformSurface_h +#define GLPlatformSurface_h + +#include "GLDefs.h" +#include "IntRect.h" +#include <wtf/Noncopyable.h> + +// Encapsulates a surface that can be rendered to with GL, hiding platform +// specific management. +namespace WebCore { + +class GLPlatformSurface { + WTF_MAKE_NONCOPYABLE(GLPlatformSurface); + +public: + enum Attributes { + Default = 0x00, // No Alpha channel. Only R,G,B values set. + SupportAlpha = 0x01, + DoubleBuffered = 0x02 + }; + + typedef unsigned SurfaceAttributes; + // Creates a GL surface used for offscreen rendering. + static std::unique_ptr<GLPlatformSurface> createOffScreenSurface(SurfaceAttributes = GLPlatformSurface::Default); + + virtual ~GLPlatformSurface(); + + const IntRect& geometry() const; + + // Get the underlying platform specific buffer handle. + // The handle will be null if surface doesn't support + // buffer sharing. + PlatformBufferHandle handle() const; + + PlatformDrawable drawable() const; + + virtual SurfaceAttributes attributes() const; + + virtual void swapBuffers(); + + virtual bool isCurrentDrawable() const = 0; + + virtual void onMakeCurrent(); + + // Convenience Function to update surface backbuffer with texture contents. + // Note that the function doesn't track or restore any GL states. + // Function does the following(in order): + // a) Blits texture contents to back buffer. + // b) Calls Swap Buffers. + virtual void updateContents(const uint32_t); + + virtual void setGeometry(const IntRect&); + + virtual PlatformSurfaceConfig configuration(); + + virtual void destroy(); + +protected: + GLPlatformSurface(SurfaceAttributes); + + PlatformDrawable m_drawable; + PlatformBufferHandle m_bufferHandle; + IntRect m_rect; +}; + +} + +#endif diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp index 02e1b9ec8..25c9a221c 100644 --- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp +++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp @@ -11,10 +11,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 @@ -26,7 +26,7 @@ #include "config.h" -#if USE(3D_GRAPHICS) +#if ENABLE(GRAPHICS_CONTEXT_3D) #include "GraphicsContext3D.h" #if PLATFORM(IOS) @@ -44,14 +44,21 @@ #include <wtf/MainThread.h> #include <wtf/text/CString.h> +#if USE(ACCELERATE) +#include <Accelerate/Accelerate.h> +#endif + #if PLATFORM(IOS) #import <OpenGLES/ES2/glext.h> // From <OpenGLES/glext.h> #define GL_RGBA32F_ARB 0x8814 #define GL_RGB32F_ARB 0x8815 #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> +#undef GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED +#elif PLATFORM(GTK) || PLATFORM(WIN) #include "OpenGLShims.h" #endif @@ -65,7 +72,32 @@ void GraphicsContext3D::releaseShaderCompiler() void GraphicsContext3D::readPixelsAndConvertToBGRAIfNecessary(int x, int y, int width, int height, unsigned char* pixels) { - ::glReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels); + // NVIDIA drivers have a bug where calling readPixels in BGRA can return the wrong values for the alpha channel when the alpha is off for the context. + if (!m_attrs.alpha && getExtensions().isNVIDIA()) { + ::glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); +#if USE(ACCELERATE) + vImage_Buffer src; + src.height = height; + src.width = width; + src.rowBytes = width * 4; + src.data = pixels; + + vImage_Buffer dest; + dest.height = height; + dest.width = width; + dest.rowBytes = width * 4; + dest.data = pixels; + + // Swap pixel channels from RGBA to BGRA. + const uint8_t map[4] = { 2, 1, 0, 3 }; + vImagePermuteChannels_ARGB8888(&src, &dest, map, kvImageNoFlags); +#else + int totalBytes = width * height * 4; + for (int i = 0; i < totalBytes; i += 4) + std::swap(pixels[i], pixels[i + 2]); +#endif + } else + ::glReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels); } void GraphicsContext3D::validateAttributes() @@ -89,9 +121,9 @@ bool GraphicsContext3D::reshapeFBOs(const IntSize& size) // We don't allow the logic where stencil is required and depth is not. // See GraphicsContext3D::validateAttributes. - Extensions3D* extensions = getExtensions(); + Extensions3D& extensions = getExtensions(); // Use a 24 bit depth buffer where we know we have it. - if (extensions->supports("GL_EXT_packed_depth_stencil")) + if (extensions.supports("GL_EXT_packed_depth_stencil")) internalDepthStencilFormat = GL_DEPTH24_STENCIL8_EXT; else #if PLATFORM(IOS) @@ -110,7 +142,11 @@ bool GraphicsContext3D::reshapeFBOs(const IntSize& size) sampleCount = maxSampleCount; ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleColorBuffer); +#if PLATFORM(IOS) + ::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, GL_RGBA8_OES, width, height); +#else ::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, m_internalColorFormat, width, height); +#endif ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_multisampleColorBuffer); if (m_attrs.stencil || m_attrs.depth) { ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); @@ -143,9 +179,31 @@ bool GraphicsContext3D::reshapeFBOs(const IntSize& size) ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture); ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0); ::glBindTexture(GL_TEXTURE_2D, 0); +#if USE(COORDINATED_GRAPHICS_THREADED) + ::glBindTexture(GL_TEXTURE_2D, m_intermediateTexture); + ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0); + ::glBindTexture(GL_TEXTURE_2D, 0); +#endif } #endif + attachDepthAndStencilBufferIfNeeded(internalDepthStencilFormat, width, height); + + bool mustRestoreFBO = true; + if (m_attrs.antialias) { + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); + if (m_state.boundFBO == m_multisampleFBO) + mustRestoreFBO = false; + } else { + if (m_state.boundFBO == m_fbo) + mustRestoreFBO = false; + } + + return mustRestoreFBO; +} + +void GraphicsContext3D::attachDepthAndStencilBufferIfNeeded(GLuint internalDepthStencilFormat, int width, int height) +{ if (!m_attrs.antialias && (m_attrs.stencil || m_attrs.depth)) { ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthStencilBuffer); ::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalDepthStencilFormat, width, height); @@ -160,18 +218,6 @@ bool GraphicsContext3D::reshapeFBOs(const IntSize& size) // FIXME: cleanup notImplemented(); } - - bool mustRestoreFBO = true; - if (m_attrs.antialias) { - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); - if (m_state.boundFBO == m_multisampleFBO) - mustRestoreFBO = false; - } else { - if (m_state.boundFBO == m_fbo) - mustRestoreFBO = false; - } - - return mustRestoreFBO; } void GraphicsContext3D::resolveMultisamplingIfNecessary(const IntRect& rect) @@ -181,11 +227,20 @@ void GraphicsContext3D::resolveMultisamplingIfNecessary(const IntRect& rect) TemporaryOpenGLSetting scopedDepth(GL_DEPTH_TEST, GL_FALSE); TemporaryOpenGLSetting scopedStencil(GL_STENCIL_TEST, GL_FALSE); +#if PLATFORM(IOS) + GLint boundFrameBuffer; + ::glGetIntegerv(GL_FRAMEBUFFER_BINDING, &boundFrameBuffer); +#endif + ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); #if PLATFORM(IOS) UNUSED_PARAM(rect); + ::glFlush(); ::glResolveMultisampleFramebufferAPPLE(); + const GLenum discards[] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT }; + ::glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER_APPLE, 2, discards); + ::glBindFramebuffer(GL_FRAMEBUFFER, boundFrameBuffer); #else IntRect resolveRect = rect; if (rect.isEmpty()) @@ -236,10 +291,29 @@ void GraphicsContext3D::getIntegerv(GC3Denum pname, GC3Dint* value) *value /= 4; break; case MAX_VARYING_VECTORS: - ::glGetIntegerv(GL_MAX_VARYING_FLOATS, value); - *value /= 4; + if (isGLES2Compliant()) { + ASSERT(::glGetError() == GL_NO_ERROR); + ::glGetIntegerv(GL_MAX_VARYING_VECTORS, value); + if (::glGetError() == GL_INVALID_ENUM) { + ::glGetIntegerv(GL_MAX_VARYING_COMPONENTS, value); + *value /= 4; + } + } else { + ::glGetIntegerv(GL_MAX_VARYING_FLOATS, value); + *value /= 4; + } break; #endif + case MAX_TEXTURE_SIZE: + ::glGetIntegerv(MAX_TEXTURE_SIZE, value); + if (getExtensions().requiresRestrictedMaximumTextureSize()) + *value = std::min(4096, *value); + break; + case MAX_CUBE_MAP_TEXTURE_SIZE: + ::glGetIntegerv(MAX_CUBE_MAP_TEXTURE_SIZE, value); + if (getExtensions().requiresRestrictedMaximumTextureSize()) + *value = std::min(1024, *value); + break; default: ::glGetIntegerv(pname, value); } @@ -283,14 +357,15 @@ bool GraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum inte return false; } + GC3Denum openGLFormat = format; GC3Denum openGLInternalFormat = internalformat; +#if !PLATFORM(IOS) if (type == GL_FLOAT) { if (format == GL_RGBA) openGLInternalFormat = GL_RGBA32F_ARB; else if (format == GL_RGB) openGLInternalFormat = GL_RGB32F_ARB; } else if (type == HALF_FLOAT_OES) { -#if !PLATFORM(IOS) if (format == GL_RGBA) openGLInternalFormat = GL_RGBA16F_ARB; else if (format == GL_RGB) @@ -302,9 +377,25 @@ bool GraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum inte else if (format == GL_LUMINANCE_ALPHA) openGLInternalFormat = GL_LUMINANCE_ALPHA16F_ARB; type = GL_HALF_FLOAT_ARB; + } + + ASSERT(format != Extensions3D::SRGB8_ALPHA8_EXT); + if (format == Extensions3D::SRGB_ALPHA_EXT) + openGLFormat = GL_RGBA; + else if (format == Extensions3D::SRGB_EXT) + openGLFormat = GL_RGB; #endif + + if (m_usingCoreProfile && openGLInternalFormat == ALPHA) { + // We are using a core profile. This means that GL_ALPHA, which is a valid format in WebGL for texImage2D + // is not supported in OpenGL. It needs to be backed with a GL_RED plane. We change the formats to GL_RED + // (both need to be GL_ALPHA in WebGL) and instruct the texture to swizzle the red component values with + // the the alpha component values. + openGLInternalFormat = openGLFormat = RED; + texParameteri(target, TEXTURE_SWIZZLE_A, RED); } - texImage2DDirect(target, level, openGLInternalFormat, width, height, border, format, type, pixels); + + texImage2DDirect(target, level, openGLInternalFormat, width, height, border, openGLFormat, type, pixels); return true; } @@ -328,12 +419,14 @@ void GraphicsContext3D::clearDepth(GC3Dclampf depth) #endif } -Extensions3D* GraphicsContext3D::getExtensions() +#if !PLATFORM(GTK) +Extensions3D& GraphicsContext3D::getExtensions() { if (!m_extensions) - m_extensions = adoptPtr(new Extensions3DOpenGL(this)); - return m_extensions.get(); + m_extensions = std::make_unique<Extensions3DOpenGL>(this, isGLES2Compliant()); + return *m_extensions; } +#endif void GraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data) { @@ -351,31 +444,6 @@ void GraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsi ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); } -#if !PLATFORM(MAC) -void GraphicsContext3D::drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount) -{ - UNUSED_PARAM(mode); - UNUSED_PARAM(first); - UNUSED_PARAM(count); - UNUSED_PARAM(primcount); -} - -void GraphicsContext3D::drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset, GC3Dsizei primcount) -{ - UNUSED_PARAM(mode); - UNUSED_PARAM(count); - UNUSED_PARAM(type); - UNUSED_PARAM(offset); - UNUSED_PARAM(primcount); -} - -void GraphicsContext3D::vertexAttribDivisor(GC3Duint index, GC3Duint divisor) -{ - UNUSED_PARAM(index); - UNUSED_PARAM(divisor); -} -#endif - } -#endif // USE(3D_GRAPHICS) +#endif // ENABLE(GRAPHICS_CONTEXT_3D) 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) diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp index 546b2d433..6b608c66d 100644 --- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp +++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.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" @@ -37,6 +37,12 @@ #include "IntSize.h" #include "NotImplemented.h" +#if PLATFORM(WIN) +#include <GLSLANG/ShaderLang.h> +#else +#include <ANGLE/ShaderLang.h> +#endif + namespace WebCore { void GraphicsContext3D::releaseShaderCompiler() @@ -90,7 +96,7 @@ bool GraphicsContext3D::reshapeFBOs(const IntSize& size) // We don't allow the logic where stencil is required and depth is not. // See GraphicsContext3D::validateAttributes. - bool supportPackedDepthStencilBuffer = (m_attrs.stencil || m_attrs.depth) && getExtensions()->supports("GL_OES_packed_depth_stencil"); + bool supportPackedDepthStencilBuffer = (m_attrs.stencil || m_attrs.depth) && getExtensions().supports("GL_OES_packed_depth_stencil"); // Resize regular FBO. bool mustRestoreFBO = false; @@ -110,29 +116,64 @@ bool GraphicsContext3D::reshapeFBOs(const IntSize& size) ::glBindTexture(GL_TEXTURE_2D, 0); } - // We don't support antialiasing yet. See GraphicsContext3D::validateAttributes. - ASSERT(!m_attrs.antialias); - - if (m_attrs.stencil || m_attrs.depth) { - // Use a 24 bit depth buffer where we know we have it. - if (supportPackedDepthStencilBuffer) { - ::glBindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer); - ::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height); - if (m_attrs.stencil) - ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer); - if (m_attrs.depth) - ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer); - ::glBindRenderbuffer(GL_RENDERBUFFER, 0); - } else { - if (m_attrs.stencil) { - ::glBindRenderbuffer(GL_RENDERBUFFER, m_stencilBuffer); - ::glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height); - ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencilBuffer); +#if USE(COORDINATED_GRAPHICS_THREADED) + ::glBindTexture(GL_TEXTURE_2D, m_intermediateTexture); + ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0); + ::glBindTexture(GL_TEXTURE_2D, 0); +#endif + + Extensions3DOpenGLES& extensions = static_cast<Extensions3DOpenGLES&>(getExtensions()); + if (extensions.isImagination() && m_attrs.antialias) { + GLint maxSampleCount; + ::glGetIntegerv(Extensions3D::MAX_SAMPLES_IMG, &maxSampleCount); + GLint sampleCount = std::min(8, maxSampleCount); + + extensions.framebufferTexture2DMultisampleIMG(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0, sampleCount); + + if (m_attrs.stencil || m_attrs.depth) { + // Use a 24 bit depth buffer where we know we have it. + if (supportPackedDepthStencilBuffer) { + ::glBindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer); + extensions.renderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, GL_DEPTH24_STENCIL8_OES, width, height); + if (m_attrs.stencil) + ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer); + if (m_attrs.depth) + ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer); + } else { + if (m_attrs.stencil) { + ::glBindRenderbuffer(GL_RENDERBUFFER, m_stencilBuffer); + extensions.renderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, GL_STENCIL_INDEX8, width, height); + ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencilBuffer); + } + if (m_attrs.depth) { + ::glBindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer); + extensions.renderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, GL_DEPTH_COMPONENT16, width, height); + ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBuffer); + } } - if (m_attrs.depth) { - ::glBindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer); - ::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); - ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBuffer); + ::glBindRenderbuffer(GL_RENDERBUFFER, 0); + } + } else { + if (m_attrs.stencil || m_attrs.depth) { + // Use a 24 bit depth buffer where we know we have it. + if (supportPackedDepthStencilBuffer) { + ::glBindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer); + ::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height); + if (m_attrs.stencil) + ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer); + if (m_attrs.depth) + ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer); + } else { + if (m_attrs.stencil) { + ::glBindRenderbuffer(GL_RENDERBUFFER, m_stencilBuffer); + ::glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height); + ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencilBuffer); + } + if (m_attrs.depth) { + ::glBindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer); + ::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); + ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBuffer); + } } ::glBindRenderbuffer(GL_RENDERBUFFER, 0); } @@ -145,7 +186,7 @@ bool GraphicsContext3D::reshapeFBOs(const IntSize& size) return mustRestoreFBO; } -void GraphicsContext3D::resolveMultisamplingIfNecessary(const IntRect& rect) +void GraphicsContext3D::resolveMultisamplingIfNecessary(const IntRect&) { // FIXME: We don't support antialiasing yet. notImplemented(); @@ -187,11 +228,8 @@ void GraphicsContext3D::validateAttributes() { validateDepthStencil("GL_OES_packed_depth_stencil"); - if (m_attrs.antialias) { - Extensions3D* extensions = getExtensions(); - if (!extensions->supports("GL_IMG_multisampled_render_to_texture")) - m_attrs.antialias = false; - } + if (m_attrs.antialias && !getExtensions().supports("GL_IMG_multisampled_render_to_texture")) + m_attrs.antialias = false; } void GraphicsContext3D::depthRange(GC3Dclampf zNear, GC3Dclampf zFar) @@ -206,36 +244,171 @@ void GraphicsContext3D::clearDepth(GC3Dclampf depth) ::glClearDepthf(depth); } -void GraphicsContext3D::drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount) +#if !PLATFORM(GTK) +Extensions3D& GraphicsContext3D::getExtensions() +{ + if (!m_extensions) + m_extensions = std::make_unique<Extensions3DOpenGLES>(this, isGLES2Compliant()); + return *m_extensions; +} +#endif + +#if PLATFORM(WIN) && !USE(CAIRO) +RefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3DAttributes attributes, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle) { - UNUSED_PARAM(mode); - UNUSED_PARAM(first); - UNUSED_PARAM(count); - UNUSED_PARAM(primcount); + // This implementation doesn't currently support rendering directly to the HostWindow. + if (renderStyle == RenderDirectlyToHostWindow) + return nullptr; + + static bool initialized = false; + static bool success = true; + if (!initialized) { +#if !USE(OPENGL_ES_2) + success = initializeOpenGLShims(); +#endif + initialized = true; + } + if (!success) + return nullptr; + + return adoptRef(new GraphicsContext3D(attributes, hostWindow, renderStyle)); } -void GraphicsContext3D::drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset, GC3Dsizei primcount) +GraphicsContext3D::GraphicsContext3D(GraphicsContext3DAttributes attributes, HostWindow*, GraphicsContext3D::RenderStyle renderStyle) + : m_currentWidth(0) + , m_currentHeight(0) + , m_compiler(isGLES2Compliant() ? SH_ESSL_OUTPUT : SH_GLSL_COMPATIBILITY_OUTPUT) + , m_attrs(attributes) + , m_texture(0) + , m_fbo(0) + , m_depthStencilBuffer(0) + , m_multisampleFBO(0) + , m_multisampleDepthStencilBuffer(0) + , m_multisampleColorBuffer(0) + , m_private(std::make_unique<GraphicsContext3DPrivate>(this, renderStyle)) { - UNUSED_PARAM(mode); - UNUSED_PARAM(count); - UNUSED_PARAM(type); - UNUSED_PARAM(offset); - UNUSED_PARAM(primcount); + makeContextCurrent(); + + validateAttributes(); + + if (renderStyle == RenderOffscreen) { + // Create a texture to render into. + ::glGenTextures(1, &m_texture); + ::glBindTexture(GL_TEXTURE_2D, m_texture); + ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + ::glBindTexture(GL_TEXTURE_2D, 0); + + // Create an FBO. + ::glGenFramebuffers(1, &m_fbo); + ::glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); + + m_state.boundFBO = m_fbo; + if (!m_attrs.antialias && (m_attrs.stencil || m_attrs.depth)) + ::glGenRenderbuffers(1, &m_depthStencilBuffer); + + // Create a multisample FBO. + if (m_attrs.antialias) { + ::glGenFramebuffers(1, &m_multisampleFBO); + ::glBindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO); + m_state.boundFBO = m_multisampleFBO; + ::glGenRenderbuffers(1, &m_multisampleColorBuffer); + if (m_attrs.stencil || m_attrs.depth) + ::glGenRenderbuffers(1, &m_multisampleDepthStencilBuffer); + } + } + + // ANGLE initialization. + ShBuiltInResources ANGLEResources; + ShInitBuiltInResources(&ANGLEResources); + + getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &ANGLEResources.MaxVertexAttribs); + getIntegerv(GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS, &ANGLEResources.MaxVertexUniformVectors); + getIntegerv(GraphicsContext3D::MAX_VARYING_VECTORS, &ANGLEResources.MaxVaryingVectors); + getIntegerv(GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxVertexTextureImageUnits); + getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxCombinedTextureImageUnits); + getIntegerv(GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxTextureImageUnits); + getIntegerv(GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS, &ANGLEResources.MaxFragmentUniformVectors); + + // Always set to 1 for OpenGL ES. + ANGLEResources.MaxDrawBuffers = 1; + + GC3Dint range[2], precision; + getShaderPrecisionFormat(GraphicsContext3D::FRAGMENT_SHADER, GraphicsContext3D::HIGH_FLOAT, range, &precision); + ANGLEResources.FragmentPrecisionHigh = (range[0] || range[1] || precision); + + m_compiler.setResources(ANGLEResources); + +#if !USE(OPENGL_ES_2) + ::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); + ::glEnable(GL_POINT_SPRITE); +#endif + + ::glClearColor(0, 0, 0, 0); } -void GraphicsContext3D::vertexAttribDivisor(GC3Duint index, GC3Duint divisor) +GraphicsContext3D::~GraphicsContext3D() { - UNUSED_PARAM(index); - UNUSED_PARAM(divisor); + makeContextCurrent(); + ::glDeleteTextures(1, &m_texture); + if (m_attrs.antialias) { + ::glDeleteRenderbuffers(1, &m_multisampleColorBuffer); + if (m_attrs.stencil || m_attrs.depth) + ::glDeleteRenderbuffers(1, &m_multisampleDepthStencilBuffer); + ::glDeleteFramebuffers(1, &m_multisampleFBO); + } else { + if (m_attrs.stencil || m_attrs.depth) + ::glDeleteRenderbuffers(1, &m_depthStencilBuffer); + } + ::glDeleteFramebuffers(1, &m_fbo); } -Extensions3D* GraphicsContext3D::getExtensions() +void GraphicsContext3D::setContextLostCallback(std::unique_ptr<ContextLostCallback>) { - if (!m_extensions) - m_extensions = adoptPtr(new Extensions3DOpenGLES(this)); - return m_extensions.get(); } +void GraphicsContext3D::setErrorMessageCallback(std::unique_ptr<ErrorMessageCallback>) +{ +} + +bool GraphicsContext3D::makeContextCurrent() +{ + if (!m_private) + return false; + return m_private->makeContextCurrent(); +} + +void GraphicsContext3D::checkGPUStatusIfNecessary() +{ +} + +PlatformGraphicsContext3D GraphicsContext3D::platformGraphicsContext3D() +{ + return m_private->platformContext(); +} + +Platform3DObject GraphicsContext3D::platformTexture() const +{ + return m_texture; +} + +bool GraphicsContext3D::isGLES2Compliant() const +{ +#if USE(OPENGL_ES_2) + return true; +#else + return false; +#endif +} + +PlatformLayer* GraphicsContext3D::platformLayer() const +{ + return m_webGLLayer->platformLayer(); +} +#endif + } -#endif // USE(3D_GRAPHICS) +#endif // ENABLE(GRAPHICS_CONTEXT_3D) diff --git a/Source/WebCore/platform/graphics/opengl/TemporaryOpenGLSetting.cpp b/Source/WebCore/platform/graphics/opengl/TemporaryOpenGLSetting.cpp index a0163770c..7438d9e14 100644 --- a/Source/WebCore/platform/graphics/opengl/TemporaryOpenGLSetting.cpp +++ b/Source/WebCore/platform/graphics/opengl/TemporaryOpenGLSetting.cpp @@ -26,7 +26,7 @@ #include "config.h" -#if USE(3D_GRAPHICS) +#if ENABLE(GRAPHICS_CONTEXT_3D) #include "TemporaryOpenGLSetting.h" #if USE(OPENGL_ES_2) @@ -36,7 +36,7 @@ #include <OpenGLES/ES2/gl.h> #elif PLATFORM(MAC) #include <OpenGL/gl.h> -#elif PLATFORM(GTK) || PLATFORM(EFL) || PLATFORM(WIN) +#elif PLATFORM(GTK) || PLATFORM(WIN) #include "OpenGLShims.h" #endif diff --git a/Source/WebCore/platform/graphics/opengl/TemporaryOpenGLSetting.h b/Source/WebCore/platform/graphics/opengl/TemporaryOpenGLSetting.h index 833f8b6be..cb51695b7 100644 --- a/Source/WebCore/platform/graphics/opengl/TemporaryOpenGLSetting.h +++ b/Source/WebCore/platform/graphics/opengl/TemporaryOpenGLSetting.h @@ -38,7 +38,7 @@ namespace WebCore { // value upon destruction, making it an alternative to checking, clearing, and resetting each flag // at all of a block's exit points. // -// Based on WTF::TemporaryChange<> +// Based on WTF::SetForScope<> class TemporaryOpenGLSetting { WTF_MAKE_NONCOPYABLE(TemporaryOpenGLSetting); |