Title: [149365] trunk/Source/WebCore
Revision
149365
Author
[email protected]
Date
2013-04-30 06:47:49 -0700 (Tue, 30 Apr 2013)

Log Message

[Texmap] Use fewer intermediate surfaces when compositing filters
https://bugs.webkit.org/show_bug.cgi?id=115224

Patch by Noam Rosenthal <[email protected]> on 2013-04-30
Reviewed by Allan Sandfeld Jensen.

Until now, when rendering CSS filters, the filters were applied to the texture
and then the resulting texture would be composited to the target surface with
its transform/opacity.
This requires at least two intermediate surface passes for every filtered layer.

This patch makes it so that the last filter pass is applied together with the
resulting surface's opacity and transform, during composition.

Tested by css3/filters tests, whichn now scroll/zoom a lot faster.

* platform/graphics/texmap/TextureMapper.h:
(WebCore::BitmapTexture::applyFilters):
* platform/graphics/texmap/TextureMapperGL.cpp:
(WebCore::TextureMapperGLData::TextureMapperGLData):
(TextureMapperGLData):
(WebCore):
(WebCore::optionsForFilterType):
(WebCore::getPassesRequiredForFilter):
(WebCore::gauss):
(WebCore::gaussianKernel):
(WebCore::prepareFilterProgram):
(WebCore::TextureMapperGL::drawTexture):
(WebCore::TextureMapperGL::drawFiltered):
(WebCore::isCustomFilter):
* platform/graphics/texmap/TextureMapperGL.h:
(TextureMapperGL):
(BitmapTextureGL):
(FilterInfo):
* platform/graphics/texmap/TextureMapperImageBuffer.cpp:
(WebCore::BitmapTextureImageBuffer::applyFilters):
* platform/graphics/texmap/TextureMapperImageBuffer.h:
(BitmapTextureImageBuffer):
(WebCore::BitmapTextureGL::FilterInfo::FilterInfo):
(WebCore::BitmapTextureGL::filterInfo):
(WebCore::BitmapTextureGL::applyFilters):
    Modify TextureMapperGL to remember the last filter operation applied
    to a BitmapTexture and apply it when the texture is composited.

* platform/graphics/texmap/TextureMapperLayer.cpp:
(WebCore::TextureMapperLayer::paintIntoSurface):
    Simplify the call to applyFilters, since now TextureMapperGL is responsible
    for maintaining the content texture.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (149364 => 149365)


--- trunk/Source/WebCore/ChangeLog	2013-04-30 13:47:10 UTC (rev 149364)
+++ trunk/Source/WebCore/ChangeLog	2013-04-30 13:47:49 UTC (rev 149365)
@@ -1,3 +1,54 @@
+2013-04-30  Noam Rosenthal  <[email protected]>
+
+        [Texmap] Use fewer intermediate surfaces when compositing filters
+        https://bugs.webkit.org/show_bug.cgi?id=115224
+
+        Reviewed by Allan Sandfeld Jensen.
+
+        Until now, when rendering CSS filters, the filters were applied to the texture
+        and then the resulting texture would be composited to the target surface with
+        its transform/opacity.
+        This requires at least two intermediate surface passes for every filtered layer.
+
+        This patch makes it so that the last filter pass is applied together with the 
+        resulting surface's opacity and transform, during composition.
+
+        Tested by css3/filters tests, whichn now scroll/zoom a lot faster.
+
+        * platform/graphics/texmap/TextureMapper.h:
+        (WebCore::BitmapTexture::applyFilters):
+        * platform/graphics/texmap/TextureMapperGL.cpp:
+        (WebCore::TextureMapperGLData::TextureMapperGLData):
+        (TextureMapperGLData):
+        (WebCore):
+        (WebCore::optionsForFilterType):
+        (WebCore::getPassesRequiredForFilter):
+        (WebCore::gauss):
+        (WebCore::gaussianKernel):
+        (WebCore::prepareFilterProgram):
+        (WebCore::TextureMapperGL::drawTexture):
+        (WebCore::TextureMapperGL::drawFiltered):
+        (WebCore::isCustomFilter):
+        * platform/graphics/texmap/TextureMapperGL.h:
+        (TextureMapperGL):
+        (BitmapTextureGL):
+        (FilterInfo):
+        * platform/graphics/texmap/TextureMapperImageBuffer.cpp:
+        (WebCore::BitmapTextureImageBuffer::applyFilters):
+        * platform/graphics/texmap/TextureMapperImageBuffer.h:
+        (BitmapTextureImageBuffer):
+        (WebCore::BitmapTextureGL::FilterInfo::FilterInfo):
+        (WebCore::BitmapTextureGL::filterInfo):
+        (WebCore::BitmapTextureGL::applyFilters):
+            Modify TextureMapperGL to remember the last filter operation applied
+            to a BitmapTexture and apply it when the texture is composited.
+
+        * platform/graphics/texmap/TextureMapperLayer.cpp:
+        (WebCore::TextureMapperLayer::paintIntoSurface):
+            Simplify the call to applyFilters, since now TextureMapperGL is responsible
+            for maintaining the content texture.
+
+
 2013-04-30  Christophe Dumez  <[email protected]>
 
         [EFL] Enable scaled cursors

Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapper.h (149364 => 149365)


