OLD | NEW |
| (Empty) |
1 // Copyright 2011 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 | |
6 #include "config.h" | |
7 | |
8 #include "CCLayerTreeHostCommon.h" | |
9 | |
10 #include "CCLayerImpl.h" | |
11 #include "CCLayerIterator.h" | |
12 #include "CCLayerSorter.h" | |
13 #include "CCMathUtil.h" | |
14 #include "CCRenderSurface.h" | |
15 #include "FloatQuad.h" | |
16 #include "IntRect.h" | |
17 #include "LayerChromium.h" | |
18 #include "RenderSurfaceChromium.h" | |
19 #include <public/WebTransformationMatrix.h> | |
20 | |
21 using WebKit::WebTransformationMatrix; | |
22 | |
23 namespace cc { | |
24 | |
25 CCScrollAndScaleSet::CCScrollAndScaleSet() | |
26 { | |
27 } | |
28 | |
29 CCScrollAndScaleSet::~CCScrollAndScaleSet() | |
30 { | |
31 } | |
32 | |
33 IntRect CCLayerTreeHostCommon::calculateVisibleRect(const IntRect& targetSurface
Rect, const IntRect& layerBoundRect, const WebTransformationMatrix& transform) | |
34 { | |
35 // Is this layer fully contained within the target surface? | |
36 IntRect layerInSurfaceSpace = CCMathUtil::mapClippedRect(transform, layerBou
ndRect); | |
37 if (targetSurfaceRect.contains(layerInSurfaceSpace)) | |
38 return layerBoundRect; | |
39 | |
40 // If the layer doesn't fill up the entire surface, then find the part of | |
41 // the surface rect where the layer could be visible. This avoids trying to | |
42 // project surface rect points that are behind the projection point. | |
43 IntRect minimalSurfaceRect = targetSurfaceRect; | |
44 minimalSurfaceRect.intersect(layerInSurfaceSpace); | |
45 | |
46 // Project the corners of the target surface rect into the layer space. | |
47 // This bounding rectangle may be larger than it needs to be (being | |
48 // axis-aligned), but is a reasonable filter on the space to consider. | |
49 // Non-invertible transforms will create an empty rect here. | |
50 const WebTransformationMatrix surfaceToLayer = transform.inverse(); | |
51 IntRect layerRect = enclosingIntRect(CCMathUtil::projectClippedRect(surfaceT
oLayer, FloatRect(minimalSurfaceRect))); | |
52 layerRect.intersect(layerBoundRect); | |
53 return layerRect; | |
54 } | |
55 | |
56 template<typename LayerType> | |
57 static inline bool layerIsInExisting3DRenderingContext(LayerType* layer) | |
58 { | |
59 // According to current W3C spec on CSS transforms, a layer is part of an es
tablished | |
60 // 3d rendering context if its parent has transform-style of preserves-3d. | |
61 return layer->parent() && layer->parent()->preserves3D(); | |
62 } | |
63 | |
64 template<typename LayerType> | |
65 static bool layerIsRootOfNewRenderingContext(LayerType* layer) | |
66 { | |
67 // According to current W3C spec on CSS transforms (Section 6.1), a layer is
the | |
68 // beginning of 3d rendering context if its parent does not have transform-s
tyle: | |
69 // preserve-3d, but this layer itself does. | |
70 if (layer->parent()) | |
71 return !layer->parent()->preserves3D() && layer->preserves3D(); | |
72 | |
73 return layer->preserves3D(); | |
74 } | |
75 | |
76 template<typename LayerType> | |
77 static bool isLayerBackFaceVisible(LayerType* layer) | |
78 { | |
79 // The current W3C spec on CSS transforms says that backface visibility shou
ld be | |
80 // determined differently depending on whether the layer is in a "3d renderi
ng | |
81 // context" or not. For Chromium code, we can determine whether we are in a
3d | |
82 // rendering context by checking if the parent preserves 3d. | |
83 | |
84 if (layerIsInExisting3DRenderingContext(layer)) | |
85 return layer->drawTransform().isBackFaceVisible(); | |
86 | |
87 // In this case, either the layer establishes a new 3d rendering context, or
is not in | |
88 // a 3d rendering context at all. | |
89 return layer->transform().isBackFaceVisible(); | |
90 } | |
91 | |
92 template<typename LayerType> | |
93 static bool isSurfaceBackFaceVisible(LayerType* layer, const WebTransformationMa
trix& drawTransform) | |
94 { | |
95 if (layerIsInExisting3DRenderingContext(layer)) | |
96 return drawTransform.isBackFaceVisible(); | |
97 | |
98 if (layerIsRootOfNewRenderingContext(layer)) | |
99 return layer->transform().isBackFaceVisible(); | |
100 | |
101 // If the renderSurface is not part of a new or existing rendering context,
then the | |
102 // layers that contribute to this surface will decide back-face visibility f
or themselves. | |
103 return false; | |
104 } | |
105 | |
106 template<typename LayerType> | |
107 static inline bool layerClipsSubtree(LayerType* layer) | |
108 { | |
109 return layer->masksToBounds() || layer->maskLayer(); | |
110 } | |
111 | |
112 template<typename LayerType> | |
113 static IntRect calculateVisibleContentRect(LayerType* layer) | |
114 { | |
115 ASSERT(layer->renderTarget()); | |
116 | |
117 // Nothing is visible if the layer bounds are empty. | |
118 if (!layer->drawsContent() || layer->contentBounds().isEmpty() || layer->dra
wableContentRect().isEmpty()) | |
119 return IntRect(); | |
120 | |
121 IntRect targetSurfaceClipRect; | |
122 | |
123 // First, compute visible bounds in target surface space. | |
124 if (layer->renderTarget()->renderSurface()->clipRect().isEmpty()) | |
125 targetSurfaceClipRect = layer->drawableContentRect(); | |
126 else { | |
127 // In this case the target surface does clip layers that contribute to i
t. So, we | |
128 // have convert the current surface's clipRect from its ancestor surface
space to | |
129 // the current surface space. | |
130 targetSurfaceClipRect = enclosingIntRect(CCMathUtil::projectClippedRect(
layer->renderTarget()->renderSurface()->drawTransform().inverse(), layer->render
Target()->renderSurface()->clipRect())); | |
131 targetSurfaceClipRect.intersect(layer->drawableContentRect()); | |
132 } | |
133 | |
134 if (targetSurfaceClipRect.isEmpty()) | |
135 return IntRect(); | |
136 | |
137 return CCLayerTreeHostCommon::calculateVisibleRect(targetSurfaceClipRect, In
tRect(IntPoint(), layer->contentBounds()), layer->drawTransform()); | |
138 } | |
139 | |
140 static bool isScaleOrTranslation(const WebTransformationMatrix& m) | |
141 { | |
142 return !m.m12() && !m.m13() && !m.m14() | |
143 && !m.m21() && !m.m23() && !m.m24() | |
144 && !m.m31() && !m.m32() && !m.m43() | |
145 && m.m44(); | |
146 } | |
147 | |
148 static inline bool transformToParentIsKnown(CCLayerImpl*) | |
149 { | |
150 return true; | |
151 } | |
152 | |
153 static inline bool transformToParentIsKnown(LayerChromium* layer) | |
154 { | |
155 return !layer->transformIsAnimating(); | |
156 } | |
157 | |
158 static inline bool transformToScreenIsKnown(CCLayerImpl*) | |
159 { | |
160 return true; | |
161 } | |
162 | |
163 static inline bool transformToScreenIsKnown(LayerChromium* layer) | |
164 { | |
165 return !layer->screenSpaceTransformIsAnimating(); | |
166 } | |
167 | |
168 template<typename LayerType> | |
169 static bool layerShouldBeSkipped(LayerType* layer) | |
170 { | |
171 // Layers can be skipped if any of these conditions are met. | |
172 // - does not draw content. | |
173 // - is transparent | |
174 // - has empty bounds | |
175 // - the layer is not double-sided, but its back face is visible. | |
176 // | |
177 // Some additional conditions need to be computed at a later point after the
recursion is finished. | |
178 // - the intersection of render surface content and layer clipRect is empt
y | |
179 // - the visibleContentRect is empty | |
180 // | |
181 // Note, if the layer should not have been drawn due to being fully transpar
ent, | |
182 // we would have skipped the entire subtree and never made it into this func
tion, | |
183 // so it is safe to omit this check here. | |
184 | |
185 if (!layer->drawsContent() || layer->bounds().isEmpty()) | |
186 return true; | |
187 | |
188 LayerType* backfaceTestLayer = layer; | |
189 if (layer->useParentBackfaceVisibility()) { | |
190 ASSERT(layer->parent()); | |
191 ASSERT(!layer->parent()->useParentBackfaceVisibility()); | |
192 backfaceTestLayer = layer->parent(); | |
193 } | |
194 | |
195 // The layer should not be drawn if (1) it is not double-sided and (2) the b
ack of the layer is known to be facing the screen. | |
196 if (!backfaceTestLayer->doubleSided() && transformToScreenIsKnown(backfaceTe
stLayer) && isLayerBackFaceVisible(backfaceTestLayer)) | |
197 return true; | |
198 | |
199 return false; | |
200 } | |
201 | |
202 static inline bool subtreeShouldBeSkipped(CCLayerImpl* layer) | |
203 { | |
204 // The opacity of a layer always applies to its children (either implicitly | |
205 // via a render surface or explicitly if the parent preserves 3D), so the | |
206 // entire subtree can be skipped if this layer is fully transparent. | |
207 return !layer->opacity(); | |
208 } | |
209 | |
210 static inline bool subtreeShouldBeSkipped(LayerChromium* layer) | |
211 { | |
212 // If the opacity is being animated then the opacity on the main thread is u
nreliable | |
213 // (since the impl thread may be using a different opacity), so it should no
t be trusted. | |
214 // In particular, it should not cause the subtree to be skipped. | |
215 return !layer->opacity() && !layer->opacityIsAnimating(); | |
216 } | |
217 | |
218 template<typename LayerType> | |
219 static bool subtreeShouldRenderToSeparateSurface(LayerType* layer, bool axisAlig
nedWithRespectToParent) | |
220 { | |
221 // The root layer has a special render surface that is set up externally, so | |
222 // it shouldn't be treated as a surface in this code. | |
223 if (!layer->parent()) | |
224 return false; | |
225 | |
226 // Cache this value, because otherwise it walks the entire subtree several t
imes. | |
227 bool descendantDrawsContent = layer->descendantDrawsContent(); | |
228 | |
229 // | |
230 // A layer and its descendants should render onto a new RenderSurface if any
of these rules hold: | |
231 // | |
232 | |
233 // If we force it. | |
234 if (layer->forceRenderSurface()) | |
235 return true; | |
236 | |
237 // If the layer uses a mask. | |
238 if (layer->maskLayer()) | |
239 return true; | |
240 | |
241 // If the layer has a reflection. | |
242 if (layer->replicaLayer()) | |
243 return true; | |
244 | |
245 // If the layer uses a CSS filter. | |
246 if (!layer->filters().isEmpty() || !layer->backgroundFilters().isEmpty()) | |
247 return true; | |
248 | |
249 // If the layer flattens its subtree (i.e. the layer doesn't preserve-3d), b
ut it is | |
250 // treated as a 3D object by its parent (i.e. parent does preserve-3d). | |
251 if (layerIsInExisting3DRenderingContext(layer) && !layer->preserves3D() && d
escendantDrawsContent) | |
252 return true; | |
253 | |
254 // If the layer clips its descendants but it is not axis-aligned with respec
t to its parent. | |
255 if (layerClipsSubtree(layer) && !axisAlignedWithRespectToParent && descendan
tDrawsContent) | |
256 return true; | |
257 | |
258 // If the layer has opacity != 1 and does not have a preserves-3d transform
style. | |
259 if (layer->opacity() != 1 && !layer->preserves3D() && descendantDrawsContent
) | |
260 return true; | |
261 | |
262 return false; | |
263 } | |
264 | |
265 WebTransformationMatrix computeScrollCompensationForThisLayer(CCLayerImpl* scrol
lingLayer, const WebTransformationMatrix& parentMatrix) | |
266 { | |
267 // For every layer that has non-zero scrollDelta, we have to compute a trans
form that can undo the | |
268 // scrollDelta translation. In particular, we want this matrix to premultipl
y a fixed-position layer's | |
269 // parentMatrix, so we design this transform in three steps as follows. The
steps described here apply | |
270 // from right-to-left, so Step 1 would be the right-most matrix: | |
271 // | |
272 // Step 1. transform from target surface space to the exact space where
scrollDelta is actually applied. | |
273 // -- this is inverse of the matrix in step 3 | |
274 // Step 2. undo the scrollDelta | |
275 // -- this is just a translation by scrollDelta. | |
276 // Step 3. transform back to target surface space. | |
277 // -- this transform is the "partialLayerOriginTransform" = (paren
tMatrix * scale(layer->pageScaleDelta())); | |
278 // | |
279 // These steps create a matrix that both start and end in targetSurfaceSpace
. So this matrix can | |
280 // pre-multiply any fixed-position layer's drawTransform to undo the scrollD
eltas -- as long as | |
281 // that fixed position layer is fixed onto the same renderTarget as this scr
ollingLayer. | |
282 // | |
283 | |
284 WebTransformationMatrix partialLayerOriginTransform = parentMatrix; | |
285 partialLayerOriginTransform.multiply(scrollingLayer->implTransform()); | |
286 | |
287 WebTransformationMatrix scrollCompensationForThisLayer = partialLayerOriginT
ransform; // Step 3 | |
288 scrollCompensationForThisLayer.translate(scrollingLayer->scrollDelta().width
(), scrollingLayer->scrollDelta().height()); // Step 2 | |
289 scrollCompensationForThisLayer.multiply(partialLayerOriginTransform.inverse(
)); // Step 1 | |
290 return scrollCompensationForThisLayer; | |
291 } | |
292 | |
293 WebTransformationMatrix computeScrollCompensationMatrixForChildren(LayerChromium
* currentLayer, const WebTransformationMatrix& currentParentMatrix, const WebTra
nsformationMatrix& currentScrollCompensation) | |
294 { | |
295 // The main thread (i.e. LayerChromium) does not need to worry about scroll
compensation. | |
296 // So we can just return an identity matrix here. | |
297 return WebTransformationMatrix(); | |
298 } | |
299 | |
300 WebTransformationMatrix computeScrollCompensationMatrixForChildren(CCLayerImpl*
layer, const WebTransformationMatrix& parentMatrix, const WebTransformationMatri
x& currentScrollCompensationMatrix) | |
301 { | |
302 // "Total scroll compensation" is the transform needed to cancel out all scr
ollDelta translations that | |
303 // occurred since the nearest container layer, even if there are renderSurfa
ces in-between. | |
304 // | |
305 // There are some edge cases to be aware of, that are not explicit in the co
de: | |
306 // - A layer that is both a fixed-position and container should not be its
own container, instead, that means | |
307 // it is fixed to an ancestor, and is a container for any fixed-position
descendants. | |
308 // - A layer that is a fixed-position container and has a renderSurface sho
uld behave the same as a container | |
309 // without a renderSurface, the renderSurface is irrelevant in that case. | |
310 // - A layer that does not have an explicit container is simply fixed to th
e viewport | |
311 // (i.e. the root renderSurface, and it would still compensate for root l
ayer's scrollDelta). | |
312 // - If the fixed-position layer has its own renderSurface, then the render
Surface is | |
313 // the one who gets fixed. | |
314 // | |
315 // This function needs to be called AFTER layers create their own renderSurf
aces. | |
316 // | |
317 | |
318 // Avoid the overheads (including stack allocation and matrix initialization
/copy) if we know that the scroll compensation doesn't need to be reset or adjus
ted. | |
319 if (!layer->isContainerForFixedPositionLayers() && layer->scrollDelta().isZe
ro() && !layer->renderSurface()) | |
320 return currentScrollCompensationMatrix; | |
321 | |
322 // Start as identity matrix. | |
323 WebTransformationMatrix nextScrollCompensationMatrix; | |
324 | |
325 // If this layer is not a container, then it inherits the existing scroll co
mpensations. | |
326 if (!layer->isContainerForFixedPositionLayers()) | |
327 nextScrollCompensationMatrix = currentScrollCompensationMatrix; | |
328 | |
329 // If the current layer has a non-zero scrollDelta, then we should compute i
ts local scrollCompensation | |
330 // and accumulate it to the nextScrollCompensationMatrix. | |
331 if (!layer->scrollDelta().isZero()) { | |
332 WebTransformationMatrix scrollCompensationForThisLayer = computeScrollCo
mpensationForThisLayer(layer, parentMatrix); | |
333 nextScrollCompensationMatrix.multiply(scrollCompensationForThisLayer); | |
334 } | |
335 | |
336 // If the layer created its own renderSurface, we have to adjust nextScrollC
ompensationMatrix. | |
337 // The adjustment allows us to continue using the scrollCompensation on the
next surface. | |
338 // Step 1 (right-most in the math): transform from the new surface to the o
riginal ancestor surface | |
339 // Step 2: apply the scroll compensation | |
340 // Step 3: transform back to the new surface. | |
341 if (layer->renderSurface() && !nextScrollCompensationMatrix.isIdentity()) | |
342 nextScrollCompensationMatrix = layer->renderSurface()->drawTransform().i
nverse() * nextScrollCompensationMatrix * layer->renderSurface()->drawTransform(
); | |
343 | |
344 return nextScrollCompensationMatrix; | |
345 } | |
346 | |
347 // Should be called just before the recursive calculateDrawTransformsInternal(). | |
348 template<typename LayerType, typename LayerList> | |
349 void setupRootLayerAndSurfaceForRecursion(LayerType* rootLayer, LayerList& rende
rSurfaceLayerList, const IntSize& deviceViewportSize) | |
350 { | |
351 if (!rootLayer->renderSurface()) | |
352 rootLayer->createRenderSurface(); | |
353 | |
354 rootLayer->renderSurface()->setContentRect(IntRect(IntPoint::zero(), deviceV
iewportSize)); | |
355 rootLayer->renderSurface()->clearLayerLists(); | |
356 | |
357 ASSERT(renderSurfaceLayerList.empty()); | |
358 renderSurfaceLayerList.push_back(rootLayer); | |
359 } | |
360 | |
361 // Recursively walks the layer tree starting at the given node and computes all
the | |
362 // necessary transformations, clipRects, render surfaces, etc. | |
363 template<typename LayerType, typename LayerList, typename RenderSurfaceType, typ
ename LayerSorter> | |
364 static void calculateDrawTransformsInternal(LayerType* layer, LayerType* rootLay
er, const WebTransformationMatrix& parentMatrix, | |
365 const WebTransformationMatrix& fullHierarchyMatrix, const WebTransformationM
atrix& currentScrollCompensationMatrix, | |
366 const IntRect& clipRectFromAncestor, bool ancestorClipsSubtree, | |
367 RenderSurfaceType* nearestAncestorThatMovesPixels, LayerList& renderSurfaceL
ayerList, LayerList& layerList, | |
368 LayerSorter* layerSorter, int maxTextureSize, float deviceScaleFactor, IntRe
ct& drawableContentRectOfSubtree) | |
369 { | |
370 // This function computes the new matrix transformations recursively for thi
s | |
371 // layer and all its descendants. It also computes the appropriate render su
rfaces. | |
372 // Some important points to remember: | |
373 // | |
374 // 0. Here, transforms are notated in Matrix x Vector order, and in words we
describe what | |
375 // the transform does from left to right. | |
376 // | |
377 // 1. In our terminology, the "layer origin" refers to the top-left corner o
f a layer, and the | |
378 // positive Y-axis points downwards. This interpretation is valid because
the orthographic | |
379 // projection applied at draw time flips the Y axis appropriately. | |
380 // | |
381 // 2. The anchor point, when given as a FloatPoint object, is specified in "
unit layer space", | |
382 // where the bounds of the layer map to [0, 1]. However, as a WebTransfor
mationMatrix object, | |
383 // the transform to the anchor point is specified in "layer space", where
the bounds | |
384 // of the layer map to [bounds.width(), bounds.height()]. | |
385 // | |
386 // 3. Definition of various transforms used: | |
387 // M[parent] is the parent matrix, with respect to the nearest render
surface, passed down recursively. | |
388 // M[root] is the full hierarchy, with respect to the root, passed do
wn recursively. | |
389 // Tr[origin] is the translation matrix from the parent's origin to t
his layer's origin. | |
390 // Tr[origin2anchor] is the translation from the layer's origin to it
s anchor point | |
391 // Tr[origin2center] is the translation from the layer's origin to it
s center | |
392 // M[layer] is the layer's matrix (applied at the anchor point) | |
393 // M[sublayer] is the layer's sublayer transform (applied at the laye
r's center) | |
394 // S[layer2content] is the ratio of a layer's contentBounds() to its
bounds(). | |
395 // | |
396 // Some composite transforms can help in understanding the sequence of tr
ansforms: | |
397 // compositeLayerTransform = Tr[origin2anchor] * M[layer] * Tr[origin
2anchor].inverse() | |
398 // compositeSublayerTransform = Tr[origin2center] * M[sublayer] * Tr[
origin2center].inverse() | |
399 // | |
400 // In words, the layer transform is applied about the anchor point, and t
he sublayer transform is | |
401 // applied about the center of the layer. | |
402 // | |
403 // 4. When a layer (or render surface) is drawn, it is drawn into a "target
render surface". Therefore the draw | |
404 // transform does not necessarily transform from screen space to local la
yer space. Instead, the draw transform | |
405 // is the transform between the "target render surface space" and local l
ayer space. Note that render surfaces, | |
406 // except for the root, also draw themselves into a different target rend
er surface, and so their draw | |
407 // transform and origin transforms are also described with respect to the
target. | |
408 // | |
409 // Using these definitions, then: | |
410 // | |
411 // The draw transform for the layer is: | |
412 // M[draw] = M[parent] * Tr[origin] * compositeLayerTransform * S[lay
er2content] | |
413 // = M[parent] * Tr[layer->position() + anchor] * M[layer] *
Tr[anchor2origin] * S[layer2content] | |
414 // | |
415 // Interpreting the math left-to-right, this transforms from the laye
r's render surface to the origin of the layer in content space. | |
416 // | |
417 // The screen space transform is: | |
418 // M[screenspace] = M[root] * Tr[origin] * compositeLayerTransform *
S[layer2content] | |
419 // = M[root] * Tr[layer->position() + anchor] * M[laye
r] * Tr[anchor2origin] * S[layer2content] | |
420 // | |
421 // Interpreting the math left-to-right, this transforms from the root
render surface's content space to the local layer's origin in layer space. | |
422 // | |
423 // The transform hierarchy that is passed on to children (i.e. the child's p
arentMatrix) is: | |
424 // M[parent]_for_child = M[parent] * Tr[origin] * compositeLayerTrans
form * compositeSublayerTransform | |
425 // = M[parent] * Tr[layer->position() + anchor] *
M[layer] * Tr[anchor2origin] * compositeSublayerTransform | |
426 // | |
427 // and a similar matrix for the full hierarchy with respect to the ro
ot. | |
428 // | |
429 // Finally, note that the final matrix used by the shader for the layer is P
* M[draw] * S . This final product | |
430 // is computed in drawTexturedQuad(), where: | |
431 // P is the projection matrix | |
432 // S is the scale adjustment (to scale up a canonical quad to the lay
er's size) | |
433 // | |
434 // When a render surface has a replica layer, that layer's transform is used
to draw a second copy of the surface. | |
435 // Transforms named here are relative to the surface, unless they specify th
ey are relative to the replica layer. | |
436 // | |
437 // We will denote a scale by device scale S[deviceScale] | |
438 // | |
439 // The render surface draw transform to its target surface origin is: | |
440 // M[surfaceDraw] = M[owningLayer->Draw] | |
441 // | |
442 // The render surface origin transform to its the root (screen space) origin
is: | |
443 // M[surface2root] = M[owningLayer->screenspace] * S[deviceScale].in
verse() | |
444 // | |
445 // The replica draw transform to its target surface origin is: | |
446 // M[replicaDraw] = S[deviceScale] * M[surfaceDraw] * Tr[replica->pos
ition() + replica->anchor()] * Tr[replica] * Tr[origin2anchor].inverse() * S[con
tentsScale].inverse() | |
447 // | |
448 // The replica draw transform to the root (screen space) origin is: | |
449 // M[replica2root] = M[surface2root] * Tr[replica->position()] * Tr[r
eplica] * Tr[origin2anchor].inverse() | |
450 // | |
451 | |
452 // If we early-exit anywhere in this function, the drawableContentRect of th
is subtree should be considered empty. | |
453 drawableContentRectOfSubtree = IntRect(); | |
454 | |
455 if (subtreeShouldBeSkipped(layer)) | |
456 return; | |
457 | |
458 IntRect clipRectForSubtree; | |
459 bool subtreeShouldBeClipped = false; | |
460 | |
461 float drawOpacity = layer->opacity(); | |
462 bool drawOpacityIsAnimating = layer->opacityIsAnimating(); | |
463 if (layer->parent() && layer->parent()->preserves3D()) { | |
464 drawOpacity *= layer->parent()->drawOpacity(); | |
465 drawOpacityIsAnimating |= layer->parent()->drawOpacityIsAnimating(); | |
466 } | |
467 | |
468 IntSize bounds = layer->bounds(); | |
469 FloatPoint anchorPoint = layer->anchorPoint(); | |
470 FloatPoint position = layer->position() - layer->scrollDelta(); | |
471 | |
472 WebTransformationMatrix layerLocalTransform; | |
473 // LT = M[impl transformation] | |
474 layerLocalTransform.multiply(layer->implTransform()); | |
475 // LT = M[impl transformation] * Tr[origin] * Tr[origin2anchor] | |
476 layerLocalTransform.translate3d(position.x() + anchorPoint.x() * bounds.widt
h(), position.y() + anchorPoint.y() * bounds.height(), layer->anchorPointZ()); | |
477 // LT = M[impl transformation] * Tr[origin] * Tr[origin2anchor] * M[layer] | |
478 layerLocalTransform.multiply(layer->transform()); | |
479 // LT = S[impl transformation] * Tr[origin] * Tr[origin2anchor] * M[layer] *
Tr[anchor2origin] | |
480 layerLocalTransform.translate3d(-anchorPoint.x() * bounds.width(), -anchorPo
int.y() * bounds.height(), -layer->anchorPointZ()); | |
481 | |
482 WebTransformationMatrix combinedTransform = parentMatrix; | |
483 combinedTransform.multiply(layerLocalTransform); | |
484 | |
485 if (layer->fixedToContainerLayer()) { | |
486 // Special case: this layer is a composited fixed-position layer; we nee
d to | |
487 // explicitly compensate for all ancestors' nonzero scrollDeltas to keep
this layer | |
488 // fixed correctly. | |
489 combinedTransform = currentScrollCompensationMatrix * combinedTransform; | |
490 } | |
491 | |
492 // The drawTransform that gets computed below is effectively the layer's dra
wTransform, unless | |
493 // the layer itself creates a renderSurface. In that case, the renderSurface
re-parents the transforms. | |
494 WebTransformationMatrix drawTransform = combinedTransform; | |
495 if (!layer->contentBounds().isEmpty() && !layer->bounds().isEmpty()) { | |
496 // M[draw] = M[parent] * LT * S[layer2content] | |
497 drawTransform.scaleNonUniform(layer->bounds().width() / static_cast<doub
le>(layer->contentBounds().width()), | |
498 layer->bounds().height() / static_cast<dou
ble>(layer->contentBounds().height())); | |
499 } | |
500 | |
501 // layerScreenSpaceTransform represents the transform between root layer's "
screen space" and local content space. | |
502 WebTransformationMatrix layerScreenSpaceTransform = fullHierarchyMatrix; | |
503 if (!layer->preserves3D()) | |
504 CCMathUtil::flattenTransformTo2d(layerScreenSpaceTransform); | |
505 layerScreenSpaceTransform.multiply(drawTransform); | |
506 layer->setScreenSpaceTransform(layerScreenSpaceTransform); | |
507 | |
508 bool animatingTransformToTarget = layer->transformIsAnimating(); | |
509 bool animatingTransformToScreen = animatingTransformToTarget; | |
510 if (layer->parent()) { | |
511 animatingTransformToTarget |= layer->parent()->drawTransformIsAnimating(
); | |
512 animatingTransformToScreen |= layer->parent()->screenSpaceTransformIsAni
mating(); | |
513 } | |
514 | |
515 FloatRect contentRect(FloatPoint(), layer->contentBounds()); | |
516 | |
517 // fullHierarchyMatrix is the matrix that transforms objects between screen
space (except projection matrix) and the most recent RenderSurface's space. | |
518 // nextHierarchyMatrix will only change if this layer uses a new RenderSurfa
ce, otherwise remains the same. | |
519 WebTransformationMatrix nextHierarchyMatrix = fullHierarchyMatrix; | |
520 WebTransformationMatrix sublayerMatrix; | |
521 | |
522 if (subtreeShouldRenderToSeparateSurface(layer, isScaleOrTranslation(combine
dTransform))) { | |
523 // Check back-face visibility before continuing with this surface and it
s subtree | |
524 if (!layer->doubleSided() && transformToParentIsKnown(layer) && isSurfac
eBackFaceVisible(layer, combinedTransform)) | |
525 return; | |
526 | |
527 if (!layer->renderSurface()) | |
528 layer->createRenderSurface(); | |
529 | |
530 RenderSurfaceType* renderSurface = layer->renderSurface(); | |
531 renderSurface->clearLayerLists(); | |
532 | |
533 // The origin of the new surface is the upper left corner of the layer. | |
534 renderSurface->setDrawTransform(drawTransform); | |
535 WebTransformationMatrix layerDrawTransform; | |
536 layerDrawTransform.scale(deviceScaleFactor); | |
537 if (!layer->contentBounds().isEmpty() && !layer->bounds().isEmpty()) { | |
538 layerDrawTransform.scaleNonUniform(layer->bounds().width() / static_
cast<double>(layer->contentBounds().width()), | |
539 layer->bounds().height() / static
_cast<double>(layer->contentBounds().height())); | |
540 } | |
541 layer->setDrawTransform(layerDrawTransform); | |
542 | |
543 // The sublayer matrix transforms centered layer rects into target | |
544 // surface content space. | |
545 sublayerMatrix.makeIdentity(); | |
546 sublayerMatrix.scale(deviceScaleFactor); | |
547 | |
548 // The opacity value is moved from the layer to its surface, so that the
entire subtree properly inherits opacity. | |
549 renderSurface->setDrawOpacity(drawOpacity); | |
550 renderSurface->setDrawOpacityIsAnimating(drawOpacityIsAnimating); | |
551 layer->setDrawOpacity(1); | |
552 layer->setDrawOpacityIsAnimating(false); | |
553 | |
554 renderSurface->setTargetSurfaceTransformsAreAnimating(animatingTransform
ToTarget); | |
555 renderSurface->setScreenSpaceTransformsAreAnimating(animatingTransformTo
Screen); | |
556 animatingTransformToTarget = false; | |
557 layer->setDrawTransformIsAnimating(animatingTransformToTarget); | |
558 layer->setScreenSpaceTransformIsAnimating(animatingTransformToScreen); | |
559 | |
560 // Update the aggregate hierarchy matrix to include the transform of the | |
561 // newly created RenderSurface. | |
562 nextHierarchyMatrix.multiply(renderSurface->drawTransform()); | |
563 | |
564 // The new renderSurface here will correctly clip the entire subtree. So
, we do | |
565 // not need to continue propagating the clipping state further down the
tree. This | |
566 // way, we can avoid transforming clipRects from ancestor target surface
space to | |
567 // current target surface space that could cause more w < 0 headaches. | |
568 subtreeShouldBeClipped = false; | |
569 | |
570 if (layer->maskLayer()) { | |
571 layer->maskLayer()->setRenderTarget(layer); | |
572 layer->maskLayer()->setVisibleContentRect(IntRect(IntPoint(), layer-
>contentBounds())); | |
573 } | |
574 | |
575 if (layer->replicaLayer() && layer->replicaLayer()->maskLayer()) { | |
576 layer->replicaLayer()->maskLayer()->setRenderTarget(layer); | |
577 layer->replicaLayer()->maskLayer()->setVisibleContentRect(IntRect(In
tPoint(), layer->contentBounds())); | |
578 } | |
579 | |
580 if (layer->filters().hasFilterThatMovesPixels()) | |
581 nearestAncestorThatMovesPixels = renderSurface; | |
582 | |
583 // The render surface clipRect is expressed in the space where this surf
ace draws, i.e. the same space as clipRectFromAncestor. | |
584 if (ancestorClipsSubtree) | |
585 renderSurface->setClipRect(clipRectFromAncestor); | |
586 else | |
587 renderSurface->setClipRect(IntRect()); | |
588 | |
589 renderSurface->setNearestAncestorThatMovesPixels(nearestAncestorThatMove
sPixels); | |
590 | |
591 renderSurfaceLayerList.push_back(layer); | |
592 } else { | |
593 layer->setDrawTransform(drawTransform); | |
594 layer->setDrawTransformIsAnimating(animatingTransformToTarget); | |
595 layer->setScreenSpaceTransformIsAnimating(animatingTransformToScreen); | |
596 sublayerMatrix = combinedTransform; | |
597 | |
598 layer->setDrawOpacity(drawOpacity); | |
599 layer->setDrawOpacityIsAnimating(drawOpacityIsAnimating); | |
600 | |
601 if (layer != rootLayer) { | |
602 ASSERT(layer->parent()); | |
603 layer->clearRenderSurface(); | |
604 | |
605 // Layers without renderSurfaces directly inherit the ancestor's cli
p status. | |
606 subtreeShouldBeClipped = ancestorClipsSubtree; | |
607 if (ancestorClipsSubtree) | |
608 clipRectForSubtree = clipRectFromAncestor; | |
609 | |
610 // Layers that are not their own renderTarget will render into the t
arget of their nearest ancestor. | |
611 layer->setRenderTarget(layer->parent()->renderTarget()); | |
612 } else { | |
613 // FIXME: This root layer special case code should eventually go awa
y. https://bugs.webkit.org/show_bug.cgi?id=92290 | |
614 ASSERT(!layer->parent()); | |
615 ASSERT(layer->renderSurface()); | |
616 ASSERT(ancestorClipsSubtree); | |
617 layer->renderSurface()->setClipRect(clipRectFromAncestor); | |
618 subtreeShouldBeClipped = false; | |
619 } | |
620 } | |
621 | |
622 IntRect rectInTargetSpace = enclosingIntRect(CCMathUtil::mapClippedRect(laye
r->drawTransform(), contentRect)); | |
623 | |
624 if (layerClipsSubtree(layer)) { | |
625 subtreeShouldBeClipped = true; | |
626 if (ancestorClipsSubtree && !layer->renderSurface()) { | |
627 clipRectForSubtree = clipRectFromAncestor; | |
628 clipRectForSubtree.intersect(rectInTargetSpace); | |
629 } else | |
630 clipRectForSubtree = rectInTargetSpace; | |
631 } | |
632 | |
633 // Flatten to 2D if the layer doesn't preserve 3D. | |
634 if (!layer->preserves3D()) | |
635 CCMathUtil::flattenTransformTo2d(sublayerMatrix); | |
636 | |
637 // Apply the sublayer transform at the center of the layer. | |
638 sublayerMatrix.translate(0.5 * bounds.width(), 0.5 * bounds.height()); | |
639 sublayerMatrix.multiply(layer->sublayerTransform()); | |
640 sublayerMatrix.translate(-0.5 * bounds.width(), -0.5 * bounds.height()); | |
641 | |
642 LayerList& descendants = (layer->renderSurface() ? layer->renderSurface()->l
ayerList() : layerList); | |
643 | |
644 // Any layers that are appended after this point are in the layer's subtree
and should be included in the sorting process. | |
645 unsigned sortingStartIndex = descendants.size(); | |
646 | |
647 if (!layerShouldBeSkipped(layer)) | |
648 descendants.push_back(layer); | |
649 | |
650 WebTransformationMatrix nextScrollCompensationMatrix = computeScrollCompensa
tionMatrixForChildren(layer, parentMatrix, currentScrollCompensationMatrix);; | |
651 | |
652 IntRect accumulatedDrawableContentRectOfChildren; | |
653 for (size_t i = 0; i < layer->children().size(); ++i) { | |
654 LayerType* child = CCLayerTreeHostCommon::getChildAsRawPtr(layer->childr
en(), i); | |
655 IntRect drawableContentRectOfChildSubtree; | |
656 calculateDrawTransformsInternal<LayerType, LayerList, RenderSurfaceType,
LayerSorter>(child, rootLayer, sublayerMatrix, nextHierarchyMatrix, nextScrollC
ompensationMatrix, | |
657
clipRectForSubtree, subtreeShouldBeClipped, nearestAncestorThatMov
esPixels, | |
658
renderSurfaceLayerList, descendants, layerSorter, maxTextureSize,
deviceScaleFactor, drawableContentRectOfChildSubtree); | |
659 if (!drawableContentRectOfChildSubtree.isEmpty()) { | |
660 accumulatedDrawableContentRectOfChildren.unite(drawableContentRectOf
ChildSubtree); | |
661 if (child->renderSurface()) | |
662 descendants.push_back(child); | |
663 } | |
664 } | |
665 | |
666 // Compute the total drawableContentRect for this subtree (the rect is in ta
rgetSurface space) | |
667 IntRect localDrawableContentRectOfSubtree = accumulatedDrawableContentRectOf
Children; | |
668 if (layer->drawsContent()) | |
669 localDrawableContentRectOfSubtree.unite(rectInTargetSpace); | |
670 if (subtreeShouldBeClipped) | |
671 localDrawableContentRectOfSubtree.intersect(clipRectForSubtree); | |
672 | |
673 // Compute the layer's drawable content rect (the rect is in targetSurface s
pace) | |
674 IntRect drawableContentRectOfLayer = rectInTargetSpace; | |
675 if (subtreeShouldBeClipped) | |
676 drawableContentRectOfLayer.intersect(clipRectForSubtree); | |
677 layer->setDrawableContentRect(drawableContentRectOfLayer); | |
678 | |
679 // Compute the layer's visible content rect (the rect is in content space) | |
680 IntRect visibleContentRectOfLayer = calculateVisibleContentRect(layer); | |
681 layer->setVisibleContentRect(visibleContentRectOfLayer); | |
682 | |
683 // Compute the remaining properties for the render surface, if the layer has
one. | |
684 if (layer->renderSurface() && layer != rootLayer) { | |
685 RenderSurfaceType* renderSurface = layer->renderSurface(); | |
686 IntRect clippedContentRect = localDrawableContentRectOfSubtree; | |
687 | |
688 // Don't clip if the layer is reflected as the reflection shouldn't be | |
689 // clipped. If the layer is animating, then the surface's transform to | |
690 // its target is not known on the main thread, and we should not use it | |
691 // to clip. | |
692 if (!layer->replicaLayer() && transformToParentIsKnown(layer)) { | |
693 // Note, it is correct to use ancestorClipsSubtree here, because we
are looking at this layer's renderSurface, not the layer itself. | |
694 if (ancestorClipsSubtree && !clippedContentRect.isEmpty()) { | |
695 IntRect surfaceClipRect = CCLayerTreeHostCommon::calculateVisibl
eRect(renderSurface->clipRect(), clippedContentRect, renderSurface->drawTransfor
m()); | |
696 clippedContentRect.intersect(surfaceClipRect); | |
697 } | |
698 } | |
699 | |
700 // The RenderSurface backing texture cannot exceed the maximum supported | |
701 // texture size. | |
702 clippedContentRect.setWidth(std::min(clippedContentRect.width(), maxText
ureSize)); | |
703 clippedContentRect.setHeight(std::min(clippedContentRect.height(), maxTe
xtureSize)); | |
704 | |
705 if (clippedContentRect.isEmpty()) | |
706 renderSurface->clearLayerLists(); | |
707 | |
708 renderSurface->setContentRect(clippedContentRect); | |
709 renderSurface->setScreenSpaceTransform(layer->screenSpaceTransform()); | |
710 | |
711 if (layer->replicaLayer()) { | |
712 WebTransformationMatrix surfaceOriginToReplicaOriginTransform; | |
713 surfaceOriginToReplicaOriginTransform.scale(deviceScaleFactor); | |
714 surfaceOriginToReplicaOriginTransform.translate(layer->replicaLayer(
)->position().x() + layer->replicaLayer()->anchorPoint().x() * bounds.width(), | |
715 layer->replicaLayer(
)->position().y() + layer->replicaLayer()->anchorPoint().y() * bounds.height()); | |
716 surfaceOriginToReplicaOriginTransform.multiply(layer->replicaLayer()
->transform()); | |
717 surfaceOriginToReplicaOriginTransform.translate(-layer->replicaLayer
()->anchorPoint().x() * bounds.width(), -layer->replicaLayer()->anchorPoint().y(
) * bounds.height()); | |
718 surfaceOriginToReplicaOriginTransform.scale(1 / deviceScaleFactor); | |
719 | |
720 // Compute the replica's "originTransform" that maps from the replic
a's origin space to the target surface origin space. | |
721 WebTransformationMatrix replicaOriginTransform = layer->renderSurfac
e()->drawTransform() * surfaceOriginToReplicaOriginTransform; | |
722 renderSurface->setReplicaDrawTransform(replicaOriginTransform); | |
723 | |
724 // Compute the replica's "screenSpaceTransform" that maps from the r
eplica's origin space to the screen's origin space. | |
725 WebTransformationMatrix replicaScreenSpaceTransform = layer->renderS
urface()->screenSpaceTransform() * surfaceOriginToReplicaOriginTransform; | |
726 renderSurface->setReplicaScreenSpaceTransform(replicaScreenSpaceTran
sform); | |
727 } | |
728 | |
729 // If a render surface has no layer list, then it and none of its childr
en needed to get drawn. | |
730 if (!layer->renderSurface()->layerList().size()) { | |
731 // FIXME: Originally we asserted that this layer was already at the
end of the | |
732 // list, and only needed to remove that layer. For now, we re
move the | |
733 // entire subtree of surfaces to fix a crash bug. The root ca
use is | |
734 // https://bugs.webkit.org/show_bug.cgi?id=74147 and we shoul
d be able | |
735 // to put the original assert after fixing that. | |
736 while (renderSurfaceLayerList.back() != layer) { | |
737 renderSurfaceLayerList.back()->clearRenderSurface(); | |
738 renderSurfaceLayerList.pop_back(); | |
739 } | |
740 ASSERT(renderSurfaceLayerList.back() == layer); | |
741 renderSurfaceLayerList.pop_back(); | |
742 layer->clearRenderSurface(); | |
743 return; | |
744 } | |
745 } | |
746 | |
747 // If neither this layer nor any of its children were added, early out. | |
748 if (sortingStartIndex == descendants.size()) | |
749 return; | |
750 | |
751 // If preserves-3d then sort all the descendants in 3D so that they can be | |
752 // drawn from back to front. If the preserves-3d property is also set on the
parent then | |
753 // skip the sorting as the parent will sort all the descendants anyway. | |
754 if (descendants.size() && layer->preserves3D() && (!layer->parent() || !laye
r->parent()->preserves3D())) | |
755 sortLayers(descendants.begin() + sortingStartIndex, descendants.end(), l
ayerSorter); | |
756 | |
757 if (layer->renderSurface()) | |
758 drawableContentRectOfSubtree = enclosingIntRect(layer->renderSurface()->
drawableContentRect()); | |
759 else | |
760 drawableContentRectOfSubtree = localDrawableContentRectOfSubtree; | |
761 | |
762 if (layer->hasContributingDelegatedRenderPasses()) | |
763 layer->renderTarget()->renderSurface()->addContributingDelegatedRenderPa
ssLayer(layer); | |
764 } | |
765 | |
766 void CCLayerTreeHostCommon::calculateDrawTransforms(LayerChromium* rootLayer, co
nst IntSize& deviceViewportSize, float deviceScaleFactor, int maxTextureSize, st
d::vector<scoped_refptr<LayerChromium> >& renderSurfaceLayerList) | |
767 { | |
768 IntRect totalDrawableContentRect; | |
769 WebTransformationMatrix identityMatrix; | |
770 WebTransformationMatrix deviceScaleTransform; | |
771 deviceScaleTransform.scale(deviceScaleFactor); | |
772 | |
773 setupRootLayerAndSurfaceForRecursion<LayerChromium, std::vector<scoped_refpt
r<LayerChromium> > >(rootLayer, renderSurfaceLayerList, deviceViewportSize); | |
774 | |
775 cc::calculateDrawTransformsInternal<LayerChromium, std::vector<scoped_refptr
<LayerChromium> >, RenderSurfaceChromium, void>(rootLayer, rootLayer, deviceScal
eTransform, identityMatrix, identityMatrix, | |
776
rootLayer->renderSurface()->contentRect
(), true, 0, renderSurfaceLayerList, | |
777
rootLayer->renderSurface()->layerList()
, 0, maxTextureSize, deviceScaleFactor, totalDrawableContentRect); | |
778 } | |
779 | |
780 void CCLayerTreeHostCommon::calculateDrawTransforms(CCLayerImpl* rootLayer, cons
t IntSize& deviceViewportSize, float deviceScaleFactor, CCLayerSorter* layerSort
er, int maxTextureSize, std::vector<CCLayerImpl*>& renderSurfaceLayerList) | |
781 { | |
782 IntRect totalDrawableContentRect; | |
783 WebTransformationMatrix identityMatrix; | |
784 WebTransformationMatrix deviceScaleTransform; | |
785 deviceScaleTransform.scale(deviceScaleFactor); | |
786 | |
787 setupRootLayerAndSurfaceForRecursion<CCLayerImpl, std::vector<CCLayerImpl*>
>(rootLayer, renderSurfaceLayerList, deviceViewportSize); | |
788 | |
789 cc::calculateDrawTransformsInternal<CCLayerImpl, std::vector<CCLayerImpl*>,
CCRenderSurface, CCLayerSorter>(rootLayer, rootLayer, deviceScaleTransform, iden
tityMatrix, identityMatrix, | |
790
rootLayer->renderSurface()->contentRect(), true,
0, renderSurfaceLayerList, | |
791
rootLayer->renderSurface()->layerList(), layerSo
rter, maxTextureSize, deviceScaleFactor, totalDrawableContentRect); | |
792 } | |
793 | |
794 static bool pointHitsRect(const IntPoint& viewportPoint, const WebTransformation
Matrix& localSpaceToScreenSpaceTransform, FloatRect localSpaceRect) | |
795 { | |
796 // If the transform is not invertible, then assume that this point doesn't h
it this rect. | |
797 if (!localSpaceToScreenSpaceTransform.isInvertible()) | |
798 return false; | |
799 | |
800 // Transform the hit test point from screen space to the local space of the
given rect. | |
801 bool clipped = false; | |
802 FloatPoint hitTestPointInLocalSpace = CCMathUtil::projectPoint(localSpaceToS
creenSpaceTransform.inverse(), FloatPoint(viewportPoint), clipped); | |
803 | |
804 // If projectPoint could not project to a valid value, then we assume that t
his point doesn't hit this rect. | |
805 if (clipped) | |
806 return false; | |
807 | |
808 return localSpaceRect.contains(hitTestPointInLocalSpace); | |
809 } | |
810 | |
811 static bool pointIsClippedBySurfaceOrClipRect(const IntPoint& viewportPoint, CCL
ayerImpl* layer) | |
812 { | |
813 CCLayerImpl* currentLayer = layer; | |
814 | |
815 // Walk up the layer tree and hit-test any renderSurfaces and any layer clip
Rects that are active. | |
816 while (currentLayer) { | |
817 if (currentLayer->renderSurface() && !pointHitsRect(viewportPoint, curre
ntLayer->renderSurface()->screenSpaceTransform(), currentLayer->renderSurface()-
>contentRect())) | |
818 return true; | |
819 | |
820 // Note that drawableContentRects are actually in targetSurface space, s
o the transform we | |
821 // have to provide is the target surface's screenSpaceTransform. | |
822 CCLayerImpl* renderTarget = currentLayer->renderTarget(); | |
823 if (layerClipsSubtree(currentLayer) && !pointHitsRect(viewportPoint, ren
derTarget->renderSurface()->screenSpaceTransform(), currentLayer->drawableConten
tRect())) | |
824 return true; | |
825 | |
826 currentLayer = currentLayer->parent(); | |
827 } | |
828 | |
829 // If we have finished walking all ancestors without having already exited,
then the point is not clipped by any ancestors. | |
830 return false; | |
831 } | |
832 | |
833 CCLayerImpl* CCLayerTreeHostCommon::findLayerThatIsHitByPoint(const IntPoint& vi
ewportPoint, std::vector<CCLayerImpl*>& renderSurfaceLayerList) | |
834 { | |
835 CCLayerImpl* foundLayer = 0; | |
836 | |
837 typedef CCLayerIterator<CCLayerImpl, std::vector<CCLayerImpl*>, CCRenderSurf
ace, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType; | |
838 CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList); | |
839 | |
840 for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayer
List); it != end; ++it) { | |
841 // We don't want to consider renderSurfaces for hit testing. | |
842 if (!it.representsItself()) | |
843 continue; | |
844 | |
845 CCLayerImpl* currentLayer = (*it); | |
846 | |
847 FloatRect contentRect(FloatPoint::zero(), currentLayer->contentBounds())
; | |
848 if (!pointHitsRect(viewportPoint, currentLayer->screenSpaceTransform(),
contentRect)) | |
849 continue; | |
850 | |
851 // At this point, we think the point does hit the layer, but we need to
walk up | |
852 // the parents to ensure that the layer was not clipped in such a way th
at the | |
853 // hit point actually should not hit the layer. | |
854 if (pointIsClippedBySurfaceOrClipRect(viewportPoint, currentLayer)) | |
855 continue; | |
856 | |
857 foundLayer = currentLayer; | |
858 break; | |
859 } | |
860 | |
861 // This can potentially return 0, which means the viewportPoint did not succ
essfully hit test any layers, not even the root layer. | |
862 return foundLayer; | |
863 } | |
864 | |
865 } // namespace cc | |
OLD | NEW |