summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
authorsenorblanco@chromium.org <senorblanco@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-23 04:45:45 +0000
committersenorblanco@chromium.org <senorblanco@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-23 04:45:45 +0000
commit4000abf6e302ba8ad6129b2e21e0261b197a561f (patch)
treea2e2f6131d620d29f2e8e304fe289b6921ac787d /cc
parent17b0006c5d67977ef7acb21fde2a2dc19dd4e32c (diff)
downloadchromium_src-4000abf6e302ba8ad6129b2e21e0261b197a561f.zip
chromium_src-4000abf6e302ba8ad6129b2e21e0261b197a561f.tar.gz
chromium_src-4000abf6e302ba8ad6129b2e21e0261b197a561f.tar.bz2
Implement SkImageFilter support in the compositor.
Review URL: https://chromiumcodereview.appspot.com/11175009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@163507 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r--cc/damage_tracker.cc9
-rw-r--r--cc/damage_tracker.h4
-rw-r--r--cc/damage_tracker_unittest.cc36
-rw-r--r--cc/gl_renderer.cc83
-rw-r--r--cc/layer.cc17
-rw-r--r--cc/layer.h6
-rw-r--r--cc/layer_impl.cc14
-rw-r--r--cc/layer_impl.h4
-rw-r--r--cc/layer_impl_unittest.cc4
-rw-r--r--cc/layer_tree_host_common.cc6
-rw-r--r--cc/layer_tree_host_impl.cc2
-rw-r--r--cc/occlusion_tracker.cc4
-rw-r--r--cc/render_pass.cc8
-rw-r--r--cc/render_pass.h6
-rw-r--r--cc/render_pass_unittest.cc5
-rw-r--r--cc/render_surface_impl.cc1
16 files changed, 196 insertions, 13 deletions
diff --git a/cc/damage_tracker.cc b/cc/damage_tracker.cc
index 60421c0..2528db6 100644
--- a/cc/damage_tracker.cc
+++ b/cc/damage_tracker.cc
@@ -51,7 +51,7 @@ static inline void expandDamageRectInsideRectWithFilters(FloatRect& damageRect,
damageRect.unite(expandedDamageRect);
}
-void DamageTracker::updateDamageTrackingState(const std::vector<LayerImpl*>& layerList, int targetSurfaceLayerID, bool targetSurfacePropertyChangedOnlyFromDescendant, const IntRect& targetSurfaceContentRect, LayerImpl* targetSurfaceMaskLayer, const WebKit::WebFilterOperations& filters)
+void DamageTracker::updateDamageTrackingState(const std::vector<LayerImpl*>& layerList, int targetSurfaceLayerID, bool targetSurfacePropertyChangedOnlyFromDescendant, const IntRect& targetSurfaceContentRect, LayerImpl* targetSurfaceMaskLayer, const WebKit::WebFilterOperations& filters, SkImageFilter* filter)
{
//
// This function computes the "damage rect" of a target surface, and updates the state
@@ -134,8 +134,13 @@ void DamageTracker::updateDamageTrackingState(const std::vector<LayerImpl*>& lay
damageRectForThisUpdate.uniteIfNonZero(damageFromSurfaceMask);
damageRectForThisUpdate.uniteIfNonZero(damageFromLeftoverRects);
- if (filters.hasFilterThatMovesPixels())
+ if (filters.hasFilterThatMovesPixels()) {
expandRectWithFilters(damageRectForThisUpdate, filters);
+ } else if (filter) {
+ // TODO(senorblanco): Once SkImageFilter reports its outsets, use
+ // those here to limit damage.
+ damageRectForThisUpdate = targetSurfaceContentRect;
+ }
}
// Damage accumulates until we are notified that we actually did draw on that frame.
diff --git a/cc/damage_tracker.h b/cc/damage_tracker.h
index f72c3f0..59a13401 100644
--- a/cc/damage_tracker.h
+++ b/cc/damage_tracker.h
@@ -14,6 +14,8 @@ namespace WebKit {
class WebFilterOperations;
}
+class SkImageFilter;
+
namespace cc {
class LayerImpl;
@@ -28,7 +30,7 @@ public:
void didDrawDamagedArea() { m_currentDamageRect = FloatRect(); }
void forceFullDamageNextUpdate() { m_forceFullDamageNextUpdate = true; }
- void updateDamageTrackingState(const std::vector<LayerImpl*>& layerList, int targetSurfaceLayerID, bool targetSurfacePropertyChangedOnlyFromDescendant, const IntRect& targetSurfaceContentRect, LayerImpl* targetSurfaceMaskLayer, const WebKit::WebFilterOperations&);
+ void updateDamageTrackingState(const std::vector<LayerImpl*>& layerList, int targetSurfaceLayerID, bool targetSurfacePropertyChangedOnlyFromDescendant, const IntRect& targetSurfaceContentRect, LayerImpl* targetSurfaceMaskLayer, const WebKit::WebFilterOperations&, SkImageFilter* filter);
const FloatRect& currentDamageRect() { return m_currentDamageRect; }
diff --git a/cc/damage_tracker_unittest.cc b/cc/damage_tracker_unittest.cc
index 5f1ed01..dbc0fb0 100644
--- a/cc/damage_tracker_unittest.cc
+++ b/cc/damage_tracker_unittest.cc
@@ -13,6 +13,7 @@
#include "cc/single_thread_proxy.h"
#include "cc/test/geometry_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/effects/SkBlurImageFilter.h"
#include <public/WebFilterOperation.h>
#include <public/WebFilterOperations.h>
@@ -59,7 +60,7 @@ void emulateDrawingOneFrame(LayerImpl* root)
// Iterate back-to-front, so that damage correctly propagates from descendant surfaces to ancestors.
for (int i = renderSurfaceLayerList.size() - 1; i >= 0; --i) {
RenderSurfaceImpl* targetSurface = renderSurfaceLayerList[i]->renderSurface();
- targetSurface->damageTracker()->updateDamageTrackingState(targetSurface->layerList(), targetSurface->owningLayerId(), targetSurface->surfacePropertyChangedOnlyFromDescendant(), targetSurface->contentRect(), renderSurfaceLayerList[i]->maskLayer(), renderSurfaceLayerList[i]->filters());
+ targetSurface->damageTracker()->updateDamageTrackingState(targetSurface->layerList(), targetSurface->owningLayerId(), targetSurface->surfacePropertyChangedOnlyFromDescendant(), targetSurface->contentRect(), renderSurfaceLayerList[i]->maskLayer(), renderSurfaceLayerList[i]->filters(), renderSurfaceLayerList[i]->filter());
}
root->resetAllChangeTrackingForSubtree();
@@ -392,6 +393,37 @@ TEST_F(DamageTrackerTest, verifyDamageForBlurredSurface)
EXPECT_FLOAT_RECT_EQ(expectedDamageRect, rootDamageRect);
}
+TEST_F(DamageTrackerTest, verifyDamageForImageFilter)
+{
+ scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithOneSurface();
+ LayerImpl* child = root->children()[0];
+ FloatRect rootDamageRect, childDamageRect;
+
+ // Allow us to set damage on child too.
+ child->setDrawsContent(true);
+
+ SkAutoTUnref<SkImageFilter> filter(new SkBlurImageFilter(SkIntToScalar(2),
+ SkIntToScalar(2)));
+ // Setting the filter will damage the whole surface.
+ clearDamageForAllSurfaces(root.get());
+ child->setFilter(filter);
+ emulateDrawingOneFrame(root.get());
+ rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
+ childDamageRect = child->renderSurface()->damageTracker()->currentDamageRect();
+ EXPECT_FLOAT_RECT_EQ(FloatRect(100, 100, 30, 30), rootDamageRect);
+ EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 30, 30), childDamageRect);
+
+ // CASE 1: Setting the update rect should damage the whole surface (for now)
+ clearDamageForAllSurfaces(root.get());
+ child->setUpdateRect(FloatRect(0, 0, 1, 1));
+ emulateDrawingOneFrame(root.get());
+
+ rootDamageRect = root->renderSurface()->damageTracker()->currentDamageRect();
+ childDamageRect = child->renderSurface()->damageTracker()->currentDamageRect();
+ EXPECT_FLOAT_RECT_EQ(FloatRect(100, 100, 30, 30), rootDamageRect);
+ EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 30, 30), childDamageRect);
+}
+
TEST_F(DamageTrackerTest, verifyDamageForBackgroundBlurredChild)
{
scoped_ptr<LayerImpl> root = createAndSetUpTestTreeWithTwoSurfaces();
@@ -1095,7 +1127,7 @@ TEST_F(DamageTrackerTest, verifyDamageForEmptyLayerList)
ASSERT_TRUE(root == root->renderTarget());
RenderSurfaceImpl* targetSurface = root->renderSurface();
targetSurface->clearLayerLists();
- targetSurface->damageTracker()->updateDamageTrackingState(targetSurface->layerList(), targetSurface->owningLayerId(), false, IntRect(), 0, WebFilterOperations());
+ targetSurface->damageTracker()->updateDamageTrackingState(targetSurface->layerList(), targetSurface->owningLayerId(), false, IntRect(), 0, WebFilterOperations(), 0);
FloatRect damageRect = targetSurface->damageTracker()->currentDamageRect();
EXPECT_TRUE(damageRect.isEmpty());
diff --git a/cc/gl_renderer.cc b/cc/gl_renderer.cc
index a55c800..e49acc5 100644
--- a/cc/gl_renderer.cc
+++ b/cc/gl_renderer.cc
@@ -8,7 +8,6 @@
#include "CCDamageTracker.h"
#include "FloatQuad.h"
-#include "GrTexture.h"
#include "NotImplemented.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
@@ -31,6 +30,10 @@
#include "third_party/khronos/GLES2/gl2ext.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/gpu/GrContext.h"
+#include "third_party/skia/include/gpu/GrTexture.h"
+#include "third_party/skia/include/gpu/SkGpuDevice.h"
+#include "third_party/skia/include/gpu/SkGrTexturePixelRef.h"
#include "ui/gfx/rect_conversions.h"
#include <public/WebGraphicsContext3D.h>
#include <public/WebSharedGraphicsContext3D.h>
@@ -331,13 +334,29 @@ void GLRenderer::drawDebugBorderQuad(const DrawingFrame& frame, const DebugBorde
GLC(context(), context()->drawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, 6 * sizeof(unsigned short)));
}
+static WebGraphicsContext3D* getFilterContext()
+{
+ if (Proxy::hasImplThread())
+ return WebSharedGraphicsContext3D::compositorThreadContext();
+ else
+ return WebSharedGraphicsContext3D::mainThreadContext();
+}
+
+static GrContext* getFilterGrContext()
+{
+ if (Proxy::hasImplThread())
+ return WebSharedGraphicsContext3D::compositorThreadGrContext();
+ else
+ return WebSharedGraphicsContext3D::mainThreadGrContext();
+}
+
static inline SkBitmap applyFilters(GLRenderer* renderer, const WebKit::WebFilterOperations& filters, ScopedTexture* sourceTexture)
{
if (filters.isEmpty())
return SkBitmap();
- WebGraphicsContext3D* filterContext = Proxy::hasImplThread() ? WebSharedGraphicsContext3D::compositorThreadContext() : WebSharedGraphicsContext3D::mainThreadContext();
- GrContext* filterGrContext = Proxy::hasImplThread() ? WebSharedGraphicsContext3D::compositorThreadGrContext() : WebSharedGraphicsContext3D::mainThreadGrContext();
+ WebGraphicsContext3D* filterContext = getFilterContext();
+ GrContext* filterGrContext = getFilterGrContext();
if (!filterContext || !filterGrContext)
return SkBitmap();
@@ -349,6 +368,57 @@ static inline SkBitmap applyFilters(GLRenderer* renderer, const WebKit::WebFilte
return source;
}
+static SkBitmap applyImageFilter(GLRenderer* renderer, SkImageFilter* filter, ScopedTexture* sourceTexture)
+{
+ if (!filter)
+ return SkBitmap();
+
+ WebGraphicsContext3D* context3d = getFilterContext();
+ GrContext* grContext = getFilterGrContext();
+
+ if (!context3d || !grContext)
+ return SkBitmap();
+
+ renderer->context()->flush();
+
+ ResourceProvider::ScopedWriteLockGL lock(renderer->resourceProvider(), sourceTexture->id());
+
+ // Wrap the source texture in a Ganesh platform texture.
+ GrPlatformTextureDesc platformTextureDescription;
+ platformTextureDescription.fWidth = sourceTexture->size().width();
+ platformTextureDescription.fHeight = sourceTexture->size().height();
+ platformTextureDescription.fConfig = kSkia8888_GrPixelConfig;
+ platformTextureDescription.fTextureHandle = lock.textureId();
+ SkAutoTUnref<GrTexture> texture(grContext->createPlatformTexture(platformTextureDescription));
+
+ // Place the platform texture inside an SkBitmap.
+ SkBitmap source;
+ source.setConfig(SkBitmap::kARGB_8888_Config, sourceTexture->size().width(), sourceTexture->size().height());
+ source.setPixelRef(new SkGrPixelRef(texture.get()))->unref();
+
+ // Create a scratch texture for backing store.
+ GrTextureDesc desc;
+ desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
+ desc.fSampleCnt = 0;
+ desc.fWidth = source.width();
+ desc.fHeight = source.height();
+ desc.fConfig = kSkia8888_GrPixelConfig;
+ GrAutoScratchTexture scratchTexture(grContext, desc, GrContext::kExact_ScratchTexMatch);
+
+ // Create a device and canvas using that backing store.
+ SkGpuDevice device(grContext, scratchTexture.detach());
+ SkCanvas canvas(&device);
+
+ // Draw the source bitmap through the filter to the canvas.
+ SkPaint paint;
+ paint.setImageFilter(filter);
+ canvas.clear(0x0);
+ canvas.drawSprite(source, 0, 0, &paint);
+ canvas.flush();
+ context3d->flush();
+ return device.accessBitmap(false);
+}
+
scoped_ptr<ScopedTexture> GLRenderer::drawBackgroundFilters(DrawingFrame& frame, const RenderPassDrawQuad* quad, const WebKit::WebFilterOperations& filters, const WebTransformationMatrix& contentsDeviceTransform)
{
// This method draws a background filter, which applies a filter to any pixels behind the quad and seen through its background.
@@ -442,7 +512,12 @@ void GLRenderer::drawRenderPassQuad(DrawingFrame& frame, const RenderPassDrawQua
// FIXME: Cache this value so that we don't have to do it for both the surface and its replica.
// Apply filters to the contents texture.
- SkBitmap filterBitmap = applyFilters(this, renderPass->filters(), contentsTexture);
+ SkBitmap filterBitmap;
+ if (renderPass->filter()) {
+ filterBitmap = applyImageFilter(this, renderPass->filter(), contentsTexture);
+ } else {
+ filterBitmap = applyFilters(this, renderPass->filters(), contentsTexture);
+ }
scoped_ptr<ResourceProvider::ScopedReadLockGL> contentsResourceLock;
unsigned contentsTextureId = 0;
if (filterBitmap.getTexture()) {
diff --git a/cc/layer.cc b/cc/layer.cc
index e522fe5..975a2c1 100644
--- a/cc/layer.cc
+++ b/cc/layer.cc
@@ -12,6 +12,7 @@
#include "cc/layer_impl.h"
#include "cc/layer_tree_host.h"
#include "cc/settings.h"
+#include "third_party/skia/include/core/SkImageFilter.h"
#include <public/WebAnimationDelegate.h>
#include <public/WebLayerScrollClient.h>
#include <public/WebSize.h>
@@ -44,6 +45,7 @@ Layer::Layer()
, m_debugBorderColor(0)
, m_debugBorderWidth(0)
, m_opacity(1.0)
+ , m_filter(0)
, m_anchorPointZ(0)
, m_isContainerForFixedPositionLayers(false)
, m_fixedToContainerLayer(false)
@@ -81,6 +83,8 @@ Layer::~Layer()
// Remove the parent reference from all children.
removeAllChildren();
+
+ SkSafeUnref(m_filter);
}
void Layer::setUseLCDText(bool useLCDText)
@@ -315,6 +319,7 @@ void Layer::setReplicaLayer(Layer* layer)
void Layer::setFilters(const WebKit::WebFilterOperations& filters)
{
+ DCHECK(!m_filter);
if (m_filters == filters)
return;
m_filters = filters;
@@ -323,6 +328,17 @@ void Layer::setFilters(const WebKit::WebFilterOperations& filters)
LayerTreeHost::setNeedsFilterContext(true);
}
+void Layer::setFilter(SkImageFilter* filter)
+{
+ DCHECK(m_filters.isEmpty());
+ if (m_filter == filter)
+ return;
+ SkRefCnt_SafeAssign(m_filter, filter);
+ setNeedsCommit();
+ if (filter)
+ LayerTreeHost::setNeedsFilterContext(true);
+}
+
void Layer::setBackgroundFilters(const WebKit::WebFilterOperations& backgroundFilters)
{
if (m_backgroundFilters == backgroundFilters)
@@ -544,6 +560,7 @@ void Layer::pushPropertiesTo(LayerImpl* layer)
layer->setForceRenderSurface(m_forceRenderSurface);
layer->setDrawsContent(drawsContent());
layer->setFilters(filters());
+ layer->setFilter(filter());
layer->setBackgroundFilters(backgroundFilters());
layer->setUseLCDText(m_useLCDText);
layer->setMasksToBounds(m_masksToBounds);
diff --git a/cc/layer.h b/cc/layer.h
index 03df556..a298825 100644
--- a/cc/layer.h
+++ b/cc/layer.h
@@ -22,6 +22,8 @@ class WebAnimationDelegate;
class WebLayerScrollClient;
}
+class SkImageFilter;
+
namespace cc {
class ActiveAnimation;
@@ -95,6 +97,9 @@ public:
void setFilters(const WebKit::WebFilterOperations&);
const WebKit::WebFilterOperations& filters() const { return m_filters; }
+ void setFilter(SkImageFilter* filter);
+ SkImageFilter* filter() const { return m_filter; }
+
// Background filters are filters applied to what is behind this layer, when they are viewed through non-opaque
// regions in this layer. They are used through the WebLayer interface, and are not exposed to HTML.
void setBackgroundFilters(const WebKit::WebFilterOperations&);
@@ -335,6 +340,7 @@ private:
float m_debugBorderWidth;
std::string m_debugName;
float m_opacity;
+ SkImageFilter* m_filter;
WebKit::WebFilterOperations m_filters;
WebKit::WebFilterOperations m_backgroundFilters;
float m_anchorPointZ;
diff --git a/cc/layer_impl.cc b/cc/layer_impl.cc
index 2b6f462..1297409 100644
--- a/cc/layer_impl.cc
+++ b/cc/layer_impl.cc
@@ -15,6 +15,7 @@
#include "cc/quad_sink.h"
#include "cc/scrollbar_animation_controller.h"
#include "cc/settings.h"
+#include "third_party/skia/include/core/SkImageFilter.h"
using WebKit::WebTransformationMatrix;
@@ -52,6 +53,7 @@ LayerImpl::LayerImpl(int id)
, m_drawOpacityIsAnimating(false)
, m_debugBorderColor(0)
, m_debugBorderWidth(0)
+ , m_filter(0)
, m_drawTransformIsAnimating(false)
, m_screenSpaceTransformIsAnimating(false)
#ifndef NDEBUG
@@ -69,6 +71,7 @@ LayerImpl::~LayerImpl()
#ifndef NDEBUG
DCHECK(!m_betweenWillDrawAndDidDraw);
#endif
+ SkSafeUnref(m_filter);
}
void LayerImpl::addChild(scoped_ptr<LayerImpl> child)
@@ -473,6 +476,7 @@ void LayerImpl::setBackgroundColor(SkColor backgroundColor)
void LayerImpl::setFilters(const WebKit::WebFilterOperations& filters)
{
+ DCHECK(!m_filter);
if (m_filters == filters)
return;
@@ -489,6 +493,16 @@ void LayerImpl::setBackgroundFilters(const WebKit::WebFilterOperations& backgrou
m_layerPropertyChanged = true;
}
+void LayerImpl::setFilter(SkImageFilter* filter)
+{
+ DCHECK(m_filters.isEmpty());
+ if (m_filter == filter)
+ return;
+
+ SkRefCnt_SafeAssign(m_filter, filter);
+ noteLayerPropertyChangedForSubtree();
+}
+
void LayerImpl::setMasksToBounds(bool masksToBounds)
{
if (m_masksToBounds == masksToBounds)
diff --git a/cc/layer_impl.h b/cc/layer_impl.h
index e9d8e87..05f3b44 100644
--- a/cc/layer_impl.h
+++ b/cc/layer_impl.h
@@ -110,6 +110,9 @@ public:
void setBackgroundFilters(const WebKit::WebFilterOperations&);
const WebKit::WebFilterOperations& backgroundFilters() const { return m_backgroundFilters; }
+ void setFilter(SkImageFilter*);
+ SkImageFilter* filter() const { return m_filter; }
+
void setMasksToBounds(bool);
bool masksToBounds() const { return m_masksToBounds; }
@@ -362,6 +365,7 @@ private:
WebKit::WebFilterOperations m_filters;
WebKit::WebFilterOperations m_backgroundFilters;
+ SkImageFilter* m_filter;
WebKit::WebTransformationMatrix m_drawTransform;
WebKit::WebTransformationMatrix m_screenSpaceTransform;
diff --git a/cc/layer_impl_unittest.cc b/cc/layer_impl_unittest.cc
index 2e3ccec..def19a9 100644
--- a/cc/layer_impl_unittest.cc
+++ b/cc/layer_impl_unittest.cc
@@ -9,6 +9,7 @@
#include "cc/single_thread_proxy.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/effects/SkBlurImageFilter.h"
#include <public/WebFilterOperation.h>
#include <public/WebFilterOperations.h>
@@ -82,6 +83,7 @@ TEST(LayerImplTest, verifyLayerChangesAreTrackedProperly)
arbitraryTransform.scale3d(0.1, 0.2, 0.3);
WebFilterOperations arbitraryFilters;
arbitraryFilters.append(WebFilterOperation::createOpacityFilter(0.5));
+ SkAutoTUnref<SkImageFilter> arbitraryFilter(new SkBlurImageFilter(SK_Scalar1, SK_Scalar1));
// These properties are internal, and should not be considered "change" when they are used.
EXECUTE_AND_VERIFY_SUBTREE_DID_NOT_CHANGE(root->setUseLCDText(true));
@@ -98,6 +100,8 @@ TEST(LayerImplTest, verifyLayerChangesAreTrackedProperly)
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->setAnchorPoint(arbitraryFloatPoint));
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->setAnchorPointZ(arbitraryNumber));
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->setFilters(arbitraryFilters));
+ EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->setFilters(WebFilterOperations()));
+ EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->setFilter(arbitraryFilter));
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->setMaskLayer(LayerImpl::create(4)));
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->setMasksToBounds(true));
EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->setContentsOpaque(true));
diff --git a/cc/layer_tree_host_common.cc b/cc/layer_tree_host_common.cc
index e9b5148..6975c9f 100644
--- a/cc/layer_tree_host_common.cc
+++ b/cc/layer_tree_host_common.cc
@@ -242,7 +242,7 @@ static bool subtreeShouldRenderToSeparateSurface(LayerType* layer, bool axisAlig
return true;
// If the layer uses a CSS filter.
- if (!layer->filters().isEmpty() || !layer->backgroundFilters().isEmpty())
+ if (!layer->filters().isEmpty() || !layer->backgroundFilters().isEmpty() || layer->filter())
return true;
// If the layer flattens its subtree (i.e. the layer doesn't preserve-3d), but it is
@@ -576,7 +576,9 @@ static void calculateDrawTransformsInternal(LayerType* layer, LayerType* rootLay
layer->replicaLayer()->maskLayer()->setVisibleContentRect(IntRect(IntPoint(), layer->contentBounds()));
}
- if (layer->filters().hasFilterThatMovesPixels())
+ // FIXME: make this smarter for the SkImageFilter case (check for
+ // pixel-moving filters)
+ if (layer->filters().hasFilterThatMovesPixels() || layer->filter())
nearestAncestorThatMovesPixels = renderSurface;
// The render surface clipRect is expressed in the space where this surface draws, i.e. the same space as clipRectFromAncestor.
diff --git a/cc/layer_tree_host_impl.cc b/cc/layer_tree_host_impl.cc
index d566ebc..a87302e 100644
--- a/cc/layer_tree_host_impl.cc
+++ b/cc/layer_tree_host_impl.cc
@@ -338,7 +338,7 @@ void LayerTreeHostImpl::trackDamageForAllSurfaces(LayerImpl* rootDrawLayer, cons
LayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex];
RenderSurfaceImpl* renderSurface = renderSurfaceLayer->renderSurface();
DCHECK(renderSurface);
- renderSurface->damageTracker()->updateDamageTrackingState(renderSurface->layerList(), renderSurfaceLayer->id(), renderSurface->surfacePropertyChangedOnlyFromDescendant(), renderSurface->contentRect(), renderSurfaceLayer->maskLayer(), renderSurfaceLayer->filters());
+ renderSurface->damageTracker()->updateDamageTrackingState(renderSurface->layerList(), renderSurfaceLayer->id(), renderSurface->surfacePropertyChangedOnlyFromDescendant(), renderSurface->contentRect(), renderSurfaceLayer->maskLayer(), renderSurfaceLayer->filters(), renderSurfaceLayer->filter());
}
}
diff --git a/cc/occlusion_tracker.cc b/cc/occlusion_tracker.cc
index 6024f0c..d357505 100644
--- a/cc/occlusion_tracker.cc
+++ b/cc/occlusion_tracker.cc
@@ -101,7 +101,9 @@ void OcclusionTrackerBase<LayerType, RenderSurfaceType>::finishedRenderTarget(co
RenderSurfaceType* surface = finishedTarget->renderSurface();
// If the occlusion within the surface can not be applied to things outside of the surface's subtree, then clear the occlusion here so it won't be used.
- if (finishedTarget->maskLayer() || !surfaceOpacityKnown(surface) || surface->drawOpacity() < 1 || finishedTarget->filters().hasFilterThatAffectsOpacity()) {
+ // TODO(senorblanco): Make this smarter for SkImageFilter case: once
+ // SkImageFilters can report affectsOpacity(), call that.
+ if (finishedTarget->maskLayer() || !surfaceOpacityKnown(surface) || surface->drawOpacity() < 1 || finishedTarget->filters().hasFilterThatAffectsOpacity() || finishedTarget->filter()) {
m_stack.last().occlusionInScreen = Region();
m_stack.last().occlusionInTarget = Region();
} else {
diff --git a/cc/render_pass.cc b/cc/render_pass.cc
index 384c2a8..57f9829 100644
--- a/cc/render_pass.cc
+++ b/cc/render_pass.cc
@@ -12,6 +12,7 @@
#include "cc/quad_culler.h"
#include "cc/shared_quad_state.h"
#include "cc/solid_color_draw_quad.h"
+#include "third_party/skia/include/core/SkImageFilter.h"
using WebKit::WebTransformationMatrix;
@@ -28,6 +29,7 @@ RenderPass::RenderPass(Id id, gfx::Rect outputRect, const WebKit::WebTransformat
, m_outputRect(outputRect)
, m_hasTransparentBackground(true)
, m_hasOcclusionFromOutsideTargetSurface(false)
+ , m_filter(0)
{
DCHECK(id.layerId > 0);
DCHECK(id.index >= 0);
@@ -35,6 +37,7 @@ RenderPass::RenderPass(Id id, gfx::Rect outputRect, const WebKit::WebTransformat
RenderPass::~RenderPass()
{
+ SkSafeUnref(m_filter);
}
scoped_ptr<RenderPass> RenderPass::copy(Id newId) const
@@ -47,6 +50,7 @@ scoped_ptr<RenderPass> RenderPass::copy(Id newId) const
copyPass->setHasOcclusionFromOutsideTargetSurface(m_hasOcclusionFromOutsideTargetSurface);
copyPass->setFilters(m_filters);
copyPass->setBackgroundFilters(m_backgroundFilters);
+ copyPass->setFilter(m_filter);
return copyPass.Pass();
}
@@ -103,4 +107,8 @@ void RenderPass::appendQuadsToFillScreen(LayerImpl* rootLayer, SkColor screenBac
}
}
+void RenderPass::setFilter(SkImageFilter* filter) {
+ SkRefCnt_SafeAssign(m_filter, filter);
+}
+
} // namespace cc
diff --git a/cc/render_pass.h b/cc/render_pass.h
index ce0005e..076cfe4 100644
--- a/cc/render_pass.h
+++ b/cc/render_pass.h
@@ -18,6 +18,8 @@
#include <public/WebTransformationMatrix.h>
#include <vector>
+class SkImageFilter;
+
namespace cc {
class LayerImpl;
@@ -91,6 +93,9 @@ public:
const WebKit::WebFilterOperations& backgroundFilters() const { return m_backgroundFilters; }
void setBackgroundFilters(const WebKit::WebFilterOperations& filters) { m_backgroundFilters = filters; }
+ SkImageFilter* filter() const { return m_filter; }
+ void setFilter(SkImageFilter* filter);
+
bool hasTransparentBackground() const { return m_hasTransparentBackground; }
void setHasTransparentBackground(bool transparent) { m_hasTransparentBackground = transparent; }
@@ -109,6 +114,7 @@ protected:
bool m_hasOcclusionFromOutsideTargetSurface;
WebKit::WebFilterOperations m_filters;
WebKit::WebFilterOperations m_backgroundFilters;
+ SkImageFilter* m_filter;
DISALLOW_COPY_AND_ASSIGN(RenderPass);
};
diff --git a/cc/render_pass_unittest.cc b/cc/render_pass_unittest.cc
index 5764e1a..42e6c2e 100644
--- a/cc/render_pass_unittest.cc
+++ b/cc/render_pass_unittest.cc
@@ -9,6 +9,7 @@
#include "CCCheckerboardDrawQuad.h"
#include "cc/test/geometry_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/effects/SkBlurImageFilter.h"
#include <public/WebFilterOperations.h>
#include <public/WebTransformationMatrix.h>
@@ -38,6 +39,7 @@ struct RenderPassSize {
bool m_hasOcclusionFromOutsideTargetSurface;
WebKit::WebFilterOperations m_filters;
WebKit::WebFilterOperations m_backgroundFilters;
+ SkImageFilter* m_filter;
};
TEST(RenderPassTest, copyShouldBeIdenticalExceptIdAndQuads)
@@ -56,12 +58,14 @@ TEST(RenderPassTest, copyShouldBeIdenticalExceptIdAndQuads)
filters.append(WebFilterOperation::createGrayscaleFilter(0.2f));
backgroundFilters.append(WebFilterOperation::createInvertFilter(0.2f));
+ SkAutoTUnref<SkBlurImageFilter> filter(new SkBlurImageFilter(SK_Scalar1, SK_Scalar1));
pass->setDamageRect(damageRect);
pass->setHasTransparentBackground(hasTransparentBackground);
pass->setHasOcclusionFromOutsideTargetSurface(hasOcclusionFromOutsideTargetSurface);
pass->setFilters(filters);
pass->setBackgroundFilters(backgroundFilters);
+ pass->setFilter(filter);
// Stick a quad in the pass, this should not get copied.
TestRenderPass* testPass = static_cast<TestRenderPass*>(pass.get());
@@ -79,6 +83,7 @@ TEST(RenderPassTest, copyShouldBeIdenticalExceptIdAndQuads)
EXPECT_EQ(pass->hasOcclusionFromOutsideTargetSurface(), copy->hasOcclusionFromOutsideTargetSurface());
EXPECT_EQ(pass->filters(), copy->filters());
EXPECT_EQ(pass->backgroundFilters(), copy->backgroundFilters());
+ EXPECT_EQ(pass->filter(), copy->filter());
EXPECT_EQ(0u, copy->quadList().size());
EXPECT_EQ(sizeof(RenderPassSize), sizeof(RenderPass));
diff --git a/cc/render_surface_impl.cc b/cc/render_surface_impl.cc
index 59c443b..a455a98 100644
--- a/cc/render_surface_impl.cc
+++ b/cc/render_surface_impl.cc
@@ -193,6 +193,7 @@ void RenderSurfaceImpl::appendRenderPasses(RenderPassSink& passSink)
scoped_ptr<RenderPass> pass = RenderPass::create(renderPassId(), m_contentRect, m_screenSpaceTransform);
pass->setDamageRect(m_damageTracker->currentDamageRect());
pass->setFilters(m_owningLayer->filters());
+ pass->setFilter(m_owningLayer->filter());
pass->setBackgroundFilters(m_owningLayer->backgroundFilters());
passSink.appendRenderPass(pass.Pass());
}