Title: [120545] trunk/Source/WebCore
Revision
120545
Author
[email protected]
Date
2012-06-16 21:42:18 -0700 (Sat, 16 Jun 2012)

Log Message

[Texmap] Share gaussian formula between shaders in TextureMapperShaderManager.
https://bugs.webkit.org/show_bug.cgi?id=89277

This patch makes blur and drop shadow shader share gaussian formula.

On the other hand, blur and drop shadow filter computed a gaussian weight in
pixel shader. However, a gaussian kernal has always same values, so this patch
computes the gaussian kernel only one time using CPU.
It is more accurate and faster.

Patch by Huang Dongsung <[email protected]> on 2012-06-16
Reviewed by Noam Rosenthal.

Covered by existing tests, particularly css3/filters/.

* platform/graphics/texmap/TextureMapperShaderManager.cpp:
(WebCore):
(WebCore::StandardFilterProgram::StandardFilterProgram):
(WebCore::gauss):
(WebCore::gaussianKernel):
(WebCore::StandardFilterProgram::prepare):
* platform/graphics/texmap/TextureMapperShaderManager.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (120544 => 120545)


--- trunk/Source/WebCore/ChangeLog	2012-06-17 03:55:36 UTC (rev 120544)
+++ trunk/Source/WebCore/ChangeLog	2012-06-17 04:42:18 UTC (rev 120545)
@@ -1,3 +1,27 @@
+2012-06-16  Huang Dongsung  <[email protected]>
+
+        [Texmap] Share gaussian formula between shaders in TextureMapperShaderManager.
+        https://bugs.webkit.org/show_bug.cgi?id=89277
+
+        This patch makes blur and drop shadow shader share gaussian formula.
+
+        On the other hand, blur and drop shadow filter computed a gaussian weight in
+        pixel shader. However, a gaussian kernal has always same values, so this patch
+        computes the gaussian kernel only one time using CPU.
+        It is more accurate and faster.
+
+        Reviewed by Noam Rosenthal.
+
+        Covered by existing tests, particularly css3/filters/.
+
+        * platform/graphics/texmap/TextureMapperShaderManager.cpp:
+        (WebCore):
+        (WebCore::StandardFilterProgram::StandardFilterProgram):
+        (WebCore::gauss):
+        (WebCore::gaussianKernel):
+        (WebCore::StandardFilterProgram::prepare):
+        * platform/graphics/texmap/TextureMapperShaderManager.h:
+
 2012-06-16  Robert Kroeger  <[email protected]>
 
         [chromium] Make the deviceScaleFactor dynamically adjustable.

Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp (120544 => 120545)


--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp	2012-06-17 03:55:36 UTC (rev 120544)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp	2012-06-17 04:42:18 UTC (rev 120545)
@@ -38,10 +38,12 @@
     "precision mediump float; \n"
 #endif
 
-#define VERTEX_SHADER(src...) OES2_PRECISION_DEFINITIONS#src
+#define STRINGIFY_VAL(src...) #src
+#define VERTEX_SHADER(src...) OES2_PRECISION_DEFINITIONS\
+                              STRINGIFY_VAL(src)
 #define FRAGMENT_SHADER(src...) OES2_PRECISION_DEFINITIONS\
                                 OES2_FRAGMENT_SHADER_DEFAULT_PRECISION\
-                                #src
+                                STRINGIFY_VAL(src)
 
 static const char* fragmentShaderSourceOpacityAndMask =
     FRAGMENT_SHADER(
@@ -352,6 +354,11 @@
 }
 
 #if ENABLE(CSS_FILTERS)
+
+// 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()
 {
     glDetachShader(m_id, m_vertexShader);
@@ -475,16 +482,8 @@
             varying highp vec2 v_texCoord;
             uniform lowp vec2 u_blurRadius;
             uniform sampler2D u_texture;
-            const float pi = 3.14159;
-            const float e = 2.71828;
+            uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH];
 
-            // FIXME: share gaussian formula between shaders.
-            lowp float gaussian(lowp float value)
-            {
-                // Normal distribution formula, when the mean is 0 and the standard deviation is 1.
-                return pow(e, -pow(value, 2.) / 2.) / (sqrt(2. * pi));
-            }
-
             lowp vec4 sampleColor(float radius)
             {
                 vec2 coord = v_texCoord + radius * u_blurRadius;
@@ -493,16 +492,13 @@
 
             vec4 blur()
             {
-                // Create a normal distribution of 20 values between 0. and 2.
-                vec4 total = vec4(0., 0., 0., 0.);
-                float totalWeight = 0.;
-                for (float i = -2.; i <= 2.; i += .2) {
-                    float weight = gaussian(i);
-                    total += sampleColor(i) * weight;
-                    totalWeight += weight;
+                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];
                 }
 
-                return total / totalWeight;
+                return total;
             }
 
             void main(void)
@@ -520,16 +516,8 @@
                 uniform lowp float u_shadowBlurRadius;
                 uniform lowp vec2 u_shadowOffset;
                 uniform sampler2D u_texture;
-                const float pi = 3.14159;
-                const float e = 2.71828;
+                uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH];
 
