1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #if USE(ACCELERATED_COMPOSITING)
9 #include "CCOcclusionTracker.h"
11 #include "CCLayerImpl.h"
12 #include "CCMathUtil.h"
13 #include "CCOverdrawMetrics.h"
14 #include "LayerChromium.h"
18 using WebKit::WebTransformationMatrix
;
22 template<typename LayerType
, typename RenderSurfaceType
>
23 CCOcclusionTrackerBase
<LayerType
, RenderSurfaceType
>::CCOcclusionTrackerBase(IntRect rootTargetRect
, bool recordMetricsForFrame
)
24 : m_rootTargetRect(rootTargetRect
)
25 , m_overdrawMetrics(CCOverdrawMetrics::create(recordMetricsForFrame
))
26 , m_occludingScreenSpaceRects(0)
30 template<typename LayerType
, typename RenderSurfaceType
>
31 void CCOcclusionTrackerBase
<LayerType
, RenderSurfaceType
>::enterLayer(const CCLayerIteratorPosition
<LayerType
>& layerIterator
)
33 LayerType
* renderTarget
= layerIterator
.targetRenderSurfaceLayer
;
35 if (layerIterator
.representsItself
)
36 enterRenderTarget(renderTarget
);
37 else if (layerIterator
.representsTargetRenderSurface
)
38 finishedRenderTarget(renderTarget
);
41 template<typename LayerType
, typename RenderSurfaceType
>
42 void CCOcclusionTrackerBase
<LayerType
, RenderSurfaceType
>::leaveLayer(const CCLayerIteratorPosition
<LayerType
>& layerIterator
)
44 LayerType
* renderTarget
= layerIterator
.targetRenderSurfaceLayer
;
46 if (layerIterator
.representsItself
)
47 markOccludedBehindLayer(layerIterator
.currentLayer
);
48 else if (layerIterator
.representsContributingRenderSurface
)
49 leaveToRenderTarget(renderTarget
);
52 template<typename LayerType
, typename RenderSurfaceType
>
53 void CCOcclusionTrackerBase
<LayerType
, RenderSurfaceType
>::enterRenderTarget(const LayerType
* newTarget
)
55 if (!m_stack
.isEmpty() && m_stack
.last().target
== newTarget
)
58 const LayerType
* oldTarget
= m_stack
.isEmpty() ? 0 : m_stack
.last().target
;
59 const RenderSurfaceType
* oldAncestorThatMovesPixels
= !oldTarget
? 0 : oldTarget
->renderSurface()->nearestAncestorThatMovesPixels();
60 const RenderSurfaceType
* newAncestorThatMovesPixels
= newTarget
->renderSurface()->nearestAncestorThatMovesPixels();
62 m_stack
.append(StackObject(newTarget
));
64 // We copy the screen occlusion into the new RenderSurface subtree, but we never copy in the
65 // target occlusion, since we are looking at a new RenderSurface target.
67 // If we are entering a subtree that is going to move pixels around, then the occlusion we've computed
68 // so far won't apply to the pixels we're drawing here in the same way. We discard the occlusion thus
69 // far to be safe, and ensure we don't cull any pixels that are moved such that they become visible.
70 bool enteringSubtreeThatMovesPixels
= newAncestorThatMovesPixels
&& newAncestorThatMovesPixels
!= oldAncestorThatMovesPixels
;
72 bool copyScreenOcclusionForward
= m_stack
.size() > 1 && !enteringSubtreeThatMovesPixels
;
73 if (copyScreenOcclusionForward
) {
74 int lastIndex
= m_stack
.size() - 1;
75 m_stack
[lastIndex
].occlusionInScreen
= m_stack
[lastIndex
- 1].occlusionInScreen
;
79 static inline bool layerOpacityKnown(const LayerChromium
* layer
) { return !layer
->drawOpacityIsAnimating(); }
80 static inline bool layerOpacityKnown(const CCLayerImpl
*) { return true; }
81 static inline bool layerTransformsToTargetKnown(const LayerChromium
* layer
) { return !layer
->drawTransformIsAnimating(); }
82 static inline bool layerTransformsToTargetKnown(const CCLayerImpl
*) { return true; }
83 static inline bool layerTransformsToScreenKnown(const LayerChromium
* layer
) { return !layer
->screenSpaceTransformIsAnimating(); }
84 static inline bool layerTransformsToScreenKnown(const CCLayerImpl
*) { return true; }
86 static inline bool surfaceOpacityKnown(const RenderSurfaceChromium
* surface
) { return !surface
->drawOpacityIsAnimating(); }
87 static inline bool surfaceOpacityKnown(const CCRenderSurface
*) { return true; }
88 static inline bool surfaceTransformsToTargetKnown(const RenderSurfaceChromium
* surface
) { return !surface
->targetSurfaceTransformsAreAnimating(); }
89 static inline bool surfaceTransformsToTargetKnown(const CCRenderSurface
*) { return true; }
90 static inline bool surfaceTransformsToScreenKnown(const RenderSurfaceChromium
* surface
) { return !surface
->screenSpaceTransformsAreAnimating(); }
91 static inline bool surfaceTransformsToScreenKnown(const CCRenderSurface
*) { return true; }
93 static inline bool layerIsInUnsorted3dRenderingContext(const LayerChromium
* layer
) { return layer
->parent() && layer
->parent()->preserves3D(); }
94 static inline bool layerIsInUnsorted3dRenderingContext(const CCLayerImpl
*) { return false; }
96 template<typename LayerType
, typename RenderSurfaceType
>
97 void CCOcclusionTrackerBase
<LayerType
, RenderSurfaceType
>::finishedRenderTarget(const LayerType
* finishedTarget
)
99 // Make sure we know about the target surface.
100 enterRenderTarget(finishedTarget
);
102 RenderSurfaceType
* surface
= finishedTarget
->renderSurface();
104 // 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.
105 if (finishedTarget
->maskLayer() || !surfaceOpacityKnown(surface
) || surface
->drawOpacity() < 1 || finishedTarget
->filters().hasFilterThatAffectsOpacity()) {
106 m_stack
.last().occlusionInScreen
= Region();
107 m_stack
.last().occlusionInTarget
= Region();
109 if (!surfaceTransformsToTargetKnown(surface
))
110 m_stack
.last().occlusionInTarget
= Region();
111 if (!surfaceTransformsToScreenKnown(surface
))
112 m_stack
.last().occlusionInScreen
= Region();
116 template<typename RenderSurfaceType
>
117 static inline Region
transformSurfaceOpaqueRegion(const RenderSurfaceType
* surface
, const Region
& region
, const WebTransformationMatrix
& transform
)
119 // Verify that rects within the |surface| will remain rects in its target surface after applying |transform|. If this is true, then
120 // apply |transform| to each rect within |region| in order to transform the entire Region.
123 FloatQuad transformedBoundsQuad
= CCMathUtil::mapQuad(transform
, FloatQuad(region
.bounds()), clipped
);
124 // FIXME: Find a rect interior to each transformed quad.
125 if (clipped
|| !transformedBoundsQuad
.isRectilinear())
128 Region transformedRegion
;
130 Vector
<IntRect
> rects
= region
.rects();
131 for (size_t i
= 0; i
< rects
.size(); ++i
) {
132 // We've already checked for clipping in the mapQuad call above, these calls should not clip anything further.
133 IntRect transformedRect
= enclosedIntRect(CCMathUtil::mapClippedRect(transform
, FloatRect(rects
[i
])));
134 if (!surface
->clipRect().isEmpty())
135 transformedRect
.intersect(surface
->clipRect());
136 transformedRegion
.unite(transformedRect
);
138 return transformedRegion
;
141 static inline void reduceOcclusion(const IntRect
& affectedArea
, const IntRect
& expandedPixel
, Region
& occlusion
)
143 if (affectedArea
.isEmpty())
146 Region affectedOcclusion
= intersect(occlusion
, affectedArea
);
147 Vector
<IntRect
> affectedOcclusionRects
= affectedOcclusion
.rects();
149 occlusion
.subtract(affectedArea
);
150 for (size_t j
= 0; j
< affectedOcclusionRects
.size(); ++j
) {
151 IntRect
& occlusionRect
= affectedOcclusionRects
[j
];
153 // Shrink the rect by expanding the non-opaque pixels outside the rect.
155 // The expandedPixel is the IntRect for a single pixel after being
156 // expanded by filters on the layer. The original pixel would be
157 // IntRect(0, 0, 1, 1), and the expanded pixel is the rect, relative
158 // to this original rect, that the original pixel can influence after
160 // To convert the expandedPixel IntRect back to filter outsets:
162 // width = leftOutset + rightOutset
163 // maxX = x + width = -leftOutset + leftOutset + rightOutset = rightOutset
165 // The leftOutset of the filters moves pixels on the right side of
166 // the occlusionRect into it, shrinking its right edge.
167 int shrinkLeft
= occlusionRect
.x() == affectedArea
.x() ? 0 : expandedPixel
.maxX();
168 int shrinkTop
= occlusionRect
.y() == affectedArea
.y() ? 0 : expandedPixel
.maxY();
169 int shrinkRight
= occlusionRect
.maxX() == affectedArea
.maxX() ? 0 : -expandedPixel
.x();
170 int shrinkBottom
= occlusionRect
.maxY() == affectedArea
.maxY() ? 0 : -expandedPixel
.y();
172 occlusionRect
.move(shrinkLeft
, shrinkTop
);
173 occlusionRect
.contract(shrinkLeft
+ shrinkRight
, shrinkTop
+ shrinkBottom
);
175 occlusion
.unite(occlusionRect
);
179 template<typename LayerType
>
180 static void reduceOcclusionBelowSurface(LayerType
* contributingLayer
, const IntRect
& surfaceRect
, const WebTransformationMatrix
& surfaceTransform
, LayerType
* renderTarget
, Region
& occlusionInTarget
, Region
& occlusionInScreen
)
182 if (surfaceRect
.isEmpty())
185 IntRect boundsInTarget
= enclosingIntRect(CCMathUtil::mapClippedRect(surfaceTransform
, FloatRect(surfaceRect
)));
186 if (!contributingLayer
->renderSurface()->clipRect().isEmpty())
187 boundsInTarget
.intersect(contributingLayer
->renderSurface()->clipRect());
189 int outsetTop
, outsetRight
, outsetBottom
, outsetLeft
;
190 contributingLayer
->backgroundFilters().getOutsets(outsetTop
, outsetRight
, outsetBottom
, outsetLeft
);
192 // The filter can move pixels from outside of the clip, so allow affectedArea to expand outside the clip.
193 boundsInTarget
.move(-outsetLeft
, -outsetTop
);
194 boundsInTarget
.expand(outsetLeft
+ outsetRight
, outsetTop
+ outsetBottom
);
196 IntRect boundsInScreen
= enclosingIntRect(CCMathUtil::mapClippedRect(renderTarget
->renderSurface()->screenSpaceTransform(), FloatRect(boundsInTarget
)));
198 IntRect
filterOutsetsInTarget(-outsetLeft
, -outsetTop
, outsetLeft
+ outsetRight
, outsetTop
+ outsetBottom
);
199 IntRect filterOutsetsInScreen
= enclosingIntRect(CCMathUtil::mapClippedRect(renderTarget
->renderSurface()->screenSpaceTransform(), FloatRect(filterOutsetsInTarget
)));
201 reduceOcclusion(boundsInTarget
, filterOutsetsInTarget
, occlusionInTarget
);
202 reduceOcclusion(boundsInScreen
, filterOutsetsInScreen
, occlusionInScreen
);
205 template<typename LayerType
, typename RenderSurfaceType
>
206 void CCOcclusionTrackerBase
<LayerType
, RenderSurfaceType
>::leaveToRenderTarget(const LayerType
* newTarget
)
208 int lastIndex
= m_stack
.size() - 1;
209 bool surfaceWillBeAtTopAfterPop
= m_stack
.size() > 1 && m_stack
[lastIndex
- 1].target
== newTarget
;
211 // We merge the screen occlusion from the current RenderSurface subtree out to its parent target RenderSurface.
212 // The target occlusion can be merged out as well but needs to be transformed to the new target.
214 const LayerType
* oldTarget
= m_stack
[lastIndex
].target
;
215 const RenderSurfaceType
* oldSurface
= oldTarget
->renderSurface();
216 Region oldTargetOcclusionInNewTarget
= transformSurfaceOpaqueRegion
<RenderSurfaceType
>(oldSurface
, m_stack
[lastIndex
].occlusionInTarget
, oldSurface
->drawTransform());
217 if (oldTarget
->hasReplica() && !oldTarget
->replicaHasMask())
218 oldTargetOcclusionInNewTarget
.unite(transformSurfaceOpaqueRegion
<RenderSurfaceType
>(oldSurface
, m_stack
[lastIndex
].occlusionInTarget
, oldSurface
->replicaDrawTransform()));
220 IntRect unoccludedSurfaceRect
;
221 IntRect unoccludedReplicaRect
;
222 if (oldTarget
->backgroundFilters().hasFilterThatMovesPixels()) {
223 unoccludedSurfaceRect
= unoccludedContributingSurfaceContentRect(oldTarget
, false, oldSurface
->contentRect());
224 if (oldTarget
->hasReplica())
225 unoccludedReplicaRect
= unoccludedContributingSurfaceContentRect(oldTarget
, true, oldSurface
->contentRect());
228 if (surfaceWillBeAtTopAfterPop
) {
229 // Merge the top of the stack down.
230 m_stack
[lastIndex
- 1].occlusionInScreen
.unite(m_stack
[lastIndex
].occlusionInScreen
);
231 m_stack
[lastIndex
- 1].occlusionInTarget
.unite(oldTargetOcclusionInNewTarget
);
232 m_stack
.removeLast();
234 // Replace the top of the stack with the new pushed surface. Copy the occluded screen region to the top.
235 m_stack
.last().target
= newTarget
;
236 m_stack
.last().occlusionInTarget
= oldTargetOcclusionInNewTarget
;
239 if (oldTarget
->backgroundFilters().hasFilterThatMovesPixels()) {
240 reduceOcclusionBelowSurface(oldTarget
, unoccludedSurfaceRect
, oldSurface
->drawTransform(), newTarget
, m_stack
.last().occlusionInTarget
, m_stack
.last().occlusionInScreen
);
241 if (oldTarget
->hasReplica())
242 reduceOcclusionBelowSurface(oldTarget
, unoccludedReplicaRect
, oldSurface
->replicaDrawTransform(), newTarget
, m_stack
.last().occlusionInTarget
, m_stack
.last().occlusionInScreen
);
246 // FIXME: Remove usePaintTracking when paint tracking is on for paint culling.
247 template<typename LayerType
>
248 static inline void addOcclusionBehindLayer(Region
& region
, const LayerType
* layer
, const WebTransformationMatrix
& transform
, const Region
& opaqueContents
, const IntRect
& clipRectInTarget
, const IntSize
& minimumTrackingSize
, Vector
<IntRect
>* occludingScreenSpaceRects
)
250 ASSERT(layer
->visibleContentRect().contains(opaqueContents
.bounds()));
253 FloatQuad visibleTransformedQuad
= CCMathUtil::mapQuad(transform
, FloatQuad(layer
->visibleContentRect()), clipped
);
254 // FIXME: Find a rect interior to each transformed quad.
255 if (clipped
|| !visibleTransformedQuad
.isRectilinear())
258 Vector
<IntRect
> contentRects
= opaqueContents
.rects();
259 for (size_t i
= 0; i
< contentRects
.size(); ++i
) {
260 // We've already checked for clipping in the mapQuad call above, these calls should not clip anything further.
261 IntRect transformedRect
= enclosedIntRect(CCMathUtil::mapClippedRect(transform
, FloatRect(contentRects
[i
])));
262 transformedRect
.intersect(clipRectInTarget
);
263 if (transformedRect
.width() >= minimumTrackingSize
.width() || transformedRect
.height() >= minimumTrackingSize
.height()) {
264 if (occludingScreenSpaceRects
)
265 occludingScreenSpaceRects
->append(transformedRect
);
266 region
.unite(transformedRect
);
271 template<typename LayerType
, typename RenderSurfaceType
>
272 void CCOcclusionTrackerBase
<LayerType
, RenderSurfaceType
>::markOccludedBehindLayer(const LayerType
* layer
)
274 ASSERT(!m_stack
.isEmpty());
275 ASSERT(layer
->renderTarget() == m_stack
.last().target
);
276 if (m_stack
.isEmpty())
279 if (!layerOpacityKnown(layer
) || layer
->drawOpacity() < 1)
282 if (layerIsInUnsorted3dRenderingContext(layer
))
285 Region opaqueContents
= layer
->visibleContentOpaqueRegion();
286 if (opaqueContents
.isEmpty())
289 IntRect clipRectInTarget
= layerClipRectInTarget(layer
);
290 if (layerTransformsToTargetKnown(layer
))
291 addOcclusionBehindLayer
<LayerType
>(m_stack
.last().occlusionInTarget
, layer
, layer
->drawTransform(), opaqueContents
, clipRectInTarget
, m_minimumTrackingSize
, 0);
293 // We must clip the occlusion within the layer's clipRectInTarget within screen space as well. If the clip rect can't be moved to screen space and
294 // remain rectilinear, then we don't add any occlusion in screen space.
296 if (layerTransformsToScreenKnown(layer
)) {
297 WebTransformationMatrix targetToScreenTransform
= m_stack
.last().target
->renderSurface()->screenSpaceTransform();
299 FloatQuad clipQuadInScreen
= CCMathUtil::mapQuad(targetToScreenTransform
, FloatQuad(FloatRect(clipRectInTarget
)), clipped
);
300 // FIXME: Find a rect interior to the transformed clip quad.
301 if (clipped
|| !clipQuadInScreen
.isRectilinear())
303 IntRect clipRectInScreen
= intersection(m_rootTargetRect
, enclosedIntRect(clipQuadInScreen
.boundingBox()));
304 addOcclusionBehindLayer
<LayerType
>(m_stack
.last().occlusionInScreen
, layer
, layer
->screenSpaceTransform(), opaqueContents
, clipRectInScreen
, m_minimumTrackingSize
, m_occludingScreenSpaceRects
);
308 static inline bool testContentRectOccluded(const IntRect
& contentRect
, const WebTransformationMatrix
& contentSpaceTransform
, const IntRect
& clipRectInTarget
, const Region
& occlusion
)
310 FloatRect transformedRect
= CCMathUtil::mapClippedRect(contentSpaceTransform
, FloatRect(contentRect
));
311 // Take the enclosingIntRect, as we want to include partial pixels in the test.
312 IntRect targetRect
= intersection(enclosingIntRect(transformedRect
), clipRectInTarget
);
313 return targetRect
.isEmpty() || occlusion
.contains(targetRect
);
316 template<typename LayerType
, typename RenderSurfaceType
>
317 bool CCOcclusionTrackerBase
<LayerType
, RenderSurfaceType
>::occluded(const LayerType
* layer
, const IntRect
& contentRect
, bool* hasOcclusionFromOutsideTargetSurface
) const
319 if (hasOcclusionFromOutsideTargetSurface
)
320 *hasOcclusionFromOutsideTargetSurface
= false;
322 ASSERT(!m_stack
.isEmpty());
323 if (m_stack
.isEmpty())
325 if (contentRect
.isEmpty())
328 ASSERT(layer
->renderTarget() == m_stack
.last().target
);
330 if (layerTransformsToTargetKnown(layer
) && testContentRectOccluded(contentRect
, layer
->drawTransform(), layerClipRectInTarget(layer
), m_stack
.last().occlusionInTarget
))
333 if (layerTransformsToScreenKnown(layer
) && testContentRectOccluded(contentRect
, layer
->screenSpaceTransform(), m_rootTargetRect
, m_stack
.last().occlusionInScreen
)) {
334 if (hasOcclusionFromOutsideTargetSurface
)
335 *hasOcclusionFromOutsideTargetSurface
= true;
342 // Determines what portion of rect, if any, is unoccluded (not occluded by region). If
343 // the resulting unoccluded region is not rectangular, we return a rect containing it.
344 static inline IntRect
rectSubtractRegion(const IntRect
& rect
, const Region
& region
)
346 Region
rectRegion(rect
);
347 rectRegion
.subtract(region
);
348 return rectRegion
.bounds();
351 static inline IntRect
computeUnoccludedContentRect(const IntRect
& contentRect
, const WebTransformationMatrix
& contentSpaceTransform
, const IntRect
& clipRectInTarget
, const Region
& occlusion
)
353 if (!contentSpaceTransform
.isInvertible())
356 // Take the enclosingIntRect at each step, as we want to contain any unoccluded partial pixels in the resulting IntRect.
357 FloatRect transformedRect
= CCMathUtil::mapClippedRect(contentSpaceTransform
, FloatRect(contentRect
));
358 IntRect shrunkRect
= rectSubtractRegion(intersection(enclosingIntRect(transformedRect
), clipRectInTarget
), occlusion
);
359 IntRect unoccludedRect
= enclosingIntRect(CCMathUtil::projectClippedRect(contentSpaceTransform
.inverse(), FloatRect(shrunkRect
)));
360 // The rect back in content space is a bounding box and may extend outside of the original contentRect, so clamp it to the contentRectBounds.
361 return intersection(unoccludedRect
, contentRect
);
364 template<typename LayerType
, typename RenderSurfaceType
>
365 IntRect CCOcclusionTrackerBase
<LayerType
, RenderSurfaceType
>::unoccludedContentRect(const LayerType
* layer
, const IntRect
& contentRect
, bool* hasOcclusionFromOutsideTargetSurface
) const
367 ASSERT(!m_stack
.isEmpty());
368 if (m_stack
.isEmpty())
370 if (contentRect
.isEmpty())
373 ASSERT(layer
->renderTarget() == m_stack
.last().target
);
375 // We want to return a rect that contains all the visible parts of |contentRect| in both screen space and in the target surface.
376 // So we find the visible parts of |contentRect| in each space, and take the intersection.
378 IntRect unoccludedInScreen
= contentRect
;
379 if (layerTransformsToScreenKnown(layer
))
380 unoccludedInScreen
= computeUnoccludedContentRect(contentRect
, layer
->screenSpaceTransform(), m_rootTargetRect
, m_stack
.last().occlusionInScreen
);
382 IntRect unoccludedInTarget
= contentRect
;
383 if (layerTransformsToTargetKnown(layer
))
384 unoccludedInTarget
= computeUnoccludedContentRect(contentRect
, layer
->drawTransform(), layerClipRectInTarget(layer
), m_stack
.last().occlusionInTarget
);
386 if (hasOcclusionFromOutsideTargetSurface
)
387 *hasOcclusionFromOutsideTargetSurface
= (intersection(unoccludedInScreen
, unoccludedInTarget
) != unoccludedInTarget
);
389 return intersection(unoccludedInScreen
, unoccludedInTarget
);
392 template<typename LayerType
, typename RenderSurfaceType
>
393 IntRect CCOcclusionTrackerBase
<LayerType
, RenderSurfaceType
>::unoccludedContributingSurfaceContentRect(const LayerType
* layer
, bool forReplica
, const IntRect
& contentRect
, bool* hasOcclusionFromOutsideTargetSurface
) const
395 ASSERT(!m_stack
.isEmpty());
396 // The layer is a contributing renderTarget so it should have a surface.
397 ASSERT(layer
->renderSurface());
398 // The layer is a contributing renderTarget so its target should be itself.
399 ASSERT(layer
->renderTarget() == layer
);
400 // The layer should not be the root, else what is is contributing to?
401 ASSERT(layer
->parent());
402 // This should be called while the layer is still considered the current target in the occlusion tracker.
403 ASSERT(layer
== m_stack
.last().target
);
405 if (contentRect
.isEmpty())
408 RenderSurfaceType
* surface
= layer
->renderSurface();
410 IntRect surfaceClipRect
= surface
->clipRect();
411 if (surfaceClipRect
.isEmpty()) {
412 LayerType
* contributingSurfaceRenderTarget
= layer
->parent()->renderTarget();
413 surfaceClipRect
= intersection(contributingSurfaceRenderTarget
->renderSurface()->contentRect(), enclosingIntRect(surface
->drawableContentRect()));
416 // A contributing surface doesn't get occluded by things inside its own surface, so only things outside the surface can occlude it. That occlusion is
417 // found just below the top of the stack (if it exists).
418 bool hasOcclusion
= m_stack
.size() > 1;
420 const WebTransformationMatrix
& transformToScreen
= forReplica
? surface
->replicaScreenSpaceTransform() : surface
->screenSpaceTransform();
421 const WebTransformationMatrix
& transformToTarget
= forReplica
? surface
->replicaDrawTransform() : surface
->drawTransform();
423 IntRect unoccludedInScreen
= contentRect
;
424 if (surfaceTransformsToScreenKnown(surface
)) {
426 const StackObject
& secondLast
= m_stack
[m_stack
.size() - 2];
427 unoccludedInScreen
= computeUnoccludedContentRect(contentRect
, transformToScreen
, m_rootTargetRect
, secondLast
.occlusionInScreen
);
429 unoccludedInScreen
= computeUnoccludedContentRect(contentRect
, transformToScreen
, m_rootTargetRect
, Region());
432 IntRect unoccludedInTarget
= contentRect
;
433 if (surfaceTransformsToTargetKnown(surface
)) {
435 const StackObject
& secondLast
= m_stack
[m_stack
.size() - 2];
436 unoccludedInTarget
= computeUnoccludedContentRect(contentRect
, transformToTarget
, surfaceClipRect
, secondLast
.occlusionInTarget
);
438 unoccludedInTarget
= computeUnoccludedContentRect(contentRect
, transformToTarget
, surfaceClipRect
, Region());
441 if (hasOcclusionFromOutsideTargetSurface
)
442 *hasOcclusionFromOutsideTargetSurface
= (intersection(unoccludedInScreen
, unoccludedInTarget
) != unoccludedInTarget
);
444 return intersection(unoccludedInScreen
, unoccludedInTarget
);
447 template<typename LayerType
, typename RenderSurfaceType
>
448 IntRect CCOcclusionTrackerBase
<LayerType
, RenderSurfaceType
>::layerClipRectInTarget(const LayerType
* layer
) const
450 // FIXME: we could remove this helper function, but unit tests currently override this
451 // function, and they need to be verified/adjusted before this can be removed.
452 return layer
->drawableContentRect();
455 // Declare the possible functions here for the linker.
456 template CCOcclusionTrackerBase
<LayerChromium
, RenderSurfaceChromium
>::CCOcclusionTrackerBase(IntRect rootTargetRect
, bool recordMetricsForFrame
);
457 template void CCOcclusionTrackerBase
<LayerChromium
, RenderSurfaceChromium
>::enterLayer(const CCLayerIteratorPosition
<LayerChromium
>&);
458 template void CCOcclusionTrackerBase
<LayerChromium
, RenderSurfaceChromium
>::leaveLayer(const CCLayerIteratorPosition
<LayerChromium
>&);
459 template void CCOcclusionTrackerBase
<LayerChromium
, RenderSurfaceChromium
>::enterRenderTarget(const LayerChromium
* newTarget
);
460 template void CCOcclusionTrackerBase
<LayerChromium
, RenderSurfaceChromium
>::finishedRenderTarget(const LayerChromium
* finishedTarget
);
461 template void CCOcclusionTrackerBase
<LayerChromium
, RenderSurfaceChromium
>::leaveToRenderTarget(const LayerChromium
* newTarget
);
462 template void CCOcclusionTrackerBase
<LayerChromium
, RenderSurfaceChromium
>::markOccludedBehindLayer(const LayerChromium
*);
463 template bool CCOcclusionTrackerBase
<LayerChromium
, RenderSurfaceChromium
>::occluded(const LayerChromium
*, const IntRect
& contentRect
, bool* hasOcclusionFromOutsideTargetSurface
) const;
464 template IntRect CCOcclusionTrackerBase
<LayerChromium
, RenderSurfaceChromium
>::unoccludedContentRect(const LayerChromium
*, const IntRect
& contentRect
, bool* hasOcclusionFromOutsideTargetSurface
) const;
465 template IntRect CCOcclusionTrackerBase
<LayerChromium
, RenderSurfaceChromium
>::unoccludedContributingSurfaceContentRect(const LayerChromium
*, bool forReplica
, const IntRect
& contentRect
, bool* hasOcclusionFromOutsideTargetSurface
) const;
466 template IntRect CCOcclusionTrackerBase
<LayerChromium
, RenderSurfaceChromium
>::layerClipRectInTarget(const LayerChromium
*) const;
468 template CCOcclusionTrackerBase
<CCLayerImpl
, CCRenderSurface
>::CCOcclusionTrackerBase(IntRect rootTargetRect
, bool recordMetricsForFrame
);
469 template void CCOcclusionTrackerBase
<CCLayerImpl
, CCRenderSurface
>::enterLayer(const CCLayerIteratorPosition
<CCLayerImpl
>&);
470 template void CCOcclusionTrackerBase
<CCLayerImpl
, CCRenderSurface
>::leaveLayer(const CCLayerIteratorPosition
<CCLayerImpl
>&);
471 template void CCOcclusionTrackerBase
<CCLayerImpl
, CCRenderSurface
>::enterRenderTarget(const CCLayerImpl
* newTarget
);
472 template void CCOcclusionTrackerBase
<CCLayerImpl
, CCRenderSurface
>::finishedRenderTarget(const CCLayerImpl
* finishedTarget
);
473 template void CCOcclusionTrackerBase
<CCLayerImpl
, CCRenderSurface
>::leaveToRenderTarget(const CCLayerImpl
* newTarget
);
474 template void CCOcclusionTrackerBase
<CCLayerImpl
, CCRenderSurface
>::markOccludedBehindLayer(const CCLayerImpl
*);
475 template bool CCOcclusionTrackerBase
<CCLayerImpl
, CCRenderSurface
>::occluded(const CCLayerImpl
*, const IntRect
& contentRect
, bool* hasOcclusionFromOutsideTargetSurface
) const;
476 template IntRect CCOcclusionTrackerBase
<CCLayerImpl
, CCRenderSurface
>::unoccludedContentRect(const CCLayerImpl
*, const IntRect
& contentRect
, bool* hasOcclusionFromOutsideTargetSurface
) const;
477 template IntRect CCOcclusionTrackerBase
<CCLayerImpl
, CCRenderSurface
>::unoccludedContributingSurfaceContentRect(const CCLayerImpl
*, bool forReplica
, const IntRect
& contentRect
, bool* hasOcclusionFromOutsideTargetSurface
) const;
478 template IntRect CCOcclusionTrackerBase
<CCLayerImpl
, CCRenderSurface
>::layerClipRectInTarget(const CCLayerImpl
*) const;
481 } // namespace WebCore
482 #endif // USE(ACCELERATED_COMPOSITING)