https://bugs.webkit.org/show_bug.cgi?id=77498
Patch by Dana Jansens <danakj@chromium.org> on 2012-02-16
Reviewed by James Robinson.
Source/WebCore:
The new CSS filter support within the compositor changes how
occlusion tracking needs to function. A filter can change the
alpha value of pixels, making an otherwise opaque pixel no
longer so. Secondly, a filter may move color values around
on a surface, which can cause otherwise occluded areas to
become visible and require painting.
New unit tests: CCLayerTreeHostTest.cpp
Tests: compositing/culling/filter-occlusion-alpha-large.html
compositing/culling/filter-occlusion-alpha.html
compositing/culling/filter-occlusion-blur-large.html
compositing/culling/filter-occlusion-blur.html
* platform/graphics/chromium/RenderSurfaceChromium.cpp:
(WebCore::RenderSurfaceChromium::RenderSurfaceChromium):
* platform/graphics/chromium/RenderSurfaceChromium.h:
(WebCore::RenderSurfaceChromium::setFilters):
(WebCore::RenderSurfaceChromium::filters):
(WebCore::RenderSurfaceChromium::setNearestAncestorThatMovesPixels):
(WebCore::RenderSurfaceChromium::nearestAncestorThatMovesPixels):
(RenderSurfaceChromium):
* platform/graphics/chromium/cc/CCLayerTreeHost.cpp:
(WebCore::enterTargetRenderSurface):
(WebCore::CCLayerTreeHost::paintLayerContents):
* platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp:
(WebCore::subtreeShouldRenderToSeparateSurface):
(WebCore::calculateDrawTransformsAndVisibilityInternal):
(WebCore::CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility):
* platform/graphics/chromium/cc/CCRenderSurface.cpp:
(WebCore::CCRenderSurface::CCRenderSurface):
* platform/graphics/chromium/cc/CCRenderSurface.h:
(WebCore::CCRenderSurface::setNearestAncestorThatMovesPixels):
(WebCore::CCRenderSurface::nearestAncestorThatMovesPixels):
(CCRenderSurface):
* platform/graphics/filters/FilterOperation.h:
(FilterOperation):
(WebCore::FilterOperation::affectsOpacity):
(WebCore::FilterOperation::movesPixels):
(WebCore::ReferenceFilterOperation::affectsOpacity):
(WebCore::ReferenceFilterOperation::movesPixels):
(ReferenceFilterOperation):
(WebCore::BasicComponentTransferFilterOperation::affectsOpacity):
(BasicComponentTransferFilterOperation):
(WebCore::BlurFilterOperation::affectsOpacity):
(WebCore::BlurFilterOperation::movesPixels):
(BlurFilterOperation):
(WebCore::DropShadowFilterOperation::affectsOpacity):
(DropShadowFilterOperation):
* platform/graphics/filters/FilterOperations.cpp:
(WebCore::FilterOperations::hasFilterThatAffectsOpacity):
(WebCore):
(WebCore::FilterOperations::hasFilterThatMovesPixels):
* platform/graphics/filters/FilterOperations.h:
(WebCore::FilterOperations::isEmpty):
(FilterOperations):
Source/WebKit/chromium:
* tests/CCLayerTreeHostTest.cpp:
(CCLayerTreeHostTestLayerOcclusionWithFilters):
(WTF::CCLayerTreeHostTestLayerOcclusionWithFilters::CCLayerTreeHostTestLayerOcclusionWithFilters):
(WTF::CCLayerTreeHostTestLayerOcclusionWithFilters::beginTest):
(WTF::CCLayerTreeHostTestLayerOcclusionWithFilters::afterTest):
(WTF):
LayoutTests:
* compositing/culling/filter-occlusion-alpha-expected.png: Added.
* compositing/culling/filter-occlusion-alpha-expected.txt: Added.
* compositing/culling/filter-occlusion-alpha-large-expected.png: Added.
* compositing/culling/filter-occlusion-alpha-large-expected.txt: Added.
* compositing/culling/filter-occlusion-alpha-large.html: Added.
* compositing/culling/filter-occlusion-alpha.html: Added.
* compositing/culling/filter-occlusion-blur-expected.txt: Added.
* compositing/culling/filter-occlusion-blur-large-expected.txt: Added.
* compositing/culling/filter-occlusion-blur-large.html: Added.
* compositing/culling/filter-occlusion-blur.html: Added.
* platform/chromium/compositing/culling/filter-occlusion-blur-expected.png: Added.
* platform/chromium/compositing/culling/filter-occlusion-blur-large-expected.png: Added.
* platform/chromium/test_expectations.txt:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@108013
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2012-02-16 Dana Jansens <danakj@chromium.org>
+
+ [Chromium] Occlusion tracking with CSS filters
+ https://bugs.webkit.org/show_bug.cgi?id=77498
+
+ Reviewed by James Robinson.
+
+ * compositing/culling/filter-occlusion-alpha-expected.png: Added.
+ * compositing/culling/filter-occlusion-alpha-expected.txt: Added.
+ * compositing/culling/filter-occlusion-alpha-large-expected.png: Added.
+ * compositing/culling/filter-occlusion-alpha-large-expected.txt: Added.
+ * compositing/culling/filter-occlusion-alpha-large.html: Added.
+ * compositing/culling/filter-occlusion-alpha.html: Added.
+ * compositing/culling/filter-occlusion-blur-expected.txt: Added.
+ * compositing/culling/filter-occlusion-blur-large-expected.txt: Added.
+ * compositing/culling/filter-occlusion-blur-large.html: Added.
+ * compositing/culling/filter-occlusion-blur.html: Added.
+ * platform/chromium/compositing/culling/filter-occlusion-blur-expected.png: Added.
+ * platform/chromium/compositing/culling/filter-occlusion-blur-large-expected.png: Added.
+ * platform/chromium/test_expectations.txt:
+
2012-02-16 Noel Gordon <noel.gordon@gmail.com>
[chromium] Rebaseline JPEG image results after r107389
--- /dev/null
+<!DOCTYPE html>
+<html><head>
+<title>CSS filter blur occlusion test.</title>
+<style type="text/css">
+ .composited {
+ -webkit-transform: translateZ(0);
+ }
+ .green-parent {
+ width: 800px;
+ height: 800px;
+ }
+ .centered {
+ width: 400px;
+ height: 400px;
+ position: absolute;
+ left: 200px;
+ top: 200px;
+ }
+ .alpha {
+ -webkit-filter: opacity(0%);
+ }
+</style>
+<script type="text/javascript">
+ if (window.layoutTestController) {
+ layoutTestController.dumpAsText(true);
+ }
+</script>
+</head>
+<body>
+<!--
+ This test guards against culling behind filters that change opacity. The red box is given
+ an opacity of 0% with a CSS filter, so only the green box behind it should be visible.
+ This version of the test causes part of the boxes to be out of view, testing the interaction
+ between their visible region with culling.
+ -->
+<div class="green-parent composted" style="position:absolute; left:0; top:0">
+ <div class="centered composited" style="background-color: green;">
+ </div>
+</div>
+<div class="composited centered alpha" style="background-color: red;">
+</div>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html><head>
+<title>CSS filter blur occlusion test.</title>
+<style type="text/css">
+ .composited {
+ -webkit-transform: translateZ(0);
+ }
+ .green-parent {
+ width: 600px;
+ height: 600px;
+ }
+ .centered {
+ width: 200px;
+ height: 200px;
+ position: absolute;
+ left: 100px;
+ top: 100px;
+ }
+ .alpha {
+ -webkit-filter: opacity(0%);
+ }
+</style>
+<script type="text/javascript">
+ if (window.layoutTestController) {
+ layoutTestController.dumpAsText(true);
+ }
+</script>
+</head>
+<body>
+<!--
+ This test guards against culling behind filters that change opacity. The red box is given
+ an opacity of 0% with a CSS filter, so only the green box behind it should be visible.
+ -->
+<div class="green-parent composted" style="position:absolute; left:0; top:0">
+ <div class="centered composited" style="background-color: green;">
+ </div>
+</div>
+<div class="composited centered alpha" style="background-color: red;">
+</div>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html><head>
+<title>CSS filter blur occlusion test.</title>
+<style type="text/css">
+ .composited {
+ -webkit-transform: translateZ(0);
+ }
+ .yellow-parent {
+ width: 800px;
+ height: 800px;
+ -webkit-filter: blur(10px);
+ }
+ .centered {
+ width: 400px;
+ height: 400px;
+ position: absolute;
+ left: 200px;
+ top: 200px;
+ }
+</style>
+<script type="text/javascript">
+ if (window.layoutTestController) {
+ layoutTestController.dumpAsText(true);
+ }
+</script>
+</head>
+<body>
+<!--
+ This test guards against over-culling of the "hidden" yellow box. Since the yellow box is blurred,
+ it becomes visible around the outside of the green box. This test causes part of the green and
+ yellow boxes to be out of view, testing the interaction of their visible region with the culling.
+ -->
+<div class="yellow-parent composted" style="position:absolute; left:0; top:0">
+ <div class="centered composited" style="background-color: yellow;">
+ </div>
+</div>
+<div class="composited centered" style="background-color: green;">
+</div>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html><head>
+<title>CSS filter blur occlusion test.</title>
+<style type="text/css">
+ .composited {
+ -webkit-transform: translateZ(0);
+ }
+ .yellow-parent {
+ width: 600px;
+ height: 600px;
+ -webkit-filter: blur(10px);
+ }
+ .centered {
+ width: 200px;
+ height: 200px;
+ position: absolute;
+ left: 100px;
+ top: 100px;
+ }
+</style>
+<script type="text/javascript">
+ if (window.layoutTestController) {
+ layoutTestController.dumpAsText(true);
+ }
+</script>
+</head>
+<body>
+<!--
+ This test guards against over-culling of the "hidden" yellow box. Since the yellow box is blurred,
+ it becomes visible around the outside of the green box.
+ -->
+<div class="yellow-parent composted" style="position:absolute; left:0; top:0">
+ <div class="centered composited" style="background-color: yellow;">
+ </div>
+</div>
+<div class="composited centered" style="background-color: green;">
+</div>
+</body>
+</html>
BUGWK78219 : svg/dynamic-updates/SVGUseElement-dom-requiredFeatures.html = IMAGE
BUGWK78219 : svg/dynamic-updates/SVGUseElement-svgdom-requiredFeatures.html = IMAGE
+// May need platform specific baselines
+BUGWK77498 : compositing/culling/filter-occlusion-alpha.html = PASS IMAGE
+BUGWK77498 : compositing/culling/filter-occlusion-alpha-large.html = PASS IMAGE
+BUGWK77498 : compositing/culling/filter-occlusion-blur.html = PASS IMAGE
+BUGWK77498 : compositing/culling/filter-occlusion-blur-large.html = PASS IMAGE
+
// Needs new baselines.
BUGWK65072 : svg/text/exs-display-none.svg = IMAGE IMAGE+TEXT
BUGWK65072 : svg/text/ems-display-none.svg = IMAGE IMAGE+TEXT
+2012-02-16 Dana Jansens <danakj@chromium.org>
+
+ [Chromium] Occlusion tracking with CSS filters
+ https://bugs.webkit.org/show_bug.cgi?id=77498
+
+ Reviewed by James Robinson.
+
+ The new CSS filter support within the compositor changes how
+ occlusion tracking needs to function. A filter can change the
+ alpha value of pixels, making an otherwise opaque pixel no
+ longer so. Secondly, a filter may move color values around
+ on a surface, which can cause otherwise occluded areas to
+ become visible and require painting.
+
+ New unit tests: CCLayerTreeHostTest.cpp
+
+ Tests: compositing/culling/filter-occlusion-alpha-large.html
+ compositing/culling/filter-occlusion-alpha.html
+ compositing/culling/filter-occlusion-blur-large.html
+ compositing/culling/filter-occlusion-blur.html
+
+ * platform/graphics/chromium/RenderSurfaceChromium.cpp:
+ (WebCore::RenderSurfaceChromium::RenderSurfaceChromium):
+ * platform/graphics/chromium/RenderSurfaceChromium.h:
+ (WebCore::RenderSurfaceChromium::setFilters):
+ (WebCore::RenderSurfaceChromium::filters):
+ (WebCore::RenderSurfaceChromium::setNearestAncestorThatMovesPixels):
+ (WebCore::RenderSurfaceChromium::nearestAncestorThatMovesPixels):
+ (RenderSurfaceChromium):
+ * platform/graphics/chromium/cc/CCLayerTreeHost.cpp:
+ (WebCore::enterTargetRenderSurface):
+ (WebCore::CCLayerTreeHost::paintLayerContents):
+ * platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp:
+ (WebCore::subtreeShouldRenderToSeparateSurface):
+ (WebCore::calculateDrawTransformsAndVisibilityInternal):
+ (WebCore::CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility):
+ * platform/graphics/chromium/cc/CCRenderSurface.cpp:
+ (WebCore::CCRenderSurface::CCRenderSurface):
+ * platform/graphics/chromium/cc/CCRenderSurface.h:
+ (WebCore::CCRenderSurface::setNearestAncestorThatMovesPixels):
+ (WebCore::CCRenderSurface::nearestAncestorThatMovesPixels):
+ (CCRenderSurface):
+ * platform/graphics/filters/FilterOperation.h:
+ (FilterOperation):
+ (WebCore::FilterOperation::affectsOpacity):
+ (WebCore::FilterOperation::movesPixels):
+ (WebCore::ReferenceFilterOperation::affectsOpacity):
+ (WebCore::ReferenceFilterOperation::movesPixels):
+ (ReferenceFilterOperation):
+ (WebCore::BasicComponentTransferFilterOperation::affectsOpacity):
+ (BasicComponentTransferFilterOperation):
+ (WebCore::BlurFilterOperation::affectsOpacity):
+ (WebCore::BlurFilterOperation::movesPixels):
+ (BlurFilterOperation):
+ (WebCore::DropShadowFilterOperation::affectsOpacity):
+ (DropShadowFilterOperation):
+ * platform/graphics/filters/FilterOperations.cpp:
+ (WebCore::FilterOperations::hasFilterThatAffectsOpacity):
+ (WebCore):
+ (WebCore::FilterOperations::hasFilterThatMovesPixels):
+ * platform/graphics/filters/FilterOperations.h:
+ (WebCore::FilterOperations::isEmpty):
+ (FilterOperations):
+
2012-02-16 Leo Yang <leo.yang@torchmobile.com.cn>
[BlackBerry] Adapt to the removal of WebStringIml.h
#include "RenderSurfaceChromium.h"
+#include "FilterOperations.h"
#include "GraphicsContext3D.h"
#include "LayerChromium.h"
#include "LayerRendererChromium.h"
, m_maskLayer(0)
, m_skipsDraw(false)
, m_drawOpacity(1)
+ , m_nearestAncestorThatMovesPixels(0)
{
}
const IntRect& clipRect() const { return m_clipRect; }
void setClipRect(const IntRect& clipRect) { m_clipRect = clipRect; }
- // We don't care about filters here, but we need to satisfy
- // calculateDrawTransformsAndVisibilityInternal when templated on this
- // class.
- void setFilters(const FilterOperations&) { }
+ void setFilters(const FilterOperations& filters) { m_filters = filters; }
+ const FilterOperations& filters() const { return m_filters; }
bool skipsDraw() const { return m_skipsDraw; }
void setSkipsDraw(bool skipsDraw) { m_skipsDraw = skipsDraw; }
void setMaskLayer(LayerChromium* maskLayer) { m_maskLayer = maskLayer; }
+ void setNearestAncestorThatMovesPixels(RenderSurfaceChromium* surface) { m_nearestAncestorThatMovesPixels = surface; }
+ const RenderSurfaceChromium* nearestAncestorThatMovesPixels() const { return m_nearestAncestorThatMovesPixels; }
+
private:
LayerChromium* m_owningLayer;
LayerChromium* m_maskLayer;
TransformationMatrix m_drawTransform;
TransformationMatrix m_replicaDrawTransform;
TransformationMatrix m_originTransform;
+ FilterOperations m_filters;
IntRect m_clipRect;
Vector<RefPtr<LayerChromium> > m_layerList;
+ // The nearest ancestor target surface that will contain the contents of this surface, and that is going
+ // to move pixels within the surface (such as with a blur). This can point to itself.
+ RenderSurfaceChromium* m_nearestAncestorThatMovesPixels;
+
// For CCLayerIteratorActions
int m_targetRenderSurfaceLayerIndexHistory;
int m_currentLayerIndexHistory;
stack.append(RenderSurfaceRegion());
stack.last().surface = newTarget;
} else if (stack.last().surface != newTarget) {
+ // If we are entering a subtree that is going to move pixels around, then the occlusion we've computed
+ // so far won't apply to the pixels we're drawing here in the same way. We discard the occlusion thus
+ // far to be safe, and ensure we don't cull any pixels that are moved such that they become visible.
+ const RenderSurfaceChromium* oldAncestorThatMovesPixels = stack.last().surface->nearestAncestorThatMovesPixels();
+ const RenderSurfaceChromium* newAncestorThatMovesPixels = newTarget->nearestAncestorThatMovesPixels();
+ bool enteringSubtreeThatMovesPixels = newAncestorThatMovesPixels && newAncestorThatMovesPixels != oldAncestorThatMovesPixels;
+
stack.append(RenderSurfaceRegion());
stack.last().surface = newTarget;
int lastIndex = stack.size() - 1;
- stack[lastIndex].occludedInScreen = stack[lastIndex - 1].occludedInScreen;
+ if (!enteringSubtreeThatMovesPixels)
+ stack[lastIndex].occludedInScreen = stack[lastIndex - 1].occludedInScreen;
}
}
paintMaskAndReplicaForRenderSurface(*it, paintType);
// FIXME: add the replica layer to the current occlusion
- if (it->maskLayer() || it->renderSurface()->drawOpacity() < 1)
+ if (it->maskLayer() || it->renderSurface()->drawOpacity() < 1 || it->renderSurface()->filters().hasFilterThatAffectsOpacity())
targetSurfaceStack.last().occludedInScreen = Region();
} else if (it.representsItself()) {
ASSERT(!it->bounds().isEmpty());
return true;
// If the layer uses a CSS filter.
- if (layer->filters().size() > 0)
+ if (!layer->filters().isEmpty())
return true;
// If the layer flattens its subtree (i.e. the layer doesn't preserve-3d), but it is
// Recursively walks the layer tree starting at the given node and computes all the
// necessary transformations, clipRects, render surfaces, etc.
template<typename LayerType, typename RenderSurfaceType, typename LayerSorter>
-static bool calculateDrawTransformsAndVisibilityInternal(LayerType* layer, LayerType* rootLayer, const TransformationMatrix& parentMatrix, const TransformationMatrix& fullHierarchyMatrix, Vector<RefPtr<LayerType> >& renderSurfaceLayerList, Vector<RefPtr<LayerType> >& layerList, LayerSorter* layerSorter, int maxTextureSize)
+static bool calculateDrawTransformsAndVisibilityInternal(LayerType* layer, LayerType* rootLayer, const TransformationMatrix& parentMatrix, const TransformationMatrix& fullHierarchyMatrix, RenderSurfaceType* nearestAncestorThatMovesPixels, Vector<RefPtr<LayerType> >& renderSurfaceLayerList, Vector<RefPtr<LayerType> >& layerList, LayerSorter* layerSorter, int maxTextureSize)
{
typedef Vector<RefPtr<LayerType> > LayerList;
layer->replicaLayer()->maskLayer()->setTargetRenderSurface(renderSurface);
renderSurface->setFilters(layer->filters());
+ if (renderSurface->filters().hasFilterThatMovesPixels())
+ nearestAncestorThatMovesPixels = renderSurface;
+ renderSurface->setNearestAncestorThatMovesPixels(nearestAncestorThatMovesPixels);
renderSurfaceLayerList.append(layer);
} else {
for (size_t i = 0; i < layer->children().size(); ++i) {
LayerType* child = layer->children()[i].get();
- bool drawsContent = calculateDrawTransformsAndVisibilityInternal<LayerType, RenderSurfaceType, LayerSorter>(child, rootLayer, sublayerMatrix, nextHierarchyMatrix, renderSurfaceLayerList, descendants, layerSorter, maxTextureSize);
+ bool drawsContent = calculateDrawTransformsAndVisibilityInternal<LayerType, RenderSurfaceType, LayerSorter>(child, rootLayer, sublayerMatrix, nextHierarchyMatrix, nearestAncestorThatMovesPixels, renderSurfaceLayerList, descendants, layerSorter, maxTextureSize);
if (drawsContent) {
if (child->renderSurface()) {
void CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(LayerChromium* layer, LayerChromium* rootLayer, const TransformationMatrix& parentMatrix, const TransformationMatrix& fullHierarchyMatrix, Vector<RefPtr<LayerChromium> >& renderSurfaceLayerList, Vector<RefPtr<LayerChromium> >& layerList, int maxTextureSize)
{
- WebCore::calculateDrawTransformsAndVisibilityInternal<LayerChromium, RenderSurfaceChromium, void*>(layer, rootLayer, parentMatrix, fullHierarchyMatrix, renderSurfaceLayerList, layerList, 0, maxTextureSize);
+ WebCore::calculateDrawTransformsAndVisibilityInternal<LayerChromium, RenderSurfaceChromium, void*>(layer, rootLayer, parentMatrix, fullHierarchyMatrix, 0, renderSurfaceLayerList, layerList, 0, maxTextureSize);
walkLayersAndCalculateVisibleLayerRects<LayerChromium, RenderSurfaceChromium>(renderSurfaceLayerList);
}
void CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(CCLayerImpl* layer, CCLayerImpl* rootLayer, const TransformationMatrix& parentMatrix, const TransformationMatrix& fullHierarchyMatrix, Vector<RefPtr<CCLayerImpl> >& renderSurfaceLayerList, Vector<RefPtr<CCLayerImpl> >& layerList, CCLayerSorter* layerSorter, int maxTextureSize)
{
- calculateDrawTransformsAndVisibilityInternal<CCLayerImpl, CCRenderSurface, CCLayerSorter>(layer, rootLayer, parentMatrix, fullHierarchyMatrix, renderSurfaceLayerList, layerList, layerSorter, maxTextureSize);
+ calculateDrawTransformsAndVisibilityInternal<CCLayerImpl, CCRenderSurface, CCLayerSorter>(layer, rootLayer, parentMatrix, fullHierarchyMatrix, 0, renderSurfaceLayerList, layerList, layerSorter, maxTextureSize);
walkLayersAndCalculateVisibleLayerRects<CCLayerImpl, CCRenderSurface>(renderSurfaceLayerList);
}
, m_skipsDraw(false)
, m_surfacePropertyChanged(false)
, m_drawOpacity(1)
+ , m_nearestAncestorThatMovesPixels(0)
{
m_damageTracker = CCDamageTracker::create();
}
const FilterOperations& filters() const { return m_filters; }
SkBitmap applyFilters(LayerRendererChromium*);
+ void setNearestAncestorThatMovesPixels(CCRenderSurface* surface) { m_nearestAncestorThatMovesPixels = surface; }
+ const CCRenderSurface* nearestAncestorThatMovesPixels() const { return m_nearestAncestorThatMovesPixels; }
+
void setReplicaDrawTransform(const TransformationMatrix& replicaDrawTransform) { m_replicaDrawTransform = replicaDrawTransform; }
const TransformationMatrix& replicaDrawTransform() const { return m_replicaDrawTransform; }
IntRect m_clipRect;
Vector<RefPtr<CCLayerImpl> > m_layerList;
+ // The nearest ancestor target surface that will contain the contents of this surface, and that is going
+ // to move pixels within the surface (such as with a blur). This can point to itself.
+ CCRenderSurface* m_nearestAncestorThatMovesPixels;
+
OwnPtr<CCDamageTracker> m_damageTracker;
// Stored in the "surface space" where this damage can be used for scissoring.
virtual bool isDefault() const { return false; }
+ // True if the alpha channel of any pixel can change under this operation.
+ virtual bool affectsOpacity() const { return false; }
+ // True if the the value of one pixel can affect the value of another pixel under this operation, such as blur.
+ virtual bool movesPixels() const { return false; }
+
protected:
FilterOperation(OperationType type)
: m_type(type)
return adoptRef(new ReferenceFilterOperation(reference, type));
}
+ virtual bool affectsOpacity() const { return true; }
+ virtual bool movesPixels() const { return true; }
+
const AtomicString& reference() const { return m_reference; }
private:
double amount() const { return m_amount; }
+ virtual bool affectsOpacity() const { return m_type == OPACITY; }
+
virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false);
private:
Length stdDeviation() const { return m_stdDeviation; }
+ virtual bool affectsOpacity() const { return true; }
+ virtual bool movesPixels() const { return true; }
+
virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false);
private:
int stdDeviation() const { return m_stdDeviation; }
Color color() const { return m_color; }
+ virtual bool affectsOpacity() const { return true; }
+
virtual PassRefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false);
private:
}
}
+bool FilterOperations::hasFilterThatAffectsOpacity() const
+{
+ for (size_t i = 0; i < m_operations.size(); ++i)
+ if (m_operations[i]->affectsOpacity())
+ return true;
+ return false;
+}
+
+bool FilterOperations::hasFilterThatMovesPixels() const
+{
+ for (size_t i = 0; i < m_operations.size(); ++i)
+ if (m_operations[i]->movesPixels())
+ return true;
+ return false;
+}
+
} // namespace WebCore
#endif // ENABLE(CSS_FILTERS)
Vector<RefPtr<FilterOperation> >& operations() { return m_operations; }
const Vector<RefPtr<FilterOperation> >& operations() const { return m_operations; }
+ bool isEmpty() const { return !m_operations.size(); }
size_t size() const { return m_operations.size(); }
const FilterOperation* at(size_t index) const { return index < m_operations.size() ? m_operations.at(index).get() : 0; }
bool hasOutsets() const;
void getOutsets(LayoutUnit& top, LayoutUnit& right, LayoutUnit& bottom, LayoutUnit& left) const;
+ bool hasFilterThatAffectsOpacity() const;
+ bool hasFilterThatMovesPixels() const;
+
private:
Vector<RefPtr<FilterOperation> > m_operations;
};
+2012-02-16 Dana Jansens <danakj@chromium.org>
+
+ [Chromium] Occlusion tracking with CSS filters
+ https://bugs.webkit.org/show_bug.cgi?id=77498
+
+ Reviewed by James Robinson.
+
+ * tests/CCLayerTreeHostTest.cpp:
+ (CCLayerTreeHostTestLayerOcclusionWithFilters):
+ (WTF::CCLayerTreeHostTestLayerOcclusionWithFilters::CCLayerTreeHostTestLayerOcclusionWithFilters):
+ (WTF::CCLayerTreeHostTestLayerOcclusionWithFilters::beginTest):
+ (WTF::CCLayerTreeHostTestLayerOcclusionWithFilters::afterTest):
+ (WTF):
+
2012-02-16 Joshua Bell <jsbell@chromium.org>
IndexedDB: Chromium WebKit API support for IDBObjectStore.delete(IDBKeyRange)
#include "CompositorFakeWebGraphicsContext3D.h"
#include "ContentLayerChromium.h"
+#include "FilterOperations.h"
#include "GraphicsContext3DPrivate.h"
#include "LayerChromium.h"
#include "Region.h"
SINGLE_AND_MULTI_THREAD_TEST_F(CCLayerTreeHostTestLayerOcclusion)
+class CCLayerTreeHostTestLayerOcclusionWithFilters : public CCLayerTreeHostTest {
+public:
+ CCLayerTreeHostTestLayerOcclusionWithFilters() { }
+
+ virtual void beginTest()
+ {
+ RefPtr<TestLayerChromium> rootLayer = TestLayerChromium::create();
+ RefPtr<TestLayerChromium> child = TestLayerChromium::create();
+ RefPtr<TestLayerChromium> child2 = TestLayerChromium::create();
+ RefPtr<TestLayerChromium> grandChild = TestLayerChromium::create();
+ RefPtr<TestLayerChromium> mask = TestLayerChromium::create();
+
+ TransformationMatrix identityMatrix;
+ TransformationMatrix childTransform;
+ childTransform.translate(250, 250);
+ childTransform.rotate(90);
+ childTransform.translate(-250, -250);
+
+ child->setMasksToBounds(true);
+
+ // If the child layer has a filter that changes alpha values, and is below child2, then child2 should contribute to occlusion on everything,
+ // and child shouldn't contribute to the rootLayer
+ setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
+ setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
+ setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
+ setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true);
+
+ {
+ FilterOperations filters;
+ filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::OPACITY));
+ child->setFilters(filters);
+ }
+
+ m_layerTreeHost->setRootLayer(rootLayer);
+ m_layerTreeHost->setViewportSize(rootLayer->bounds());
+ m_layerTreeHost->updateLayers();
+ m_layerTreeHost->commitComplete();
+
+ EXPECT_EQ_RECT(IntRect(), child2->occludedScreenSpace().bounds());
+ EXPECT_EQ(0u, child2->occludedScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), grandChild->occludedScreenSpace().bounds());
+ EXPECT_EQ(1u, grandChild->occludedScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(10, 40, 90, 60), child->occludedScreenSpace().bounds());
+ EXPECT_EQ(2u, child->occludedScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), rootLayer->occludedScreenSpace().bounds());
+ EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
+
+ // If the child layer has a filter that moves pixels/changes alpha, and is below child2, then child should not inherit occlusion from outside its subtree,
+ // and should not contribute to the rootLayer
+ setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
+ setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
+ setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
+ setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true);
+
+ {
+ FilterOperations filters;
+ filters.operations().append(BlurFilterOperation::create(Length(10, WebCore::Percent), FilterOperation::BLUR));
+ child->setFilters(filters);
+ }
+
+ m_layerTreeHost->setRootLayer(rootLayer);
+ m_layerTreeHost->setViewportSize(rootLayer->bounds());
+ m_layerTreeHost->updateLayers();
+ m_layerTreeHost->commitComplete();
+
+ EXPECT_EQ_RECT(IntRect(), child2->occludedScreenSpace().bounds());
+ EXPECT_EQ(0u, child2->occludedScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(), grandChild->occludedScreenSpace().bounds());
+ EXPECT_EQ(0u, grandChild->occludedScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), child->occludedScreenSpace().bounds());
+ EXPECT_EQ(1u, child->occludedScreenSpace().rects().size());
+ EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), rootLayer->occludedScreenSpace().bounds());
+ EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
+
+ // Kill the layerTreeHost immediately.
+ m_layerTreeHost->setRootLayer(0);
+ m_layerTreeHost.clear();
+
+ endTest();
+ }
+
+ virtual void afterTest()
+ {
+ }
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(CCLayerTreeHostTestLayerOcclusionWithFilters)
+
class CCLayerTreeHostTestManySurfaces : public CCLayerTreeHostTest {
public:
CCLayerTreeHostTestManySurfaces() { }