[Texmap] Enable css filters in TextureMapperGL
authornoam.rosenthal@nokia.com <noam.rosenthal@nokia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 2 May 2012 15:30:29 +0000 (15:30 +0000)
committernoam.rosenthal@nokia.com <noam.rosenthal@nokia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 2 May 2012 15:30:29 +0000 (15:30 +0000)
https://bugs.webkit.org/show_bug.cgi?id=75778

Source/WebCore:

Reviewed by Jocelyn Turcotte.

Added support for color filters in TextureMapperGL. Blur and shadow would be done in a
different patch.

Modified BitmapTexture::applyFilters to return a texture, since GL cannot paint a texture
into itself.
Created a shader map for standard filters, since all of them work more or less the same way
with a single uniform. Added the colorization shaders based on the W3C filter spec, as
already implemented in FEFilterRenderer.cpp and FEColorMatrix.cpp.
We use two swapping textures to render the filters.

Covered by tests in css3/filters.

* platform/graphics/texmap/TextureMapper.cpp:
(WebCore::TextureMapper::acquireTextureFromPool):
* platform/graphics/texmap/TextureMapper.h:
(WebCore::BitmapTexture::applyFilters):
* platform/graphics/texmap/TextureMapperGL.cpp:
(WebCore::BitmapTextureGL::updateContents):
(WebCore):
(WebCore::TextureMapperGL::drawFiltered):
(WebCore::BitmapTextureGL::applyFilters):
(WebCore::BitmapTextureGL::bind):
* platform/graphics/texmap/TextureMapperGL.h:
(TextureMapperGL):
(BitmapTextureGL):
* platform/graphics/texmap/TextureMapperImageBuffer.cpp:
(WebCore::BitmapTextureImageBuffer::applyFilters):
* platform/graphics/texmap/TextureMapperImageBuffer.h:
(BitmapTextureImageBuffer):
* platform/graphics/texmap/TextureMapperLayer.cpp:
(WebCore::applyFilters):
(WebCore::TextureMapperLayer::syncCompositingStateSelf):
* platform/graphics/texmap/TextureMapperShaderManager.cpp:
(WebCore::TextureMapperShaderManager::~TextureMapperShaderManager):
(WebCore):
(WebCore::StandardFilterProgram::~StandardFilterProgram):
(WebCore::StandardFilterProgram::StandardFilterProgram):
(WebCore::StandardFilterProgram::create):
(WebCore::StandardFilterProgram::prepare):
(WebCore::TextureMapperShaderManager::getShaderForFilter):
* platform/graphics/texmap/TextureMapperShaderManager.h:
(WebCore):
(StandardFilterProgram):
(WebCore::StandardFilterProgram::vertexAttrib):
(WebCore::StandardFilterProgram::texCoordAttrib):
(WebCore::StandardFilterProgram::textureUniform):
(TextureMapperShaderManager):

Source/WebKit2:

Add the plumbing in the ui-side compositing code in Qt to support filters.
Serialize the filter operations for a layer when it's changed.

Reviewed by Jocelyn Turcotte.

* Shared/WebCoreArgumentCoders.cpp:
(CoreIPC):
(CoreIPC::::encode):
(CoreIPC::::decode):
* Shared/WebCoreArgumentCoders.h:
(WebCore):
* UIProcess/LayerTreeHostProxy.cpp:
(WebKit):
(WebKit::LayerTreeHostProxy::setCompositingLayerFilters):
* UIProcess/LayerTreeHostProxy.h:
(LayerTreeHostProxy):
* UIProcess/LayerTreeHostProxy.messages.in:
* UIProcess/WebLayerTreeRenderer.cpp:
(WebKit):
(WebKit::WebLayerTreeRenderer::setLayerFilters):
* UIProcess/WebLayerTreeRenderer.h:
(WebLayerTreeRenderer):
* WebProcess/WebCoreSupport/WebGraphicsLayer.cpp:
(WebCore):
(WebCore::WebGraphicsLayer::didChangeFilters):
(WebCore::WebGraphicsLayer::setFilters):
(WebCore::WebGraphicsLayer::syncFilters):
(WebCore::WebGraphicsLayer::syncCompositingStateForThisLayerOnly):
* WebProcess/WebCoreSupport/WebGraphicsLayer.h:
(WebGraphicsLayerClient):
(WebGraphicsLayer):
* WebProcess/WebPage/qt/LayerTreeHostQt.cpp:
(WebKit):
(WebKit::LayerTreeHostQt::syncLayerFilters):
* WebProcess/WebPage/qt/LayerTreeHostQt.h:
(LayerTreeHostQt):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@115838 268f45cc-cd09-0410-ab3c-d52691b4dbfc

22 files changed:
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/texmap/TextureMapper.cpp
Source/WebCore/platform/graphics/texmap/TextureMapper.h
Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp
Source/WebCore/platform/graphics/texmap/TextureMapperGL.h
Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp
Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h
Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp
Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp
Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/WebCoreArgumentCoders.cpp
Source/WebKit2/Shared/WebCoreArgumentCoders.h
Source/WebKit2/UIProcess/LayerTreeHostProxy.cpp
Source/WebKit2/UIProcess/LayerTreeHostProxy.h
Source/WebKit2/UIProcess/LayerTreeHostProxy.messages.in
Source/WebKit2/UIProcess/WebLayerTreeRenderer.cpp
Source/WebKit2/UIProcess/WebLayerTreeRenderer.h
Source/WebKit2/WebProcess/WebCoreSupport/WebGraphicsLayer.cpp
Source/WebKit2/WebProcess/WebCoreSupport/WebGraphicsLayer.h
Source/WebKit2/WebProcess/WebPage/qt/LayerTreeHostQt.cpp
Source/WebKit2/WebProcess/WebPage/qt/LayerTreeHostQt.h