--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapper.h	2013-04-30 13:47:10 UTC (rev 149364)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapper.h	2013-04-30 13:47:49 UTC (rev 149365)
@@ -95,7 +95,7 @@
     inline bool isOpaque() const { return !(m_flags & SupportsAlpha); }
 
 #if ENABLE(CSS_FILTERS)
-    virtual PassRefPtr<BitmapTexture> applyFilters(TextureMapper*, const BitmapTexture& contentTexture, const FilterOperations&) { return this; }
+    virtual PassRefPtr<BitmapTexture> applyFilters(TextureMapper*, const FilterOperations&) { return this; }
 #endif
 
 protected:

Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp (149364 => 149365)


--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp	2013-04-30 13:47:10 UTC (rev 149364)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp	2013-04-30 13:47:49 UTC (rev 149365)
@@ -35,6 +35,7 @@
 #include <wtf/PassOwnArrayPtr.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
+#include <wtf/TemporaryChange.h>
 
 #if PLATFORM(QT)
 #include "NativeImageQt.h"
@@ -134,6 +135,9 @@
         , previousScissorState(0)
         , previousDepthState(0)
         , sharedData(TextureMapperGLData::SharedGLData::currentSharedGLData(this->context))
+#if ENABLE(CSS_FILTERS)
+        , filterInfo(0)
+#endif
     { }
 
     ~TextureMapperGLData();
@@ -152,6 +156,9 @@
     RefPtr<SharedGLData> sharedData;
     RefPtr<BitmapTexture> currentSurface;
     HashMap<const void*, Platform3DObject> vbos;
+#if ENABLE(CSS_FILTERS)
+    const BitmapTextureGL::FilterInfo* filterInfo;
+#endif
 };
 
 Platform3DObject TextureMapperGLData::getStaticVBO(GC3Denum target, GC3Dsizeiptr size, const void* data)
@@ -413,6 +420,157 @@
 #endif
 }
 
