Snapshot.h revision ed7a8fc768df158241819f062a12dafdaf8a628d
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_HWUI_SNAPSHOT_H
18#define ANDROID_HWUI_SNAPSHOT_H
19
20#include <GLES2/gl2.h>
21#include <GLES2/gl2ext.h>
22
23#include <utils/RefBase.h>
24#include <ui/Region.h>
25
26#include <SkCanvas.h>
27
28#include "Layer.h"
29#include "Matrix.h"
30#include "Rect.h"
31
32namespace android {
33namespace uirenderer {
34
35/**
36 * A snapshot holds information about the current state of the rendering
37 * surface. A snapshot is usually created whenever the user calls save()
38 * and discarded when the user calls restore(). Once a snapshot is created,
39 * it can hold information for deferred rendering.
40 *
41 * Each snapshot has a link to a previous snapshot, indicating the previous
42 * state of the renderer.
43 */
44class Snapshot: public LightRefBase<Snapshot> {
45public:
46    Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0), invisible(false), empty(false) {
47        transform = &mTransformRoot;
48        clipRect = &mClipRectRoot;
49        region = NULL;
50    }
51
52    /**
53     * Copies the specified snapshot/ The specified snapshot is stored as
54     * the previous snapshot.
55     */
56    Snapshot(const sp<Snapshot>& s, int saveFlags):
57            flags(0), previous(s), layer(NULL), fbo(s->fbo),
58            invisible(s->invisible), empty(false), viewport(s->viewport), height(s->height) {
59        if (saveFlags & SkCanvas::kMatrix_SaveFlag) {
60            mTransformRoot.load(*s->transform);
61            transform = &mTransformRoot;
62        } else {
63            transform = s->transform;
64        }
65
66        if (saveFlags & SkCanvas::kClip_SaveFlag) {
67            mClipRectRoot.set(*s->clipRect);
68            clipRect = &mClipRectRoot;
69        } else {
70            clipRect = s->clipRect;
71        }
72
73        if (s->flags & Snapshot::kFlagFboTarget) {
74            flags |= Snapshot::kFlagFboTarget;
75            region = s->region;
76        } else {
77            region = NULL;
78        }
79    }
80
81    /**
82     * Various flags set on #flags.
83     */
84    enum Flags {
85        /**
86         * Indicates that the clip region was modified. When this
87         * snapshot is restored so must the clip.
88         */
89        kFlagClipSet = 0x1,
90        /**
91         * Indicates that this snapshot was created when saving
92         * a new layer.
93         */
94        kFlagIsLayer = 0x2,
95        /**
96         * Indicates that this snapshot is a special type of layer
97         * backed by an FBO. This flag only makes sense when the
98         * flag kFlagIsLayer is also set.
99         */
100        kFlagIsFboLayer = 0x4,
101        /**
102         * Indicates that this snapshot has changed the ortho matrix.
103         */
104        kFlagDirtyOrtho = 0x8,
105        /**
106         * Indicates that this snapshot or an ancestor snapshot is
107         * an FBO layer.
108         */
109        kFlagFboTarget = 0x10
110    };
111
112    /**
113     * Modifies the current clip with the new clip rectangle and
114     * the specified operation. The specified rectangle is transformed
115     * by this snapshot's trasnformation.
116     */
117    bool clip(float left, float top, float right, float bottom,
118            SkRegion::Op op = SkRegion::kIntersect_Op) {
119        Rect r(left, top, right, bottom);
120        transform->mapRect(r);
121        return clipTransformed(r, op);
122    }
123
124    /**
125     * Modifies the current clip with the new clip rectangle and
126     * the specified operation. The specified rectangle is considered
127     * already transformed.
128     */
129    bool clipTransformed(const Rect& r, SkRegion::Op op = SkRegion::kIntersect_Op) {
130        bool clipped = false;
131
132        // NOTE: The unimplemented operations require support for regions
133        // Supporting regions would require using a stencil buffer instead
134        // of the scissor. The stencil buffer itself is not too expensive
135        // (memory cost excluded) but on fillrate limited devices, managing
136        // the stencil might have a negative impact on the framerate.
137        switch (op) {
138            case SkRegion::kDifference_Op:
139                break;
140            case SkRegion::kIntersect_Op:
141                clipped = clipRect->intersect(r);
142                if (!clipped) {
143                    clipRect->setEmpty();
144                    clipped = true;
145                }
146                break;
147            case SkRegion::kUnion_Op:
148                clipped = clipRect->unionWith(r);
149                break;
150            case SkRegion::kXOR_Op:
151                break;
152            case SkRegion::kReverseDifference_Op:
153                break;
154            case SkRegion::kReplace_Op:
155                clipRect->set(r);
156                clipped = true;
157                break;
158        }
159
160        if (clipped) {
161            flags |= Snapshot::kFlagClipSet;
162        }
163
164        return clipped;
165    }
166
167    /**
168     * Sets the current clip.
169     */
170    void setClip(float left, float top, float right, float bottom) {
171        clipRect->set(left, top, right, bottom);
172        flags |= Snapshot::kFlagClipSet;
173    }
174
175    const Rect& getLocalClip() {
176        mat4 inverse;
177        inverse.loadInverse(*transform);
178
179        mLocalClip.set(*clipRect);
180        inverse.mapRect(mLocalClip);
181
182        return mLocalClip;
183    }
184
185    void resetTransform(float x, float y, float z) {
186        transform = &mTransformRoot;
187        transform->loadTranslate(x, y, z);
188    }
189
190    void resetClip(float left, float top, float right, float bottom) {
191        clipRect = &mClipRectRoot;
192        clipRect->set(left, top, right, bottom);
193        flags |= Snapshot::kFlagClipSet;
194    }
195
196    bool isIgnored() const {
197        return invisible || empty;
198    }
199
200    /**
201     * Dirty flags.
202     */
203    int flags;
204
205    /**
206     * Previous snapshot.
207     */
208    sp<Snapshot> previous;
209
210    /**
211     * Only set when the flag kFlagIsLayer is set.
212     */
213    Layer* layer;
214
215    /**
216     * Only set when the flag kFlagIsFboLayer is set.
217     */
218    GLuint fbo;
219
220    /**
221     * Indicates that this snapshot is invisible and nothing should be drawn
222     * inside it. This flag is set only when the layer clips drawing to its
223     * bounds and is passed to subsequent snapshots.
224     */
225    bool invisible;
226
227    /**
228     * If set to true, the layer will not be composited. This is similar to
229     * invisible but this flag is not passed to subsequent snapshots.
230     */
231    bool empty;
232
233    /**
234     * Current viewport.
235     */
236    Rect viewport;
237
238    /**
239     * Height of the framebuffer the snapshot is rendering into.
240     */
241    int height;
242
243    /**
244     * Contains the previous ortho matrix.
245     */
246    mat4 orthoMatrix;
247
248    /**
249     * Local transformation. Holds the current translation, scale and
250     * rotation values.
251     */
252    mat4* transform;
253
254    /**
255     * Current clip region. The clip is stored in canvas-space coordinates,
256     * (screen-space coordinates in the regular case.)
257     */
258    Rect* clipRect;
259
260    /**
261     * The ancestor layer's dirty region.
262     */
263    Region* region;
264
265private:
266    mat4 mTransformRoot;
267    Rect mClipRectRoot;
268    Rect mLocalClip;
269
270}; // class Snapshot
271
272}; // namespace uirenderer
273}; // namespace android
274
275#endif // ANDROID_HWUI_SNAPSHOT_H
276