index dcd40f0..16c7061 100644 (file)
@@ -1,3 +1,58 @@
+2012-05-02  No'am Rosenthal  <noam.rosenthal@nokia.com>
+
+        [Texmap] Enable css filters in TextureMapperGL
+        https://bugs.webkit.org/show_bug.cgi?id=75778
+
+        Reviewed by Jocelyn Turcotte.
+
+        Added support for color filters in TextureMapperGL. Blur and shadow would be done in a
+        different patch.
+
+        Modified BitmapTexture::applyFilters to return a texture, since GL cannot paint a texture
+        into itself.
+        Created a shader map for standard filters, since all of them work more or less the same way
+        with a single uniform. Added the colorization shaders based on the W3C filter spec, as
+        already implemented in FEFilterRenderer.cpp and FEColorMatrix.cpp.
+        We use two swapping textures to render the filters.
+
+        Covered by tests in css3/filters.
+
+        * platform/graphics/texmap/TextureMapper.cpp:
+        (WebCore::TextureMapper::acquireTextureFromPool):
+        * platform/graphics/texmap/TextureMapper.h:
+        (WebCore::BitmapTexture::applyFilters):
+        * platform/graphics/texmap/TextureMapperGL.cpp:
+        (WebCore::BitmapTextureGL::updateContents):
+        (WebCore):
+        (WebCore::TextureMapperGL::drawFiltered):
+        (WebCore::BitmapTextureGL::applyFilters):
+        (WebCore::BitmapTextureGL::bind):
+        * platform/graphics/texmap/TextureMapperGL.h:
+        (TextureMapperGL):
+        (BitmapTextureGL):
+        * platform/graphics/texmap/TextureMapperImageBuffer.cpp:
+        (WebCore::BitmapTextureImageBuffer::applyFilters):
+        * platform/graphics/texmap/TextureMapperImageBuffer.h:
+        (BitmapTextureImageBuffer):
+        * platform/graphics/texmap/TextureMapperLayer.cpp:
+        (WebCore::applyFilters):
+        (WebCore::TextureMapperLayer::syncCompositingStateSelf):
+        * platform/graphics/texmap/TextureMapperShaderManager.cpp:
+        (WebCore::TextureMapperShaderManager::~TextureMapperShaderManager):
+        (WebCore):
+        (WebCore::StandardFilterProgram::~StandardFilterProgram):
+        (WebCore::StandardFilterProgram::StandardFilterProgram):
+        (WebCore::StandardFilterProgram::create):
+        (WebCore::StandardFilterProgram::prepare):
+        (WebCore::TextureMapperShaderManager::getShaderForFilter):
+        * platform/graphics/texmap/TextureMapperShaderManager.h:
+        (WebCore):
+        (StandardFilterProgram):
+        (WebCore::StandardFilterProgram::vertexAttrib):
+        (WebCore::StandardFilterProgram::texCoordAttrib):
+        (WebCore::StandardFilterProgram::textureUniform):
+        (TextureMapperShaderManager):
+
 2012-05-02  Philippe Normand  <pnormand@igalia.com>
 
         [GTK] media/track/track-cue-rendering-snap-to-lines-not-set.html fails
index 18fb086..cee45b9 100644 (file)
@@ -48,7 +48,7 @@ PassRefPtr<BitmapTexture> TextureMapper::acquireTextureFromPool(const IntSize& s
         m_texturePool.append(selectedTexture);
     }
 
-    selectedTexture->reset(size);
+    selectedTexture->reset(size, BitmapTexture::SupportsAlpha);
     return selectedTexture;
 }
 
index 045b2a8..ca31d17 100644 (file)
@@ -87,7 +87,7 @@ public:
     inline bool isOpaque() const { return !(m_flags & SupportsAlpha); }
 
 #if ENABLE(CSS_FILTERS)
-    virtual void applyFilters(const BitmapTexture& contentTexture, const FilterOperations&) { }
+    virtual PassRefPtr<BitmapTexture> applyFilters(const BitmapTexture& contentTexture, const FilterOperations&) { return this; }
 #endif
 
 protected:
