void CCDamageTracker::extendDamageForLayer(CCLayerImpl* layer, FloatRect& targetDamageRect) { // There are two ways that a layer can damage a region of the target surface: // 1. Property change (e.g. opacity, position, transforms): // - the entire region of the layer itself damages the surface. // - the old layer region also damages the surface, because this region is now exposed. // - note that in many cases the old and new layer rects may overlap, which is fine. // // 2. Repaint/update: If a region of the layer that was repainted/updated, that // region damages the surface. // // Property changes take priority over update rects. // // This method is called when we want to consider how a layer contributes to its // targetRenderSurface, even if that layer owns the targetRenderSurface itself. // To consider how a layer's targetSurface contributes to the ancestorSurface, // extendDamageForRenderSurface() must be called instead. bool layerIsNew = false; FloatRect oldRectInTargetSpace = removeRectFromCurrentFrame(layer->id(), layerIsNew); FloatRect rectInTargetSpace = CCMathUtil::mapClippedRect(layer->drawTransform(), FloatRect(FloatPoint::zero(), layer->contentBounds())); saveRectForNextFrame(layer->id(), rectInTargetSpace); if (layerIsNew || layerNeedsToRedrawOntoItsTargetSurface(layer)) { // If a layer is new or has changed, then its entire layer rect affects the target surface. targetDamageRect.uniteIfNonZero(rectInTargetSpace); // The layer's old region is now exposed on the target surface, too. // Note oldRectInTargetSpace is already in target space. targetDamageRect.uniteIfNonZero(oldRectInTargetSpace); } else if (!layer->updateRect().isEmpty()) { // If the layer properties havent changed, then the the target surface is only // affected by the layer's update area, which could be empty. FloatRect updateContentRect = layer->updateRect(); float widthScale = layer->contentBounds().width() / static_cast<float>(layer->bounds().width()); float heightScale = layer->contentBounds().height() / static_cast<float>(layer->bounds().height()); updateContentRect.scale(widthScale, heightScale); FloatRect updateRectInTargetSpace = CCMathUtil::mapClippedRect(layer->drawTransform(), updateContentRect); targetDamageRect.uniteIfNonZero(updateRectInTargetSpace); } }
void CCDamageTracker::extendDamageForLayer(CCLayerImpl* layer, FloatRect& targetDamageRect) { // There are two ways that a layer can damage a region of the target surface: // 1. Property change (e.g. opacity, position, transforms): // - the entire region of the layer itself damages the surface. // - the old layer region also damages the surface, because this region is now exposed. // - note that in many cases the old and new layer rects may overlap, which is fine. // // 2. Repaint/update: If a region of the layer that was repainted/updated, that // region damages the surface. // // Property changes take priority over update rects. // Compute the layer's "originTransform" by translating the drawTransform. TransformationMatrix originTransform = layer->drawTransform(); originTransform.translate(-0.5 * layer->bounds().width(), -0.5 * layer->bounds().height()); bool layerIsNew = false; FloatRect oldLayerRect = removeRectFromCurrentFrame(layer->id(), layerIsNew); FloatRect layerRectInTargetSpace = CCMathUtil::mapClippedRect(originTransform, FloatRect(FloatPoint::zero(), layer->bounds())); saveRectForNextFrame(layer->id(), layerRectInTargetSpace); if (layerIsNew || layer->layerPropertyChanged()) { // If a layer is new or has changed, then its entire layer rect affects the target surface. targetDamageRect.uniteIfNonZero(layerRectInTargetSpace); // The layer's old region is now exposed on the target surface, too. // Note oldLayerRect is already in target space. targetDamageRect.uniteIfNonZero(oldLayerRect); } else if (!layer->updateRect().isEmpty()) { // If the layer properties havent changed, then the the target surface is only // affected by the layer's update area, which could be empty. FloatRect updateRectInTargetSpace = CCMathUtil::mapClippedRect(originTransform, layer->updateRect()); targetDamageRect.uniteIfNonZero(updateRectInTargetSpace); } }
void CCDamageTracker::extendDamageForRenderSurface(CCLayerImpl* layer, FloatRect& targetDamageRect) { // There are two ways a "descendant surface" can damage regions of the "target surface": // 1. Property change: // - a surface's geometry can change because of // - changes to descendants (i.e. the subtree) that affect the surface's content rect // - changes to ancestor layers that propagate their property changes to their entire subtree. // - just like layers, both the old surface rect and new surface rect will // damage the target surface in this case. // // 2. Damage rect: This surface may have been damaged by its own layerList as well, and that damage // should propagate to the target surface. // CCRenderSurface* renderSurface = layer->renderSurface(); bool surfaceIsNew = false; FloatRect oldSurfaceRect = removeRectFromCurrentFrame(layer->id(), surfaceIsNew); FloatRect surfaceRectInTargetSpace = renderSurface->drawableContentRect(); // already includes replica if it exists. saveRectForNextFrame(layer->id(), surfaceRectInTargetSpace); FloatRect damageRectInLocalSpace; if (surfaceIsNew || renderSurface->surfacePropertyChanged() || layer->layerSurfacePropertyChanged()) { // The entire surface contributes damage. damageRectInLocalSpace = renderSurface->contentRect(); // The surface's old region is now exposed on the target surface, too. targetDamageRect.uniteIfNonZero(oldSurfaceRect); } else { // Only the surface's damageRect will damage the target surface. damageRectInLocalSpace = renderSurface->damageTracker()->currentDamageRect(); } // If there was damage, transform it to target space, and possibly contribute its reflection if needed. if (!damageRectInLocalSpace.isEmpty()) { const WebTransformationMatrix& drawTransform = renderSurface->drawTransform(); FloatRect damageRectInTargetSpace = CCMathUtil::mapClippedRect(drawTransform, damageRectInLocalSpace); targetDamageRect.uniteIfNonZero(damageRectInTargetSpace); if (layer->replicaLayer()) { const WebTransformationMatrix& replicaDrawTransform = renderSurface->replicaDrawTransform(); targetDamageRect.uniteIfNonZero(CCMathUtil::mapClippedRect(replicaDrawTransform, damageRectInLocalSpace)); } } // If there was damage on the replica's mask, then the target surface receives that damage as well. if (layer->replicaLayer() && layer->replicaLayer()->maskLayer()) { CCLayerImpl* replicaMaskLayer = layer->replicaLayer()->maskLayer(); bool replicaIsNew = false; removeRectFromCurrentFrame(replicaMaskLayer->id(), replicaIsNew); const WebTransformationMatrix& replicaDrawTransform = renderSurface->replicaDrawTransform(); FloatRect replicaMaskLayerRect = CCMathUtil::mapClippedRect(replicaDrawTransform, FloatRect(FloatPoint::zero(), FloatSize(replicaMaskLayer->bounds().width(), replicaMaskLayer->bounds().height()))); saveRectForNextFrame(replicaMaskLayer->id(), replicaMaskLayerRect); // In the current implementation, a change in the replica mask damages the entire replica region. if (replicaIsNew || replicaMaskLayer->layerPropertyChanged() || !replicaMaskLayer->updateRect().isEmpty()) targetDamageRect.uniteIfNonZero(replicaMaskLayerRect); } // If the layer has a background filter, this may cause pixels in our surface to be expanded, so we will need to expand any damage // at or below this layer. We expand the damage from this layer too, as we need to readback those pixels from the surface with only // the contents of layers below this one in them. This means we need to redraw any pixels in the surface being used for the blur in // this layer this frame. if (layer->backgroundFilters().hasFilterThatMovesPixels()) expandDamageRectInsideRectWithFilters(targetDamageRect, surfaceRectInTargetSpace, layer->backgroundFilters()); }
void CCDamageTracker::extendDamageForRenderSurface(CCLayerImpl* layer, FloatRect& targetDamageRect) { // There are two ways a "descendant surface" can damage regions of the "target surface": // 1. Property change: // - a surface's geometry can change because of // - changes to descendants (i.e. the subtree) that affect the surface's content rect // - changes to ancestor layers that propagate their property changes to their entire subtree. // - just like layers, both the old surface rect and new surface rect will // damage the target surface in this case. // // 2. Damage rect: This surface may have been damaged by its own layerList as well, and that damage // should propagate to the target surface. // CCRenderSurface* renderSurface = layer->renderSurface(); bool surfaceIsNew = false; FloatRect oldSurfaceRect = removeRectFromCurrentFrame(layer->id(), surfaceIsNew); FloatRect surfaceRectInTargetSpace = renderSurface->drawableContentRect(); // already includes replica if it exists. saveRectForNextFrame(layer->id(), surfaceRectInTargetSpace); FloatRect damageRectInLocalSpace; if (surfaceIsNew || renderSurface->surfacePropertyChanged()) { // The entire surface contributes damage. damageRectInLocalSpace = renderSurface->contentRect(); // The surface's old region is now exposed on the target surface, too. targetDamageRect.uniteIfNonZero(oldSurfaceRect); } else { // Only the surface's damageRect will damage the target surface. damageRectInLocalSpace = renderSurface->damageTracker()->currentDamageRect(); } // If there was damage, transform it to target space, and possibly contribute its reflection if needed. if (!damageRectInLocalSpace.isEmpty()) { const TransformationMatrix& originTransform = renderSurface->originTransform(); FloatRect damageRectInTargetSpace = CCMathUtil::mapClippedRect(originTransform, damageRectInLocalSpace); targetDamageRect.uniteIfNonZero(damageRectInTargetSpace); if (layer->replicaLayer()) { const TransformationMatrix& replicaOriginTransform = renderSurface->replicaOriginTransform(); targetDamageRect.uniteIfNonZero(CCMathUtil::mapClippedRect(replicaOriginTransform, damageRectInLocalSpace)); } } // If there was damage on the replica's mask, then the target surface receives that damage as well. if (layer->replicaLayer() && layer->replicaLayer()->maskLayer()) { CCLayerImpl* replicaMaskLayer = layer->replicaLayer()->maskLayer(); bool replicaIsNew = false; removeRectFromCurrentFrame(replicaMaskLayer->id(), replicaIsNew); // Compute the replica's "originTransform" that maps from the replica's origin space to the target surface origin space. const TransformationMatrix& replicaOriginTransform = renderSurface->replicaOriginTransform(); FloatRect replicaMaskLayerRect = CCMathUtil::mapClippedRect(replicaOriginTransform, FloatRect(FloatPoint::zero(), FloatSize(replicaMaskLayer->bounds().width(), replicaMaskLayer->bounds().height()))); saveRectForNextFrame(replicaMaskLayer->id(), replicaMaskLayerRect); // In the current implementation, a change in the replica mask damages the entire replica region. if (replicaIsNew || replicaMaskLayer->layerPropertyChanged() || !replicaMaskLayer->updateRect().isEmpty()) targetDamageRect.uniteIfNonZero(replicaMaskLayerRect); } }