summaryrefslogtreecommitdiff
path: root/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp')
-rw-r--r--Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp172
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)