index ff3c8ad..df9b8b0 100644 (file)
@@ -503,8 +503,51 @@ void BitmapTextureGL::updateContents(Image* image, const IntRect& targetRect, co
 #endif
 
     updateContents(imageData, targetRect, offset, bytesPerLine);
+}
+
+#if ENABLE(CSS_FILTERS)
+void TextureMapperGL::drawFiltered(const BitmapTexture& sourceTexture, const BitmapTexture& contentTexture, const FilterOperation& filter)
+{
+    // For standard filters, we always draw the whole texture without transformations.
+    RefPtr<StandardFilterProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderForFilter(filter);
+    if (!program) {
+        drawTexture(sourceTexture, FloatRect(FloatPoint::zero(), sourceTexture.size()), TransformationMatrix(), 1, 0);
+        return;
+    }
+    GL_CMD(glEnableVertexAttribArray(program->vertexAttrib()));
+    GL_CMD(glEnableVertexAttribArray(program->texCoordAttrib()));
+    GL_CMD(glActiveTexture(GL_TEXTURE0));
+    GL_CMD(glBindTexture(GL_TEXTURE_2D, static_cast<const BitmapTextureGL&>(sourceTexture).id()));
+    glUniform1i(program->textureUniform(), 0);
+    const GLfloat targetVertices[] = {-1, -1, 1, -1, 1, 1, -1, 1};
+    const GLfloat sourceVertices[] = {0, 0, 1, 0, 1, 1, 0, 1};
+    GL_CMD(glVertexAttribPointer(program->vertexAttrib(), 2, GL_FLOAT, GL_FALSE, 0, targetVertices));
+    GL_CMD(glVertexAttribPointer(program->texCoordAttrib(), 2, GL_FLOAT, GL_FALSE, 0, sourceVertices));
+    GL_CMD(glDisable(GL_BLEND));
+    GL_CMD(glDrawArrays(GL_TRIANGLE_FAN, 0, 4));
+    GL_CMD(glDisableVertexAttribArray(program->vertexAttrib()));
+    GL_CMD(glDisableVertexAttribArray(program->texCoordAttrib()));
+}
+
+PassRefPtr<BitmapTexture> BitmapTextureGL::applyFilters(const BitmapTexture& contentTexture, const FilterOperations& filters)
+{
+    RefPtr<BitmapTexture> previousSurface = m_textureMapper->data().currentSurface;
+
+    RefPtr<BitmapTexture> source = this;
+    RefPtr<BitmapTexture> target = m_textureMapper->acquireTextureFromPool(m_textureSize);
+    for (int i = 0; i < filters.size(); ++i) {
+        const FilterOperation* filter = filters.at(i);
+        ASSERT(filter);
 
+        m_textureMapper->bindSurface(target.get());
+        m_textureMapper->drawFiltered(i ? *source.get() : contentTexture, contentTexture, *filter);
+        std::swap(source, target);
+    }
+
+    m_textureMapper->bindSurface(previousSurface.get());
+    return source;
 }
