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/GraphicsContext3DOpenGL.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp')
-rw-r--r-- | Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp | 172 |
1 files changed, 120 insertions, 52 deletions
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) |