+#if ENABLE(CSS_FILTERS)
+
+static TextureMapperShaderProgram::Options optionsForFilterType(FilterOperation::OperationType type, unsigned pass)
+{
+    switch (type) {
+    case FilterOperation::GRAYSCALE:
+        return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::GrayscaleFilter;
+    case FilterOperation::SEPIA:
+        return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::SepiaFilter;
+    case FilterOperation::SATURATE:
+        return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::SaturateFilter;
+    case FilterOperation::HUE_ROTATE:
+        return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::HueRotateFilter;
+    case FilterOperation::INVERT:
+        return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::InvertFilter;
+    case FilterOperation::BRIGHTNESS:
+        return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::BrightnessFilter;
+    case FilterOperation::CONTRAST:
+        return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::ContrastFilter;
+    case FilterOperation::OPACITY:
+        return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::OpacityFilter;
+    case FilterOperation::BLUR:
+        return TextureMapperShaderProgram::BlurFilter;
+    case FilterOperation::DROP_SHADOW:
+        return TextureMapperShaderProgram::AlphaBlur
+            | (pass ? TextureMapperShaderProgram::ContentTexture | TextureMapperShaderProgram::SolidColor: 0);
+    default:
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+}
+
+static unsigned getPassesRequiredForFilter(FilterOperation::OperationType type)
+{
+    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:
+#if ENABLE(CSS_SHADERS)
+    case FilterOperation::CUSTOM:
+    case FilterOperation::VALIDATED_CUSTOM:
+#endif
+        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;
+    }
+}
+
+// Create a normal distribution of 21 values between -2 and 2.
+static const unsigned GaussianKernelHalfWidth = 11;
+static const float GaussianKernelStep = 0.2;
+
+static inline float gauss(float x)
+{
+    return exp(-(x * x) / 2.);
+}
+
+static float* gaussianKernel()
+{
+    static bool prepared = false;
+    static float kernel[GaussianKernelHalfWidth] = {0, };
+
+    if (prepared)
+        return kernel;
+
+    kernel[0] = gauss(0);
+    float sum = kernel[0];
+    for (unsigned i = 1; i < GaussianKernelHalfWidth; ++i) {
+        kernel[i] = gauss(i * GaussianKernelStep);
+        sum += 2 * kernel[i];
+    }
+
+    // Normalize the kernel.
+    float scale = 1 / sum;
+    for (unsigned i = 0; i < GaussianKernelHalfWidth; ++i)
+        kernel[i] *= scale;
+
+    prepared = true;
+    return kernel;
+}
+
+static void prepareFilterProgram(TextureMapperShaderProgram* program, const FilterOperation& operation, unsigned pass, const IntSize& size, GC3Duint contentTexture)
+{
+    RefPtr<GraphicsContext3D> context = program->context();
+    context->useProgram(program->programID());
+
+    switch (operation.getOperationType()) {
+    case FilterOperation::GRAYSCALE:
+    case FilterOperation::SEPIA:
+    case FilterOperation::SATURATE:
+    case FilterOperation::HUE_ROTATE:
+        context->uniform1f(program->filterAmountLocation(), static_cast<const BasicColorMatrixFilterOperation&>(operation).amount());
+        break;
+    case FilterOperation::INVERT:
+    case FilterOperation::BRIGHTNESS:
+    case FilterOperation::CONTRAST:
+    case FilterOperation::OPACITY:
+        context->uniform1f(program->filterAmountLocation(), 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());
+
+        context->uniform2f(program->blurRadiusLocation(), radius.width(), radius.height());
+        context->uniform1fv(program->gaussianKernelLocation(), GaussianKernelHalfWidth, gaussianKernel());
+        break;
+    }
+    case FilterOperation::DROP_SHADOW: {
+        const DropShadowFilterOperation& shadow = static_cast<const DropShadowFilterOperation&>(operation);
+        context->uniform1fv(program->gaussianKernelLocation(), GaussianKernelHalfWidth, gaussianKernel());
+        switch (pass) {
+        case 0:
+            // First pass: horizontal alpha blur.
+            context->uniform2f(program->blurRadiusLocation(), shadow.stdDeviation() / float(size.width()), 0);
+            context->uniform2f(program->shadowOffsetLocation(), float(shadow.location().x()) / float(size.width()), float(shadow.location().y()) / float(size.height()));
+            break;
+        case 1:
+            // Second pass: we need the shadow color and the content texture for compositing.
+            float r, g, b, a;
+            Color(premultipliedARGBFromColor(shadow.color())).getRGBA(r, g, b, a);
+            context->uniform4f(program->colorLocation(), r, g, b, a);
+            context->uniform2f(program->blurRadiusLocation(), 0, shadow.stdDeviation() / float(size.height()));
+            context->uniform2f(program->shadowOffsetLocation(), 0, 0);
+            context->activeTexture(GraphicsContext3D::TEXTURE1);
+            context->bindTexture(GraphicsContext3D::TEXTURE_2D, contentTexture);
+            context->uniform1i(program->contentTextureLocation(), 1);
+            break;
+        }
+        break;
+    }
+    default:
+        break;
+    }
+}
+#endif
+
 void TextureMapperGL::drawTexture(const BitmapTexture& texture, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, unsigned exposedEdges)
 {
     if (!texture.isValid())
@@ -422,6 +580,10 @@
         return;
 
     const BitmapTextureGL& textureGL = static_cast<const BitmapTextureGL&>(texture);
+#if ENABLE(CSS_FILTERS)
+    TemporaryChange<const BitmapTextureGL::FilterInfo*> filterInfo(data().filterInfo, textureGL.filterInfo());
+#endif
+
     drawTexture(textureGL.id(), textureGL.isOpaque() ? 0 : ShouldBlend, textureGL.size(), targetRect, matrix, opacity, exposedEdges);
 }
 
@@ -442,11 +604,30 @@
         flags |= ShouldAntialias;
     }
 