+#endif
 
 static inline TransformationMatrix createProjectionMatrix(const IntSize& size, bool mirrored)
 {
index d6cceed..4279499 100644 (file)
@@ -65,6 +65,11 @@ public:
     void platformUpdateContents(NativeImagePtr, const IntRect&, const IntRect&);
     virtual AccelerationMode accelerationMode() const { return OpenGLMode; }
 
+#if ENABLE(CSS_FILTERS)
+    void drawFiltered(const BitmapTexture& sourceTexture, const BitmapTexture& contentTexture, const FilterOperation&);
+#endif
+
+
 private:
 
     struct ClipState {
@@ -116,6 +121,10 @@ public:
     virtual void updateContents(const void*, const IntRect& target, const IntPoint& sourceOffset, int bytesPerLine);
     virtual bool isBackedByOpenGL() const { return true; }
 
+#if ENABLE(CSS_FILTERS)
+    virtual PassRefPtr<BitmapTexture> applyFilters(const BitmapTexture& contentTexture, const FilterOperations&);
+#endif
+
 private:
     GLuint m_id;
     IntSize m_textureSize;
index cdc722f..208b534 100644 (file)
@@ -110,7 +110,7 @@ void TextureMapperImageBuffer::drawTexture(const BitmapTexture& texture, const F
 }
 
 #if ENABLE(CSS_FILTERS)
-void BitmapTextureImageBuffer::applyFilters(const BitmapTexture& contentTexture, const FilterOperations& filters)
+PassRefPtr<BitmapTexture> BitmapTextureImageBuffer::applyFilters(const BitmapTexture& contentTexture, const FilterOperations& filters)
 {
     RefPtr<FilterEffectRenderer> renderer = FilterEffectRenderer::create();
     renderer->setSourceImageRect(FloatRect(FloatPoint::zero(), contentTexture.size()));
@@ -122,6 +122,7 @@ void BitmapTextureImageBuffer::applyFilters(const BitmapTexture& contentTexture,
     context->drawImageBuffer(static_cast<const BitmapTextureImageBuffer&>(contentTexture).m_image.get(), ColorSpaceDeviceRGB, IntPoint::zero());
     renderer->apply();
     m_image->context()->drawImageBuffer(renderer->output(), ColorSpaceDeviceRGB, renderer->outputRect());
+    return this;
 }
 #endif
 
index 37c98ab..8a03562 100644 (file)
@@ -37,7 +37,7 @@ public:
     virtual void updateContents(Image*, const IntRect&, const IntPoint&);
     virtual void updateContents(const void*, const IntRect& target, const IntPoint& sourceOffset, int bytesPerLine);
 #if ENABLE(CSS_FILTERS)
-    void applyFilters(const BitmapTexture&, const FilterOperations&);
+    PassRefPtr<BitmapTexture> applyFilters(const BitmapTexture&, const FilterOperations&);
 #endif
 
 private:
index 9c84642..9d83c4b 100644 (file)
@@ -304,8 +304,7 @@ static PassRefPtr<BitmapTexture> applyFilters(const FilterOperations& filters, T
         filterSurface = textureMapper->acquireTextureFromPool(targetRect.size());
     }
 
-    filterSurface->applyFilters(*source, filters);
-    return filterSurface;
+    return filterSurface->applyFilters(*source, filters);
 }
 #endif
 
@@ -442,7 +441,8 @@ void TextureMapperLayer::syncCompositingStateSelf(GraphicsLayerTextureMapper* gr
     m_state.childrenTransform = graphicsLayer->childrenTransform();
     m_state.opacity = graphicsLayer->opacity();
 #if ENABLE(CSS_FILTERS)
-    m_state.filters = graphicsLayer->filters();
+    if (changeMask & FilterChange)
+        m_state.filters = graphicsLayer->filters();
 #endif
     m_fixedToViewport = graphicsLayer->fixedToViewport();
 
index 15b1f51..a759c5f 100644 (file)
@@ -206,9 +206,220 @@ TextureMapperShaderManager::TextureMapperShaderManager()
 
 TextureMapperShaderManager::~TextureMapperShaderManager()
 {
-    m_textureMapperShaderProgramMap.clear();
 }
 
+#if ENABLE(CSS_FILTERS)
+StandardFilterProgram::~StandardFilterProgram()
+{
+    glDetachShader(m_id, m_vertexShader);
+    glDeleteShader(m_vertexShader);
+    glDetachShader(m_id, m_fragmentShader);
+    glDeleteShader(m_fragmentShader);
+    glDeleteProgram(m_id);
+}
+
+StandardFilterProgram::StandardFilterProgram(FilterOperation::OperationType type)
+    : m_id(0)
+{
+    const char* vertexShaderSource =
+            VERTEX_SHADER(
+                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(x...) \
+        OES2_PRECISION_DEFINITIONS\
+        OES2_FRAGMENT_SHADER_DEFAULT_PRECISION\
+        "varying highp vec2 v_texCoord;\n"\
+        "uniform highp float u_amount;\n"\
+        "uniform sampler2D u_texture;\n"\
+        #x\
+        "void main(void)\n { gl_FragColor = shade(texture2D(u_texture, v_texCoord)); }"
+
+    const char* fragmentShaderSource = 0;
+    switch (type) {
+    case FilterOperation::GRAYSCALE:
+        fragmentShaderSource = STANDARD_FILTER(
+            lowp vec4 shade(lowp vec4 color)
+            {
+                lowp float amount = 1.0 - u_amount;
+                return vec4((0.2126 + 0.7874 * amount) * color.r + (0.7152 - 0.7152 * amount) * color.g + (0.0722 - 0.0722 * amount) * color.b,
+                            (0.2126 - 0.2126 * amount) * color.r + (0.7152 + 0.2848 * amount) * color.g + (0.0722 - 0.0722 * amount) * color.b,
+                            (0.2126 - 0.2126 * amount) * color.r + (0.7152 - 0.7152 * amount) * color.g + (0.0722 + 0.9278 * amount) * color.b,
+                            color.a);
+            }
+        );
+        break;
+    case FilterOperation::SEPIA:
+        fragmentShaderSource = STANDARD_FILTER(
+            lowp vec4 shade(lowp vec4 color)
+            {
+                lowp float amount = 1.0 - u_amount;
+                return vec4((0.393 + 0.607 * amount) * color.r + (0.769 - 0.769 * amount) * color.g + (0.189 - 0.189 * amount) * color.b,
+                            (0.349 - 0.349 * amount) * color.r + (0.686 + 0.314 * amount) * color.g + (0.168 - 0.168 * amount) * color.b,
+                            (0.272 - 0.272 * amount) * color.r + (0.534 - 0.534 * amount) * color.g + (0.131 + 0.869 * amount) * color.b,
+                            color.a);
+            }
+        );
+        break;
+    case FilterOperation::SATURATE:
+        fragmentShaderSource = 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,
+                            (0.213 - 0.213 * u_amount) * color.r + (0.715 + 0.285 * u_amount) * color.g + (0.072 - 0.072 * u_amount) * color.b,
+                            (0.213 - 0.213 * u_amount) * color.r + (0.715 - 0.715 * u_amount) * color.g + (0.072 + 0.928 * u_amount) * color.b,
+                            color.a);
+            }
+        );
+        break;
+    case FilterOperation::HUE_ROTATE:
+        fragmentShaderSource = STANDARD_FILTER(
+            lowp vec4 shade(lowp vec4 color)
+            {
+                highp float pi = 3.14159265358979323846;
+                highp float c = cos(u_amount * pi / 180.0);
+                highp float s = sin(u_amount * pi / 180.0);
+                return vec4(color.r * (0.213 + c * 0.787 - s * 0.213) + color.g * (0.715 - c * 0.715 - s * 0.715) + color.b * (0.072 - c * 0.072 + s * 0.928),
+                            color.r * (0.213 - c * 0.213 + s * 0.143) + color.g * (0.715 + c * 0.285 + s * 0.140) + color.b * (0.072 - c * 0.072 - s * 0.283),
+                            color.r * (0.213 - c * 0.213 - s * 0.787) +  color.g * (0.715 - c * 0.715 + s * 0.715) + color.b * (0.072 + c * 0.928 + s * 0.072),
+                            color.a);
+            }
+        );
+        break;
+    case FilterOperation::INVERT:
+        fragmentShaderSource = 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(
+            lowp vec4 shade(lowp vec4 color)
+            {
+                return vec4(color.rgb * (1.0 + u_amount), color.a);
+            }
+        );
+        break;
+    case FilterOperation::CONTRAST:
+        fragmentShaderSource = 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(
+            lowp vec4 shade(lowp vec4 color)
+            {
+                return vec4(color.r, color.g, color.b, color.a * u_amount);
+            }
+        );
+        break;
+    default:
+        break;
+    }
+
+    if (!fragmentShaderSource)
+        return;
+    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
+    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
+    glShaderSource(vertexShader, 1, &vertexShaderSource, 0);
+    glShaderSource(fragmentShader, 1, &fragmentShaderSource, 0);
+    GLchar log[100];
+    GLint len;
+    GLuint programID = glCreateProgram();
+    glCompileShader(vertexShader);
+    glCompileShader(fragmentShader);
+    glGetShaderInfoLog(fragmentShader, 100, &len, log);
+    glAttachShader(programID, vertexShader);
+    glAttachShader(programID, fragmentShader);
+    glLinkProgram(programID);
+
+    m_vertexAttrib = glGetAttribLocation(programID, "a_vertex");
+    m_texCoordAttrib = glGetAttribLocation(programID, "a_texCoord");
+    m_textureUniformLocation = glGetUniformLocation(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 = glGetUniformLocation(programID, "u_amount");
+        break;
+    default:
+        break;
+    }
+    m_id = programID;
+    m_vertexShader = vertexShader;
+    m_fragmentShader = fragmentShader;
+}
+
+PassRefPtr<StandardFilterProgram> StandardFilterProgram::create(FilterOperation::OperationType type)
+{
+    RefPtr<StandardFilterProgram> program = adoptRef(new StandardFilterProgram(type));
+    if (!program->m_id)
+        return 0;
+
+    return program;
+}
+
+void StandardFilterProgram::prepare(const FilterOperation& operation)
+{
+    double amount = 0;
+    switch (operation.getOperationType()) {
+    case FilterOperation::GRAYSCALE:
+    case FilterOperation::SEPIA:
+    case FilterOperation::SATURATE:
+    case FilterOperation::HUE_ROTATE:
+        amount = static_cast<const BasicColorMatrixFilterOperation&>(operation).amount();
+        break;
+    case FilterOperation::INVERT:
+    case FilterOperation::BRIGHTNESS:
+    case FilterOperation::CONTRAST:
+    case FilterOperation::OPACITY:
+        amount = static_cast<const BasicComponentTransferFilterOperation&>(operation).amount();
+        break;
+    default:
+        break;
+    }
+    glUseProgram(m_id);
+    glUniform1f(m_uniformLocations.amount, amount);
+}
+
+PassRefPtr<StandardFilterProgram> TextureMapperShaderManager::getShaderForFilter(const FilterOperation& filter)
+{
+    RefPtr<StandardFilterProgram> program;
+    FilterOperation::OperationType type = filter.getOperationType();
+    FilterMap::iterator iterator = m_filterMap.find(type);
+    if (iterator == m_filterMap.end()) {
+        program = StandardFilterProgram::create(type);
+        if (!program)
+            return 0;
+
+        m_filterMap.add(type, program);
+    } else
+        program = iterator->second;
+
+    program->prepare(filter);
+    return program;
+}
+
+#endif
 };
 
 #endif
