diff options
author | senorblanco@chromium.org <senorblanco@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-23 04:45:45 +0000 |
---|---|---|
committer | senorblanco@chromium.org <senorblanco@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-23 04:45:45 +0000 |
commit | 4000abf6e302ba8ad6129b2e21e0261b197a561f (patch) | |
tree | a2e2f6131d620d29f2e8e304fe289b6921ac787d /cc | |
parent | 17b0006c5d67977ef7acb21fde2a2dc19dd4e32c (diff) | |
download | chromium_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.cc | 9 | ||||
-rw-r--r-- | cc/damage_tracker.h | 4 | ||||
-rw-r--r-- | cc/damage_tracker_unittest.cc | 36 | ||||
-rw-r--r-- | cc/gl_renderer.cc | 83 | ||||
-rw-r--r-- | cc/layer.cc | 17 | ||||
-rw-r--r-- | cc/layer.h | 6 | ||||
-rw-r--r-- | cc/layer_impl.cc | 14 | ||||
-rw-r--r-- | cc/layer_impl.h | 4 | ||||
-rw-r--r-- | cc/layer_impl_unittest.cc | 4 | ||||
-rw-r--r-- | cc/layer_tree_host_common.cc | 6 | ||||
-rw-r--r-- | cc/layer_tree_host_impl.cc | 2 | ||||
-rw-r--r-- | cc/occlusion_tracker.cc | 4 | ||||
-rw-r--r-- | cc/render_pass.cc | 8 | ||||
-rw-r--r-- | cc/render_pass.h | 6 | ||||
-rw-r--r-- | cc/render_pass_unittest.cc | 5 | ||||
-rw-r--r-- | cc/render_surface_impl.cc | 1 |
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); @@ -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()); } |