summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2012-10-17 16:21:14 +0200
committerSimon Hausmann <simon.hausmann@digia.com>2012-10-17 16:21:14 +0200
commit8995b83bcbfbb68245f779b64e5517627c6cc6ea (patch)
tree17985605dab9263cc2444bd4d45f189e142cca7c /Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp
parentb9c9652036d5e9f1e29c574f40bc73a35c81ace6 (diff)
Imported WebKit commit cf4f8fc6f19b0629f51860cb2d4b25e139d07e00 (http://svn.webkit.org/repository/webkit/trunk@131592)
New snapshot that includes the build fixes for Mac OS X 10.6 and earlier as well as the previously cherry-picked changes
Diffstat (limited to 'Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp')
-rw-r--r--Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp939
1 files changed, 340 insertions, 599 deletions
diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp
index 73d6fefbb..27e786713 100644
--- a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp
+++ b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp
@@ -28,249 +28,69 @@
#include "Logging.h"
#include "TextureMapperGL.h"
+#define STRINGIFY(...) #__VA_ARGS__
+
namespace WebCore {
-#define STRINGIFY(...) #__VA_ARGS__
-static const char* fragmentShaderSourceOpacityAndMask =
- STRINGIFY(
- precision mediump float;
- uniform sampler2D s_source;
- uniform sampler2D s_mask;
- uniform lowp float u_opacity;
- varying highp vec2 v_sourceTexCoord;
- varying highp vec2 v_maskTexCoord;
- void main(void)
- {
- lowp vec4 color = texture2D(s_source, v_sourceTexCoord);
- lowp vec4 maskColor = texture2D(s_mask, v_maskTexCoord);
- lowp float fragmentAlpha = u_opacity * maskColor.a;
- gl_FragColor = vec4(color.rgb * fragmentAlpha, color.a * fragmentAlpha);
- }
- );
-
-static const char* fragmentShaderSourceRectOpacityAndMask =
- STRINGIFY(
- precision mediump float;
- uniform sampler2DRect s_source;
- uniform sampler2DRect s_mask;
- uniform lowp float u_opacity;
- varying highp vec2 v_sourceTexCoord;
- varying highp vec2 v_maskTexCoord;
- void main(void)
- {
- lowp vec4 color = texture2DRect(s_source, v_sourceTexCoord);
- lowp vec4 maskColor = texture2DRect(s_mask, v_maskTexCoord);
- lowp float fragmentAlpha = u_opacity * maskColor.a;
- gl_FragColor = vec4(color.rgb * fragmentAlpha, color.a * fragmentAlpha);
- }
- );
-
-static const char* vertexShaderSourceOpacityAndMask =
- STRINGIFY(
- uniform mat4 u_matrix;
- uniform lowp float u_flip;
- attribute vec4 a_vertex;
- varying highp vec2 v_sourceTexCoord;
- varying highp vec2 v_maskTexCoord;
- void main(void)
- {
- v_sourceTexCoord = vec2(a_vertex.x, mix(a_vertex.y, 1. - a_vertex.y, u_flip));
- v_maskTexCoord = vec2(a_vertex);
- gl_Position = u_matrix * a_vertex;
- }
- );
-
-static const char* fragmentShaderSourceSimple =
- STRINGIFY(
- precision mediump float;
- uniform sampler2D s_source;
- uniform lowp float u_opacity;
- varying highp vec2 v_sourceTexCoord;
- void main(void)
- {
- lowp vec4 color = texture2D(s_source, v_sourceTexCoord);
- gl_FragColor = vec4(color.rgb * u_opacity, color.a * u_opacity);
- }
- );
-
-static const char* fragmentShaderSourceAntialiasingNoMask =
- STRINGIFY(
- precision mediump float;
- uniform sampler2D s_source;
- varying highp vec2 v_sourceTexCoord;
- uniform lowp float u_opacity;
- uniform vec3 u_expandedQuadEdgesInScreenSpace[8];
- void main()
- {
- vec4 sampledColor = texture2D(s_source, clamp(v_sourceTexCoord, 0.0, 1.0));
- vec3 pos = vec3(gl_FragCoord.xy, 1);
-
- // The data passed in u_expandedQuadEdgesInScreenSpace is merely the
- // pre-scaled coeffecients of the line equations describing the four edges
- // of the expanded quad in screen space and the rectangular bounding box
- // of the expanded quad.
- //
- // We are doing a simple distance calculation here according to the formula:
- // (A*p.x + B*p.y + C) / sqrt(A^2 + B^2) = distance from line to p
- // Note that A, B and C have already been scaled by 1 / sqrt(A^2 + B^2).
- float a0 = clamp(dot(u_expandedQuadEdgesInScreenSpace[0], pos), 0.0, 1.0);
- float a1 = clamp(dot(u_expandedQuadEdgesInScreenSpace[1], pos), 0.0, 1.0);
- float a2 = clamp(dot(u_expandedQuadEdgesInScreenSpace[2], pos), 0.0, 1.0);
- float a3 = clamp(dot(u_expandedQuadEdgesInScreenSpace[3], pos), 0.0, 1.0);
- float a4 = clamp(dot(u_expandedQuadEdgesInScreenSpace[4], pos), 0.0, 1.0);
- float a5 = clamp(dot(u_expandedQuadEdgesInScreenSpace[5], pos), 0.0, 1.0);
- float a6 = clamp(dot(u_expandedQuadEdgesInScreenSpace[6], pos), 0.0, 1.0);
- float a7 = clamp(dot(u_expandedQuadEdgesInScreenSpace[7], pos), 0.0, 1.0);
-
- // Now we want to reduce the alpha value of the fragment if it is close to the
- // edges of the expanded quad (or rectangular bounding box -- which seems to be
- // important for backfacing quads). Note that we are combining the contribution
- // from the (top || bottom) and (left || right) edge by simply multiplying. This follows
- // the approach described at: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter22.html,
- // in this case without using Gaussian weights.
- gl_FragColor = sampledColor * u_opacity * min(min(a0, a2) * min(a1, a3), min(a4, a6) * min(a5, a7));
- }
- );
-
-static const char* fragmentShaderSourceRectSimple =
- STRINGIFY(
- precision mediump float;
- uniform sampler2DRect s_source;
- uniform lowp vec2 u_textureSize;
- uniform lowp float u_opacity;
- varying highp vec2 v_sourceTexCoord;
- void main(void)
- {
- lowp vec4 color = texture2DRect(s_source, u_textureSize * v_sourceTexCoord);
- gl_FragColor = vec4(color.rgb * u_opacity, color.a * u_opacity);
- }
- );
-
-static const char* vertexShaderSourceSimple =
- STRINGIFY(
- uniform mat4 u_matrix;
- uniform lowp float u_flip;
- attribute vec4 a_vertex;
- varying highp vec2 v_sourceTexCoord;
- void main(void)
- {
- v_sourceTexCoord = vec2(a_vertex.x, mix(a_vertex.y, 1. - a_vertex.y, u_flip));
- gl_Position = u_matrix * a_vertex;
- }
- );
-
-static const char* vertexShaderSourceSolidColor =
- STRINGIFY(
- uniform mat4 u_matrix;
- attribute vec4 a_vertex;
- void main(void)
- {
- gl_Position = u_matrix * a_vertex;
- }
- );
-
-
-static const char* fragmentShaderSourceSolidColor =
- STRINGIFY(
- precision mediump float;
- uniform vec4 u_color;
- void main(void)
- {
- gl_FragColor = u_color;
- }
- );
-
-PassRefPtr<TextureMapperShaderProgramSolidColor> TextureMapperShaderManager::solidColorProgram()
+static inline bool compositingLogEnabled()
{
- return static_pointer_cast<TextureMapperShaderProgramSolidColor>(getShaderProgram(SolidColor));
+#if !LOG_DISABLED
+ return LogCompositing.state == WTFLogChannelOn;
+#else
+ return false;
+#endif
}
-PassRefPtr<TextureMapperShaderProgramAntialiasingNoMask> TextureMapperShaderManager::antialiasingNoMaskProgram()
+TextureMapperShaderProgram::TextureMapperShaderProgram(PassRefPtr<GraphicsContext3D> context, const String& vertex, const String& fragment)
+ : m_context(context)
{
- return static_pointer_cast<TextureMapperShaderProgramAntialiasingNoMask>(getShaderProgram(AntialiasingNoMask));
+ m_vertexShader = m_context->createShader(GraphicsContext3D::VERTEX_SHADER);
+ m_fragmentShader = m_context->createShader(GraphicsContext3D::FRAGMENT_SHADER);
+ m_context->shaderSource(m_vertexShader, vertex);
+ m_context->shaderSource(m_fragmentShader, fragment);
+ m_id = m_context->createProgram();
+ m_context->compileShader(m_vertexShader);
+ m_context->compileShader(m_fragmentShader);
+ m_context->attachShader(m_id, m_vertexShader);
+ m_context->attachShader(m_id, m_fragmentShader);
+ m_context->linkProgram(m_id);
+
+ if (!compositingLogEnabled())
+ return;
+
+ if (m_context->getError() == GraphicsContext3D::NO_ERROR)
+ return;
+
+ String log = m_context->getShaderInfoLog(m_vertexShader);
+ LOG(Compositing, "Vertex shader log: %s\n", log.utf8().data());
+ log = m_context->getShaderInfoLog(m_fragmentShader);
+ LOG(Compositing, "Fragment shader log: %s\n", log.utf8().data());
+ log = m_context->getProgramInfoLog(m_id);
+ LOG(Compositing, "Program log: %s\n", log.utf8().data());
}
-PassRefPtr<TextureMapperShaderProgram> TextureMapperShaderManager::getShaderProgram(ShaderType shaderType)
+GC3Duint TextureMapperShaderProgram::getLocation(const AtomicString& name, VariableType type)
{
- RefPtr<TextureMapperShaderProgram> program;
- if (shaderType == Invalid)
- return program;
+ HashMap<AtomicString, GC3Duint>::iterator it = m_variables.find(name);
+ if (it != m_variables.end())
+ return it->value;
- TextureMapperShaderProgramMap::iterator it = m_textureMapperShaderProgramMap.find(shaderType);
- if (it != m_textureMapperShaderProgramMap.end())
- return it->second;
-
- switch (shaderType) {
- case Simple:
- program = TextureMapperShaderProgramSimple::create(m_context);
- break;
- case RectSimple:
- program = TextureMapperShaderProgramRectSimple::create(m_context);
- break;
- case AntialiasingNoMask:
- program = TextureMapperShaderProgramAntialiasingNoMask::create(m_context);
- break;
- case OpacityAndMask:
- program = TextureMapperShaderProgramOpacityAndMask::create(m_context);
- break;
- case RectOpacityAndMask:
- program = TextureMapperShaderProgramRectOpacityAndMask::create(m_context);
+ GC3Duint location = 0;
+ switch (type) {
+ case UniformVariable:
+ location = m_context->getUniformLocation(m_id, name);
break;
- case SolidColor:
- program = TextureMapperShaderProgramSolidColor::create(m_context);
+ case AttribVariable:
+ location = m_context->getAttribLocation(m_id, name);
break;
- case Invalid:
+ default:
ASSERT_NOT_REACHED();
+ break;
}
- m_textureMapperShaderProgramMap.add(shaderType, program);
- return program;
-}
-
-TextureMapperShaderProgram::TextureMapperShaderProgram(GraphicsContext3D* context, const char* vertexShaderSource, const char* fragmentShaderSource)
- : m_context(context)
- , m_id(0)
- , m_vertexAttrib(0)
- , m_vertexShader(0)
- , m_fragmentShader(0)
- , m_matrixLocation(-1)
- , m_flipLocation(-1)
- , m_textureSizeLocation(-1)
- , m_sourceTextureLocation(-1)
- , m_opacityLocation(-1)
- , m_maskTextureLocation(-1)
- , m_vertexShaderSource(vertexShaderSource)
- , m_fragmentShaderSource(fragmentShaderSource)
-{
-}
-
-void TextureMapperShaderProgram::initializeProgram()
-{
- const char* vertexShaderSourceProgram = vertexShaderSource();
- const char* fragmentShaderSourceProgram = fragmentShaderSource();
- Platform3DObject vertexShader = m_context->createShader(GraphicsContext3D::VERTEX_SHADER);
- Platform3DObject fragmentShader = m_context->createShader(GraphicsContext3D::FRAGMENT_SHADER);
- m_context->shaderSource(vertexShader, vertexShaderSourceProgram);
- m_context->shaderSource(fragmentShader, fragmentShaderSourceProgram);
- Platform3DObject programID = m_context->createProgram();
- m_context->compileShader(vertexShader);
- m_context->compileShader(fragmentShader);
-
- m_context->attachShader(programID, vertexShader);
- m_context->attachShader(programID, fragmentShader);
- m_context->linkProgram(programID);
-
- m_vertexAttrib = m_context->getAttribLocation(programID, "a_vertex");
-
- m_id = programID;
- m_vertexShader = vertexShader;
- m_fragmentShader = fragmentShader;
-}
-void TextureMapperShaderProgram::getUniformLocation(GC3Dint &variable, const char* name)
-{
- variable = m_context->getUniformLocation(m_id, name);
- ASSERT(variable >= 0);
+ m_variables.add(name, location);
+ return location;
}
TextureMapperShaderProgram::~TextureMapperShaderProgram()
@@ -286,120 +106,189 @@ TextureMapperShaderProgram::~TextureMapperShaderProgram()
m_context->deleteProgram(programID);
}
-TextureMapperShaderProgramSimple::TextureMapperShaderProgramSimple(GraphicsContext3D* context)
- : TextureMapperShaderProgram(context, vertexShaderSourceSimple, fragmentShaderSourceSimple)
-{
- initializeProgram();
- getUniformLocation(m_flipLocation, "u_flip");
- getUniformLocation(m_matrixLocation, "u_matrix");
- getUniformLocation(m_sourceTextureLocation, "s_source");
- getUniformLocation(m_opacityLocation, "u_opacity");
-}
+struct ShaderSpec {
+ String vertexShader;
+ String fragmentShader;
+ ShaderSpec(const char* vertex = 0, const char* fragment = 0)
+ : vertexShader(vertex ? String(ASCIILiteral(vertex)) : String())
+ , fragmentShader(fragment ? String(ASCIILiteral(fragment)) : String())
+ {
+ }
+};
-TextureMapperShaderProgramSolidColor::TextureMapperShaderProgramSolidColor(GraphicsContext3D* context)
- : TextureMapperShaderProgram(context, vertexShaderSourceSolidColor, fragmentShaderSourceSolidColor)
+static void getShaderSpec(TextureMapperShaderManager::ShaderKey key, String& vertexSource, String& fragmentSource)
{
- initializeProgram();
- getUniformLocation(m_matrixLocation, "u_matrix");
- getUniformLocation(m_colorLocation, "u_color");
-}
+ static Vector<ShaderSpec> specs = Vector<ShaderSpec>();
+ static const char* fragmentOpacityAndMask =
+ STRINGIFY(
+ precision mediump float;
+ uniform sampler2D s_sampler;
+ uniform sampler2D s_mask;
+ uniform lowp float u_opacity;
+ varying highp vec2 v_sourceTexCoord;
+ varying highp vec2 v_maskTexCoord;
+ void main(void)
+ {
+ lowp vec4 color = texture2D(s_sampler, v_sourceTexCoord);
+ lowp vec4 maskColor = texture2D(s_mask, v_maskTexCoord);
+ lowp float fragmentAlpha = u_opacity * maskColor.a;
+ gl_FragColor = vec4(color.rgb * fragmentAlpha, color.a * fragmentAlpha);
+ }
+ );
-TextureMapperShaderProgramRectSimple::TextureMapperShaderProgramRectSimple(GraphicsContext3D* context)
- : TextureMapperShaderProgram(context, vertexShaderSourceSimple, fragmentShaderSourceRectSimple)
-{
- initializeProgram();
- getUniformLocation(m_matrixLocation, "u_matrix");
- getUniformLocation(m_flipLocation, "u_flip");
- getUniformLocation(m_textureSizeLocation, "u_textureSize");
- getUniformLocation(m_sourceTextureLocation, "s_source");
- getUniformLocation(m_opacityLocation, "u_opacity");
-}
+ static const char* fragmentRectOpacityAndMask =
+ STRINGIFY(
+ precision mediump float;
+ uniform sampler2DRect s_sampler;
+ uniform sampler2DRect s_mask;
+ uniform lowp float u_opacity;
+ varying highp vec2 v_sourceTexCoord;
+ varying highp vec2 v_maskTexCoord;
+ void main(void)
+ {
+ lowp vec4 color = texture2DRect(s_sampler, v_sourceTexCoord);
+ lowp vec4 maskColor = texture2DRect(s_mask, v_maskTexCoord);
+ lowp float fragmentAlpha = u_opacity * maskColor.a;
+ gl_FragColor = vec4(color.rgb * fragmentAlpha, color.a * fragmentAlpha);
+ }
+ );
-TextureMapperShaderProgramOpacityAndMask::TextureMapperShaderProgramOpacityAndMask(GraphicsContext3D* context)
- : TextureMapperShaderProgram(context, vertexShaderSourceOpacityAndMask, fragmentShaderSourceOpacityAndMask)
-{
- initializeProgram();
- getUniformLocation(m_matrixLocation, "u_matrix");
- getUniformLocation(m_flipLocation, "u_flip");
- getUniformLocation(m_sourceTextureLocation, "s_source");
- getUniformLocation(m_maskTextureLocation, "s_mask");
- getUniformLocation(m_opacityLocation, "u_opacity");
-}
+ static const char* vertexOpacityAndMask =
+ STRINGIFY(
+ uniform mat4 u_matrix;
+ uniform lowp float u_flip;
+ attribute vec4 a_vertex;
+ varying highp vec2 v_sourceTexCoord;
+ varying highp vec2 v_maskTexCoord;
+ void main(void)
+ {
+ v_sourceTexCoord = vec2(a_vertex.x, mix(a_vertex.y, 1. - a_vertex.y, u_flip));
+ v_maskTexCoord = vec2(a_vertex);
+ gl_Position = u_matrix * a_vertex;
+ }
+ );
-TextureMapperShaderProgramRectOpacityAndMask::TextureMapperShaderProgramRectOpacityAndMask(GraphicsContext3D* context)
- : TextureMapperShaderProgram(context, vertexShaderSourceOpacityAndMask, fragmentShaderSourceRectOpacityAndMask)
-{
- initializeProgram();
- getUniformLocation(m_matrixLocation, "u_matrix");
- getUniformLocation(m_flipLocation, "u_flip");
- getUniformLocation(m_sourceTextureLocation, "s_source");
- getUniformLocation(m_maskTextureLocation, "s_mask");
- getUniformLocation(m_opacityLocation, "u_opacity");
-}
+ static const char* fragmentSimple =
+ STRINGIFY(
+ precision mediump float;
+ uniform sampler2D s_sampler;
+ uniform lowp float u_opacity;
+ varying highp vec2 v_sourceTexCoord;
+ void main(void)
+ {
+ lowp vec4 color = texture2D(s_sampler, v_sourceTexCoord);
+ gl_FragColor = vec4(color.rgb * u_opacity, color.a * u_opacity);
+ }
+ );
-TextureMapperShaderProgramAntialiasingNoMask::TextureMapperShaderProgramAntialiasingNoMask(GraphicsContext3D* context)
- : TextureMapperShaderProgram(context, vertexShaderSourceSimple, fragmentShaderSourceAntialiasingNoMask)
-{
- initializeProgram();
- getUniformLocation(m_matrixLocation, "u_matrix");
- getUniformLocation(m_sourceTextureLocation, "s_source");
- getUniformLocation(m_opacityLocation, "u_opacity");
- getUniformLocation(m_expandedQuadEdgesInScreenSpaceLocation, "u_expandedQuadEdgesInScreenSpace");
- getUniformLocation(m_flipLocation, "u_flip");
-}
+ static const char* fragmentAntialiasingNoMask =
+ STRINGIFY(
+ precision mediump float;
+ uniform sampler2D s_sampler;
+ varying highp vec2 v_sourceTexCoord;
+ uniform lowp float u_opacity;
+ uniform vec3 u_expandedQuadEdgesInScreenSpace[8];
+ void main()
+ {
+ vec4 sampledColor = texture2D(s_sampler, clamp(v_sourceTexCoord, 0.0, 1.0));
+ vec3 pos = vec3(gl_FragCoord.xy, 1);
+
+ // The data passed in u_expandedQuadEdgesInScreenSpace is merely the
+ // pre-scaled coeffecients of the line equations describing the four edges
+ // of the expanded quad in screen space and the rectangular bounding box
+ // of the expanded quad.
+ //
+ // We are doing a simple distance calculation here according to the formula:
+ // (A*p.x + B*p.y + C) / sqrt(A^2 + B^2) = distance from line to p
+ // Note that A, B and C have already been scaled by 1 / sqrt(A^2 + B^2).
+ float a0 = clamp(dot(u_expandedQuadEdgesInScreenSpace[0], pos), 0.0, 1.0);
+ float a1 = clamp(dot(u_expandedQuadEdgesInScreenSpace[1], pos), 0.0, 1.0);
+ float a2 = clamp(dot(u_expandedQuadEdgesInScreenSpace[2], pos), 0.0, 1.0);
+ float a3 = clamp(dot(u_expandedQuadEdgesInScreenSpace[3], pos), 0.0, 1.0);
+ float a4 = clamp(dot(u_expandedQuadEdgesInScreenSpace[4], pos), 0.0, 1.0);
+ float a5 = clamp(dot(u_expandedQuadEdgesInScreenSpace[5], pos), 0.0, 1.0);
+ float a6 = clamp(dot(u_expandedQuadEdgesInScreenSpace[6], pos), 0.0, 1.0);
+ float a7 = clamp(dot(u_expandedQuadEdgesInScreenSpace[7], pos), 0.0, 1.0);
+
+ // Now we want to reduce the alpha value of the fragment if it is close to the
+ // edges of the expanded quad (or rectangular bounding box -- which seems to be
+ // important for backfacing quads). Note that we are combining the contribution
+ // from the (top || bottom) and (left || right) edge by simply multiplying. This follows
+ // the approach described at: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter22.html,
+ // in this case without using Gaussian weights.
+ gl_FragColor = sampledColor * u_opacity * min(min(a0, a2) * min(a1, a3), min(a4, a6) * min(a5, a7));
+ }
+ );
-TextureMapperShaderManager::TextureMapperShaderManager(GraphicsContext3D* context)
- : m_context(context)
-{
-}
+ static const char* fragmentRectSimple =
+ STRINGIFY(
+ precision mediump float;
+ uniform sampler2DRect s_sampler;
+ uniform lowp vec2 s_samplerSize;
+ uniform lowp float u_opacity;
+ varying highp vec2 v_sourceTexCoord;
+ void main(void)
+ {
+ lowp vec4 color = texture2DRect(s_sampler, s_samplerSize * v_sourceTexCoord);
+ gl_FragColor = vec4(color.rgb * u_opacity, color.a * u_opacity);
+ }
+ );
-TextureMapperShaderManager::~TextureMapperShaderManager()
-{
-}
+ static const char* vertexSimple =
+ STRINGIFY(
+ uniform mat4 u_matrix;
+ uniform lowp float u_flip;
+ attribute vec4 a_vertex;
+ varying highp vec2 v_sourceTexCoord;
+ void main(void)
+ {
+ v_sourceTexCoord = vec2(a_vertex.x, mix(a_vertex.y, 1. - a_vertex.y, u_flip));
+ gl_Position = u_matrix * a_vertex;
+ }
+ );
-#if ENABLE(CSS_FILTERS)
+ static const char* vertexSolidColor =
+ STRINGIFY(
+ uniform mat4 u_matrix;
+ attribute vec4 a_vertex;
+ void main(void)
+ {
+ gl_Position = u_matrix * a_vertex;
+ }
+ );
-// Create a normal distribution of 21 values between -2 and 2.
-#define GAUSSIAN_KERNEL_HALF_WIDTH 11
-#define GAUSSIAN_KERNEL_STEP 0.2
-StandardFilterProgram::~StandardFilterProgram()
-{
- m_context->detachShader(m_id, m_vertexShader);
- m_context->deleteShader(m_vertexShader);
- m_context->detachShader(m_id, m_fragmentShader);
- m_context->deleteShader(m_fragmentShader);
- m_context->deleteProgram(m_id);
-}
+ static const char* fragmentSolidColor =
+ STRINGIFY(
+ precision mediump float;
+ uniform vec4 u_color;
+ void main(void)
+ {
+ gl_FragColor = u_color;
+ }
+ );
-StandardFilterProgram::StandardFilterProgram(GraphicsContext3D* context, FilterOperation::OperationType type, unsigned pass)
- : m_context(context)
- , m_id(0)
-{
- const char* vertexShaderSource =
- STRINGIFY(
- attribute vec4 a_vertex;
- attribute vec4 a_texCoord;
- varying highp vec2 v_texCoord;
- void main(void)
- {
- v_texCoord = vec2(a_texCoord);
- gl_Position = a_vertex;
- }
- );
+ static const char* vertexFilter =
+ STRINGIFY(
+ attribute vec4 a_vertex;
+ attribute vec4 a_texCoord;
+ varying highp vec2 v_texCoord;
+ void main(void)
+ {
+ v_texCoord = vec2(a_texCoord);
+ gl_Position = a_vertex;
+ }
+ );
#define STANDARD_FILTER(...) \
"precision mediump float;\n"\
"varying highp vec2 v_texCoord;\n"\
"uniform highp float u_amount;\n"\
- "uniform sampler2D u_texture;\n"\
- #__VA_ARGS__ \
- "void main(void)\n { gl_FragColor = shade(texture2D(u_texture, v_texCoord)); }"
+ "uniform sampler2D s_sampler;\n"#__VA_ARGS__ \
+ "void main(void)\n { gl_FragColor = shade(texture2D(s_sampler, v_texCoord)); }"
- const char* fragmentShaderSource = 0;
- switch (type) {
- case FilterOperation::GRAYSCALE:
- fragmentShaderSource = STANDARD_FILTER(
+ static const char* fragmentGrayscaleFilter =
+ STANDARD_FILTER(
lowp vec4 shade(lowp vec4 color)
{
lowp float amount = 1.0 - u_amount;
@@ -409,9 +298,9 @@ StandardFilterProgram::StandardFilterProgram(GraphicsContext3D* context, FilterO
color.a);
}
);
- break;
- case FilterOperation::SEPIA:
- fragmentShaderSource = STANDARD_FILTER(
+
+ static const char* fragmentSepiaFilter =
+ STANDARD_FILTER(
lowp vec4 shade(lowp vec4 color)
{
lowp float amount = 1.0 - u_amount;
@@ -421,9 +310,9 @@ StandardFilterProgram::StandardFilterProgram(GraphicsContext3D* context, FilterO
color.a);
}
);
- break;
- case FilterOperation::SATURATE:
- fragmentShaderSource = STANDARD_FILTER(
+
+ static const char* fragmentSaturateFilter =
+ STANDARD_FILTER(
lowp vec4 shade(lowp vec4 color)
{
return vec4((0.213 + 0.787 * u_amount) * color.r + (0.715 - 0.715 * u_amount) * color.g + (0.072 - 0.072 * u_amount) * color.b,
@@ -432,9 +321,9 @@ StandardFilterProgram::StandardFilterProgram(GraphicsContext3D* context, FilterO
color.a);
}
);
- break;
- case FilterOperation::HUE_ROTATE:
- fragmentShaderSource = STANDARD_FILTER(
+
+ static const char* fragmentHueRotateFilter =
+ STANDARD_FILTER(
lowp vec4 shade(lowp vec4 color)
{
highp float pi = 3.14159265358979323846;
@@ -446,58 +335,62 @@ StandardFilterProgram::StandardFilterProgram(GraphicsContext3D* context, FilterO
color.a);
}
);
- break;
- case FilterOperation::INVERT:
- fragmentShaderSource = STANDARD_FILTER(
+
+ static const char* fragmentInvertFilter =
+ STANDARD_FILTER(
lowp float invert(lowp float n) { return (1.0 - n) * u_amount + n * (1.0 - u_amount); }
lowp vec4 shade(lowp vec4 color)
{
return vec4(invert(color.r), invert(color.g), invert(color.b), color.a);
}
);
- break;
- case FilterOperation::BRIGHTNESS:
- fragmentShaderSource = STANDARD_FILTER(
+
+ static const char* fragmentBrightnessFilter =
+ STANDARD_FILTER(
lowp vec4 shade(lowp vec4 color)
{
return vec4(color.rgb * (1.0 + u_amount), color.a);
}
);
- break;
- case FilterOperation::CONTRAST:
- fragmentShaderSource = STANDARD_FILTER(
+
+ static const char* fragmentContrastFilter =
+ STANDARD_FILTER(
lowp float contrast(lowp float n) { return (n - 0.5) * u_amount + 0.5; }
lowp vec4 shade(lowp vec4 color)
{
return vec4(contrast(color.r), contrast(color.g), contrast(color.b), color.a);
}
);
- break;
- case FilterOperation::OPACITY:
- fragmentShaderSource = STANDARD_FILTER(
+
+ static const char* fragmentOpacityFilter =
+ STANDARD_FILTER(
lowp vec4 shade(lowp vec4 color)
{
return vec4(color.r, color.g, color.b, color.a * u_amount);
}
);
- break;
- case FilterOperation::BLUR:
- fragmentShaderSource = STRINGIFY(
+
+#define BLUR_CONSTANTS "#define GAUSSIAN_KERNEL_HALF_WIDTH 11\n#define GAUSSIAN_KERNEL_STEP 0.2\n"
+
+ static const char* fragmentBlurFilter =
+ BLUR_CONSTANTS
+ STRINGIFY(
+ // Create a normal distribution of 21 values between -2 and 2.
precision mediump float;
varying highp vec2 v_texCoord;
uniform lowp vec2 u_blurRadius;
- uniform sampler2D u_texture;
+ uniform sampler2D s_sampler;
uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH];
lowp vec4 sampleColor(float radius)
{
vec2 coord = v_texCoord + radius * u_blurRadius;
- return texture2D(u_texture, coord) * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.);
+ return texture2D(s_sampler, coord) * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.);
}
vec4 blur()
{
- vec4 total = sampleColor(0) * u_gaussianKernel[0];
+ vec4 total = sampleColor(0.) * u_gaussianKernel[0];
for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) {
total += sampleColor(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];
total += sampleColor(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];
@@ -511,282 +404,130 @@ StandardFilterProgram::StandardFilterProgram(GraphicsContext3D* context, FilterO
gl_FragColor = blur();
}
);
- break;
- case FilterOperation::DROP_SHADOW:
- switch (pass) {
- case 0: {
- // First pass: horizontal alpha blur.
- fragmentShaderSource = STRINGIFY(
- precision mediump float;
- varying highp vec2 v_texCoord;
- uniform lowp float u_shadowBlurRadius;
- uniform lowp vec2 u_shadowOffset;
- uniform sampler2D u_texture;
- uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH];
-
- lowp float sampleAlpha(float radius)
- {
- vec2 coord = v_texCoord - u_shadowOffset + vec2(radius * u_shadowBlurRadius, 0.);
- return texture2D(u_texture, coord).a * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.);
- }
- lowp float shadowBlurHorizontal()
- {
- float total = sampleAlpha(0) * u_gaussianKernel[0];
- for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) {
- total += sampleAlpha(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];
- total += sampleAlpha(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];
- }
-
- return total;
- }
+ static const char* fragmentShadowFilter1 =
+ BLUR_CONSTANTS
+ STRINGIFY(
+ precision mediump float;
+ varying highp vec2 v_texCoord;
+ uniform lowp float u_blurRadius;
+ uniform lowp vec2 u_shadowOffset;
+ uniform sampler2D s_sampler;
+ uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH];
- void main(void)
- {
- gl_FragColor = vec4(1., 1., 1., 1.) * shadowBlurHorizontal();
- }
- );
- break;
+ lowp float sampleAlpha(float radius)
+ {
+ vec2 coord = v_texCoord - u_shadowOffset + vec2(radius * u_blurRadius, 0.);
+ return texture2D(s_sampler, coord).a * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.);
}
- case 1: {
- // Second pass: vertical alpha blur and composite with origin.
- fragmentShaderSource = STRINGIFY(
- precision mediump float;
- varying highp vec2 v_texCoord;
- uniform lowp float u_shadowBlurRadius;
- uniform lowp vec4 u_shadowColor;
- uniform sampler2D u_texture;
- uniform sampler2D u_contentTexture;
- uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH];
-
- lowp float sampleAlpha(float r)
- {
- vec2 coord = v_texCoord + vec2(0., r * u_shadowBlurRadius);
- return texture2D(u_texture, coord).a * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.);
- }
-
- lowp float shadowBlurVertical()
- {
- float total = sampleAlpha(0) * u_gaussianKernel[0];
- for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) {
- total += sampleAlpha(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];
- total += sampleAlpha(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];
- }
- return total;
- }
-
- lowp vec4 sourceOver(lowp vec4 source, lowp vec4 destination)
- {
- // Composite the shadow with the original texture.
- return source + destination * (1. - source.a);
+ lowp float shadowBlurHorizontal()
+ {
+ float total = sampleAlpha(0.) * u_gaussianKernel[0];
+ for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) {
+ total += sampleAlpha(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];
+ total += sampleAlpha(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];
}
- void main(void)
- {
- gl_FragColor = sourceOver(texture2D(u_contentTexture, v_texCoord), shadowBlurVertical() * u_shadowColor);
- }
- );
- break;
+ return total;
}
- break;
- }
- default:
- break;
- }
- if (!fragmentShaderSource)
- return;
- Platform3DObject vertexShader = m_context->createShader(GraphicsContext3D::VERTEX_SHADER);
- Platform3DObject fragmentShader = m_context->createShader(GraphicsContext3D::FRAGMENT_SHADER);
- m_context->shaderSource(vertexShader, vertexShaderSource);
- m_context->shaderSource(fragmentShader, fragmentShaderSource);
- Platform3DObject programID = m_context->createProgram();
- m_context->compileShader(vertexShader);
- m_context->compileShader(fragmentShader);
-#if !LOG_DISABLED
- String log;
- m_context->getShaderInfoLog(fragmentShader);
- WTFLog(&LogCompositing, "%s\n", log.ascii().data());
-#endif
- m_context->attachShader(programID, vertexShader);
- m_context->attachShader(programID, fragmentShader);
- m_context->linkProgram(programID);
+ void main(void)
+ {
+ gl_FragColor = vec4(1., 1., 1., 1.) * shadowBlurHorizontal();
+ }
+ );
- m_vertexAttrib = m_context->getAttribLocation(programID, "a_vertex");
- m_texCoordAttrib = m_context->getAttribLocation(programID, "a_texCoord");
- m_textureUniformLocation = m_context->getUniformLocation(programID, "u_texture");
- switch (type) {
- case FilterOperation::GRAYSCALE:
- case FilterOperation::SEPIA:
- case FilterOperation::SATURATE:
- case FilterOperation::HUE_ROTATE:
- case FilterOperation::INVERT:
- case FilterOperation::BRIGHTNESS:
- case FilterOperation::CONTRAST:
- case FilterOperation::OPACITY:
- m_uniformLocations.amount = m_context->getUniformLocation(programID, "u_amount");
- break;
- case FilterOperation::BLUR:
- m_uniformLocations.blur.radius = m_context->getUniformLocation(programID, "u_blurRadius");
- m_uniformLocations.blur.gaussianKernel = m_context->getUniformLocation(programID, "u_gaussianKernel");
- break;
- case FilterOperation::DROP_SHADOW:
- m_uniformLocations.shadow.blurRadius = m_context->getUniformLocation(programID, "u_shadowBlurRadius");
- m_uniformLocations.shadow.gaussianKernel = m_context->getUniformLocation(programID, "u_gaussianKernel");
- if (!pass)
- m_uniformLocations.shadow.offset = m_context->getUniformLocation(programID, "u_shadowOffset");
- else {
- // We only need the color and the content texture in the second pass, the first pass is only a horizontal alpha blur.
- m_uniformLocations.shadow.color = m_context->getUniformLocation(programID, "u_shadowColor");
- m_uniformLocations.shadow.contentTexture = m_context->getUniformLocation(programID, "u_contentTexture");
- }
- break;
- default:
- break;
- }
- m_id = programID;
- m_vertexShader = vertexShader;
- m_fragmentShader = fragmentShader;
-}
+ // Second pass: vertical alpha blur and composite with origin.
+ static const char* fragmentShadowFilter2 =
+ BLUR_CONSTANTS
+ STRINGIFY(
+ precision mediump float;
+ varying highp vec2 v_texCoord;
+ uniform lowp float u_blurRadius;
+ uniform lowp vec4 u_shadowColor;
+ uniform sampler2D s_sampler;
+ uniform sampler2D s_contentTexture;
+ uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH];
-PassRefPtr<StandardFilterProgram> StandardFilterProgram::create(GraphicsContext3D* context, FilterOperation::OperationType type, unsigned pass)
-{
- RefPtr<StandardFilterProgram> program = adoptRef(new StandardFilterProgram(context, type, pass));
- if (!program->m_id)
- return 0;
+ lowp float sampleAlpha(float r)
+ {
+ vec2 coord = v_texCoord + vec2(0., r * u_blurRadius);
+ return texture2D(s_sampler, coord).a * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.);
+ }
- return program;
-}
+ lowp float shadowBlurVertical()
+ {
+ float total = sampleAlpha(0.) * u_gaussianKernel[0];
+ for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) {
+ total += sampleAlpha(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];
+ total += sampleAlpha(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];
+ }
-static inline float gauss(float x)
-{
- return exp(-(x * x) / 2.);
-}
+ return total;
+ }
-static float* gaussianKernel()
-{
- static bool prepared = false;
- static float kernel[GAUSSIAN_KERNEL_HALF_WIDTH] = {0, };
+ lowp vec4 sourceOver(lowp vec4 source, lowp vec4 destination)
+ {
+ // Composite the shadow with the original texture.
+ return source + destination * (1. - source.a);
+ }
- if (prepared)
- return kernel;
+ void main(void)
+ {
+ gl_FragColor = sourceOver(texture2D(s_contentTexture, v_texCoord), shadowBlurVertical() * u_shadowColor);
+ }
+ );
- kernel[0] = gauss(0);
- float sum = kernel[0];
- for (unsigned i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; ++i) {
- kernel[i] = gauss(i * GAUSSIAN_KERNEL_STEP);
- sum += 2 * kernel[i];
+ if (specs.isEmpty()) {
+ specs.resize(TextureMapperShaderManager::LastFilter);
+ specs[TextureMapperShaderManager::Default] = ShaderSpec(vertexSimple, fragmentSimple);
+ specs[TextureMapperShaderManager::SolidColor] = ShaderSpec(vertexSolidColor, fragmentSolidColor);
+ specs[TextureMapperShaderManager::Rect] = ShaderSpec(vertexSimple, fragmentRectSimple);
+ specs[TextureMapperShaderManager::Masked] = ShaderSpec(vertexOpacityAndMask, fragmentOpacityAndMask);
+ specs[TextureMapperShaderManager::MaskedRect] = ShaderSpec(vertexOpacityAndMask, fragmentRectOpacityAndMask);
+ specs[TextureMapperShaderManager::Antialiased] = ShaderSpec(vertexSimple, fragmentAntialiasingNoMask);
+ specs[TextureMapperShaderManager::GrayscaleFilter] = ShaderSpec(vertexFilter, fragmentGrayscaleFilter);
+ specs[TextureMapperShaderManager::SepiaFilter] = ShaderSpec(vertexFilter, fragmentSepiaFilter);
+ specs[TextureMapperShaderManager::SaturateFilter] = ShaderSpec(vertexFilter, fragmentSaturateFilter);
+ specs[TextureMapperShaderManager::HueRotateFilter] = ShaderSpec(vertexFilter, fragmentHueRotateFilter);
+ specs[TextureMapperShaderManager::BrightnessFilter] = ShaderSpec(vertexFilter, fragmentBrightnessFilter);
+ specs[TextureMapperShaderManager::ContrastFilter] = ShaderSpec(vertexFilter, fragmentContrastFilter);
+ specs[TextureMapperShaderManager::InvertFilter] = ShaderSpec(vertexFilter, fragmentInvertFilter);
+ specs[TextureMapperShaderManager::OpacityFilter] = ShaderSpec(vertexFilter, fragmentOpacityFilter);
+ specs[TextureMapperShaderManager::BlurFilter] = ShaderSpec(vertexFilter, fragmentBlurFilter);
+ specs[TextureMapperShaderManager::ShadowFilterPass1] = ShaderSpec(vertexFilter, fragmentShadowFilter1);
+ specs[TextureMapperShaderManager::ShadowFilterPass2] = ShaderSpec(vertexFilter, fragmentShadowFilter2);
}
- // Normalize the kernel
- float scale = 1 / sum;
- for (unsigned i = 0; i < GAUSSIAN_KERNEL_HALF_WIDTH; ++i)
- kernel[i] *= scale;
-
- prepared = true;
- return kernel;
+ ASSERT(specs.size() > key);
+ ShaderSpec& spec = specs[key];
+ vertexSource = spec.vertexShader;
+ fragmentSource = spec.fragmentShader;
}
-void StandardFilterProgram::prepare(const FilterOperation& operation, unsigned pass, const IntSize& size, GC3Duint contentTexture)
+TextureMapperShaderManager::TextureMapperShaderManager(GraphicsContext3D* context)
+ : m_context(context)
{
- m_context->useProgram(m_id);
- switch (operation.getOperationType()) {
- case FilterOperation::GRAYSCALE:
- case FilterOperation::SEPIA:
- case FilterOperation::SATURATE:
- case FilterOperation::HUE_ROTATE:
- m_context->uniform1f(m_uniformLocations.amount, static_cast<const BasicColorMatrixFilterOperation&>(operation).amount());
- break;
- case FilterOperation::INVERT:
- case FilterOperation::BRIGHTNESS:
- case FilterOperation::CONTRAST:
- case FilterOperation::OPACITY:
- m_context->uniform1f(m_uniformLocations.amount, static_cast<const BasicComponentTransferFilterOperation&>(operation).amount());
- break;
- case FilterOperation::BLUR: {
- const BlurFilterOperation& blur = static_cast<const BlurFilterOperation&>(operation);
- FloatSize radius;
-
- // Blur is done in two passes, first horizontally and then vertically. The same shader is used for both.
- if (pass)
- radius.setHeight(floatValueForLength(blur.stdDeviation(), size.height()) / size.height());
- else
- radius.setWidth(floatValueForLength(blur.stdDeviation(), size.width()) / size.width());
-
- m_context->uniform2f(m_uniformLocations.blur.radius, radius.width(), radius.height());
- m_context->uniform1fv(m_uniformLocations.blur.gaussianKernel, GAUSSIAN_KERNEL_HALF_WIDTH, gaussianKernel());
- break;
- }
- case FilterOperation::DROP_SHADOW: {
- const DropShadowFilterOperation& shadow = static_cast<const DropShadowFilterOperation&>(operation);
- switch (pass) {
- case 0:
- // First pass: vertical alpha blur.
- m_context->uniform2f(m_uniformLocations.shadow.offset, float(shadow.location().x()) / float(size.width()), float(shadow.location().y()) / float(size.height()));
- m_context->uniform1f(m_uniformLocations.shadow.blurRadius, shadow.stdDeviation() / float(size.width()));
- m_context->uniform1fv(m_uniformLocations.shadow.gaussianKernel, GAUSSIAN_KERNEL_HALF_WIDTH, gaussianKernel());
- break;
- case 1:
- // Second pass: we need the shadow color and the content texture for compositing.
- m_context->uniform1f(m_uniformLocations.shadow.blurRadius, shadow.stdDeviation() / float(size.height()));
- m_context->uniform1fv(m_uniformLocations.shadow.gaussianKernel, GAUSSIAN_KERNEL_HALF_WIDTH, gaussianKernel());
- m_context->activeTexture(GraphicsContext3D::TEXTURE1);
- m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, contentTexture);
- m_context->uniform1i(m_uniformLocations.shadow.contentTexture, 1);
- float r, g, b, a;
- shadow.color().getRGBA(r, g, b, a);
- m_context->uniform4f(m_uniformLocations.shadow.color, r, g, b, a);
- break;
- }
- break;
- }
- default:
- break;
- }
}
-PassRefPtr<StandardFilterProgram> TextureMapperShaderManager::getShaderForFilter(const FilterOperation& filter, unsigned pass)
+TextureMapperShaderManager::~TextureMapperShaderManager()
{
- RefPtr<StandardFilterProgram> program;
- FilterOperation::OperationType type = filter.getOperationType();
- int key = int(type) | (pass << 16);
- FilterMap::iterator iterator = m_filterMap.find(key);
- if (iterator == m_filterMap.end()) {
- program = StandardFilterProgram::create(m_context, type, pass);
- if (!program)
- return 0;
-
- m_filterMap.add(key, program);
- } else
- program = iterator->second;
-
- return program;
}
-unsigned TextureMapperShaderManager::getPassesRequiredForFilter(const FilterOperation& operation) const
+PassRefPtr<TextureMapperShaderProgram> TextureMapperShaderManager::getShaderProgram(ShaderKey key)
{
- switch (operation.getOperationType()) {
- case FilterOperation::GRAYSCALE:
- case FilterOperation::SEPIA:
- case FilterOperation::SATURATE:
- case FilterOperation::HUE_ROTATE:
- case FilterOperation::INVERT:
- case FilterOperation::BRIGHTNESS:
- case FilterOperation::CONTRAST:
- case FilterOperation::OPACITY:
- return 1;
- case FilterOperation::BLUR:
- case FilterOperation::DROP_SHADOW:
- // We use two-passes (vertical+horizontal) for blur and drop-shadow.
- return 2;
- default:
- return 0;
- }
-
+ TextureMapperShaderProgramMap::iterator it = m_programs.find(key);
+ if (it != m_programs.end())
+ return it->value;
+
+ String vertexShader;
+ String fragmentShader;
+ getShaderSpec(key, vertexShader, fragmentShader);
+ RefPtr<TextureMapperShaderProgram> program = TextureMapperShaderProgram::create(m_context, vertexShader, fragmentShader);
+ m_programs.add(key, program);
+ return program;
}
-
-#endif
};
#endif