1e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck/*
2e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck * Copyright (C) 2014 The Android Open Source Project
3e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck *
4e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck * Licensed under the Apache License, Version 2.0 (the "License");
5e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck * you may not use this file except in compliance with the License.
6e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck * You may obtain a copy of the License at
7e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck *
8e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck *      http://www.apache.org/licenses/LICENSE-2.0
9e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck *
10e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck * Unless required by applicable law or agreed to in writing, software
11e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck * distributed under the License is distributed on an "AS IS" BASIS,
12e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck * See the License for the specific language governing permissions and
14e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck * limitations under the License.
15e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck */
16e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck
17e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck#include "DamageAccumulator.h"
18e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck
1952eb4e01a49fe2e94555c000de38bbcbbb13401bMark Salyzyn#include <log/log.h>
20e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck
21e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck#include "RenderNode.h"
22e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck#include "utils/MathUtils.h"
23e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck
24e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Recknamespace android {
25e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Recknamespace uirenderer {
26e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck
27a447d29c65fb811cd184775a3476101a1cede929John Reckenum TransformType {
282dc223d23764a78f052529e86a59a1979d03b811John Reck    TransformInvalid = 0,
29a447d29c65fb811cd184775a3476101a1cede929John Reck    TransformRenderNode,
30a447d29c65fb811cd184775a3476101a1cede929John Reck    TransformMatrix4,
3125fbb3fa1138675379102a44405852555cefccbdJohn Reck    TransformNone,
32a447d29c65fb811cd184775a3476101a1cede929John Reck};
33a447d29c65fb811cd184775a3476101a1cede929John Reck
34e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reckstruct DirtyStack {
35a447d29c65fb811cd184775a3476101a1cede929John Reck    TransformType type;
36a447d29c65fb811cd184775a3476101a1cede929John Reck    union {
37a447d29c65fb811cd184775a3476101a1cede929John Reck        const RenderNode* renderNode;
38a447d29c65fb811cd184775a3476101a1cede929John Reck        const Matrix4* matrix4;
39a447d29c65fb811cd184775a3476101a1cede929John Reck    };
40e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    // When this frame is pop'd, this rect is mapped through the above transform
41e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    // and applied to the previous (aka parent) frame
42e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    SkRect pendingDirty;
43e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    DirtyStack* prev;
44e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    DirtyStack* next;
45e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck};
46e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck
47e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn ReckDamageAccumulator::DamageAccumulator() {
487df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck    mHead = mAllocator.create_trivial<DirtyStack>();
49e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    memset(mHead, 0, sizeof(DirtyStack));
50e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    // Create a root that we will not pop off
51e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    mHead->prev = mHead;
522dc223d23764a78f052529e86a59a1979d03b811John Reck    mHead->type = TransformNone;
53e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck}
54e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck
5569e5adffb19135d51bde8e458f4907d7265f3e23Chris Craikstatic void computeTransformImpl(const DirtyStack* currentFrame, Matrix4* outMatrix) {
5669e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik    if (currentFrame->prev != currentFrame) {
5769e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik        computeTransformImpl(currentFrame->prev, outMatrix);
5869e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik    }
5969e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik    switch (currentFrame->type) {
601bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        case TransformRenderNode:
611bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            currentFrame->renderNode->applyViewPropertyTransforms(*outMatrix);
621bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            break;
631bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        case TransformMatrix4:
641bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            outMatrix->multiply(*currentFrame->matrix4);
651bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            break;
661bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        case TransformNone:
671bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            // nothing to be done
681bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            break;
691bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        default:
701bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            LOG_ALWAYS_FATAL("Tried to compute transform with an invalid type: %d",
711bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                             currentFrame->type);
7269e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik    }
7369e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik}
7469e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik
7569e5adffb19135d51bde8e458f4907d7265f3e23Chris Craikvoid DamageAccumulator::computeCurrentTransform(Matrix4* outMatrix) const {
7669e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik    outMatrix->loadIdentity();
7769e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik    computeTransformImpl(mHead, outMatrix);
7869e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik}
7969e5adffb19135d51bde8e458f4907d7265f3e23Chris Craik
80a447d29c65fb811cd184775a3476101a1cede929John Reckvoid DamageAccumulator::pushCommon() {
81e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    if (!mHead->next) {
827df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck        DirtyStack* nextFrame = mAllocator.create_trivial<DirtyStack>();
83d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik        nextFrame->next = nullptr;
84e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck        nextFrame->prev = mHead;
85e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck        mHead->next = nextFrame;
86e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    }
87e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    mHead = mHead->next;
88e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    mHead->pendingDirty.setEmpty();
89e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck}
90e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck
91a447d29c65fb811cd184775a3476101a1cede929John Reckvoid DamageAccumulator::pushTransform(const RenderNode* transform) {
92a447d29c65fb811cd184775a3476101a1cede929John Reck    pushCommon();
93a447d29c65fb811cd184775a3476101a1cede929John Reck    mHead->type = TransformRenderNode;
94a447d29c65fb811cd184775a3476101a1cede929John Reck    mHead->renderNode = transform;
95a447d29c65fb811cd184775a3476101a1cede929John Reck}
96a447d29c65fb811cd184775a3476101a1cede929John Reck
97a447d29c65fb811cd184775a3476101a1cede929John Reckvoid DamageAccumulator::pushTransform(const Matrix4* transform) {
98a447d29c65fb811cd184775a3476101a1cede929John Reck    pushCommon();
99a447d29c65fb811cd184775a3476101a1cede929John Reck    mHead->type = TransformMatrix4;
100a447d29c65fb811cd184775a3476101a1cede929John Reck    mHead->matrix4 = transform;
101a447d29c65fb811cd184775a3476101a1cede929John Reck}
102a447d29c65fb811cd184775a3476101a1cede929John Reck
103a447d29c65fb811cd184775a3476101a1cede929John Reckvoid DamageAccumulator::popTransform() {
104e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    LOG_ALWAYS_FATAL_IF(mHead->prev == mHead, "Cannot pop the root frame!");
105e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    DirtyStack* dirtyFrame = mHead;
106e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    mHead = mHead->prev;
10725fbb3fa1138675379102a44405852555cefccbdJohn Reck    switch (dirtyFrame->type) {
1081bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        case TransformRenderNode:
1091bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            applyRenderNodeTransform(dirtyFrame);
1101bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            break;
1111bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        case TransformMatrix4:
1121bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            applyMatrix4Transform(dirtyFrame);
1131bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            break;
1141bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        case TransformNone:
1151bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            mHead->pendingDirty.join(dirtyFrame->pendingDirty);
1161bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            break;
1171bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        default:
1181bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            LOG_ALWAYS_FATAL("Tried to pop an invalid type: %d", dirtyFrame->type);
119a447d29c65fb811cd184775a3476101a1cede929John Reck    }
120a447d29c65fb811cd184775a3476101a1cede929John Reck}
121a447d29c65fb811cd184775a3476101a1cede929John Reck
122a447d29c65fb811cd184775a3476101a1cede929John Reckstatic inline void mapRect(const Matrix4* matrix, const SkRect& in, SkRect* out) {
123a447d29c65fb811cd184775a3476101a1cede929John Reck    if (in.isEmpty()) return;
124a447d29c65fb811cd184775a3476101a1cede929John Reck    Rect temp(in);
125c128823940fb0be96eda810fa9f0c75f66d944b0John Reck    if (CC_LIKELY(!matrix->isPerspective())) {
126c128823940fb0be96eda810fa9f0c75f66d944b0John Reck        matrix->mapRect(temp);
127c128823940fb0be96eda810fa9f0c75f66d944b0John Reck    } else {
128c128823940fb0be96eda810fa9f0c75f66d944b0John Reck        // Don't attempt to calculate damage for a perspective transform
129c128823940fb0be96eda810fa9f0c75f66d944b0John Reck        // as the numbers this works with can break the perspective
130c128823940fb0be96eda810fa9f0c75f66d944b0John Reck        // calculations. Just give up and expand to DIRTY_MIN/DIRTY_MAX
131c128823940fb0be96eda810fa9f0c75f66d944b0John Reck        temp.set(DIRTY_MIN, DIRTY_MIN, DIRTY_MAX, DIRTY_MAX);
132c128823940fb0be96eda810fa9f0c75f66d944b0John Reck    }
133a447d29c65fb811cd184775a3476101a1cede929John Reck    out->join(RECT_ARGS(temp));
134a447d29c65fb811cd184775a3476101a1cede929John Reck}
135a447d29c65fb811cd184775a3476101a1cede929John Reck
136a447d29c65fb811cd184775a3476101a1cede929John Reckvoid DamageAccumulator::applyMatrix4Transform(DirtyStack* frame) {
137a447d29c65fb811cd184775a3476101a1cede929John Reck    mapRect(frame->matrix4, frame->pendingDirty, &mHead->pendingDirty);
138a447d29c65fb811cd184775a3476101a1cede929John Reck}
139a447d29c65fb811cd184775a3476101a1cede929John Reck
140a447d29c65fb811cd184775a3476101a1cede929John Reckstatic inline void mapRect(const RenderProperties& props, const SkRect& in, SkRect* out) {
141a447d29c65fb811cd184775a3476101a1cede929John Reck    if (in.isEmpty()) return;
142a447d29c65fb811cd184775a3476101a1cede929John Reck    const SkMatrix* transform = props.getTransformMatrix();
143a447d29c65fb811cd184775a3476101a1cede929John Reck    SkRect temp(in);
144a447d29c65fb811cd184775a3476101a1cede929John Reck    if (transform && !transform->isIdentity()) {
145c128823940fb0be96eda810fa9f0c75f66d944b0John Reck        if (CC_LIKELY(!transform->hasPerspective())) {
146c128823940fb0be96eda810fa9f0c75f66d944b0John Reck            transform->mapRect(&temp);
147c128823940fb0be96eda810fa9f0c75f66d944b0John Reck        } else {
148c128823940fb0be96eda810fa9f0c75f66d944b0John Reck            // Don't attempt to calculate damage for a perspective transform
149c128823940fb0be96eda810fa9f0c75f66d944b0John Reck            // as the numbers this works with can break the perspective
150c128823940fb0be96eda810fa9f0c75f66d944b0John Reck            // calculations. Just give up and expand to DIRTY_MIN/DIRTY_MAX
151c128823940fb0be96eda810fa9f0c75f66d944b0John Reck            temp.set(DIRTY_MIN, DIRTY_MIN, DIRTY_MAX, DIRTY_MAX);
152c128823940fb0be96eda810fa9f0c75f66d944b0John Reck        }
153a447d29c65fb811cd184775a3476101a1cede929John Reck    }
154a447d29c65fb811cd184775a3476101a1cede929John Reck    temp.offset(props.getLeft(), props.getTop());
155a447d29c65fb811cd184775a3476101a1cede929John Reck    out->join(temp);
156a447d29c65fb811cd184775a3476101a1cede929John Reck}
157a447d29c65fb811cd184775a3476101a1cede929John Reck
158a447d29c65fb811cd184775a3476101a1cede929John Reckstatic DirtyStack* findParentRenderNode(DirtyStack* frame) {
159a447d29c65fb811cd184775a3476101a1cede929John Reck    while (frame->prev != frame) {
160a447d29c65fb811cd184775a3476101a1cede929John Reck        frame = frame->prev;
161a447d29c65fb811cd184775a3476101a1cede929John Reck        if (frame->type == TransformRenderNode) {
162a447d29c65fb811cd184775a3476101a1cede929John Reck            return frame;
163e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck        }
164a447d29c65fb811cd184775a3476101a1cede929John Reck    }
165d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik    return nullptr;
166a447d29c65fb811cd184775a3476101a1cede929John Reck}
167a447d29c65fb811cd184775a3476101a1cede929John Reck
168a447d29c65fb811cd184775a3476101a1cede929John Reckstatic DirtyStack* findProjectionReceiver(DirtyStack* frame) {
169a447d29c65fb811cd184775a3476101a1cede929John Reck    if (frame) {
170a447d29c65fb811cd184775a3476101a1cede929John Reck        while (frame->prev != frame) {
171a447d29c65fb811cd184775a3476101a1cede929John Reck            frame = frame->prev;
1721bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            if (frame->type == TransformRenderNode && frame->renderNode->hasProjectionReceiver()) {
173a447d29c65fb811cd184775a3476101a1cede929John Reck                return frame;
174e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck            }
175a447d29c65fb811cd184775a3476101a1cede929John Reck        }
176a447d29c65fb811cd184775a3476101a1cede929John Reck    }
177d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik    return nullptr;
178a447d29c65fb811cd184775a3476101a1cede929John Reck}
179a447d29c65fb811cd184775a3476101a1cede929John Reck
180a447d29c65fb811cd184775a3476101a1cede929John Reckstatic void applyTransforms(DirtyStack* frame, DirtyStack* end) {
181a447d29c65fb811cd184775a3476101a1cede929John Reck    SkRect* rect = &frame->pendingDirty;
182a447d29c65fb811cd184775a3476101a1cede929John Reck    while (frame != end) {
183a447d29c65fb811cd184775a3476101a1cede929John Reck        if (frame->type == TransformRenderNode) {
184a447d29c65fb811cd184775a3476101a1cede929John Reck            mapRect(frame->renderNode->properties(), *rect, rect);
185a447d29c65fb811cd184775a3476101a1cede929John Reck        } else {
186a447d29c65fb811cd184775a3476101a1cede929John Reck            mapRect(frame->matrix4, *rect, rect);
187a447d29c65fb811cd184775a3476101a1cede929John Reck        }
188a447d29c65fb811cd184775a3476101a1cede929John Reck        frame = frame->prev;
189a447d29c65fb811cd184775a3476101a1cede929John Reck    }
190a447d29c65fb811cd184775a3476101a1cede929John Reck}
191a447d29c65fb811cd184775a3476101a1cede929John Reck
192a447d29c65fb811cd184775a3476101a1cede929John Reckvoid DamageAccumulator::applyRenderNodeTransform(DirtyStack* frame) {
193a447d29c65fb811cd184775a3476101a1cede929John Reck    if (frame->pendingDirty.isEmpty()) {
194a447d29c65fb811cd184775a3476101a1cede929John Reck        return;
195a447d29c65fb811cd184775a3476101a1cede929John Reck    }
196a447d29c65fb811cd184775a3476101a1cede929John Reck
197a447d29c65fb811cd184775a3476101a1cede929John Reck    const RenderProperties& props = frame->renderNode->properties();
198ce9f308063cc2bc7851f3f58c881da8a7271eeccJohn Reck    if (props.getAlpha() <= 0) {
199ce9f308063cc2bc7851f3f58c881da8a7271eeccJohn Reck        return;
200ce9f308063cc2bc7851f3f58c881da8a7271eeccJohn Reck    }
201a447d29c65fb811cd184775a3476101a1cede929John Reck
202a447d29c65fb811cd184775a3476101a1cede929John Reck    // Perform clipping
203293e868bfc1b07aad2cb2ebeee5b07424852c510John Reck    if (props.getClipDamageToBounds() && !frame->pendingDirty.isEmpty()) {
204a447d29c65fb811cd184775a3476101a1cede929John Reck        if (!frame->pendingDirty.intersect(0, 0, props.getWidth(), props.getHeight())) {
205a447d29c65fb811cd184775a3476101a1cede929John Reck            frame->pendingDirty.setEmpty();
206a447d29c65fb811cd184775a3476101a1cede929John Reck        }
207a447d29c65fb811cd184775a3476101a1cede929John Reck    }
208a447d29c65fb811cd184775a3476101a1cede929John Reck
209a447d29c65fb811cd184775a3476101a1cede929John Reck    // apply all transforms
210a447d29c65fb811cd184775a3476101a1cede929John Reck    mapRect(props, frame->pendingDirty, &mHead->pendingDirty);
211a447d29c65fb811cd184775a3476101a1cede929John Reck
212a447d29c65fb811cd184775a3476101a1cede929John Reck    // project backwards if necessary
213a447d29c65fb811cd184775a3476101a1cede929John Reck    if (props.getProjectBackwards() && !frame->pendingDirty.isEmpty()) {
214a447d29c65fb811cd184775a3476101a1cede929John Reck        // First, find our parent RenderNode:
215a447d29c65fb811cd184775a3476101a1cede929John Reck        DirtyStack* parentNode = findParentRenderNode(frame);
216a447d29c65fb811cd184775a3476101a1cede929John Reck        // Find our parent's projection receiver, which is what we project onto
217a447d29c65fb811cd184775a3476101a1cede929John Reck        DirtyStack* projectionReceiver = findProjectionReceiver(parentNode);
218a447d29c65fb811cd184775a3476101a1cede929John Reck        if (projectionReceiver) {
219a447d29c65fb811cd184775a3476101a1cede929John Reck            applyTransforms(frame, projectionReceiver);
220a447d29c65fb811cd184775a3476101a1cede929John Reck            projectionReceiver->pendingDirty.join(frame->pendingDirty);
221e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck        }
222a447d29c65fb811cd184775a3476101a1cede929John Reck
223a447d29c65fb811cd184775a3476101a1cede929John Reck        frame->pendingDirty.setEmpty();
224e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    }
225e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck}
226e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck
227e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reckvoid DamageAccumulator::dirty(float left, float top, float right, float bottom) {
228e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    mHead->pendingDirty.join(left, top, right, bottom);
229e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck}
230e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck
231c71bfcaa182e3d4fd9874362d3b4781fda934a21Chris Craikvoid DamageAccumulator::peekAtDirty(SkRect* dest) const {
23225fbb3fa1138675379102a44405852555cefccbdJohn Reck    *dest = mHead->pendingDirty;
23325fbb3fa1138675379102a44405852555cefccbdJohn Reck}
23425fbb3fa1138675379102a44405852555cefccbdJohn Reck
235e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reckvoid DamageAccumulator::finish(SkRect* totalDirty) {
2361bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    LOG_ALWAYS_FATAL_IF(mHead->prev != mHead, "Cannot finish, mismatched push/pop calls! %p vs. %p",
2371bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                        mHead->prev, mHead);
238e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    // Root node never has a transform, so this is the fully mapped dirty rect
239e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    *totalDirty = mHead->pendingDirty;
24071487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed    totalDirty->roundOut(totalDirty);
241e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    mHead->pendingDirty.setEmpty();
242e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck}
243e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck
244e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck} /* namespace uirenderer */
245e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck} /* namespace android */
246