OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "config.h" | |
6 | |
7 #if USE(ACCELERATED_COMPOSITING) | |
8 | |
9 #include "CCOcclusionTracker.h" | |
10 | |
11 #include "CCLayerImpl.h" | |
12 #include "CCMathUtil.h" | |
13 #include "CCOverdrawMetrics.h" | |
14 #include "LayerChromium.h" | |
15 #include <algorithm> | |
16 | |
17 using namespace std; | |
18 using WebKit::WebTransformationMatrix; | |
19 | |
20 namespace cc { | |
21 | |
22 template<typename LayerType, typename RenderSurfaceType> | |
23 CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::CCOcclusionTrackerBase(Int
Rect rootTargetRect, bool recordMetricsForFrame) | |
24 : m_rootTargetRect(rootTargetRect) | |
25 , m_overdrawMetrics(CCOverdrawMetrics::create(recordMetricsForFrame)) | |
26 , m_occludingScreenSpaceRects(0) | |
27 { | |
28 } | |
29 | |
30 template<typename LayerType, typename RenderSurfaceType> | |
31 void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::enterLayer(const CCLa
yerIteratorPosition<LayerType>& layerIterator) | |
32 { | |
33 LayerType* renderTarget = layerIterator.targetRenderSurfaceLayer; | |
34 | |
35 if (layerIterator.representsItself) | |
36 enterRenderTarget(renderTarget); | |
37 else if (layerIterator.representsTargetRenderSurface) | |
38 finishedRenderTarget(renderTarget); | |
39 } | |
40 | |
41 template<typename LayerType, typename RenderSurfaceType> | |
42 void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::leaveLayer(const CCLa
yerIteratorPosition<LayerType>& layerIterator) | |
43 { | |
44 LayerType* renderTarget = layerIterator.targetRenderSurfaceLayer; | |
45 | |
46 if (layerIterator.representsItself) | |
47 markOccludedBehindLayer(layerIterator.currentLayer); | |
48 else if (layerIterator.representsContributingRenderSurface) | |
49 leaveToRenderTarget(renderTarget); | |
50 } | |
51 | |
52 template<typename LayerType, typename RenderSurfaceType> | |
53 void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::enterRenderTarget(con
st LayerType* newTarget) | |
54 { | |
55 if (!m_stack.isEmpty() && m_stack.last().target == newTarget) | |
56 return; | |
57 | |
58 const LayerType* oldTarget = m_stack.isEmpty() ? 0 : m_stack.last().target; | |
59 const RenderSurfaceType* oldAncestorThatMovesPixels = !oldTarget ? 0 : oldTa
rget->renderSurface()->nearestAncestorThatMovesPixels(); | |
60 const RenderSurfaceType* newAncestorThatMovesPixels = newTarget->renderSurfa
ce()->nearestAncestorThatMovesPixels(); | |
61 | |
62 m_stack.append(StackObject(newTarget)); | |
63 | |
64 // We copy the screen occlusion into the new RenderSurface subtree, but we n
ever copy in the | |
65 // target occlusion, since we are looking at a new RenderSurface target. | |
66 | |
67 // If we are entering a subtree that is going to move pixels around, then th
e occlusion we've computed | |
68 // so far won't apply to the pixels we're drawing here in the same way. We d
iscard the occlusion thus | |
69 // far to be safe, and ensure we don't cull any pixels that are moved such t
hat they become visible. | |
70 bool enteringSubtreeThatMovesPixels = newAncestorThatMovesPixels && newAnces
torThatMovesPixels != oldAncestorThatMovesPixels; | |
71 | |
72 bool copyScreenOcclusionForward = m_stack.size() > 1 && !enteringSubtreeThat
MovesPixels; | |
73 if (copyScreenOcclusionForward) { | |
74 int lastIndex = m_stack.size() - 1; | |
75 m_stack[lastIndex].occlusionInScreen = m_stack[lastIndex - 1].occlusionI
nScreen; | |
76 } | |
77 } | |
78 | |
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) { re
turn !layer->drawTransformIsAnimating(); } | |
82 static inline bool layerTransformsToTargetKnown(const CCLayerImpl*) { return tru
e; } | |
83 static inline bool layerTransformsToScreenKnown(const LayerChromium* layer) { re
turn !layer->screenSpaceTransformIsAnimating(); } | |
84 static inline bool layerTransformsToScreenKnown(const CCLayerImpl*) { return tru
e; } | |
85 | |
86 static inline bool surfaceOpacityKnown(const RenderSurfaceChromium* surface) { r
eturn !surface->drawOpacityIsAnimating(); } | |
87 static inline bool surfaceOpacityKnown(const CCRenderSurface*) { return true; } | |
88 static inline bool surfaceTransformsToTargetKnown(const RenderSurfaceChromium* s
urface) { return !surface->targetSurfaceTransformsAreAnimating(); } | |
89 static inline bool surfaceTransformsToTargetKnown(const CCRenderSurface*) { retu
rn true; } | |
90 static inline bool surfaceTransformsToScreenKnown(const RenderSurfaceChromium* s
urface) { return !surface->screenSpaceTransformsAreAnimating(); } | |
91 static inline bool surfaceTransformsToScreenKnown(const CCRenderSurface*) { retu
rn true; } | |
92 | |
93 static inline bool layerIsInUnsorted3dRenderingContext(const LayerChromium* laye
r) { return layer->parent() && layer->parent()->preserves3D(); } | |
94 static inline bool layerIsInUnsorted3dRenderingContext(const CCLayerImpl*) { ret
urn false; } | |
95 | |
96 template<typename LayerType, typename RenderSurfaceType> | |
97 void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::finishedRenderTarget(
const LayerType* finishedTarget) | |
98 { | |
99 // Make sure we know about the target surface. | |
100 enterRenderTarget(finishedTarget); | |
101 | |
102 RenderSurfaceType* surface = finishedTarget->renderSurface(); | |
103 | |
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(); | |
108 } else { | |
109 if (!surfaceTransformsToTargetKnown(surface)) | |
110 m_stack.last().occlusionInTarget = Region(); | |
111 if (!surfaceTransformsToScreenKnown(surface)) | |
112 m_stack.last().occlusionInScreen = Region(); | |
113 } | |
114 } | |
115 | |
116 template<typename RenderSurfaceType> | |
117 static inline Region transformSurfaceOpaqueRegion(const RenderSurfaceType* surfa
ce, const Region& region, const WebTransformationMatrix& transform) | |
118 { | |
119 // Verify that rects within the |surface| will remain rects in its target su
rface after applying |transform|. If this is true, then | |
120 // apply |transform| to each rect within |region| in order to transform the
entire Region. | |
121 | |
122 bool clipped; | |
123 FloatQuad transformedBoundsQuad = CCMathUtil::mapQuad(transform, FloatQuad(r
egion.bounds()), clipped); | |
124 // FIXME: Find a rect interior to each transformed quad. | |
125 if (clipped || !transformedBoundsQuad.isRectilinear()) | |
126 return Region(); | |
127 | |
128 Region transformedRegion; | |
129 | |
130 Vector<WebCore::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 c
alls should not clip anything further. | |
133 IntRect transformedRect = enclosedIntRect(CCMathUtil::mapClippedRect(tra
nsform, FloatRect(rects[i]))); | |
134 if (!surface->clipRect().isEmpty()) | |
135 transformedRect.intersect(surface->clipRect()); | |
136 transformedRegion.unite(transformedRect); | |
137 } | |
138 return transformedRegion; | |
139 } | |
140 | |
141 static inline void reduceOcclusion(const IntRect& affectedArea, const IntRect& e
xpandedPixel, Region& occlusion) | |
142 { | |
143 if (affectedArea.isEmpty()) | |
144 return; | |
145 | |
146 Region affectedOcclusion = intersect(occlusion, affectedArea); | |
147 Vector<WebCore::IntRect> affectedOcclusionRects = affectedOcclusion.rects(); | |
148 | |
149 occlusion.subtract(affectedArea); | |
150 for (size_t j = 0; j < affectedOcclusionRects.size(); ++j) { | |
151 WebCore::IntRect& occlusionRect = affectedOcclusionRects[j]; | |
152 | |
153 // Shrink the rect by expanding the non-opaque pixels outside the rect. | |
154 | |
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 | |
159 // being filtered. | |
160 // To convert the expandedPixel IntRect back to filter outsets: | |
161 // x = -leftOutset | |
162 // width = leftOutset + rightOutset | |
163 // maxX = x + width = -leftOutset + leftOutset + rightOutset = rightOuts
et | |
164 | |
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 : expandedPix
el.maxX(); | |
168 int shrinkTop = occlusionRect.y() == affectedArea.y() ? 0 : expandedPixe
l.maxY(); | |
169 int shrinkRight = occlusionRect.maxX() == affectedArea.maxX() ? 0 : -exp
andedPixel.x(); | |
170 int shrinkBottom = occlusionRect.maxY() == affectedArea.maxY() ? 0 : -ex
pandedPixel.y(); | |
171 | |
172 occlusionRect.move(shrinkLeft, shrinkTop); | |
173 occlusionRect.contract(shrinkLeft + shrinkRight, shrinkTop + shrinkBotto
m); | |
174 | |
175 occlusion.unite(occlusionRect); | |
176 } | |
177 } | |
178 | |
179 template<typename LayerType> | |
180 static void reduceOcclusionBelowSurface(LayerType* contributingLayer, const IntR
ect& surfaceRect, const WebTransformationMatrix& surfaceTransform, LayerType* re
nderTarget, Region& occlusionInTarget, Region& occlusionInScreen) | |
181 { | |
182 if (surfaceRect.isEmpty()) | |
183 return; | |
184 | |
185 IntRect boundsInTarget = enclosingIntRect(CCMathUtil::mapClippedRect(surface
Transform, FloatRect(surfaceRect))); | |
186 if (!contributingLayer->renderSurface()->clipRect().isEmpty()) | |
187 boundsInTarget.intersect(contributingLayer->renderSurface()->clipRect())
; | |
188 | |
189 int outsetTop, outsetRight, outsetBottom, outsetLeft; | |
190 contributingLayer->backgroundFilters().getOutsets(outsetTop, outsetRight, ou
tsetBottom, outsetLeft); | |
191 | |
192 // The filter can move pixels from outside of the clip, so allow affectedAre
a to expand outside the clip. | |
193 boundsInTarget.move(-outsetLeft, -outsetTop); | |
194 boundsInTarget.expand(outsetLeft + outsetRight, outsetTop + outsetBottom); | |
195 | |
196 IntRect boundsInScreen = enclosingIntRect(CCMathUtil::mapClippedRect(renderT
arget->renderSurface()->screenSpaceTransform(), FloatRect(boundsInTarget))); | |
197 | |
198 IntRect filterOutsetsInTarget(-outsetLeft, -outsetTop, outsetLeft + outsetRi
ght, outsetTop + outsetBottom); | |
199 IntRect filterOutsetsInScreen = enclosingIntRect(CCMathUtil::mapClippedRect(
renderTarget->renderSurface()->screenSpaceTransform(), FloatRect(filterOutsetsIn
Target))); | |
200 | |
201 reduceOcclusion(boundsInTarget, filterOutsetsInTarget, occlusionInTarget); | |
202 reduceOcclusion(boundsInScreen, filterOutsetsInScreen, occlusionInScreen); | |
203 } | |
204 | |
205 template<typename LayerType, typename RenderSurfaceType> | |
206 void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::leaveToRenderTarget(c
onst LayerType* newTarget) | |
207 { | |
208 int lastIndex = m_stack.size() - 1; | |
209 bool surfaceWillBeAtTopAfterPop = m_stack.size() > 1 && m_stack[lastIndex -
1].target == newTarget; | |
210 | |
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 transforme
d to the new target. | |
213 | |
214 const LayerType* oldTarget = m_stack[lastIndex].target; | |
215 const RenderSurfaceType* oldSurface = oldTarget->renderSurface(); | |
216 Region oldTargetOcclusionInNewTarget = transformSurfaceOpaqueRegion<RenderSu
rfaceType>(oldSurface, m_stack[lastIndex].occlusionInTarget, oldSurface->drawTra
nsform()); | |
217 if (oldTarget->hasReplica() && !oldTarget->replicaHasMask()) | |
218 oldTargetOcclusionInNewTarget.unite(transformSurfaceOpaqueRegion<RenderS
urfaceType>(oldSurface, m_stack[lastIndex].occlusionInTarget, oldSurface->replic
aDrawTransform())); | |
219 | |
220 IntRect unoccludedSurfaceRect; | |
221 IntRect unoccludedReplicaRect; | |
222 if (oldTarget->backgroundFilters().hasFilterThatMovesPixels()) { | |
223 unoccludedSurfaceRect = unoccludedContributingSurfaceContentRect(oldTarg
et, false, oldSurface->contentRect()); | |
224 if (oldTarget->hasReplica()) | |
225 unoccludedReplicaRect = unoccludedContributingSurfaceContentRect(old
Target, true, oldSurface->contentRect()); | |
226 } | |
227 | |
228 if (surfaceWillBeAtTopAfterPop) { | |
229 // Merge the top of the stack down. | |
230 m_stack[lastIndex - 1].occlusionInScreen.unite(m_stack[lastIndex].occlus
ionInScreen); | |
231 m_stack[lastIndex - 1].occlusionInTarget.unite(oldTargetOcclusionInNewTa
rget); | |
232 m_stack.removeLast(); | |
233 } else { | |
234 // Replace the top of the stack with the new pushed surface. Copy the oc
cluded screen region to the top. | |
235 m_stack.last().target = newTarget; | |
236 m_stack.last().occlusionInTarget = oldTargetOcclusionInNewTarget; | |
237 } | |
238 | |
239 if (oldTarget->backgroundFilters().hasFilterThatMovesPixels()) { | |
240 reduceOcclusionBelowSurface(oldTarget, unoccludedSurfaceRect, oldSurface
->drawTransform(), newTarget, m_stack.last().occlusionInTarget, m_stack.last().o
cclusionInScreen); | |
241 if (oldTarget->hasReplica()) | |
242 reduceOcclusionBelowSurface(oldTarget, unoccludedReplicaRect, oldSur
face->replicaDrawTransform(), newTarget, m_stack.last().occlusionInTarget, m_sta
ck.last().occlusionInScreen); | |
243 } | |
244 } | |
245 | |
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* laye
r, const WebTransformationMatrix& transform, const Region& opaqueContents, const
IntRect& clipRectInTarget, const IntSize& minimumTrackingSize, Vector<IntRect>*
occludingScreenSpaceRects) | |
249 { | |
250 ASSERT(layer->visibleContentRect().contains(opaqueContents.bounds())); | |
251 | |
252 bool clipped; | |
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()) | |
256 return; | |
257 | |
258 Vector<WebCore::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 c
alls should not clip anything further. | |
261 IntRect transformedRect = enclosedIntRect(CCMathUtil::mapClippedRect(tra
nsform, FloatRect(contentRects[i]))); | |
262 transformedRect.intersect(clipRectInTarget); | |
263 if (transformedRect.width() >= minimumTrackingSize.width() || transforme
dRect.height() >= minimumTrackingSize.height()) { | |
264 if (occludingScreenSpaceRects) | |
265 occludingScreenSpaceRects->append(transformedRect); | |
266 region.unite(transformedRect); | |
267 } | |
268 } | |
269 } | |
270 | |
271 template<typename LayerType, typename RenderSurfaceType> | |
272 void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::markOccludedBehindLay
er(const LayerType* layer) | |
273 { | |
274 ASSERT(!m_stack.isEmpty()); | |
275 ASSERT(layer->renderTarget() == m_stack.last().target); | |
276 if (m_stack.isEmpty()) | |
277 return; | |
278 | |
279 if (!layerOpacityKnown(layer) || layer->drawOpacity() < 1) | |
280 return; | |
281 | |
282 if (layerIsInUnsorted3dRenderingContext(layer)) | |
283 return; | |
284 | |
285 Region opaqueContents = layer->visibleContentOpaqueRegion(); | |
286 if (opaqueContents.isEmpty()) | |
287 return; | |
288 | |
289 IntRect clipRectInTarget = layerClipRectInTarget(layer); | |
290 if (layerTransformsToTargetKnown(layer)) | |
291 addOcclusionBehindLayer<LayerType>(m_stack.last().occlusionInTarget, lay
er, layer->drawTransform(), opaqueContents, clipRectInTarget, m_minimumTrackingS
ize, 0); | |
292 | |
293 // We must clip the occlusion within the layer's clipRectInTarget within scr
een 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. | |
295 | |
296 if (layerTransformsToScreenKnown(layer)) { | |
297 WebTransformationMatrix targetToScreenTransform = m_stack.last().target-
>renderSurface()->screenSpaceTransform(); | |
298 bool clipped; | |
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()) | |
302 return; | |
303 IntRect clipRectInScreen = intersection(m_rootTargetRect, enclosedIntRec
t(clipQuadInScreen.boundingBox())); | |
304 addOcclusionBehindLayer<LayerType>(m_stack.last().occlusionInScreen, lay
er, layer->screenSpaceTransform(), opaqueContents, clipRectInScreen, m_minimumTr
ackingSize, m_occludingScreenSpaceRects); | |
305 } | |
306 } | |
307 | |
308 static inline bool testContentRectOccluded(const IntRect& contentRect, const Web
TransformationMatrix& contentSpaceTransform, const IntRect& clipRectInTarget, co
nst Region& occlusion) | |
309 { | |
310 FloatRect transformedRect = CCMathUtil::mapClippedRect(contentSpaceTransform
, FloatRect(contentRect)); | |
311 // Take the enclosingIntRect, as we want to include partial pixels in the te
st. | |
312 IntRect targetRect = intersection(enclosingIntRect(transformedRect), clipRec
tInTarget); | |
313 return targetRect.isEmpty() || occlusion.contains(targetRect); | |
314 } | |
315 | |
316 template<typename LayerType, typename RenderSurfaceType> | |
317 bool CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::occluded(const LayerT
ype* layer, const IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurfa
ce) const | |
318 { | |
319 if (hasOcclusionFromOutsideTargetSurface) | |
320 *hasOcclusionFromOutsideTargetSurface = false; | |
321 | |
322 ASSERT(!m_stack.isEmpty()); | |
323 if (m_stack.isEmpty()) | |
324 return false; | |
325 if (contentRect.isEmpty()) | |
326 return true; | |
327 | |
328 ASSERT(layer->renderTarget() == m_stack.last().target); | |
329 | |
330 if (layerTransformsToTargetKnown(layer) && testContentRectOccluded(contentRe
ct, layer->drawTransform(), layerClipRectInTarget(layer), m_stack.last().occlusi
onInTarget)) | |
331 return true; | |
332 | |
333 if (layerTransformsToScreenKnown(layer) && testContentRectOccluded(contentRe
ct, layer->screenSpaceTransform(), m_rootTargetRect, m_stack.last().occlusionInS
creen)) { | |
334 if (hasOcclusionFromOutsideTargetSurface) | |
335 *hasOcclusionFromOutsideTargetSurface = true; | |
336 return true; | |
337 } | |
338 | |
339 return false; | |
340 } | |
341 | |
342 // Determines what portion of rect, if any, is unoccluded (not occluded by regio
n). If | |
343 // the resulting unoccluded region is not rectangular, we return a rect containi
ng it. | |
344 static inline IntRect rectSubtractRegion(const IntRect& rect, const Region& regi
on) | |
345 { | |
346 Region rectRegion(rect); | |
347 rectRegion.subtract(region); | |
348 return rectRegion.bounds(); | |
349 } | |
350 | |
351 static inline IntRect computeUnoccludedContentRect(const IntRect& contentRect, c
onst WebTransformationMatrix& contentSpaceTransform, const IntRect& clipRectInTa
rget, const Region& occlusion) | |
352 { | |
353 if (!contentSpaceTransform.isInvertible()) | |
354 return contentRect; | |
355 | |
356 // Take the enclosingIntRect at each step, as we want to contain any unocclu
ded partial pixels in the resulting IntRect. | |
357 FloatRect transformedRect = CCMathUtil::mapClippedRect(contentSpaceTransform
, FloatRect(contentRect)); | |
358 IntRect shrunkRect = rectSubtractRegion(intersection(enclosingIntRect(transf
ormedRect), clipRectInTarget), occlusion); | |
359 IntRect unoccludedRect = enclosingIntRect(CCMathUtil::projectClippedRect(con
tentSpaceTransform.inverse(), FloatRect(shrunkRect))); | |
360 // The rect back in content space is a bounding box and may extend outside o
f the original contentRect, so clamp it to the contentRectBounds. | |
361 return intersection(unoccludedRect, contentRect); | |
362 } | |
363 | |
364 template<typename LayerType, typename RenderSurfaceType> | |
365 IntRect CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::unoccludedContentR
ect(const LayerType* layer, const IntRect& contentRect, bool* hasOcclusionFromOu
tsideTargetSurface) const | |
366 { | |
367 ASSERT(!m_stack.isEmpty()); | |
368 if (m_stack.isEmpty()) | |
369 return contentRect; | |
370 if (contentRect.isEmpty()) | |
371 return contentRect; | |
372 | |
373 ASSERT(layer->renderTarget() == m_stack.last().target); | |
374 | |
375 // We want to return a rect that contains all the visible parts of |contentR
ect| 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. | |
377 | |
378 IntRect unoccludedInScreen = contentRect; | |
379 if (layerTransformsToScreenKnown(layer)) | |
380 unoccludedInScreen = computeUnoccludedContentRect(contentRect, layer->sc
reenSpaceTransform(), m_rootTargetRect, m_stack.last().occlusionInScreen); | |
381 | |
382 IntRect unoccludedInTarget = contentRect; | |
383 if (layerTransformsToTargetKnown(layer)) | |
384 unoccludedInTarget = computeUnoccludedContentRect(contentRect, layer->dr
awTransform(), layerClipRectInTarget(layer), m_stack.last().occlusionInTarget); | |
385 | |
386 if (hasOcclusionFromOutsideTargetSurface) | |
387 *hasOcclusionFromOutsideTargetSurface = (intersection(unoccludedInScreen
, unoccludedInTarget) != unoccludedInTarget); | |
388 | |
389 return intersection(unoccludedInScreen, unoccludedInTarget); | |
390 } | |
391 | |
392 template<typename LayerType, typename RenderSurfaceType> | |
393 IntRect CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::unoccludedContribu
tingSurfaceContentRect(const LayerType* layer, bool forReplica, const IntRect& c
ontentRect, bool* hasOcclusionFromOutsideTargetSurface) const | |
394 { | |
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 tar
get in the occlusion tracker. | |
403 ASSERT(layer == m_stack.last().target); | |
404 | |
405 if (contentRect.isEmpty()) | |
406 return contentRect; | |
407 | |
408 RenderSurfaceType* surface = layer->renderSurface(); | |
409 | |
410 IntRect surfaceClipRect = surface->clipRect(); | |
411 if (surfaceClipRect.isEmpty()) { | |
412 LayerType* contributingSurfaceRenderTarget = layer->parent()->renderTarg
et(); | |
413 surfaceClipRect = intersection(contributingSurfaceRenderTarget->renderSu
rface()->contentRect(), enclosingIntRect(surface->drawableContentRect())); | |
414 } | |
415 | |
416 // A contributing surface doesn't get occluded by things inside its own surf
ace, 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; | |
419 | |
420 const WebTransformationMatrix& transformToScreen = forReplica ? surface->rep
licaScreenSpaceTransform() : surface->screenSpaceTransform(); | |
421 const WebTransformationMatrix& transformToTarget = forReplica ? surface->rep
licaDrawTransform() : surface->drawTransform(); | |
422 | |
423 IntRect unoccludedInScreen = contentRect; | |
424 if (surfaceTransformsToScreenKnown(surface)) { | |
425 if (hasOcclusion) { | |
426 const StackObject& secondLast = m_stack[m_stack.size() - 2]; | |
427 unoccludedInScreen = computeUnoccludedContentRect(contentRect, trans
formToScreen, m_rootTargetRect, secondLast.occlusionInScreen); | |
428 } else | |
429 unoccludedInScreen = computeUnoccludedContentRect(contentRect, trans
formToScreen, m_rootTargetRect, Region()); | |
430 } | |
431 | |
432 IntRect unoccludedInTarget = contentRect; | |
433 if (surfaceTransformsToTargetKnown(surface)) { | |
434 if (hasOcclusion) { | |
435 const StackObject& secondLast = m_stack[m_stack.size() - 2]; | |
436 unoccludedInTarget = computeUnoccludedContentRect(contentRect, trans
formToTarget, surfaceClipRect, secondLast.occlusionInTarget); | |
437 } else | |
438 unoccludedInTarget = computeUnoccludedContentRect(contentRect, trans
formToTarget, surfaceClipRect, Region()); | |
439 } | |
440 | |
441 if (hasOcclusionFromOutsideTargetSurface) | |
442 *hasOcclusionFromOutsideTargetSurface = (intersection(unoccludedInScreen
, unoccludedInTarget) != unoccludedInTarget); | |
443 | |
444 return intersection(unoccludedInScreen, unoccludedInTarget); | |
445 } | |
446 | |
447 template<typename LayerType, typename RenderSurfaceType> | |
448 IntRect CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::layerClipRectInTar
get(const LayerType* layer) const | |
449 { | |
450 // FIXME: we could remove this helper function, but unit tests currently ove
rride this | |
451 // function, and they need to be verified/adjusted before this can be
removed. | |
452 return layer->drawableContentRect(); | |
453 } | |
454 | |
455 // Declare the possible functions here for the linker. | |
456 template CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::CCOcclusi
onTrackerBase(IntRect rootTargetRect, bool recordMetricsForFrame); | |
457 template void CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::ente
rLayer(const CCLayerIteratorPosition<LayerChromium>&); | |
458 template void CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::leav
eLayer(const CCLayerIteratorPosition<LayerChromium>&); | |
459 template void CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::ente
rRenderTarget(const LayerChromium* newTarget); | |
460 template void CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::fini
shedRenderTarget(const LayerChromium* finishedTarget); | |
461 template void CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::leav
eToRenderTarget(const LayerChromium* newTarget); | |
462 template void CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::mark
OccludedBehindLayer(const LayerChromium*); | |
463 template bool CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::occl
uded(const LayerChromium*, const IntRect& contentRect, bool* hasOcclusionFromOut
sideTargetSurface) const; | |
464 template IntRect CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::u
noccludedContentRect(const LayerChromium*, const IntRect& contentRect, bool* has
OcclusionFromOutsideTargetSurface) const; | |
465 template IntRect CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::u
noccludedContributingSurfaceContentRect(const LayerChromium*, bool forReplica, c
onst IntRect& contentRect, bool* hasOcclusionFromOutsideTargetSurface) const; | |
466 template IntRect CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::l
ayerClipRectInTarget(const LayerChromium*) const; | |
467 | |
468 template CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::CCOcclusionTracke
rBase(IntRect rootTargetRect, bool recordMetricsForFrame); | |
469 template void CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::enterLayer(c
onst CCLayerIteratorPosition<CCLayerImpl>&); | |
470 template void CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::leaveLayer(c
onst CCLayerIteratorPosition<CCLayerImpl>&); | |
471 template void CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::enterRenderT
arget(const CCLayerImpl* newTarget); | |
472 template void CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::finishedRend
erTarget(const CCLayerImpl* finishedTarget); | |
473 template void CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::leaveToRende
rTarget(const CCLayerImpl* newTarget); | |
474 template void CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::markOccluded
BehindLayer(const CCLayerImpl*); | |
475 template bool CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::occluded(con
st CCLayerImpl*, const IntRect& contentRect, bool* hasOcclusionFromOutsideTarget
Surface) const; | |
476 template IntRect CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::unocclude
dContentRect(const CCLayerImpl*, const IntRect& contentRect, bool* hasOcclusionF
romOutsideTargetSurface) const; | |
477 template IntRect CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::unocclude
dContributingSurfaceContentRect(const CCLayerImpl*, bool forReplica, const IntRe
ct& contentRect, bool* hasOcclusionFromOutsideTargetSurface) const; | |
478 template IntRect CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::layerClip
RectInTarget(const CCLayerImpl*) const; | |
479 | |
480 | |
481 } // namespace cc | |
482 #endif // USE(ACCELERATED_COMPOSITING) | |
OLD | NEW |