+#if ENABLE(CSS_FILTERS)
+    RefPtr<FilterOperation> filter = data().filterInfo ? data().filterInfo->filter: 0;
+    GC3Duint filterContentTextureID = 0;
+
+    if (filter) {
+        if (data().filterInfo->contentTexture)
+            filterContentTextureID = toBitmapTextureGL(data().filterInfo->contentTexture.get())->id();
+        options |= optionsForFilterType(filter->getOperationType(), data().filterInfo->pass);
+        if (filter->affectsOpacity())
+            flags |= ShouldBlend;
+    }
+#endif
+
     if (useAntialiasing || opacity < 1)
         flags |= ShouldBlend;
 
     RefPtr<TextureMapperShaderProgram> program;
     program = data().sharedGLData().getShaderProgram(options);
+
+#if ENABLE(CSS_FILTERS)
+    if (filter)
+        prepareFilterProgram(program.get(), *filter.get(), data().filterInfo->pass, textureSize, filterContentTextureID);
+#endif
+
     drawTexturedQuadWithProgram(program.get(), texture, flags, textureSize, targetRect, modelViewMatrix, opacity);
 }
 
@@ -737,157 +918,7 @@
     updateContents(imageData, targetRect, offset, bytesPerLine, updateContentsFlag);
 }
 
-#if ENABLE(CSS_FILTERS)
-
-static TextureMapperShaderProgram::Options optionsForFilterType(FilterOperation::OperationType type, unsigned pass)
-{
-    switch (type) {
-    case FilterOperation::GRAYSCALE:
-        return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::GrayscaleFilter;
-    case FilterOperation::SEPIA:
-        return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::SepiaFilter;
-    case FilterOperation::SATURATE:
-        return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::SaturateFilter;
-    case FilterOperation::HUE_ROTATE:
-        return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::HueRotateFilter;
-    case FilterOperation::INVERT:
-        return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::InvertFilter;
-    case FilterOperation::BRIGHTNESS:
-        return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::BrightnessFilter;
-    case FilterOperation::CONTRAST:
-        return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::ContrastFilter;
-    case FilterOperation::OPACITY:
-        return TextureMapperShaderProgram::Texture | TextureMapperShaderProgram::OpacityFilter;
-    case FilterOperation::BLUR:
-        return TextureMapperShaderProgram::BlurFilter;
-    case FilterOperation::DROP_SHADOW:
-        return TextureMapperShaderProgram::AlphaBlur
-            | (pass ? TextureMapperShaderProgram::ContentTexture | TextureMapperShaderProgram::SolidColor: 0);
-    default:
-        ASSERT_NOT_REACHED();
-        return 0;
-    }
-}
-
-static unsigned getPassesRequiredForFilter(FilterOperation::OperationType type)
-{
-    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:
 #if ENABLE(CSS_SHADERS)
-    case FilterOperation::CUSTOM:
-    case FilterOperation::VALIDATED_CUSTOM:
-#endif
-        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;
-    }
-}
-
-// Create a normal distribution of 21 values between -2 and 2.
-static const unsigned GaussianKernelHalfWidth = 11;
-static const float GaussianKernelStep = 0.2;
-
-static inline float gauss(float x)
-{
-    return exp(-(x * x) / 2.);
-}
-
-static float* gaussianKernel()
-{
-    static bool prepared = false;
-    static float kernel[GaussianKernelHalfWidth] = {0, };
-
-    if (prepared)
-        return kernel;
-
-    kernel[0] = gauss(0);
-    float sum = kernel[0];
-    for (unsigned i = 1; i < GaussianKernelHalfWidth; ++i) {
-        kernel[i] = gauss(i * GaussianKernelStep);
-        sum += 2 * kernel[i];
-    }
-
-    // Normalize the kernel.
-    float scale = 1 / sum;
-    for (unsigned i = 0; i < GaussianKernelHalfWidth; ++i)
-        kernel[i] *= scale;
-
-    prepared = true;
-    return kernel;
-}
-
-static void prepareFilterProgram(TextureMapperShaderProgram* program, const FilterOperation& operation, unsigned pass, const IntSize& size, GC3Duint contentTexture)
-{
-    RefPtr<GraphicsContext3D> context = program->context();
-    context->useProgram(program->programID());
-
-    switch (operation.getOperationType()) {
-    case FilterOperation::GRAYSCALE:
-    case FilterOperation::SEPIA:
-    case FilterOperation::SATURATE:
-    case FilterOperation::HUE_ROTATE:
-        context->uniform1f(program->filterAmountLocation(), static_cast<const BasicColorMatrixFilterOperation&>(operation).amount());
-        break;
-    case FilterOperation::INVERT:
-    case FilterOperation::BRIGHTNESS:
-    case FilterOperation::CONTRAST:
-    case FilterOperation::OPACITY:
-        context->uniform1f(program->filterAmountLocation(), 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());
-
-        context->uniform2f(program->blurRadiusLocation(), radius.width(), radius.height());
-        context->uniform1fv(program->gaussianKernelLocation(), GaussianKernelHalfWidth, gaussianKernel());
-        break;
-    }
-    case FilterOperation::DROP_SHADOW: {
-        const DropShadowFilterOperation& shadow = static_cast<const DropShadowFilterOperation&>(operation);
-        context->uniform1fv(program->gaussianKernelLocation(), GaussianKernelHalfWidth, gaussianKernel());
-        switch (pass) {
-        case 0:
-            // First pass: horizontal alpha blur.
-            context->uniform2f(program->blurRadiusLocation(), shadow.stdDeviation() / float(size.width()), 0);
-            context->uniform2f(program->shadowOffsetLocation(), float(shadow.location().x()) / float(size.width()), float(shadow.location().y()) / float(size.height()));
-            break;
-        case 1:
-            // Second pass: we need the shadow color and the content texture for compositing.
-            float r, g, b, a;
-            Color(premultipliedARGBFromColor(shadow.color())).getRGBA(r, g, b, a);
-            context->uniform4f(program->colorLocation(), r, g, b, a);
-            context->uniform2f(program->blurRadiusLocation(), 0, shadow.stdDeviation() / float(size.height()));
-            context->uniform2f(program->shadowOffsetLocation(), 0, 0);
-            context->activeTexture(GraphicsContext3D::TEXTURE1);
-            context->bindTexture(GraphicsContext3D::TEXTURE_2D, contentTexture);
-            context->uniform1i(program->contentTextureLocation(), 1);
-            break;
-        }
-        break;
-    }
-    default:
-        break;
-    }
-}
-
-#if ENABLE(CSS_SHADERS)
 void TextureMapperGL::removeCachedCustomFilterProgram(CustomFilterProgram* program)
 {
     m_customFilterPrograms.remove(program->programInfo());
@@ -946,53 +977,79 @@
 }
 #endif
 
