Snapshot.h revision 69e5adffb19135d51bde8e458f4907d7265f3e23
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/LinearAllocator.h>
24#include <utils/RefBase.h>
25#include <ui/Region.h>
26
27#include <SkRegion.h>
28
29#include "Layer.h"
30#include "Matrix.h"
31#include "Outline.h"
32#include "Rect.h"
33#include "utils/Macros.h"
34
35namespace android {
36namespace uirenderer {
37
38/**
39 * Temporary structure holding information for a single outline clip.
40 *
41 * These structures are treated as immutable once created, and only exist for a single frame, which
42 * is why they may only be allocated with a LinearAllocator.
43 */
44class RoundRectClipState {
45public:
46    /** static void* operator new(size_t size); PURPOSELY OMITTED, allocator only **/
47    static void* operator new(size_t size, LinearAllocator& allocator) {
48        return allocator.alloc(size);
49    }
50
51    bool areaRequiresRoundRectClip(const Rect& rect) const {
52        return rect.intersects(dangerRects[0])
53                || rect.intersects(dangerRects[1])
54                || rect.intersects(dangerRects[2])
55                || rect.intersects(dangerRects[3]);
56    }
57
58    Matrix4 matrix;
59    Rect dangerRects[4];
60    Rect innerRect;
61    float radius;
62};
63
64/**
65 * A snapshot holds information about the current state of the rendering
66 * surface. A snapshot is usually created whenever the user calls save()
67 * and discarded when the user calls restore(). Once a snapshot is created,
68 * it can hold information for deferred rendering.
69 *
70 * Each snapshot has a link to a previous snapshot, indicating the previous
71 * state of the renderer.
72 */
73class Snapshot: public LightRefBase<Snapshot> {
74public:
75
76    Snapshot();
77    Snapshot(const sp<Snapshot>& s, int saveFlags);
78
79    /**
80     * Various flags set on ::flags.
81     */
82    enum Flags {
83        /**
84         * Indicates that the clip region was modified. When this
85         * snapshot is restored so must the clip.
86         */
87        kFlagClipSet = 0x1,
88        /**
89         * Indicates that this snapshot was created when saving
90         * a new layer.
91         */
92        kFlagIsLayer = 0x2,
93        /**
94         * Indicates that this snapshot is a special type of layer
95         * backed by an FBO. This flag only makes sense when the
96         * flag kFlagIsLayer is also set.
97         *
98         * Viewport has been modified to fit the new Fbo, and must be
99         * restored when this snapshot is restored.
100         */
101        kFlagIsFboLayer = 0x4,
102        /**
103         * Indicates that this snapshot or an ancestor snapshot is
104         * an FBO layer.
105         */
106        kFlagFboTarget = 0x8,
107    };
108
109    /**
110     * Modifies the current clip with the new clip rectangle and
111     * the specified operation. The specified rectangle is transformed
112     * by this snapshot's trasnformation.
113     */
114    bool clip(float left, float top, float right, float bottom,
115            SkRegion::Op op = SkRegion::kIntersect_Op);
116
117    /**
118     * Modifies the current clip with the new clip rectangle and
119     * the specified operation. The specified rectangle is considered
120     * already transformed.
121     */
122    bool clipTransformed(const Rect& r, SkRegion::Op op = SkRegion::kIntersect_Op);
123
124    /**
125     * Modifies the current clip with the specified region and operation.
126     * The specified region is considered already transformed.
127     */
128    bool clipRegionTransformed(const SkRegion& region, SkRegion::Op op);
129
130    /**
131     * Sets the current clip.
132     */
133    void setClip(float left, float top, float right, float bottom);
134
135    /**
136     * Returns the current clip in local coordinates. The clip rect is
137     * transformed by the inverse transform matrix.
138     */
139    ANDROID_API const Rect& getLocalClip();
140
141    /**
142     * Returns the current clip in render target coordinates.
143     */
144    const Rect& getRenderTargetClip() { return *clipRect; }
145
146    /**
147     * Resets the clip to the specified rect.
148     */
149    void resetClip(float left, float top, float right, float bottom);
150
151    /**
152     * Resets the current transform to a pure 3D translation.
153     */
154    void resetTransform(float x, float y, float z);
155
156    void initializeViewport(int width, int height) {
157        mViewportData.initialize(width, height);
158    }
159
160    int getViewportWidth() const { return mViewportData.mWidth; }
161    int getViewportHeight() const { return mViewportData.mHeight; }
162    const Matrix4& getOrthoMatrix() const { return mViewportData.mOrthoMatrix; }
163
164    const Vector3& getRelativeLightCenter() const { return mRelativeLightCenter; }
165    void setRelativeLightCenter(const Vector3& lightCenter) { mRelativeLightCenter = lightCenter; }
166
167    /**
168     * Sets (and replaces) the current clipping outline
169     */
170    void setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds, float radius);
171
172    /**
173     * Indicates whether this snapshot should be ignored. A snapshot
174     * is typicalled ignored if its layer is invisible or empty.
175     */
176    bool isIgnored() const;
177
178    /**
179     * Indicates whether the current transform has perspective components.
180     */
181    bool hasPerspectiveTransform() const;
182
183    /**
184     * Dirty flags.
185     */
186    int flags;
187
188    /**
189     * Previous snapshot.
190     */
191    sp<Snapshot> previous;
192
193    /**
194     * A pointer to the currently active layer.
195     *
196     * This snapshot does not own the layer, this pointer must not be freed.
197     */
198    Layer* layer;
199
200    /**
201     * Target FBO used for rendering. Set to 0 when rendering directly
202     * into the framebuffer.
203     */
204    GLuint fbo;
205
206    /**
207     * Indicates that this snapshot is invisible and nothing should be drawn
208     * inside it. This flag is set only when the layer clips drawing to its
209     * bounds and is passed to subsequent snapshots.
210     */
211    bool invisible;
212
213    /**
214     * If set to true, the layer will not be composited. This is similar to
215     * invisible but this flag is not passed to subsequent snapshots.
216     */
217    bool empty;
218
219    /**
220     * Local transformation. Holds the current translation, scale and
221     * rotation values.
222     *
223     * This is a reference to a matrix owned by this snapshot or another
224     *  snapshot. This pointer must not be freed. See ::mTransformRoot.
225     */
226    mat4* transform;
227
228    /**
229     * Current clip rect. The clip is stored in canvas-space coordinates,
230     * (screen-space coordinates in the regular case.)
231     *
232     * This is a reference to a rect owned by this snapshot or another
233     * snapshot. This pointer must not be freed. See ::mClipRectRoot.
234     */
235    Rect* clipRect;
236
237    /**
238     * Current clip region. The clip is stored in canvas-space coordinates,
239     * (screen-space coordinates in the regular case.)
240     *
241     * This is a reference to a region owned by this snapshot or another
242     * snapshot. This pointer must not be freed. See ::mClipRegionRoot.
243     */
244    SkRegion* clipRegion;
245
246    /**
247     * The ancestor layer's dirty region.
248     *
249     * This is a reference to a region owned by a layer. This pointer must
250     * not be freed.
251     */
252    Region* region;
253
254    /**
255     * Current alpha value. This value is 1 by default, but may be set by a DisplayList which
256     * has translucent rendering in a non-overlapping View. This value will be used by
257     * the renderer to set the alpha in the current color being used for ensuing drawing
258     * operations. The value is inherited by child snapshots because the same value should
259     * be applied to descendents of the current DisplayList (for example, a TextView contains
260     * the base alpha value which should be applied to the child DisplayLists used for drawing
261     * the actual text).
262     */
263    float alpha;
264
265    /**
266     * Current clipping round rect.
267     *
268     * Points to data not owned by the snapshot, and may only be replaced by subsequent RR clips,
269     * never modified.
270     */
271    const RoundRectClipState* roundRectClipState;
272
273    void dump() const;
274
275private:
276    struct ViewportData {
277        ViewportData() : mWidth(0), mHeight(0) {}
278        void initialize(int width, int height) {
279            mWidth = width;
280            mHeight = height;
281            mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
282        }
283
284        /*
285         * Width and height of current viewport.
286         *
287         * The viewport is always defined to be (0, 0, width, height).
288         */
289        int mWidth;
290        int mHeight;
291        /**
292         * Contains the current orthographic, projection matrix.
293         */
294        mat4 mOrthoMatrix;
295    };
296
297    void ensureClipRegion();
298    void copyClipRectFromRegion();
299
300    bool clipRegionOp(float left, float top, float right, float bottom, SkRegion::Op op);
301
302    mat4 mTransformRoot;
303    Rect mClipRectRoot;
304    Rect mLocalClip; // don't use directly, call getLocalClip() which initializes this
305
306    SkRegion mClipRegionRoot;
307    ViewportData mViewportData;
308    Vector3 mRelativeLightCenter;
309
310}; // class Snapshot
311
312}; // namespace uirenderer
313}; // namespace android
314
315#endif // ANDROID_HWUI_SNAPSHOT_H
316