index 5b39a09..9d9170e 100644 (file)
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefPtr.h>
 
+#if ENABLE(CSS_FILTERS)
+#include "FilterOperations.h"
+#endif
+
 namespace WebCore {
 
 class BitmapTexture;
@@ -65,6 +69,35 @@ protected:
     GLint m_opacityVariable;
 };
 
+#if ENABLE(CSS_FILTERS)
+class StandardFilterProgram : public RefCounted<StandardFilterProgram> {
+public:
+    virtual ~StandardFilterProgram();
+    virtual void prepare(const FilterOperation&);
+    static PassRefPtr<StandardFilterProgram> create(FilterOperation::OperationType);
+    GLuint vertexAttrib() const { return m_vertexAttrib; }
+    GLuint texCoordAttrib() const { return m_texCoordAttrib; }
+    GLuint textureUniform() const { return m_textureUniformLocation; }
+private:
+    StandardFilterProgram(FilterOperation::OperationType);
+    GLuint m_id;
+    GLuint m_vertexShader;
+    GLuint m_fragmentShader;
+    GLuint m_vertexAttrib;
+    GLuint m_texCoordAttrib;
+    GLuint m_textureUniformLocation;
+    union {
+        GLuint amount;
+        GLuint stddev;
+        struct {
+            GLuint stddev;
+            GLuint color;
+            GLuint offset;
+        } shadow;
+    } m_uniformLocations;
+};
+#endif
+
 class TextureMapperShaderProgramSimple : public TextureMapperShaderProgram {
 public:
     static PassRefPtr<TextureMapperShaderProgramSimple> create();
@@ -101,6 +134,8 @@ public:
     TextureMapperShaderManager();
     virtual ~TextureMapperShaderManager();
 
+    PassRefPtr<StandardFilterProgram> getShaderForFilter(const FilterOperation&);
+
     PassRefPtr<TextureMapperShaderProgram> getShaderProgram(ShaderType shaderType)
     {
         RefPtr<TextureMapperShaderProgram> program;
@@ -128,6 +163,12 @@ public:
 private:
     typedef HashMap<ShaderType, RefPtr<TextureMapperShaderProgram>, DefaultHash<int>::Hash, HashTraits<int> > TextureMapperShaderProgramMap;
     TextureMapperShaderProgramMap m_textureMapperShaderProgramMap;
+
+#if ENABLE(CSS_FILTERS)
+    typedef HashMap<FilterOperation::OperationType, RefPtr<StandardFilterProgram>, DefaultHash<int>::Hash, HashTraits<int> > FilterMap;
+    FilterMap m_filterMap;
+#endif
+
 };
 
 }