-void TextureMapperGL::drawFiltered(const BitmapTexture& sampler, const BitmapTexture& contentTexture, const FilterOperation& filter, int pass)
+#if ENABLE(CSS_FILTERS)
+void TextureMapperGL::drawFiltered(const BitmapTexture& sampler, const BitmapTexture* contentTexture, const FilterOperation& filter, int pass)
 {
     // For standard filters, we always draw the whole texture without transformations.
     TextureMapperShaderProgram::Options options = optionsForFilterType(filter.getOperationType(), pass);
     RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().getShaderProgram(options);
     ASSERT(program);
 
-    prepareFilterProgram(program.get(), filter, pass, sampler.contentSize(), static_cast<const BitmapTextureGL&>(contentTexture).id());
+    prepareFilterProgram(program.get(), filter, pass, sampler.contentSize(), contentTexture ? static_cast<const BitmapTextureGL*>(contentTexture)->id() : 0);
     FloatRect targetRect(IntPoint::zero(), sampler.contentSize());
     drawTexturedQuadWithProgram(program.get(), static_cast<const BitmapTextureGL&>(sampler).id(), 0, IntSize(1, 1), targetRect, TransformationMatrix(), 1);
 }
 
-PassRefPtr<BitmapTexture> BitmapTextureGL::applyFilters(TextureMapper* textureMapper, const BitmapTexture& contentTexture, const FilterOperations& filters)
+static bool isCustomFilter(FilterOperation::OperationType type)
 {
-    TextureMapperGL* textureMapperGL = static_cast<TextureMapperGL*>(textureMapper);
-    RefPtr<BitmapTexture> previousSurface = textureMapperGL->data().currentSurface;
+#if ENABLE(CSS_SHADERS)
+    return type == FilterOperation::CUSTOM || type == FilterOperation::VALIDATED_CUSTOM;
+#else
+    return false;
+#endif
+}
 