-                // FIXME: share gaussian formula between shaders.
-                lowp float gaussian(lowp float value)
-                {
-                    // Normal distribution formula, when the mean is 0 and the standard deviation is 1.
-                    return pow(e, -pow(value, 2.) / 2.) / (sqrt(2. * pi));
-                }
-
                 lowp float sampleAlpha(float radius)
                 {
                     vec2 coord = v_texCoord - u_shadowOffset + vec2(radius * u_shadowBlurRadius, 0.);
@@ -538,16 +526,13 @@
 
                 lowp float shadowBlurHorizontal()
                 {
-                    // Create a normal distribution of 20 values between -2 and 2.
-                    float total = 0.;
-                    float totalWeight = 0.;
-                    for (float i = -2.; i <= 2.; i += .2) {
-                        float weight = gaussian(i);
-                        total += sampleAlpha(i) * weight;
-                        totalWeight += weight;
+                    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 / totalWeight;
+                    return total;
                 }
 
                 void main(void)
@@ -565,17 +550,8 @@
                 uniform lowp vec4 u_shadowColor;
                 uniform sampler2D u_texture;
                 uniform sampler2D u_contentTexture;
+                uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH];
 
-                // FIXME: share gaussian formula between shaders.
-                const float pi = 3.14159;
-                const float e = 2.71828;
-
-                lowp float gaussian(float value)
-                {
-                    // Normal distribution formula, when the mean is 0 and the standard deviation is 1.
-                    return pow(e, -pow(value, 2.) / 2.) / (sqrt(2. * pi));
-                }
-
                 lowp float sampleAlpha(float r)
                 {
                     vec2 coord = v_texCoord + vec2(0., r * u_shadowBlurRadius);
@@ -584,16 +560,13 @@
 
                 lowp float shadowBlurVertical()
                 {
-                    // Create a normal distribution of 20 values between -2 and 2.
-                    float total = 0.;
-                    float totalWeight = 0.;
-                    for (float i = -2.; i <= 2.; i += .2) {
-                        float weight = gaussian(i);
-                        total += sampleAlpha(i) * weight;
-                        totalWeight += weight;
+                    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 / totalWeight;
+                    return total;
                 }
 
                 lowp vec4 sourceOver(lowp vec4 source, lowp vec4 destination)
@@ -650,9 +623,11 @@
         break;
     case FilterOperation::BLUR:
         m_uniformLocations.blur.radius = glGetUniformLocation(programID, "u_blurRadius");
+        m_uniformLocations.blur.gaussianKernel = glGetUniformLocation(programID, "u_gaussianKernel");
         break;
     case FilterOperation::DROP_SHADOW:
         m_uniformLocations.shadow.blurRadius = glGetUniformLocation(programID, "u_shadowBlurRadius");
+        m_uniformLocations.shadow.gaussianKernel = glGetUniformLocation(programID, "u_gaussianKernel");
         if (!pass)
             m_uniformLocations.shadow.offset = glGetUniformLocation(programID, "u_shadowOffset");
         else {
@@ -678,6 +653,35 @@
     return program;
 }
 
+static inline float gauss(float x)
+{
+    return exp(-(x * x) / 2.);
+}
+
+static float* gaussianKernel()
+{
+    static bool prepared = false;
+    static float kernel[GAUSSIAN_KERNEL_HALF_WIDTH] = {0, };
+
+    if (prepared)
+        return kernel;
+
+    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];
+    }
+
+    // Normalize the kernel
+    float scale = 1 / sum;
+    for (unsigned i = 0; i < GAUSSIAN_KERNEL_HALF_WIDTH; ++i)
+        kernel[i] *= scale;
+
+    prepared = true;
+    return kernel;
+}
+
 void StandardFilterProgram::prepare(const FilterOperation& operation, unsigned pass, const IntSize& size, GLuint contentTexture)
 {
     glUseProgram(m_id);
@@ -705,6 +709,7 @@
             radius.setWidth(floatValueForLength(blur.stdDeviation(), size.width()) / size.width());
 
         glUniform2f(m_uniformLocations.blur.radius, radius.width(), radius.height());
+        glUniform1fv(m_uniformLocations.blur.gaussianKernel, GAUSSIAN_KERNEL_HALF_WIDTH, gaussianKernel());
         break;
     }
     case FilterOperation::DROP_SHADOW: {
@@ -714,10 +719,12 @@
             // First pass: vertical alpha blur.
             glUniform2f(m_uniformLocations.shadow.offset, float(shadow.location().x()) / float(size.width()), float(shadow.location().y()) / float(size.height()));
             glUniform1f(m_uniformLocations.shadow.blurRadius, shadow.stdDeviation() / float(size.width()));
+            glUniform1fv(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.
             glUniform1f(m_uniformLocations.shadow.blurRadius, shadow.stdDeviation() / float(size.height()));
+            glUniform1fv(m_uniformLocations.shadow.gaussianKernel, GAUSSIAN_KERNEL_HALF_WIDTH, gaussianKernel());
             glActiveTexture(GL_TEXTURE1);
             glBindTexture(GL_TEXTURE_2D, contentTexture);
             glUniform1i(m_uniformLocations.shadow.contentTexture, 1);

Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h (120544 => 120545)


--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h	2012-06-17 03:55:36 UTC (rev 120544)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h	2012-06-17 04:42:18 UTC (rev 120545)
@@ -92,6 +92,7 @@
 
         struct {
             GLuint radius;
+            GLuint gaussianKernel;
         } blur;
 
         struct {
@@ -99,6 +100,7 @@
             GLuint color;
             GLuint offset;
             GLuint contentTexture;
+            GLuint gaussianKernel;
         } shadow;
     } m_uniformLocations;
 };
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to