index e505273..0dbdcab 100644 (file)
@@ -1,3 +1,45 @@
+2012-05-02  No'am Rosenthal  <noam.rosenthal@nokia.com>
+
+        [Texmap] Enable css filters in TextureMapperGL
+        https://bugs.webkit.org/show_bug.cgi?id=75778
+
+        Add the plumbing in the ui-side compositing code in Qt to support filters.
+        Serialize the filter operations for a layer when it's changed.
+
+        Reviewed by Jocelyn Turcotte.
+
+        * Shared/WebCoreArgumentCoders.cpp:
+        (CoreIPC):
+        (CoreIPC::::encode):
+        (CoreIPC::::decode):
+        * Shared/WebCoreArgumentCoders.h:
+        (WebCore):
+        * UIProcess/LayerTreeHostProxy.cpp:
+        (WebKit):
+        (WebKit::LayerTreeHostProxy::setCompositingLayerFilters):
+        * UIProcess/LayerTreeHostProxy.h:
+        (LayerTreeHostProxy):
+        * UIProcess/LayerTreeHostProxy.messages.in:
+        * UIProcess/WebLayerTreeRenderer.cpp:
+        (WebKit):
+        (WebKit::WebLayerTreeRenderer::setLayerFilters):
+        * UIProcess/WebLayerTreeRenderer.h:
+        (WebLayerTreeRenderer):
+        * WebProcess/WebCoreSupport/WebGraphicsLayer.cpp:
+        (WebCore):
+        (WebCore::WebGraphicsLayer::didChangeFilters):
+        (WebCore::WebGraphicsLayer::setFilters):
+        (WebCore::WebGraphicsLayer::syncFilters):
+        (WebCore::WebGraphicsLayer::syncCompositingStateForThisLayerOnly):
+        * WebProcess/WebCoreSupport/WebGraphicsLayer.h:
+        (WebGraphicsLayerClient):
+        (WebGraphicsLayer):
+        * WebProcess/WebPage/qt/LayerTreeHostQt.cpp:
+        (WebKit):
+        (WebKit::LayerTreeHostQt::syncLayerFilters):
+        * WebProcess/WebPage/qt/LayerTreeHostQt.h:
+        (LayerTreeHostQt):
+
 2012-05-02  Simon Hausmann  <simon.hausmann@nokia.com>
 
         [Qt] Fix vkb showing incorrect flags/keys when content changes
index c6a1673..804568c 100644 (file)
 #include <WebCore/TranslateTransformOperation.h>
 #endif
 
+#if USE(UI_SIDE_COMPOSITING) && ENABLE(CSS_FILTERS)
+#include <WebCore/FilterOperations.h>
+#endif
+
 using namespace WebCore;
 using namespace WebKit;
 
@@ -1241,6 +1245,110 @@ bool ArgumentCoder<KeyframeValueList>::decode(ArgumentDecoder* decoder, WebCore:
 
 #endif
 
+#if USE(UI_SIDE_COMPOSITING) && ENABLE(CSS_FILTERS)
+void ArgumentCoder<WebCore::FilterOperations>::encode(ArgumentEncoder* encoder, const WebCore::FilterOperations& filters)
+{
+    encoder->encodeUInt32(filters.size());
+    for (size_t i = 0; i < filters.size(); ++i) {
+        const FilterOperation* filter = filters.at(i);
+        FilterOperation::OperationType type = filter->getOperationType();
+        encoder->encodeEnum(type);
+        switch (type) {
+        case FilterOperation::GRAYSCALE:
+        case FilterOperation::SEPIA:
+        case FilterOperation::SATURATE:
+        case FilterOperation::HUE_ROTATE:
+            encoder->encodeDouble(static_cast<const BasicColorMatrixFilterOperation*>(filter)->amount());
+            break;
+        case FilterOperation::INVERT:
+        case FilterOperation::BRIGHTNESS:
+        case FilterOperation::CONTRAST:
+        case FilterOperation::OPACITY:
+            encoder->encodeDouble(static_cast<const BasicComponentTransferFilterOperation*>(filter)->amount());
+            break;
+        case FilterOperation::BLUR:
+            ArgumentCoder<Length>::encode(encoder, static_cast<const BlurFilterOperation*>(filter)->stdDeviation());
+            break;
+        case FilterOperation::DROP_SHADOW: {
+            const DropShadowFilterOperation* shadow = static_cast<const DropShadowFilterOperation*>(filter);
+            ArgumentCoder<IntPoint>::encode(encoder, shadow->location());
+            encoder->encodeInt32(shadow->stdDeviation());
+            ArgumentCoder<Color>::encode(encoder, shadow->color());
+            break;
+        }
+        default:
+            break;
+        }
+    }
+}
+
+bool ArgumentCoder<WebCore::FilterOperations>::decode(ArgumentDecoder* decoder, WebCore::FilterOperations& filters)
+{
+    uint32_t size;
+    if (!decoder->decodeUInt32(size))
+        return false;
+
+    Vector<RefPtr<FilterOperation> >& operations = filters.operations();
+
+    for (size_t i = 0; i < size; ++i) {
+        FilterOperation::OperationType type;
+        RefPtr<FilterOperation> filter;
+        if (!decoder->decodeEnum(type))
+            return false;
+
+        switch (type) {
+        case FilterOperation::GRAYSCALE:
+        case FilterOperation::SEPIA:
+        case FilterOperation::SATURATE:
+        case FilterOperation::HUE_ROTATE: {
+            double value;
+            if (!decoder->decodeDouble(value))
+                return false;
+            filter = BasicColorMatrixFilterOperation::create(value, type);
+            break;
+        }
+        case FilterOperation::INVERT:
+        case FilterOperation::BRIGHTNESS:
+        case FilterOperation::CONTRAST:
+        case FilterOperation::OPACITY: {
+            double value;
+            if (!decoder->decodeDouble(value))
+                return false;
+            filter = BasicComponentTransferFilterOperation::create(value, type);
+            break;
+        }
+        case FilterOperation::BLUR: {
+            Length length;
+            if (!ArgumentCoder<Length>::decode(decoder, length))
+                return false;
+            filter = BlurFilterOperation::create(length, type);
+            break;
+        }
+        case FilterOperation::DROP_SHADOW: {
+            IntPoint location;
+            int32_t stdDeviation;
+            Color color;
+            if (!ArgumentCoder<IntPoint>::decode(decoder, location))
+                return false;
+            if (!decoder->decodeInt32(stdDeviation))
+                return false;
+            if (!ArgumentCoder<Color>::decode(decoder, color))
+                return false;
+            filter = DropShadowFilterOperation::create(location, stdDeviation, color, type);
+            break;
+        }
+        default:
+            break;
+        }
+
+        if (filter)
+            operations.append(filter);
+    }
+
+    return true;
+}
+#endif
+
 #endif
 
 } // namespace CoreIPC