-    RefPtr<BitmapTexture> source = this;
-    RefPtr<BitmapTexture> target = textureMapper->acquireTextureFromPool(m_textureSize);
+PassRefPtr<BitmapTexture> BitmapTextureGL::applyFilters(TextureMapper* textureMapper, const FilterOperations& filters)
+{
+    if (filters.isEmpty())
+        return this;
 
-    bool useContentTexture = true;
+    TextureMapperGL* texmapGL = static_cast<TextureMapperGL*>(textureMapper);
+    RefPtr<BitmapTexture> previousSurface = texmapGL->data().currentSurface;
+    RefPtr<BitmapTexture> resultSurface = this;
+    RefPtr<BitmapTexture> intermediateSurface;
+    RefPtr<BitmapTexture> spareSurface;
+
+    m_filterInfo = FilterInfo();
+
     for (size_t i = 0; i < filters.size(); ++i) {
-        const FilterOperation* filter = filters.at(i);
+        RefPtr<FilterOperation> filter = filters.operations()[i];
         ASSERT(filter);
 
+        bool custom = isCustomFilter(filter->getOperationType());
+
         int numPasses = getPassesRequiredForFilter(filter->getOperationType());
         for (int j = 0; j < numPasses; ++j) {
-            textureMapperGL->bindSurface(target.get());
-            const BitmapTexture& sourceTexture = useContentTexture ? contentTexture : *source;
+            bool last = (i == filters.size() - 1) && (j == numPasses - 1);
+            if (custom || !last) {
+                if (!intermediateSurface)
+                    intermediateSurface = texmapGL->acquireTextureFromPool(contentSize());
+                texmapGL->bindSurface(intermediateSurface.get());
+            }
+
 #if ENABLE(CSS_SHADERS)
-            if (filter->getOperationType() == FilterOperation::CUSTOM || filter->getOperationType() == FilterOperation::VALIDATED_CUSTOM) {
-                if (textureMapperGL->drawUsingCustomFilter(*target, sourceTexture, *filter)) {
-                    // Only swap if the draw was successful.
-                    std::swap(source, target);
-                    useContentTexture = false;
-                }
+            if (custom) {
+                if (texmapGL->drawUsingCustomFilter(*intermediateSurface.get(), *resultSurface.get(), *filter))
+                    std::swap(resultSurface, intermediateSurface);
                 continue;
             }
 #endif
-            textureMapperGL->drawFiltered(sourceTexture, contentTexture, *filter, j);
-            std::swap(source, target);
-            useContentTexture = false;
+            if (last) {
+                toBitmapTextureGL(resultSurface.get())->m_filterInfo = BitmapTextureGL::FilterInfo(filter, j, spareSurface);
+                break;
+            }
+
+            texmapGL->drawFiltered(*resultSurface.get(), spareSurface.get(), *filter, j);
+            if (!j && filter->getOperationType() == FilterOperation::DROP_SHADOW) {
+                spareSurface = resultSurface;
+                resultSurface.clear();
+            }
+            std::swap(resultSurface, intermediateSurface);
         }
     }
 
-    textureMapperGL->bindSurface(previousSurface.get());
-    return source;
+    texmapGL->bindSurface(previousSurface.get());
+    return resultSurface;
 }
 #endif
 

Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h (149364 => 149365)


--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h	2013-04-30 13:47:10 UTC (rev 149364)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h	2013-04-30 13:47:49 UTC (rev 149365)
@@ -23,6 +23,7 @@
 #if USE(ACCELERATED_COMPOSITING)
 
 #include "CustomFilterProgramInfo.h"
+#include "FilterOperation.h"
 #include "FloatQuad.h"
 #include "GraphicsContext3D.h"
 #include "IntSize.h"
@@ -70,7 +71,7 @@
     inline GraphicsContext3D* graphicsContext3D() const { return m_context3D.get(); }
 
 #if ENABLE(CSS_FILTERS)
-    void drawFiltered(const BitmapTexture& sourceTexture, const BitmapTexture& contentTexture, const FilterOperation&, int pass);
+    void drawFiltered(const BitmapTexture& sourceTexture, const BitmapTexture* contentTexture, const FilterOperation&, int pass);
 #endif
 #if ENABLE(CSS_SHADERS)
     bool drawUsingCustomFilter(BitmapTexture& targetTexture, const BitmapTexture& sourceTexture, const FilterOperation&);
@@ -169,7 +170,19 @@
     virtual bool isBackedByOpenGL() const { return true; }
 
 #if ENABLE(CSS_FILTERS)
-    virtual PassRefPtr<BitmapTexture> applyFilters(TextureMapper*, const BitmapTexture& contentTexture, const FilterOperations&);
+    virtual PassRefPtr<BitmapTexture> applyFilters(TextureMapper*, const FilterOperations&) OVERRIDE;
+    struct FilterInfo {
+        RefPtr<FilterOperation> filter;
+        unsigned pass;
+        RefPtr<BitmapTexture> contentTexture;
+
+        FilterInfo(PassRefPtr<FilterOperation> f = 0, unsigned p = 0, PassRefPtr<BitmapTexture> t = 0)
+            : filter(f)
+            , pass(p)
+            , contentTexture(t)
+            { }
+    };
+    const FilterInfo* filterInfo() const { return &m_filterInfo; }
 #endif
 
 private:
@@ -191,6 +204,10 @@
     void clearIfNeeded();
     void createFboIfNeeded();
 
+#if ENABLE(CSS_FILTERS)
+    FilterInfo m_filterInfo;
+#endif
+
     friend class TextureMapperGL;
 };
 

Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp (149364 => 149365)


