| 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 |