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_LAYER_H
18#define ANDROID_HWUI_LAYER_H
19
20#include <sys/types.h>
21
22#include <GLES2/gl2.h>
23
24#include <ui/Region.h>
25
26#include <SkXfermode.h>
27
28#include "Rect.h"
29#include "SkiaColorFilter.h"
30#include "Texture.h"
31#include "Vertex.h"
32
33namespace android {
34namespace uirenderer {
35
36///////////////////////////////////////////////////////////////////////////////
37// Layers
38///////////////////////////////////////////////////////////////////////////////
39
40// Forward declarations
41class OpenGLRenderer;
42class DisplayList;
43
44/**
45 * A layer has dimensions and is backed by an OpenGL texture or FBO.
46 */
47struct Layer {
48    Layer(const uint32_t layerWidth, const uint32_t layerHeight);
49    ~Layer();
50
51    void removeFbo();
52
53    /**
54     * Sets this layer's region to a rectangle. Computes the appropriate
55     * texture coordinates.
56     */
57    void setRegionAsRect() {
58        const android::Rect& bounds = region.getBounds();
59        regionRect.set(bounds.leftTop().x, bounds.leftTop().y,
60               bounds.rightBottom().x, bounds.rightBottom().y);
61
62        const float texX = 1.0f / float(texture.width);
63        const float texY = 1.0f / float(texture.height);
64        const float height = layer.getHeight();
65        texCoords.set(
66               regionRect.left * texX, (height - regionRect.top) * texY,
67               regionRect.right * texX, (height - regionRect.bottom) * texY);
68
69        regionRect.translate(layer.left, layer.top);
70    }
71
72    void updateDeferred(OpenGLRenderer* renderer, DisplayList* displayList,
73            int left, int top, int right, int bottom) {
74        this->renderer = renderer;
75        this->displayList = displayList;
76        const Rect r(left, top, right, bottom);
77        dirtyRect.unionWith(r);
78        deferredUpdateScheduled = true;
79    }
80
81    inline uint32_t getWidth() {
82        return texture.width;
83    }
84
85    inline uint32_t getHeight() {
86        return texture.height;
87    }
88
89    void setSize(uint32_t width, uint32_t height) {
90        texture.width = width;
91        texture.height = height;
92    }
93
94    ANDROID_API void setPaint(SkPaint* paint);
95
96    inline void setBlend(bool blend) {
97        texture.blend = blend;
98    }
99
100    inline bool isBlend() {
101        return texture.blend;
102    }
103
104    inline void setAlpha(int alpha) {
105        this->alpha = alpha;
106    }
107
108    inline void setAlpha(int alpha, SkXfermode::Mode mode) {
109        this->alpha = alpha;
110        this->mode = mode;
111    }
112
113    inline int getAlpha() {
114        return alpha;
115    }
116
117    inline SkXfermode::Mode getMode() {
118        return mode;
119    }
120
121    inline void setEmpty(bool empty) {
122        this->empty = empty;
123    }
124
125    inline bool isEmpty() {
126        return empty;
127    }
128
129    inline void setFbo(GLuint fbo) {
130        this->fbo = fbo;
131    }
132
133    inline GLuint getFbo() {
134        return fbo;
135    }
136
137    inline GLuint getTexture() {
138        return texture.id;
139    }
140
141    inline GLenum getRenderTarget() {
142        return renderTarget;
143    }
144
145    inline void setRenderTarget(GLenum renderTarget) {
146        this->renderTarget = renderTarget;
147    }
148
149    void setWrap(GLenum wrap, bool bindTexture = false, bool force = false) {
150        texture.setWrap(wrap, bindTexture, force, renderTarget);
151    }
152
153    void setFilter(GLenum filter, bool bindTexture = false, bool force = false) {
154        texture.setFilter(filter, bindTexture, force, renderTarget);
155    }
156
157    inline bool isCacheable() {
158        return cacheable;
159    }
160
161    inline void setCacheable(bool cacheable) {
162        this->cacheable = cacheable;
163    }
164
165    inline bool isDirty() {
166        return dirty;
167    }
168
169    inline void setDirty(bool dirty) {
170        this->dirty = dirty;
171    }
172
173    inline bool isTextureLayer() {
174        return textureLayer;
175    }
176
177    inline void setTextureLayer(bool textureLayer) {
178        this->textureLayer = textureLayer;
179    }
180
181    inline SkiaColorFilter* getColorFilter() {
182        return colorFilter;
183    }
184
185    ANDROID_API void setColorFilter(SkiaColorFilter* filter);
186
187    inline void bindTexture() {
188        if (texture.id) {
189            glBindTexture(renderTarget, texture.id);
190        }
191    }
192
193    inline void generateTexture() {
194        if (!texture.id) {
195            glGenTextures(1, &texture.id);
196        }
197    }
198
199    inline void deleteTexture() {
200        if (texture.id) {
201            glDeleteTextures(1, &texture.id);
202            texture.id = 0;
203        }
204    }
205
206    /**
207     * When the caller frees the texture itself, the caller
208     * must call this method to tell this layer that it lost
209     * the texture.
210     */
211    void clearTexture() {
212        texture.id = 0;
213    }
214
215    inline void deleteFbo() {
216        if (fbo) glDeleteFramebuffers(1, &fbo);
217    }
218
219    inline void allocateTexture(GLenum format, GLenum storage) {
220#if DEBUG_LAYERS
221        ALOGD("  Allocate layer: %dx%d", getWidth(), getHeight());
222#endif
223        glTexImage2D(renderTarget, 0, format, getWidth(), getHeight(), 0, format, storage, NULL);
224    }
225
226    inline mat4& getTexTransform() {
227        return texTransform;
228    }
229
230    inline mat4& getTransform() {
231        return transform;
232    }
233
234    /**
235     * Bounds of the layer.
236     */
237    Rect layer;
238    /**
239     * Texture coordinates of the layer.
240     */
241    Rect texCoords;
242
243    /**
244     * Dirty region indicating what parts of the layer
245     * have been drawn.
246     */
247    Region region;
248    /**
249     * If the region is a rectangle, coordinates of the
250     * region are stored here.
251     */
252    Rect regionRect;
253
254    /**
255     * If the layer can be rendered as a mesh, this is non-null.
256     */
257    TextureVertex* mesh;
258    uint16_t* meshIndices;
259    GLsizei meshElementCount;
260
261    /**
262     * Used for deferred updates.
263     */
264    bool deferredUpdateScheduled;
265    OpenGLRenderer* renderer;
266    DisplayList* displayList;
267    Rect dirtyRect;
268
269private:
270    /**
271     * Name of the FBO used to render the layer. If the name is 0
272     * this layer is not backed by an FBO, but a simple texture.
273     */
274    GLuint fbo;
275
276    /**
277     * Indicates whether this layer has been used already.
278     */
279    bool empty;
280
281    /**
282     * The texture backing this layer.
283     */
284    Texture texture;
285
286    /**
287     * If set to true (by default), the layer can be reused.
288     */
289    bool cacheable;
290
291    /**
292     * When set to true, this layer must be treated as a texture
293     * layer.
294     */
295    bool textureLayer;
296
297    /**
298     * When set to true, this layer is dirty and should be cleared
299     * before any rendering occurs.
300     */
301    bool dirty;
302
303    /**
304     * Indicates the render target.
305     */
306    GLenum renderTarget;
307
308    /**
309     * Color filter used to draw this layer. Optional.
310     */
311    SkiaColorFilter* colorFilter;
312
313    /**
314     * Opacity of the layer.
315     */
316    int alpha;
317    /**
318     * Blending mode of the layer.
319     */
320    SkXfermode::Mode mode;
321
322    /**
323     * Optional texture coordinates transform.
324     */
325    mat4 texTransform;
326
327    /**
328     * Optional transform.
329     */
330    mat4 transform;
331
332}; // struct Layer
333
334}; // namespace uirenderer
335}; // namespace android
336
337#endif // ANDROID_HWUI_LAYER_H
338