[BlackBerry] Enable CSS Filter Effects
https://bugs.webkit.org/show_bug.cgi?id=92685
Patch by Joshua Netterfield <jnetterfield@rim.com> on 2012-07-31
Reviewed by Rob Buis.
Enable CSS filter effects, with the exception of custom effects (CSS shaders) and reference effects (SVG effects)
.:
Internally reviewed by Arvid Nilsson <anilsson@rim.com> and Antonio Gomes <agomes@rim.com>.
* Source/cmake/OptionsBlackBerry.cmake: Add LayerFilterRenderer
* Source/cmakeconfig.h.cmake: Acknowledge CSS filter effects
Source/WebCore:
No new tests, because this is covered by tests from other platforms.
Internally reviewed by Arvid Nilsson <anilsson@rim.com> and Antonio Gomes <agomes@rim.com>.
* CMakeLists.txt:
* PlatformBlackBerry.cmake:
* platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp:
(WebCore):
(WebCore::GraphicsLayerBlackBerry::setFilters):
(WebCore::GraphicsLayerBlackBerry::updateFilters):
* platform/graphics/blackberry/GraphicsLayerBlackBerry.h:
(GraphicsLayerBlackBerry):
(WebCore::GraphicsLayerBlackBerry::filters):
* platform/graphics/blackberry/LayerCompositingThread.h:
(LayerOverride):
(WebCore):
(WebCore::LayerCompositingThread::filterOperationsChanged):
(WebCore::LayerCompositingThread::setFilterOperationsChanged):
(LayerCompositingThread):
(WebCore::LayerCompositingThread::filterActions):
(WebCore::LayerCompositingThread::setFilterActions):
* platform/graphics/blackberry/LayerData.h:
(LayerData):
(WebCore::LayerData::filters):
* platform/graphics/blackberry/LayerFilterRenderer.cpp: Added.
(WebCore):
(WebCore::operationTypeToProgramID):
(WebCore::Uniformf::Uniformf):
(WebCore::Uniform1f::apply):
(WebCore::Uniform1f::create):
(WebCore::Uniform1f::Uniform1f):
(WebCore::Uniform2f::apply):
(WebCore::Uniform2f::create):
(WebCore::Uniform2f::Uniform2f):
(WebCore::Uniform3f::apply):
(WebCore::Uniform3f::create):
(WebCore::Uniform3f::Uniform3f):
(WebCore::LayerFilterRendererAction::create):
(WebCore::LayerFilterRendererAction::LayerFilterRendererAction):
(WebCore::LayerFilterRendererAction::~LayerFilterRendererAction):
(WebCore::LayerFilterRendererAction::useActionOn):
(WebCore::LayerFilterRenderer::create):
(WebCore::LayerFilterRenderer::LayerFilterRenderer):
(WebCore::LayerFilterRenderer::bindCommonAttribLocation):
(WebCore::LayerFilterRenderer::initializeSharedGLObjects):
(WebCore::LayerFilterRenderer::ping):
(WebCore::LayerFilterRenderer::pong):
(WebCore::LayerFilterRenderer::pushSnapshot):
(WebCore::LayerFilterRenderer::popSnapshot):
(WebCore::LayerFilterRenderer::actionsForOperations):
(WebCore::LayerFilterRenderer::applyActions):
* platform/graphics/blackberry/LayerFilterRenderer.h: Added.
(WebCore):
(Uniformf):
(WebCore::Uniformf::location):
(Uniform1f):
(Uniform2f):
(Uniform3f):
(LayerFilterRendererAction):
(WebCore::LayerFilterRendererAction::shouldPushSnapshot):
(WebCore::LayerFilterRendererAction::setPushSnapshot):
(WebCore::LayerFilterRendererAction::shouldPopSnapshot):
(WebCore::LayerFilterRendererAction::setPopSnapshot):
(WebCore::LayerFilterRendererAction::appendUniform):
(LayerFilterRenderer):
(WebCore::LayerFilterRenderer::isEnabled):
(WebCore::LayerFilterRenderer::disable):
* platform/graphics/blackberry/LayerRenderer.cpp:
(WebCore::LayerRenderer::loadShader):
(WebCore::LayerRenderer::loadShaderProgram):
(WebCore::LayerRenderer::drawLayersOnSurfaces):
(WebCore::LayerRenderer::updateLayersRecursive):
(WebCore):
(WebCore::LayerRenderer::initializeSharedGLObjects):
* platform/graphics/blackberry/LayerRenderer.h:
(LayerRenderer):
* platform/graphics/blackberry/LayerWebKitThread.cpp:
(WebCore::LayerWebKitThread::LayerWebKitThread):
(WebCore::LayerWebKitThread::commitOnCompositingThread):
(WebCore):
(WebCore::LayerWebKitThread::filtersCanBeComposited):
* platform/graphics/blackberry/LayerWebKitThread.h:
(LayerWebKitThread):
(WebCore::LayerWebKitThread::setFilters):
* platform/graphics/filters/FECustomFilter.cpp:
(WebCore::FECustomFilter::platformApplySoftware):
(WebCore::FECustomFilter::resizeContext):
(WebCore::FECustomFilter::bindProgramAndBuffers):
* platform/graphics/filters/FilterOperation.h:
(WebCore):
(FilterOperation):
Tools:
Internally reviewed by Arvid Nilsson <anilsson@rim.com> and Antonio Gomes <agomes@rim.com>.
* Scripts/webkitperl/FeatureList.pm: Acknowledge CSS filter effects.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@124242 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/ChangeLog b/ChangeLog
index 7b49164..ab81a1d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2012-07-31 Joshua Netterfield <jnetterfield@rim.com>
+
+ [BlackBerry] Enable CSS Filter Effects
+ https://bugs.webkit.org/show_bug.cgi?id=92685
+
+ Reviewed by Rob Buis.
+
+ Enable CSS filter effects, with the exception of custom effects (CSS shaders) and reference effects (SVG effects)
+
+ Internally reviewed by Arvid Nilsson <anilsson@rim.com> and Antonio Gomes <agomes@rim.com>.
+
+ * Source/cmake/OptionsBlackBerry.cmake: Add LayerFilterRenderer
+ * Source/cmakeconfig.h.cmake: Acknowledge CSS filter effects
+
2012-07-31 Ryosuke Niwa <rniwa@webkit.org>
Perf-o-matic: dashboard images are not generated properly from incrementally updated JSON
diff --git a/Source/WebCore/CMakeLists.txt b/Source/WebCore/CMakeLists.txt
index 53610df..23d2521 100644
--- a/Source/WebCore/CMakeLists.txt
+++ b/Source/WebCore/CMakeLists.txt
@@ -1038,6 +1038,7 @@
css/WebKitCSSMatrix.cpp
css/WebKitCSSRegionRule.cpp
css/WebKitCSSSVGDocumentValue.cpp
+ css/WebKitCSSShaderValue.cpp
css/WebKitCSSTransformValue.cpp
css/WrapShapeFunctions.cpp
@@ -1605,6 +1606,7 @@
loader/cache/CachedResourceHandle.cpp
loader/cache/CachedResourceLoader.cpp
loader/cache/CachedScript.cpp
+ loader/cache/CachedShader.cpp
loader/cache/CachedSVGDocument.cpp
loader/cache/CachedTextTrack.cpp
loader/cache/CachedXSLStyleSheet.cpp
@@ -1821,10 +1823,11 @@
platform/graphics/TiledBackingStore.cpp
platform/graphics/WidthIterator.cpp
+ platform/graphics/filters/CustomFilterCompiledProgram.cpp
platform/graphics/filters/CustomFilterGlobalContext.cpp
platform/graphics/filters/CustomFilterMesh.cpp
+ platform/graphics/filters/CustomFilterOperation.cpp
platform/graphics/filters/CustomFilterProgram.cpp
- platform/graphics/filters/CustomFilterCompiledProgram.cpp
platform/graphics/filters/DistantLightSource.cpp
platform/graphics/filters/FEBlend.cpp
platform/graphics/filters/FEColorMatrix.cpp
@@ -1849,16 +1852,15 @@
platform/graphics/filters/FilterOperations.cpp
platform/graphics/filters/LightSource.cpp
platform/graphics/filters/PointLightSource.cpp
- platform/graphics/filters/SpotLightSource.cpp
platform/graphics/filters/SourceAlpha.cpp
platform/graphics/filters/SourceGraphic.cpp
+ platform/graphics/filters/SpotLightSource.cpp
platform/graphics/filters/arm/NEONHelpers.h
platform/graphics/filters/arm/FEBlendNEON.h
platform/graphics/filters/arm/FECompositeArithmeticNEON.h
platform/graphics/filters/arm/FEGaussianBlurNEON.h
platform/graphics/filters/arm/FELightingNEON.cpp
- platform/graphics/filters/arm/FELightingNEON.h
platform/graphics/texmap/TextureMapper.cpp
platform/graphics/texmap/TextureMapperBackingStore.cpp
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 608c8d9..0615639 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,104 @@
+2012-07-31 Joshua Netterfield <jnetterfield@rim.com>
+
+ [BlackBerry] Enable CSS Filter Effects
+ https://bugs.webkit.org/show_bug.cgi?id=92685
+
+ Reviewed by Rob Buis.
+
+ Enable CSS filter effects, with the exception of custom effects (CSS shaders) and reference effects (SVG effects)
+
+ No new tests, because this is covered by tests from other platforms.
+
+ Internally reviewed by Arvid Nilsson <anilsson@rim.com> and Antonio Gomes <agomes@rim.com>.
+
+ * CMakeLists.txt:
+ * PlatformBlackBerry.cmake:
+ * platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp:
+ (WebCore):
+ (WebCore::GraphicsLayerBlackBerry::setFilters):
+ (WebCore::GraphicsLayerBlackBerry::updateFilters):
+ * platform/graphics/blackberry/GraphicsLayerBlackBerry.h:
+ (GraphicsLayerBlackBerry):
+ (WebCore::GraphicsLayerBlackBerry::filters):
+ * platform/graphics/blackberry/LayerCompositingThread.h:
+ (LayerOverride):
+ (WebCore):
+ (WebCore::LayerCompositingThread::filterOperationsChanged):
+ (WebCore::LayerCompositingThread::setFilterOperationsChanged):
+ (LayerCompositingThread):
+ (WebCore::LayerCompositingThread::filterActions):
+ (WebCore::LayerCompositingThread::setFilterActions):
+ * platform/graphics/blackberry/LayerData.h:
+ (LayerData):
+ (WebCore::LayerData::filters):
+ * platform/graphics/blackberry/LayerFilterRenderer.cpp: Added.
+ (WebCore):
+ (WebCore::operationTypeToProgramID):
+ (WebCore::Uniformf::Uniformf):
+ (WebCore::Uniform1f::apply):
+ (WebCore::Uniform1f::create):
+ (WebCore::Uniform1f::Uniform1f):
+ (WebCore::Uniform2f::apply):
+ (WebCore::Uniform2f::create):
+ (WebCore::Uniform2f::Uniform2f):
+ (WebCore::Uniform3f::apply):
+ (WebCore::Uniform3f::create):
+ (WebCore::Uniform3f::Uniform3f):
+ (WebCore::LayerFilterRendererAction::create):
+ (WebCore::LayerFilterRendererAction::LayerFilterRendererAction):
+ (WebCore::LayerFilterRendererAction::~LayerFilterRendererAction):
+ (WebCore::LayerFilterRendererAction::useActionOn):
+ (WebCore::LayerFilterRenderer::create):
+ (WebCore::LayerFilterRenderer::LayerFilterRenderer):
+ (WebCore::LayerFilterRenderer::bindCommonAttribLocation):
+ (WebCore::LayerFilterRenderer::initializeSharedGLObjects):
+ (WebCore::LayerFilterRenderer::ping):
+ (WebCore::LayerFilterRenderer::pong):
+ (WebCore::LayerFilterRenderer::pushSnapshot):
+ (WebCore::LayerFilterRenderer::popSnapshot):
+ (WebCore::LayerFilterRenderer::actionsForOperations):
+ (WebCore::LayerFilterRenderer::applyActions):
+ * platform/graphics/blackberry/LayerFilterRenderer.h: Added.
+ (WebCore):
+ (Uniformf):
+ (WebCore::Uniformf::location):
+ (Uniform1f):
+ (Uniform2f):
+ (Uniform3f):
+ (LayerFilterRendererAction):
+ (WebCore::LayerFilterRendererAction::shouldPushSnapshot):
+ (WebCore::LayerFilterRendererAction::setPushSnapshot):
+ (WebCore::LayerFilterRendererAction::shouldPopSnapshot):
+ (WebCore::LayerFilterRendererAction::setPopSnapshot):
+ (WebCore::LayerFilterRendererAction::appendUniform):
+ (LayerFilterRenderer):
+ (WebCore::LayerFilterRenderer::isEnabled):
+ (WebCore::LayerFilterRenderer::disable):
+ * platform/graphics/blackberry/LayerRenderer.cpp:
+ (WebCore::LayerRenderer::loadShader):
+ (WebCore::LayerRenderer::loadShaderProgram):
+ (WebCore::LayerRenderer::drawLayersOnSurfaces):
+ (WebCore::LayerRenderer::updateLayersRecursive):
+ (WebCore):
+ (WebCore::LayerRenderer::initializeSharedGLObjects):
+ * platform/graphics/blackberry/LayerRenderer.h:
+ (LayerRenderer):
+ * platform/graphics/blackberry/LayerWebKitThread.cpp:
+ (WebCore::LayerWebKitThread::LayerWebKitThread):
+ (WebCore::LayerWebKitThread::commitOnCompositingThread):
+ (WebCore):
+ (WebCore::LayerWebKitThread::filtersCanBeComposited):
+ * platform/graphics/blackberry/LayerWebKitThread.h:
+ (LayerWebKitThread):
+ (WebCore::LayerWebKitThread::setFilters):
+ * platform/graphics/filters/FECustomFilter.cpp:
+ (WebCore::FECustomFilter::platformApplySoftware):
+ (WebCore::FECustomFilter::resizeContext):
+ (WebCore::FECustomFilter::bindProgramAndBuffers):
+ * platform/graphics/filters/FilterOperation.h:
+ (WebCore):
+ (FilterOperation):
+
2012-07-31 Alexis Menard <alexis.menard@openbossa.org>
Get rid of "parser" type casts in CSSGrammar.y
diff --git a/Source/WebCore/PlatformBlackBerry.cmake b/Source/WebCore/PlatformBlackBerry.cmake
index 1ae5fe6..a816b14 100644
--- a/Source/WebCore/PlatformBlackBerry.cmake
+++ b/Source/WebCore/PlatformBlackBerry.cmake
@@ -272,6 +272,7 @@
${WEBCORE_DIR}/platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp
${WEBCORE_DIR}/platform/graphics/blackberry/LayerAnimation.cpp
${WEBCORE_DIR}/platform/graphics/blackberry/LayerCompositingThread.cpp
+ ${WEBCORE_DIR}/platform/graphics/blackberry/LayerFilterRenderer.cpp
${WEBCORE_DIR}/platform/graphics/blackberry/LayerRenderer.cpp
${WEBCORE_DIR}/platform/graphics/blackberry/LayerRendererSurface.cpp
${WEBCORE_DIR}/platform/graphics/blackberry/LayerTile.cpp
diff --git a/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp b/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp
index 1b81f54..e2779c3 100644
--- a/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp
+++ b/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp
@@ -51,6 +51,7 @@
#include "Image.h"
#include "LayerAnimation.h"
#include "LayerWebKitThread.h"
+#include "NotImplemented.h"
namespace WebCore {
@@ -292,6 +293,26 @@
updateHasFixedAncestorInDOMTree();
}
+#if ENABLE(CSS_FILTERS)
+bool GraphicsLayerBlackBerry::setFilters(const FilterOperations& filters)
+{
+ if (m_filters == filters)
+ return true;
+
+ bool canCompositeFilters = LayerWebKitThread::filtersCanBeComposited(filters);
+ if (canCompositeFilters) {
+ m_filters = filters;
+ GraphicsLayer::setFilters(filters);
+ updateFilters();
+ } else {
+ m_filters.clear();
+ notImplemented();
+ }
+
+ return canCompositeFilters;
+}
+#endif
+
void GraphicsLayerBlackBerry::setBackgroundColor(const Color& color)
{
if (m_backgroundColorSet && m_backgroundColor == color)
@@ -803,6 +824,16 @@
clearLayerBackgroundColor(*m_contentsLayer);
}
+#if ENABLE(CSS_FILTERS)
+void GraphicsLayerBlackBerry::updateFilters()
+{
+ if (!m_filters.size())
+ return;
+
+ primaryLayer()->setFilters(m_filters);
+}
+#endif
+
void GraphicsLayerBlackBerry::updateAnimations()
{
// When there is a transform layer, the transform must be set on that layer
diff --git a/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.h b/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.h
index c266947..d8d6b6a 100644
--- a/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.h
+++ b/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.h
@@ -29,13 +29,15 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "Platform.h"
+
#ifndef GraphicsLayerBlackBerry_h
#define GraphicsLayerBlackBerry_h
#if USE(ACCELERATED_COMPOSITING)
+#include "FilterOperations.h"
#include "GraphicsLayer.h"
-
#include <wtf/Vector.h>
namespace WebCore {
@@ -77,6 +79,12 @@
virtual void setHasFixedContainer(bool);
virtual void setHasFixedAncestorInDOMTree(bool);
+#if ENABLE(CSS_FILTERS)
+ // Returns true if filter can be rendered by the compositor
+ virtual bool setFilters(const FilterOperations &);
+ const FilterOperations& filters() const { return m_filters; }
+#endif
+
virtual void setBackgroundColor(const Color&);
virtual void clearBackgroundColor();
@@ -146,6 +154,9 @@
void updateHasFixedContainer();
void updateHasFixedAncestorInDOMTree();
void updateLayerBackgroundColor();
+#if ENABLE(CSS_FILTERS)
+ void updateFilters();
+#endif
void updateAnimations();
void updateContentsImage(Image*);
@@ -159,6 +170,10 @@
RefPtr<LayerWebKitThread> m_transformLayer;
RefPtr<LayerWebKitThread> m_contentsLayer;
+#if ENABLE(CSS_FILTERS)
+ FilterOperations m_filters;
+#endif
+
Vector<RefPtr<LayerAnimation> > m_runningAnimations;
Vector<RefPtr<LayerAnimation> > m_suspendedAnimations;
double m_suspendTime;
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.cpp b/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.cpp
index c750ebd..81c9180 100644
--- a/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.cpp
+++ b/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.cpp
@@ -79,6 +79,9 @@
, m_visible(false)
, m_commitScheduled(false)
, m_client(client)
+#if ENABLE(CSS_FILTERS)
+ , m_filterOperationsChanged(false)
+#endif
{
}
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.h b/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.h
index b335606..df07844 100644
--- a/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.h
+++ b/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.h
@@ -35,9 +35,11 @@
#if USE(ACCELERATED_COMPOSITING)
+#include "FilterOperations.h"
#include "FloatQuad.h"
#include "LayerAnimation.h"
#include "LayerData.h"
+#include "LayerFilterRenderer.h"
#include "LayerRendererSurface.h"
#include "LayerTiler.h"
@@ -101,6 +103,7 @@
IntSize m_bounds;
TransformationMatrix m_transform;
float m_opacity;
+
Vector<RefPtr<LayerAnimation> > m_animations;
unsigned m_positionSet : 1;
@@ -110,6 +113,8 @@
unsigned m_opacitySet : 1;
};
+class LayerFilterRendererAction;
+
class LayerCompositingThread : public ThreadSafeRefCounted<LayerCompositingThread>, public LayerData, public BlackBerry::Platform::GuardedPointerBase {
public:
static PassRefPtr<LayerCompositingThread> create(LayerType, LayerCompositingThreadClient*);
@@ -207,6 +212,14 @@
LayerOverride* override();
void clearOverride();
+#if ENABLE(CSS_FILTERS)
+ bool filterOperationsChanged() const { return m_filterOperationsChanged; }
+ void setFilterOperationsChanged(bool changed) { m_filterOperationsChanged = changed; }
+
+ Vector<RefPtr<LayerFilterRendererAction> > filterActions() const { return m_filterActions; }
+ void setFilterActions(const Vector<RefPtr<LayerFilterRendererAction> >& actions) { m_filterActions = actions; }
+#endif
+
protected:
virtual ~LayerCompositingThread();
@@ -251,6 +264,11 @@
OwnPtr<LayerOverride> m_override;
LayerCompositingThreadClient* m_client;
+
+#if ENABLE(CSS_FILTERS)
+ bool m_filterOperationsChanged;
+ Vector<RefPtr<LayerFilterRendererAction> > m_filterActions;
+#endif
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerData.h b/Source/WebCore/platform/graphics/blackberry/LayerData.h
index d991215..7ec581b 100644
--- a/Source/WebCore/platform/graphics/blackberry/LayerData.h
+++ b/Source/WebCore/platform/graphics/blackberry/LayerData.h
@@ -34,6 +34,7 @@
#define LayerData_h
#include "Color.h"
+#include "FilterOperations.h"
#include "FloatPoint.h"
#include "FloatRect.h"
#include "IntRect.h"
@@ -59,6 +60,25 @@
LayerProgramShaderBGRA,
NumberOfLayerProgramShaders };
+#if ENABLE(CSS_FILTERS)
+ enum CSSFilterShaders { CSSFilterShaderGrayscale = 0,
+ CSSFilterShaderSepia,
+ CSSFilterShaderSaturate,
+ CSSFilterShaderHueRotate,
+ CSSFilterShaderInvert,
+ CSSFilterShaderBrightness,
+ CSSFilterShaderContrast,
+ CSSFilterShaderOpacity,
+ CSSFilterShaderBlurY,
+ CSSFilterShaderBlurX,
+ CSSFilterShaderShadow,
+ CSSFilterShaderPassthrough,
+#if ENABLE(CSS_SHADERS)
+ CSSFilterShaderCustom,
+#endif
+ NumberOfCSSFilterShaders };
+#endif
+
LayerData(LayerType type)
: m_layerType(type)
, m_anchorPoint(0.5, 0.5)
@@ -115,6 +135,10 @@
float opacity() const { return m_opacity; }
+#if ENABLE(CSS_FILTERS)
+ FilterOperations filters() const { return m_filters; }
+#endif
+
bool isOpaque() const { return m_isOpaque; }
FloatPoint position() const { return m_position; }
@@ -177,6 +201,9 @@
TransformationMatrix m_sublayerTransform;
float m_opacity;
+#if ENABLE(CSS_FILTERS)
+ FilterOperations m_filters;
+#endif
float m_anchorPointZ;
float m_borderWidth;
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerFilterRenderer.cpp b/Source/WebCore/platform/graphics/blackberry/LayerFilterRenderer.cpp
new file mode 100644
index 0000000..8797c10
--- /dev/null
+++ b/Source/WebCore/platform/graphics/blackberry/LayerFilterRenderer.cpp
@@ -0,0 +1,591 @@
+/*
+ * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+
+#if USE(ACCELERATED_COMPOSITING) && ENABLE(CSS_FILTERS)
+
+#include "LayerFilterRenderer.h"
+
+#include "FilterOperation.h"
+#include "LayerCompositingThread.h"
+#include "LayerRenderer.h"
+#include "NotImplemented.h"
+#include "PlatformString.h"
+#include "TextureCacheCompositingThread.h"
+
+#include <BlackBerryPlatformGraphics.h>
+#include <BlackBerryPlatformLog.h>
+#include <Vector.h>
+
+#include <cstring>
+#include <limits>
+
+namespace WebCore {
+
+static int operationTypeToProgramID(const FilterOperation::OperationType& t)
+{
+ switch (t) {
+ case FilterOperation::GRAYSCALE:
+ return LayerData::CSSFilterShaderGrayscale;
+ case FilterOperation::SEPIA:
+ return LayerData::CSSFilterShaderSepia;
+ case FilterOperation::SATURATE:
+ return LayerData::CSSFilterShaderSaturate;
+ case FilterOperation::HUE_ROTATE:
+ return LayerData::CSSFilterShaderHueRotate;
+ case FilterOperation::INVERT:
+ return LayerData::CSSFilterShaderInvert;
+ case FilterOperation::OPACITY:
+ return LayerData::CSSFilterShaderOpacity;
+ case FilterOperation::BRIGHTNESS:
+ return LayerData::CSSFilterShaderBrightness;
+ case FilterOperation::CONTRAST:
+ return LayerData::CSSFilterShaderContrast;
+ case FilterOperation::BLUR:
+ return LayerData::CSSFilterShaderBlurY;
+ case FilterOperation::DROP_SHADOW:
+ return LayerData::CSSFilterShaderShadow;
+#if ENABLE(CSS_SHADERS)
+ case FilterOperation::CUSTOM:
+ return LayerData::CSSFilterCustom;
+#endif
+ default:
+ ASSERT_NOT_REACHED();
+ return -1;
+ }
+}
+
+Uniformf::Uniformf(int c_location)
+ : m_location(c_location)
+{
+}
+
+void Uniform1f::apply()
+{
+ glUniform1f(location(), m_val);
+}
+
+PassRefPtr<Uniformf> Uniform1f::create(int location, float val)
+{
+ return adoptRef(new Uniform1f(location, val));
+}
+
+Uniform1f::Uniform1f(int c_location, float c_val)
+ : Uniformf(c_location)
+ , m_val(c_val)
+{
+}
+
+void Uniform2f::apply()
+{
+ glUniform2f(location(), m_val[0], m_val[1]);
+}
+
+PassRefPtr<Uniformf> Uniform2f::create(int location, float val0, float val1)
+{
+ return adoptRef(new Uniform2f(location, val0, val1));
+}
+
+Uniform2f::Uniform2f(int c_location, float c_val0, float c_val1)
+ : Uniformf(c_location)
+{
+ m_val[0] = c_val0;
+ m_val[1] = c_val1;
+}
+
+void Uniform3f::apply()
+{
+ glUniform3f(location(), m_val[0], m_val[1], m_val[2]);
+}
+
+PassRefPtr<Uniformf> Uniform3f::create(int location, float val0, float val1, float val2)
+{
+ return adoptRef(new Uniform3f(location, val0, val1, val2));
+}
+
+Uniform3f::Uniform3f(int c_location, float c_val0, float c_val1, float c_val2)
+ : Uniformf(c_location)
+{
+ m_val[0] = c_val0;
+ m_val[1] = c_val1;
+ m_val[2] = c_val2;
+}
+
+PassRefPtr<LayerFilterRendererAction> LayerFilterRendererAction::create(int programId)
+{
+ return adoptRef(new LayerFilterRendererAction(programId));
+}
+
+LayerFilterRendererAction::LayerFilterRendererAction(int c_programId)
+ , m_programId(c_programId)
+ , m_pushSnapshot(false)
+ , m_popSnapshot(false)
+{
+}
+
+void LayerFilterRendererAction::useActionOn(LayerFilterRenderer* renderer)
+{
+ ASSERT(m_programId != -1);
+ if (m_programId == -1) {
+ glUseProgram(renderer->m_cssFilterProgramObject[LayerData::CSSFilterShaderPassthrough]);
+ return;
+ }
+ glUseProgram(renderer->m_cssFilterProgramObject[m_programId]);
+ for (unsigned i = 0; i < m_uniforms.size(); ++i)
+ m_uniforms[i]->apply();
+}
+
+PassOwnPtr<LayerFilterRenderer> LayerFilterRenderer::create(const int& positionLocation, const int& texCoordLocation)
+{
+ return adoptPtr(new LayerFilterRenderer(positionLocation, texCoordLocation));
+}
+
+LayerFilterRenderer::LayerFilterRenderer(const int& positionLocation, const int& texCoordLocation)
+ : m_positionLocation(positionLocation)
+ , m_texCoordLocation(texCoordLocation)
+{
+ for (int i = 0; i < LayerData::NumberOfCSSFilterShaders; ++i)
+ m_cssFilterProgramObject[i] = 0;
+
+ if (!(m_enabled = initializeSharedGLObjects()))
+ BlackBerry::Platform::logAlways(BlackBerry::Platform::LogLevelWarn, "CSS Filters are not enabled due to failed initialization.");
+}
+
+// Binds the given attribute name to a common location across all programs
+// used by the compositor. This allows the code to bind the attributes only once
+// even when switching between programs.
+//
+// This is an extension of LayerRenderer::bindCommonAttribLocation and the locations
+// will match those of LayerRenderer. See LayerFilterRenderer::LayerFilterRenderer()
+void LayerFilterRenderer::bindCommonAttribLocation(int location, const char* attribName)
+{
+ for (int i = 0; i < LayerData::NumberOfCSSFilterShaders; ++i)
+ glBindAttribLocation(m_cssFilterProgramObject[i], location, attribName);
+}
+
+bool LayerFilterRenderer::initializeSharedGLObjects()
+{
+ // See also TextureMapperShaderManager.cpp
+
+ char vertexShaderString[] =
+ "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = a_position; \n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
+
+#define STANDARD_FILTER(x...) \
+ "precision mediump float; \n"\
+ "\n"\
+ "varying mediump vec2 v_texCoord;\n"\
+ "uniform lowp sampler2D s_texture;\n"\
+ "uniform highp float u_amount;\n"\
+ #x\
+ "void main(void)\n { gl_FragColor = shade(texture2D(s_texture, v_texCoord)); }"
+
+#define OFFSET_FILTER(x...) \
+ "precision mediump float; \n"\
+ "\n"\
+ "varying mediump vec2 v_texCoord;\n"\
+ "uniform lowp sampler2D s_texture;\n"\
+ "uniform highp float u_amount;\n"\
+ "uniform mediump vec2 u_offset;\n"\
+ #x\
+ "void main(void)\n { gl_FragColor = shade(texture2D(s_texture, v_texCoord - u_offset)); }"
+
+#define BLUR_FILTER(x...) \
+ "precision highp float; \n"\
+ "\n"\
+ "varying mediump vec2 v_texCoord;\n"\
+ "uniform lowp sampler2D s_texture;\n"\
+ "uniform highp float u_amount;\n"\
+ "uniform highp float u_blurSize;\n"\
+ "const float pi = 3.1415927;\n"\
+ #x\
+ "void main(void)\n"\
+ "{\n"\
+ "vec3 incr;\n"\
+ "incr.x = 1.0 / (sqrt(2.0 * pi) * u_amount);\n"\
+ "incr.y = exp(-0.5 / (u_amount * u_amount));\n"\
+ "incr.z = incr.y * incr.y;\n"\
+ "\n"\
+ "vec4 avg = vec4(0.0, 0.0, 0.0, 0.0);\n"\
+ "float coefficientSum = 0.0;\n"\
+ "\n"\
+ "avg += texture2D(s_texture, v_texCoord.xy) * incr.x;\n"\
+ "coefficientSum += incr.x;\n"\
+ "incr.xy *= incr.yz;\n"\
+ "\n"\
+ "for (float i = 1.0; i <= numBlurPixelsPerSide; i++) {\n"\
+ " avg += texture2D(s_texture, v_texCoord.xy - i * u_blurSize * blurMultiplyVec) * incr.x;\n"\
+ " avg += texture2D(s_texture, v_texCoord.xy + i * u_blurSize * blurMultiplyVec) * incr.x;\n"\
+ " coefficientSum += 2.0 * incr.x;\n"\
+ " incr.xy *= incr.yz;\n"\
+ "}\n"\
+ "\n"\
+ "gl_FragColor = avg / coefficientSum;\n"\
+ "}"
+
+ const char* shaderStrs[LayerData::NumberOfCSSFilterShaders];
+
+ shaderStrs[LayerData::CSSFilterShaderGrayscale] = 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);
+ }
+ );
+
+ shaderStrs[LayerData::CSSFilterShaderSepia] = 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);
+ }
+ );
+
+ shaderStrs[LayerData::CSSFilterShaderSaturate] = 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);
+ }
+ );
+
+ shaderStrs[LayerData::CSSFilterShaderHueRotate] = 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);
+ }
+ );
+
+ shaderStrs[LayerData::CSSFilterShaderInvert] = 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);
+ }
+ );
+
+ shaderStrs[LayerData::CSSFilterShaderBrightness] = STANDARD_FILTER(
+ lowp vec4 shade(lowp vec4 color)
+ {
+ return vec4(color.rgb * (1.0 + u_amount), color.a);
+ }
+ );
+
+ shaderStrs[LayerData::CSSFilterShaderContrast] = 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);
+ }
+ );
+
+ shaderStrs[LayerData::CSSFilterShaderOpacity] = STANDARD_FILTER(
+ lowp vec4 shade(lowp vec4 color)
+ {
+ return vec4(color.r, color.g, color.b, color.a * u_amount);
+ }
+ );
+
+ shaderStrs[LayerData::CSSFilterShaderBlurX] = BLUR_FILTER(
+ const float numBlurPixelsPerSide = 2.0;
+ const vec2 blurMultiplyVec = vec2(1.0, 0.0);
+ );
+
+ shaderStrs[LayerData::CSSFilterShaderBlurY] = BLUR_FILTER(
+ const float numBlurPixelsPerSide = 2.0;
+ const vec2 blurMultiplyVec = vec2(0.0, 1.0);
+ );
+
+ shaderStrs[LayerData::CSSFilterShaderShadow] = OFFSET_FILTER(
+ uniform lowp vec3 u_color;
+ lowp vec4 shade(lowp vec4 color)
+ {
+ if (color.a > 0.5)
+ return vec4(u_color.r, u_color.g, u_color.b, color.a);
+ return color;
+ }
+ );
+
+ shaderStrs[LayerData::CSSFilterShaderPassthrough] = STANDARD_FILTER(
+ lowp vec4 shade(lowp vec4 color)
+ {
+ return color;
+ }
+ );
+
+ for (int i = 0; i < LayerData::NumberOfCSSFilterShaders; i++) {
+ m_cssFilterProgramObject[i] = LayerRenderer::loadShaderProgram(vertexShaderString, shaderStrs[i]);
+ if (!m_cssFilterProgramObject[i]) {
+ BlackBerry::Platform::logAlways(BlackBerry::Platform::LogLevelWarn, "Could not load CSS Filter Shader %i", i);
+ return false;
+ }
+ }
+
+ // Set ATTRIB locations - these will be the same as the programs in LayerRenderer.cpp
+ bindCommonAttribLocation(m_positionLocation, "a_position");
+ bindCommonAttribLocation(m_texCoordLocation, "a_texCoord");
+
+ // Re-link to take effect
+ for (int i = 0; i < LayerData::NumberOfCSSFilterShaders; ++i)
+ glLinkProgram(m_cssFilterProgramObject[i]);
+
+ // Get UNIFORM locations
+ for (int i = 0; i < LayerData::NumberOfCSSFilterShaders; ++i)
+ m_amountLocation[i] = glGetUniformLocation(m_cssFilterProgramObject[i], "u_amount");
+
+ m_blurAmountLocation[0] = glGetUniformLocation(m_cssFilterProgramObject[LayerData::CSSFilterShaderBlurY], "u_blurSize");
+ m_blurAmountLocation[1] = glGetUniformLocation(m_cssFilterProgramObject[LayerData::CSSFilterShaderBlurX], "u_blurSize");
+
+ m_shadowColorLocation = glGetUniformLocation(m_cssFilterProgramObject[LayerData::CSSFilterShaderShadow], "u_color");
+ m_offsetLocation = glGetUniformLocation(m_cssFilterProgramObject[LayerData::CSSFilterShaderShadow], "u_offset");
+
+ return true;
+}
+
+void LayerFilterRenderer::ping(LayerRendererSurface* surface)
+{
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture->textureId(), 0);
+ glBindTexture(GL_TEXTURE_2D, surface->texture()->textureId());
+}
+
+void LayerFilterRenderer::pong(LayerRendererSurface* surface)
+{
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, surface->texture()->textureId(), 0);
+ glBindTexture(GL_TEXTURE_2D, m_texture->textureId());
+}
+
+void LayerFilterRenderer::pushSnapshot(LayerRendererSurface* surface, int sourceId)
+{
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_snapshotTexture->textureId(), 0);
+
+ glBindTexture(GL_TEXTURE_2D, sourceId);
+ glClear(GL_COLOR_BUFFER_BIT); // to transparency
+
+ glViewport(0, 0, surface->size().width(), surface->size().height());
+
+ glUseProgram(m_cssFilterProgramObject[LayerData::CSSFilterShaderPassthrough]);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+}
+
+void LayerFilterRenderer::popSnapshot()
+{
+ // The name is slightly misleading.
+ // This DRAWS the previous texture using the current LayerFilterRendererAction, then sets the texture
+ // to the snapshot texture. Next time glDrawArrays is called, the snapshot will be drawn.
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ glBindTexture(GL_TEXTURE_2D, m_snapshotTexture->textureId());
+}
+
+Vector<RefPtr<LayerFilterRendererAction> > LayerFilterRenderer::actionsForOperations(LayerRendererSurface* surface, const Vector<RefPtr<FilterOperation> >& ops)
+{
+ Vector<RefPtr<LayerFilterRendererAction> > ret;
+ for (unsigned int i = 0; i < ops.size(); ++i) {
+ const FilterOperation& operation = *ops[i].get();
+ if (operation.getOperationType() == FilterOperation::BLUR && static_cast<const BlurFilterOperation&>(operation).stdDeviation().value() < 0.1)
+ continue;
+
+ int programId = operationTypeToProgramID(operation.getOperationType());
+ ret.append(LayerFilterRendererAction::create(programId));
+
+ switch (operation.getOperationType()) {
+ case FilterOperation::GRAYSCALE:
+ case FilterOperation::SEPIA:
+ case FilterOperation::SATURATE:
+ case FilterOperation::HUE_ROTATE:
+ ret.last()->appendUniform(Uniform1f::create(m_amountLocation[programId]
+ , static_cast<const BasicColorMatrixFilterOperation&>(operation).amount()));
+ break;
+ case FilterOperation::INVERT:
+ case FilterOperation::BRIGHTNESS:
+ case FilterOperation::CONTRAST:
+ case FilterOperation::OPACITY:
+ ret.last()->appendUniform(Uniform1f::create(m_amountLocation[programId]
+ , static_cast<const BasicComponentTransferFilterOperation&>(operation).amount()));
+ break;
+ case FilterOperation::BLUR:
+ {
+ // Blur is a two-step process:
+ // 1. blur X
+ // 2. blur Y
+ // This way we can have 2n time instead of n^2 time)
+
+ double amount = static_cast<const BlurFilterOperation&>(operation).stdDeviation().value();
+
+ // BLUR Y:
+ ret.last()->appendUniform(Uniform1f::create(m_amountLocation[LayerData::CSSFilterShaderBlurY], amount));
+ ret.last()->appendUniform(Uniform1f::create(m_blurAmountLocation[0]
+ , 1.0f / float(surface->size().height())));
+
+ // BLUR X:
+ ret.append(LayerFilterRendererAction::create(LayerData::CSSFilterShaderBlurX));
+ ret.last()->appendUniform(Uniform1f::create(m_amountLocation[LayerData::CSSFilterShaderBlurX], amount));
+ ret.last()->appendUniform(Uniform1f::create(m_blurAmountLocation[1]
+ , 1.0f / float(surface->size().width())));
+
+ }
+ break;
+ case FilterOperation::DROP_SHADOW:
+ {
+ // Shadow is a four-step process:
+ // 1. capture snapshot
+ // turn into a solid offset mask
+ // 2. blur X
+ // 3. blur Y
+ // 4. repaint original on top of mask
+ const DropShadowFilterOperation& dsfo = static_cast<const DropShadowFilterOperation&>(operation);
+ ret.last()->setPushSnapshot();
+ ret.last()->appendUniform(Uniform2f::create(m_offsetLocation
+ , float(dsfo.x()) / float(surface->size().width())
+ , float(dsfo.y()) / float(surface->size().height())));
+ ret.last()->appendUniform(Uniform3f::create(m_shadowColorLocation
+ , float(dsfo.color().red()) / 255.0f
+ , float(dsfo.color().green()) / 255.0f
+ , float(dsfo.color().blue()) / 255.0f));
+
+ // BLUR Y
+ ret.append(LayerFilterRendererAction::create(LayerData::CSSFilterShaderBlurY));
+ ret.last()->appendUniform(Uniform1f::create(m_amountLocation[LayerData::CSSFilterShaderBlurY]
+ , dsfo.stdDeviation()));
+ ret.last()->appendUniform(Uniform1f::create(m_blurAmountLocation[0]
+ , 1.0f / float(surface->size().height())));
+
+ // BLUR X
+ ret.append(LayerFilterRendererAction::create(LayerData::CSSFilterShaderBlurX));
+ ret.last()->appendUniform(Uniform1f::create(m_amountLocation[LayerData::CSSFilterShaderBlurX]
+ , dsfo.stdDeviation()));
+ ret.last()->appendUniform(Uniform1f::create(m_blurAmountLocation[1]
+ , 1.0f / float(surface->size().width())));
+
+ // Repaint original image
+ ret.append(LayerFilterRendererAction::create(LayerData::CSSFilterShaderPassthrough));
+ ret.last()->setPopSnapshot();
+ }
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ }
+
+ if (ret.size() % 2) // We need an even number of actions. See ping-pong note in applyLayerFilters().
+ ret.append(LayerFilterRendererAction::create(LayerData::CSSFilterShaderPassthrough));
+
+ return ret;
+}
+
+static float texcoords[4 * 2] = { 0, 0, 0, 1, 1, 1, 1, 0 };
+
+void LayerFilterRenderer::applyActions(unsigned& fbo, LayerCompositingThread* layer, Vector<RefPtr<LayerFilterRendererAction> > actions)
+{
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ ASSERT(!(actions.size() % 2)); // See ping-ponging note below.
+
+ if (!m_enabled)
+ return;
+
+ if (!layer->filters().size())
+ return;
+
+ if (!m_texture)
+ m_texture = textureCacheCompositingThread()->createTexture();
+
+ bool requireSnapshot = false;
+ for (unsigned i = 0; i < actions.size(); ++i) {
+ if (actions[i]->shouldPushSnapshot())
+ requireSnapshot = true;
+ }
+
+ if (!m_snapshotTexture && requireSnapshot)
+ m_snapshotTexture = textureCacheCompositingThread()->createTexture();
+
+ LayerRendererSurface* surface = layer->layerRendererSurface();
+
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, &layer->getTransformedBounds() );
+ glVertexAttribPointer(m_texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, texcoords);
+
+ m_texture->protect(surface->texture()->size());
+ if (requireSnapshot)
+ m_snapshotTexture->protect(surface->texture()->size());
+
+ if (!fbo)
+ glGenFramebuffers(1, &fbo);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+
+ for (unsigned int i = 0; i < actions.size(); ++i) {
+ // NOTE ABOUT PING-PONGING
+ // =======================
+ // Under OpenGL ES 2.0, we cannot use the fbo we are writting to as a texture, so we need to play ping-pong:
+ // 1) Draw parent surface to our texture with effect.
+ // 2) Draw our surface to parent texture with effect.
+ // 3) Repeat.
+ // Because we eventually have to end on the parent texture, we need an even number of actions.
+ // actionsForOperations takes care of that.
+
+ if (actions[i]->shouldPushSnapshot())
+ pushSnapshot(surface, (!(i % 2) ? surface->texture()->textureId() : m_texture->textureId()));
+
+ if (!(i % 2))
+ ping(surface); // Set framebuffer to ours, and texture to parent
+ else
+ pong(surface); // Set texture to parent, and framebuffer to us
+
+ glClear(GL_COLOR_BUFFER_BIT); // to transparency
+ glViewport(0, 0, surface->size().width(), surface->size().height());
+
+ actions[i]->useActionOn(this);
+
+ if (actions[i]->shouldPopSnapshot())
+ popSnapshot();
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ }
+
+ m_texture->unprotect();
+ if (requireSnapshot)
+ m_snapshotTexture->unprotect();
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING) && USE(CSS_FILTERS)
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerFilterRenderer.h b/Source/WebCore/platform/graphics/blackberry/LayerFilterRenderer.h
new file mode 100644
index 0000000..1c1f06e
--- /dev/null
+++ b/Source/WebCore/platform/graphics/blackberry/LayerFilterRenderer.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LayerFilterRenderer_h
+#define LayerFilterRenderer_h
+
+#if USE(ACCELERATED_COMPOSITING) && ENABLE(CSS_FILTERS)
+
+#include "IntRect.h"
+#include "LayerData.h"
+#include "OwnPtr.h"
+#include "Texture.h"
+#include "TransformationMatrix.h"
+
+#include <BlackBerryPlatformGLES2Context.h>
+#include <BlackBerryPlatformIntRectRegion.h>
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class LayerCompositingThread;
+class LayerFilterRenderer;
+class LayerFilterRendererAction;
+class LayerRendererSurface;
+
+class Uniformf : public RefCounted<Uniformf> {
+ WTF_MAKE_NONCOPYABLE(Uniformf);
+public:
+ virtual void apply() = 0;
+
+protected:
+ Uniformf(int location);
+ const int& location() const { return m_location; }
+
+private:
+ int m_location;
+};
+
+class Uniform1f : public Uniformf {
+public:
+ static PassRefPtr<Uniformf> create(int location, float val);
+
+protected:
+ Uniform1f(int location, float val);
+
+private:
+ virtual void apply();
+ float m_val;
+};
+
+class Uniform2f : public Uniformf {
+public:
+ static PassRefPtr<Uniformf> create(int location, float val0, float val1);
+
+protected:
+ Uniform2f(int location, float val0, float val1);
+
+private:
+ virtual void apply();
+ float m_val[2];
+};
+
+class Uniform3f : public Uniformf {
+public:
+ static PassRefPtr<Uniformf> create(int location, float val0, float val1, float val2);
+
+protected:
+ Uniform3f(int location, float val0, float val1, float val2);
+
+private:
+ virtual void apply();
+ float m_val[3];
+};
+
+class LayerFilterRendererAction : public RefCounted<LayerFilterRendererAction> {
+public:
+ static PassRefPtr<LayerFilterRendererAction> create(int programId);
+ // A vector of actions must have an even count, so if you have an odd count, add a passthrough event at the end.
+ // See the ping-pong note in LayerFilterRenderer::applyActions.
+ ~LayerFilterRendererAction();
+
+ bool shouldPushSnapshot() const { return m_pushSnapshot; }
+ void setPushSnapshot() { m_pushSnapshot = true; }
+
+ bool shouldPopSnapshot() const { return m_popSnapshot; }
+ void setPopSnapshot() { m_popSnapshot = true; }
+
+ void appendUniform(const RefPtr<Uniformf>& uniform) { m_uniforms.append(uniform); }
+ void useActionOn(LayerFilterRenderer*);
+
+protected:
+ int m_programId;
+ bool m_pushSnapshot;
+ bool m_popSnapshot;
+
+ Vector<RefPtr<Uniformf> > m_uniforms;
+private:
+ LayerFilterRendererAction(int programId);
+};
+
+class LayerFilterRenderer {
+ WTF_MAKE_NONCOPYABLE(LayerFilterRenderer);
+
+public:
+ static PassOwnPtr<LayerFilterRenderer> create(const int& positionLocation, const int& texCoordLocation);
+ void applyActions(unsigned& fbo, LayerCompositingThread*, Vector<RefPtr<LayerFilterRendererAction> >);
+ Vector<RefPtr<LayerFilterRendererAction> > actionsForOperations(LayerRendererSurface*, const Vector<RefPtr<FilterOperation> >&);
+
+ // If initialization fails, or disable() is called, this is false.
+ bool isEnabled() const { return m_enabled; }
+ void disable() { m_enabled = false; }
+
+private:
+ LayerFilterRenderer(const int& positionLocation, const int& texCoordLocation);
+ void bindCommonAttribLocation(int location, const char* attribName);
+ bool initializeSharedGLObjects();
+
+ // See note about ping-ponging in applyActions()
+ void ping(LayerRendererSurface*);
+ void pong(LayerRendererSurface*);
+
+ // This is for shadows, where we need to create a shadow, and then repaint the original image
+ // on top of the shadow.
+ void pushSnapshot(LayerRendererSurface*, int sourceId);
+ void popSnapshot();
+
+ bool m_enabled;
+
+ // ESSL attributes shared with LayerRenderer - see constructor:
+ const int m_positionLocation;
+ const int m_texCoordLocation;
+
+ // ESSL program object IDs:
+ unsigned m_cssFilterProgramObject[LayerData::NumberOfCSSFilterShaders];
+
+ // ESSL uniform locations:
+ int m_amountLocation[LayerData::NumberOfCSSFilterShaders];
+ int m_blurAmountLocation[2]; // 0 = Y, 1 = X
+ int m_shadowColorLocation;
+ int m_offsetLocation;
+
+ // Textures for playing ping-pong - see note in applyActions()
+ RefPtr<Texture> m_texture;
+ RefPtr<Texture> m_snapshotTexture;
+
+ friend class LayerFilterRendererAction;
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING) && ENABLE(CSS_FILTERS)
+
+#endif // LayerFilterRenderer_h
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerRenderer.cpp b/Source/WebCore/platform/graphics/blackberry/LayerRenderer.cpp
index 77623e5..0e42dd4 100644
--- a/Source/WebCore/platform/graphics/blackberry/LayerRenderer.cpp
+++ b/Source/WebCore/platform/graphics/blackberry/LayerRenderer.cpp
@@ -37,6 +37,7 @@
#include "LayerRenderer.h"
#include "LayerCompositingThread.h"
+#include "LayerFilterRenderer.h"
#include "PlatformString.h"
#include "TextureCacheCompositingThread.h"
@@ -64,7 +65,7 @@
#endif
}
-static GLuint loadShader(GLenum type, const char* shaderSource)
+GLuint LayerRenderer::loadShader(GLenum type, const char* shaderSource)
{
GLuint shader = glCreateShader(type);
if (!shader)
@@ -86,7 +87,7 @@
return shader;
}
-static GLuint loadShaderProgram(const char* vertexShaderSource, const char* fragmentShaderSource)
+GLuint LayerRenderer::loadShaderProgram(const char* vertexShaderSource, const char* fragmentShaderSource)
{
GLuint vertexShader;
GLuint fragmentShader;
@@ -500,6 +501,17 @@
int currentStencilValue = 0;
FloatRect clipRect(-1, -1, 2, 2);
compositeLayersRecursive(surfaceLayers[i].get(), currentStencilValue, clipRect);
+
+#if ENABLE(CSS_FILTERS)
+ if (!m_filterRenderer)
+ m_filterRenderer = LayerFilterRenderer::create(m_positionLocation, m_texCoordLocation);
+ if (layer->filterOperationsChanged()) {
+ layer->setFilterOperationsChanged(false);
+ layer->setFilterActions(m_filterRenderer->actionsForOperations(surface, layer->filters().operations()));
+ }
+ m_filterRenderer->applyActions(m_fbo, layer, layer->filterActions());
+ glClearColor(0, 0, 0, 0);
+#endif
}
// If there are layers drawed on surfaces, we need to switch to default framebuffer.
@@ -712,7 +724,11 @@
// Calculate the layer's opacity.
opacity *= layer->opacity();
+#if ENABLE(CSS_FILTERS)
+ bool useLayerRendererSurface = layer->maskLayer() || layer->replicaLayer() || layer->filters().size();
+#else
bool useLayerRendererSurface = layer->maskLayer() || layer->replicaLayer();
+#endif
if (!useLayerRendererSurface) {
layer->setDrawOpacity(opacity);
layer->clearLayerRendererSurface();
@@ -984,7 +1000,7 @@
return m_context->makeCurrent();
}
-// Binds the given attribute name to a common location across all three programs
+// Binds the given attribute name to a common location across all programs
// used by the compositor. This allows the code to bind the attributes only once
// even when switching between programs.
void LayerRenderer::bindCommonAttribLocation(int location, const char* attribName)
@@ -1053,7 +1069,6 @@
" gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha * maskColor.w; \n"
"} \n";
-
// Shaders for drawing the debug borders around the layers.
char colorVertexShaderString[] =
"attribute vec4 a_position; \n"
@@ -1139,7 +1154,7 @@
return false;
}
- // Specify the attrib location for the position and make it the same for all three programs to
+ // Specify the attrib location for the position and make it the same for all programs to
// avoid binding re-binding the vertex attributes.
bindCommonAttribLocation(m_positionLocation, "a_position");
bindCommonAttribLocation(m_texCoordLocation, "a_texCoord");
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerRenderer.h b/Source/WebCore/platform/graphics/blackberry/LayerRenderer.h
index f6c3be8..437927b 100644
--- a/Source/WebCore/platform/graphics/blackberry/LayerRenderer.h
+++ b/Source/WebCore/platform/graphics/blackberry/LayerRenderer.h
@@ -37,6 +37,7 @@
#include "IntRect.h"
#include "LayerData.h"
+#include "LayerFilterRenderer.h"
#include "TransformationMatrix.h"
#include <BlackBerryPlatformGLES2Context.h>
@@ -134,6 +135,9 @@
// If the layer has already been drawed on a surface.
bool layerAlreadyOnSurface(LayerCompositingThread*) const;
+ static GLuint loadShader(GLenum type, const char* shaderSource);
+ static GLuint loadShaderProgram(const char* vertexShaderSource, const char* fragmentShaderSource);
+
private:
void prepareFrameRecursive(LayerCompositingThread*, double animationTime, bool isContextCurrent);
void updateLayersRecursive(LayerCompositingThread*, const TransformationMatrix& parentMatrix, Vector<RefPtr<LayerCompositingThread> >& surfaceLayers, float opacity, FloatRect clipRect);
@@ -164,6 +168,10 @@
// Shader uniform and attribute locations.
const int m_positionLocation;
const int m_texCoordLocation;
+#if ENABLE(CSS_FILTERS)
+ OwnPtr<LayerFilterRenderer> m_filterRenderer;
+#endif
+
int m_samplerLocation[LayerData::NumberOfLayerProgramShaders];
int m_alphaLocation[LayerData::NumberOfLayerProgramShaders];
int m_maskSamplerLocation[LayerData::NumberOfLayerProgramShaders];
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.cpp b/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.cpp
index 15bbe0a..e9d3dff 100644
--- a/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.cpp
+++ b/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.cpp
@@ -65,6 +65,9 @@
, m_isMask(false)
, m_animationsChanged(false)
, m_clearOverrideOnCommit(false)
+#if ENABLE(CSS_FILTERS)
+ , m_filtersChanged(false)
+#endif
{
if (type == Layer)
m_tiler = LayerTiler::create(this);
@@ -284,6 +287,12 @@
m_position += m_absoluteOffset;
// Copy the base variables from this object into m_layerCompositingThread
replicate(m_layerCompositingThread.get());
+#if ENABLE(CSS_FILTERS)
+ if (m_filtersChanged) {
+ m_filtersChanged = false;
+ m_layerCompositingThread->setFilterOperationsChanged(true);
+ }
+#endif
if (m_animationsChanged) {
m_layerCompositingThread->setRunningAnimations(m_runningAnimations);
m_layerCompositingThread->setSuspendedAnimations(m_suspendedAnimations);
@@ -405,6 +414,31 @@
setNeedsDisplay();
}
+#if ENABLE(CSS_FILTERS)
+bool LayerWebKitThread::filtersCanBeComposited(const FilterOperations& filters)
+{
+ // There is work associated with compositing filters, even if there are zero filters,
+ // so if there are no filters, claim we can't composite them.
+ if (!filters.size())
+ return false;
+
+ for (unsigned i = 0; i < filters.size(); ++i) {
+ const FilterOperation* filterOperation = filters.at(i);
+ switch (filterOperation->getOperationType()) {
+ case FilterOperation::REFERENCE:
+#if ENABLE(CSS_SHADERS)
+ case FilterOperation::CUSTOM:
+#endif
+ return false;
+ default:
+ break;
+ }
+ }
+
+ return true;
+}
+#endif
+
const LayerWebKitThread* LayerWebKitThread::rootLayer() const
{
const LayerWebKitThread* layer = this;
diff --git a/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.h b/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.h
index 49a49be..e1a9254 100644
--- a/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.h
+++ b/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.h
@@ -98,6 +98,11 @@
void setOpacity(float opacity) { m_opacity = opacity; setNeedsCommit(); }
+#if ENABLE(CSS_FILTERS)
+ void setFilters(const FilterOperations& filters) { m_filters = filters; m_filtersChanged = true; setNeedsCommit(); }
+ static bool filtersCanBeComposited(const FilterOperations& filters);
+#endif
+
void setOpaque(bool isOpaque) { m_isOpaque = isOpaque; setNeedsCommit(); }
void setPosition(const FloatPoint& position) { m_position = position; setNeedsCommit(); }
@@ -202,6 +207,9 @@
unsigned m_isMask : 1;
unsigned m_animationsChanged : 1;
unsigned m_clearOverrideOnCommit : 1;
+#if ENABLE(CSS_FILTERS)
+ unsigned m_filtersChanged : 1;
+#endif
};
}
diff --git a/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp b/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp
index 36d06d3..48aba2b 100644
--- a/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp
+++ b/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp
@@ -41,6 +41,7 @@
#include "DrawingBuffer.h"
#include "GraphicsContext3D.h"
#include "ImageData.h"
+#include "NotImplemented.h"
#include "RenderTreeAsText.h"
#include "TextStream.h"
#include "Texture.h"
@@ -139,9 +140,11 @@
if (!hadContext || m_contextSize != newContextSize)
resizeContext(newContextSize);
+#if !PLATFORM(BLACKBERRY) // BlackBerry defines its own Texture class.
// Do not draw the filter if the input image cannot fit inside a single GPU texture.
if (m_inputTexture->tiles().numTilesX() != 1 || m_inputTexture->tiles().numTilesY() != 1)
return;
+#endif
// The shader had compiler errors. We cannot draw anything.
if (!m_compiledProgram->isInitialized())
@@ -185,7 +188,11 @@
void FECustomFilter::resizeContext(const IntSize& newContextSize)
{
+#if !PLATFORM(BLACKBERRY) // BlackBerry defines its own Texture class
m_inputTexture = Texture::create(m_context.get(), Texture::RGBA8, newContextSize.width(), newContextSize.height());
+#else
+ m_inputTexture = Texture::create(true);
+#endif
if (!m_frameBuffer)
m_frameBuffer = m_context->createFramebuffer();
@@ -269,8 +276,12 @@
if (m_compiledProgram->samplerLocation() != -1) {
m_context->activeTexture(GraphicsContext3D::TEXTURE0);
m_context->uniform1i(m_compiledProgram->samplerLocation(), 0);
+#if !PLATFORM(BLACKBERRY)
m_inputTexture->load(srcPixelArray->data());
m_inputTexture->bindTile(0);
+#else
+ notImplemented();
+#endif
}
if (m_compiledProgram->projectionMatrixLocation() != -1) {
diff --git a/Source/WebCore/platform/graphics/filters/FilterOperation.h b/Source/WebCore/platform/graphics/filters/FilterOperation.h
index 2a4f08a..e72600c 100644
--- a/Source/WebCore/platform/graphics/filters/FilterOperation.h
+++ b/Source/WebCore/platform/graphics/filters/FilterOperation.h
@@ -35,6 +35,10 @@
#include <wtf/RefCounted.h>
#include <wtf/text/WTFString.h>
+#if PLATFORM(BLACKBERRY)
+#include <wtf/ThreadSafeRefCounted.h>
+#endif
+
// Annoyingly, wingdi.h #defines this.
#ifdef PASSTHROUGH
#undef PASSTHROUGH
@@ -44,7 +48,11 @@
// CSS Filters
+#if PLATFORM(BLACKBERRY)
+class FilterOperation : public ThreadSafeRefCounted<FilterOperation> {
+#else
class FilterOperation : public RefCounted<FilterOperation> {
+#endif
public:
enum OperationType {
REFERENCE, // url(#somefilter)
diff --git a/Source/cmake/OptionsBlackBerry.cmake b/Source/cmake/OptionsBlackBerry.cmake
index af18cc1..197d10e 100644
--- a/Source/cmake/OptionsBlackBerry.cmake
+++ b/Source/cmake/OptionsBlackBerry.cmake
@@ -173,9 +173,15 @@
IF (ENABLE_GLES2)
WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_3D_RENDERING ON)
+ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_ACCELERATED_2D_CANVAS ON)
+ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_FILTERS ON)
+ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_SHADERS ON)
WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEBGL ON)
ELSE ()
WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_3D_RENDERING OFF)
+ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_ACCELERATED_2D_CANVAS OFF)
+ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_FILTERS OFF)
+ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_CSS_SHADERS OFF)
WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEBGL OFF)
ENDIF ()
diff --git a/Source/cmakeconfig.h.cmake b/Source/cmakeconfig.h.cmake
index e256b0e..b246291 100644
--- a/Source/cmakeconfig.h.cmake
+++ b/Source/cmakeconfig.h.cmake
@@ -25,6 +25,8 @@
#cmakedefine01 ENABLE_CSS_STICKY_POSITION
#cmakedefine01 ENABLE_CSS_VARIABLES
#cmakedefine01 ENABLE_CSS3_FLEXBOX
+#cmakedefine01 ENABLE_CSS_FILTERS
+#cmakedefine01 ENABLE_CSS_SHADERS
#cmakedefine01 ENABLE_CUSTOM_SCHEME_HANDLER
#cmakedefine01 ENABLE_DATALIST_ELEMENT
#cmakedefine01 ENABLE_DATA_TRANSFER_ITEMS
diff --git a/Tools/ChangeLog b/Tools/ChangeLog
index f177714..62a1222 100644
--- a/Tools/ChangeLog
+++ b/Tools/ChangeLog
@@ -1,3 +1,16 @@
+2012-07-31 Joshua Netterfield <jnetterfield@rim.com>
+
+ [BlackBerry] Enable CSS Filter Effects
+ https://bugs.webkit.org/show_bug.cgi?id=92685
+
+ Reviewed by Rob Buis.
+
+ Enable CSS filter effects, with the exception of custom effects (CSS shaders) and reference effects (SVG effects)
+
+ Internally reviewed by Arvid Nilsson <anilsson@rim.com> and Antonio Gomes <agomes@rim.com>.
+
+ * Scripts/webkitperl/FeatureList.pm: Acknowledge CSS filter effects.
+
2012-07-31 Dirk Pranke <dpranke@chromium.org>
nrwt: clean up prepare_lists_and_print_output, run, set_up_run a bit
diff --git a/Tools/Scripts/webkitperl/FeatureList.pm b/Tools/Scripts/webkitperl/FeatureList.pm
index 77cc1f7..344509f 100644
--- a/Tools/Scripts/webkitperl/FeatureList.pm
+++ b/Tools/Scripts/webkitperl/FeatureList.pm
@@ -163,7 +163,7 @@
define => "ENABLE_CSS_EXCLUSIONS", default => 1, value => \$cssExclusionsSupport },
{ option => "css-filters", desc => "Toggle CSS Filters support",
- define => "ENABLE_CSS_FILTERS", default => isAppleWebKit(), value => \$cssFiltersSupport },
+ define => "ENABLE_CSS_FILTERS", default => isAppleWebKit() || isBlackBerry(), value => \$cssFiltersSupport },
{ option => "css3-flexbox", desc => "Toggle CSS3 Flexbox support",
define => "ENABLE_CSS3_FLEXBOX", default => 1, value => \$css3FlexboxSupport },