--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp	2013-04-30 13:47:10 UTC (rev 149364)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp	2013-04-30 13:47:49 UTC (rev 149365)
@@ -163,7 +163,7 @@
 }
 
 #if ENABLE(CSS_FILTERS)
-PassRefPtr<BitmapTexture> BitmapTextureImageBuffer::applyFilters(TextureMapper*, const BitmapTexture&, const FilterOperations&)
+PassRefPtr<BitmapTexture> BitmapTextureImageBuffer::applyFilters(TextureMapper*, const FilterOperations&)
 {
     return this;
 }

Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h (149364 => 149365)


--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h	2013-04-30 13:47:10 UTC (rev 149364)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h	2013-04-30 13:47:49 UTC (rev 149365)
@@ -38,7 +38,7 @@
     virtual void updateContents(TextureMapper*, GraphicsLayer*, const IntRect& target, const IntPoint& offset, UpdateContentsFlag);
     virtual void updateContents(const void*, const IntRect& target, const IntPoint& sourceOffset, int bytesPerLine, UpdateContentsFlag);
 #if ENABLE(CSS_FILTERS)
-    PassRefPtr<BitmapTexture> applyFilters(TextureMapper*, const BitmapTexture&, const FilterOperations&);
+    PassRefPtr<BitmapTexture> applyFilters(TextureMapper*, const FilterOperations&);
 #endif
 
 private:

Modified: trunk/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp (149364 => 149365)


--- trunk/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp	2013-04-30 13:47:10 UTC (rev 149364)
+++ trunk/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp	2013-04-30 13:47:49 UTC (rev 149365)
@@ -250,31 +250,6 @@
 {
     m_currentFilters = filters;
 }
-
-static bool shouldKeepContentTexture(const FilterOperations& filters)
-{
-    for (size_t i = 0; i < filters.size(); ++i) {
-        switch (filters.operations().at(i)->getOperationType()) {
-        // The drop-shadow filter requires the content texture, because it needs to composite it
-        // on top of the blurred shadow color.
-        case FilterOperation::DROP_SHADOW:
-            return true;
-        default:
-            break;
-        }
-    }
-
-    return false;
-}
-
-static PassRefPtr<BitmapTexture> applyFilters(const FilterOperations& filters, TextureMapper* textureMapper, BitmapTexture* source)
-{
-    if (!filters.size())
-        return source;
-
-    RefPtr<BitmapTexture> filterSurface = shouldKeepContentTexture(filters) ? textureMapper->acquireTextureFromPool(source->size()) : source;
-    return filterSurface->applyFilters(textureMapper, *source, filters);
-}
 #endif
 
 static void resolveOverlaps(Region newRegion, Region& overlapRegion, Region& nonOverlapRegion)
@@ -407,8 +382,7 @@
     if (m_state.maskLayer)
         m_state.maskLayer->applyMask(options);
 #if ENABLE(CSS_FILTERS)
-    if (!m_currentFilters.isEmpty())
-        surface = applyFilters(m_currentFilters, options.textureMapper, surface.get());
+    surface = surface->applyFilters(options.textureMapper, m_currentFilters);
 #endif
     options.textureMapper->bindSurface(surface.get());
     return surface;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to