AssetAtlas.h revision ebd52610cfeff6e557fde284a7e1efc5e6438285
1/*
2 * Copyright (C) 2013 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_ASSET_ATLAS_H
18#define ANDROID_HWUI_ASSET_ATLAS_H
19
20#include <GLES2/gl2.h>
21
22#include <ui/GraphicBuffer.h>
23
24#include <utils/KeyedVector.h>
25
26#include <cutils/compiler.h>
27
28#include <SkBitmap.h>
29
30#include "Image.h"
31#include "Texture.h"
32#include "UvMapper.h"
33
34namespace android {
35namespace uirenderer {
36
37class Caches;
38
39/**
40 * An asset atlas holds a collection of framework bitmaps in a single OpenGL
41 * texture. Each bitmap is associated with a location, defined in pixels,
42 * inside the atlas. The atlas is generated by the framework and bound as
43 * an external texture using the EGLImageKHR extension.
44 */
45class AssetAtlas {
46public:
47    /**
48     * Entry representing the position and rotation of a
49     * bitmap inside the atlas.
50     */
51    struct Entry {
52        /**
53         * The bitmap that generated this atlas entry.
54         */
55        SkBitmap* bitmap;
56
57        /**
58         * Location of the bitmap inside the atlas, in pixels.
59         */
60        int x;
61        int y;
62
63        /**
64         * If set, the bitmap is rotated 90 degrees (clockwise)
65         * inside the atlas.
66         */
67        bool rotated;
68
69        /*
70         * A "virtual texture" object that represents the texture
71         * this entry belongs to. This texture should never be
72         * modified.
73         */
74        Texture* texture;
75
76        /**
77         * Maps texture coordinates in the [0..1] range into the
78         * correct range to sample this entry from the atlas.
79         */
80        const UvMapper uvMapper;
81
82        /**
83         * Atlas this entry belongs to.
84         */
85        const AssetAtlas& atlas;
86
87        /**
88         * Unique identifier used to merge bitmaps and 9-patches stored
89         * in the atlas.
90         */
91        const void* getMergeId() const {
92            return texture->blend ? &atlas.mBlendKey : &atlas.mOpaqueKey;
93        }
94
95    private:
96        Entry(SkBitmap* bitmap, int x, int y, bool rotated,
97                Texture* texture, const UvMapper& mapper, const AssetAtlas& atlas):
98                bitmap(bitmap), x(x), y(y), rotated(rotated),
99                texture(texture), uvMapper(mapper), atlas(atlas) {
100        }
101
102        ~Entry() {
103            delete texture;
104        }
105
106        friend class AssetAtlas;
107    };
108
109    AssetAtlas(): mTexture(NULL), mImage(NULL),
110            mBlendKey(true), mOpaqueKey(false) { }
111    ~AssetAtlas() { terminate(); }
112
113    /**
114     * Initializes the atlas with the specified buffer and
115     * map. The buffer is a gralloc'd texture that will be
116     * used as an EGLImage. The map is a list of SkBitmap*
117     * and their (x, y) positions as well as their rotation
118     * flags.
119     *
120     * This method returns immediately if the atlas is already
121     * initialized. To re-initialize the atlas, you must
122     * first call terminate().
123     */
124    ANDROID_API void init(sp<GraphicBuffer> buffer, int64_t* map, int count);
125
126    /**
127     * Destroys the atlas texture. This object can be
128     * re-initialized after calling this method.
129     *
130     * After calling this method, the width, height
131     * and texture are set to 0.
132     */
133    void terminate();
134
135    /**
136     * Returns the width of this atlas in pixels.
137     * Can return 0 if the atlas is not initialized.
138     */
139    uint32_t getWidth() const {
140        return mTexture ? mTexture->width : 0;
141    }
142
143    /**
144     * Returns the height of this atlas in pixels.
145     * Can return 0 if the atlas is not initialized.
146     */
147    uint32_t getHeight() const {
148        return mTexture ? mTexture->height : 0;
149    }
150
151    /**
152     * Returns the OpenGL name of the texture backing this atlas.
153     * Can return 0 if the atlas is not initialized.
154     */
155    GLuint getTexture() const {
156        return mTexture ? mTexture->id : 0;
157    }
158
159    /**
160     * Returns the entry in the atlas associated with the specified
161     * bitmap. If the bitmap is not in the atlas, return NULL.
162     */
163    Entry* getEntry(const SkBitmap* bitmap) const;
164
165    /**
166     * Returns the texture for the atlas entry associated with the
167     * specified bitmap. If the bitmap is not in the atlas, return NULL.
168     */
169    Texture* getEntryTexture(const SkBitmap* bitmap) const;
170
171private:
172    void createEntries(Caches& caches, int64_t* map, int count);
173    void updateTextureId();
174
175    Texture* mTexture;
176    Image* mImage;
177
178    const bool mBlendKey;
179    const bool mOpaqueKey;
180
181    KeyedVector<const SkBitmap*, Entry*> mEntries;
182}; // class AssetAtlas
183
184}; // namespace uirenderer
185}; // namespace android
186
187#endif // ANDROID_HWUI_ASSET_ATLAS_H
188