index 033e179..d02f5fc 100644 (file)
@@ -85,6 +85,12 @@ namespace WebCore {
 }
 #endif
 
+#if USE(UI_SIDE_COMPOSITING) && ENABLE(CSS_FILTERS)
+namespace WebCore {
+    class FilterOperations;
+}
+#endif
+
 namespace CoreIPC {
 
 template<> struct ArgumentCoder<WebCore::AffineTransform> {
@@ -301,6 +307,13 @@ template<> struct ArgumentCoder<RefPtr<WebCore::Animation> > {
 };
 #endif
 
+#if USE(UI_SIDE_COMPOSITING) && ENABLE(CSS_FILTERS)
+template<> struct ArgumentCoder<WebCore::FilterOperations> {
+    static void encode(ArgumentEncoder*, const WebCore::FilterOperations&);
+    static bool decode(ArgumentDecoder*, WebCore::FilterOperations&);
+};
+#endif
+
 #if USE(ACCELERATED_COMPOSITING)
 template<> struct ArgumentCoder<WebCore::KeyframeValueList> {
     static void encode(ArgumentEncoder*, const WebCore::KeyframeValueList& keyframes);
index 7466887..03a5eac 100644 (file)
@@ -105,6 +105,13 @@ void LayerTreeHostProxy::setCompositingLayerChildren(WebLayerID id, const Vector
     dispatchUpdate(bind(&WebLayerTreeRenderer::setLayerChildren, m_renderer.get(), id, children));
 }
 
+#if ENABLE(CSS_FILTERS)
+void LayerTreeHostProxy::setCompositingLayerFilters(WebLayerID id, const FilterOperations& filters)
+{
+    dispatchUpdate(bind(&WebLayerTreeRenderer::setLayerFilters, m_renderer.get(), id, filters));
+}
+#endif
+
 void LayerTreeHostProxy::didRenderFrame()
 {
     dispatchUpdate(bind(&WebLayerTreeRenderer::flushLayerChanges, m_renderer.get()));
index 191bc4d..ac3d3d2 100644 (file)
@@ -50,6 +50,9 @@ public:
     virtual ~LayerTreeHostProxy();
     void setCompositingLayerState(WebLayerID, const WebLayerInfo&);
     void setCompositingLayerChildren(WebLayerID, const Vector<WebLayerID>&);
+#if ENABLE(CSS_FILTERS)
+    void setCompositingLayerFilters(WebLayerID, const WebCore::FilterOperations&);
+#endif
     void deleteCompositingLayer(WebLayerID);
     void setRootCompositingLayer(WebLayerID);
     void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*);
index 47a1ee3..1cdae0d 100644 (file)
@@ -21,6 +21,9 @@
 messages -> LayerTreeHostProxy {
     SetCompositingLayerState(uint32_t id, WebKit::WebLayerInfo layerInfo)
     SetCompositingLayerChildren(uint32_t id, Vector<uint32_t> children)
+#if ENABLE(CSS_FILTERS)
+    SetCompositingLayerFilters(uint32_t id, WebCore::FilterOperations filters)
+#endif
     SetRootCompositingLayer(uint32_t id)
     DeleteCompositingLayer(uint32_t id)
     CreateTileForLayer(uint32_t layerID, int tileID, WebCore::IntRect targetRect, WebKit::SurfaceUpdateInfo updateInfo)
index b21b55d..fa301a2 100644 (file)
@@ -213,6 +213,18 @@ void WebLayerTreeRenderer::setLayerChildren(WebLayerID id, const Vector<WebLayer
     layer->setChildren(children);
 }
 
+#if ENABLE(CSS_FILTERS)
+void WebLayerTreeRenderer::setLayerFilters(WebLayerID id, const FilterOperations& filters)
+{
+    ensureLayer(id);
+    LayerMap::iterator it = m_layers.find(id);
+    ASSERT(it != m_layers.end());
+
+    GraphicsLayer* layer = it->second;
+    layer->setFilters(filters);
+}
+#endif
+
 void WebLayerTreeRenderer::setLayerState(WebLayerID id, const WebLayerInfo& layerInfo)
 {
     ensureLayer(id);
index 36e5b4f..042c52d 100644 (file)
@@ -77,6 +77,10 @@ public:
     void setRootLayerID(WebLayerID);
     void setLayerChildren(WebLayerID, const Vector<WebLayerID>&);
     void setLayerState(WebLayerID, const WebLayerInfo&);
+#if ENABLE(CSS_FILTERS)
+    void setLayerFilters(WebLayerID, const WebCore::FilterOperations&);
+#endif
+
     void createTile(WebLayerID, int, float scale);
     void removeTile(WebLayerID, int);
     void updateTile(WebLayerID, int, const TileUpdate&);
index 8052a02..73edf24 100644 (file)
@@ -74,6 +74,15 @@ void WebGraphicsLayer::didChangeChildren()
         client()->notifySyncRequired(this);
 }
 
+#if ENABLE(CSS_FILTERS)
+void WebGraphicsLayer::didChangeFilters()
+{
+    m_shouldSyncFilters = true;
+    if (client())
+        client()->notifySyncRequired(this);
+}
+#endif
+
 void WebGraphicsLayer::setShouldUpdateVisibleRect()
 {
     if (!transform().isAffine())
@@ -309,6 +318,17 @@ void WebGraphicsLayer::setContentsNeedsDisplay()
     setContentsToImage(image.get());
 }
 
+#if ENABLE(CSS_FILTERS)
+bool WebGraphicsLayer::setFilters(const FilterOperations& newFilters)
+{
+    if (filters() == newFilters)
+        return true;
+    didChangeFilters();
+    return GraphicsLayer::setFilters(newFilters);
+}
+#endif
+
+
 void WebGraphicsLayer::setContentsToImage(Image* image)
 {
     if (image == m_image)
@@ -413,6 +433,16 @@ void WebGraphicsLayer::syncChildren()
     m_webGraphicsLayerClient->syncLayerChildren(m_id, childIDs);
 }
 
+#if ENABLE(CSS_FILTERS)
+void WebGraphicsLayer::syncFilters()
+{
+    if (!m_shouldSyncFilters)
+        return;
+    m_shouldSyncFilters = false;
+    m_webGraphicsLayerClient->syncLayerFilters(m_id, filters());
+}
+#endif
+
 void WebGraphicsLayer::syncLayerState()
  {
     if (!m_shouldSyncLayerState)
@@ -452,6 +482,9 @@ void WebGraphicsLayer::syncCompositingStateForThisLayerOnly()
     computeTransformedVisibleRect();
     syncChildren();
     syncLayerState();
+#if ENABLE(CSS_FILTERS)
+    syncFilters();
+#endif
     updateContentBuffers();
 }
 
index 0ebbb51..c22a882 100644 (file)
@@ -57,6 +57,9 @@ public:
     virtual void releaseImageBackingStore(int64_t) = 0;
     virtual void syncLayerState(WebLayerID, const WebLayerInfo&) = 0;
     virtual void syncLayerChildren(WebLayerID, const Vector<WebLayerID>&) = 0;
+#if ENABLE(CSS_FILTERS)
+    virtual void syncLayerFilters(WebLayerID, const WebCore::FilterOperations&) = 0;
+#endif
     virtual void attachLayer(WebCore::WebGraphicsLayer*) = 0;
     virtual void detachLayer(WebCore::WebGraphicsLayer*) = 0;
     virtual void syncFixedLayers() = 0;
@@ -104,6 +107,9 @@ public:
     void setVisibleContentRectTrajectoryVector(const FloatPoint&);
     virtual void syncCompositingState(const FloatRect&);
     virtual void syncCompositingStateForThisLayerOnly();
+#if ENABLE(CSS_FILTERS)
+    bool setFilters(const FilterOperations&);
+#endif
 
     void setRootLayer(bool);
 
@@ -138,6 +144,9 @@ public:
     void setWebGraphicsLayerClient(WebKit::WebGraphicsLayerClient*);
     void syncChildren();
     void syncLayerState();
+#if ENABLE(CSS_FILTERS)
+    void syncFilters();
+#endif
     void ensureImageBackingStore();
 
     void adjustVisibleRect();
@@ -157,12 +166,17 @@ private:
     bool m_shouldUpdateVisibleRect: 1;
     bool m_shouldSyncLayerState: 1;
     bool m_shouldSyncChildren: 1;
+    bool m_shouldSyncFilters: 1;
     bool m_fixedToViewport : 1;
 
     void notifyChange();
     void didChangeGeometry();
     void didChangeLayerState();
     void didChangeChildren();
+#if ENABLE(CSS_FILTERS)
+    void didChangeFilters();
+#endif
+
     void createBackingStore();
 
     bool selfOrAncestorHaveNonAffineTransforms();
index ab120cd..964366e 100644 (file)
@@ -256,6 +256,14 @@ void LayerTreeHostQt::syncLayerChildren(WebLayerID id, const Vector<WebLayerID>&
     m_webPage->send(Messages::LayerTreeHostProxy::SetCompositingLayerChildren(id, children));
 }
 
+#if ENABLE(CSS_FILTERS)
+void LayerTreeHostQt::syncLayerFilters(WebLayerID id, const FilterOperations& filters)
+{
+    m_shouldSyncFrame = true;
+    m_webPage->send(Messages::LayerTreeHostProxy::SetCompositingLayerFilters(id, filters));
+}
+#endif
+
 void LayerTreeHostQt::attachLayer(WebGraphicsLayer* layer)
 {
     ASSERT(!m_registeredLayers.contains(layer));
index e39490a..eecb62e 100644 (file)
@@ -76,6 +76,9 @@ public:
     virtual void setVisibleContentsRect(const WebCore::IntRect&, float scale, const WebCore::FloatPoint&);
     virtual void syncLayerState(WebLayerID, const WebLayerInfo&);
     virtual void syncLayerChildren(WebLayerID, const Vector<WebLayerID>&);
+#if ENABLE(CSS_FILTERS)
+    virtual void syncLayerFilters(WebLayerID, const WebCore::FilterOperations&);
+#endif
     virtual void attachLayer(WebCore::WebGraphicsLayer*);
     virtual void detachLayer(WebCore::WebGraphicsLayer*);
     virtual void syncFixedLayers();