AssetAtlas.cpp revision 8aa195d7081b889f3a7b1f426cbd8556377aae5e
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#include "AssetAtlas.h"
18#include "Caches.h"
19
20#include <GLES2/gl2ext.h>
21
22namespace android {
23namespace uirenderer {
24
25///////////////////////////////////////////////////////////////////////////////
26// Lifecycle
27///////////////////////////////////////////////////////////////////////////////
28
29void AssetAtlas::init(sp<GraphicBuffer> buffer, int* map, int count) {
30    if (mImage) {
31        return;
32    }
33
34    mImage = new Image(buffer);
35
36    if (mImage->getTexture()) {
37        Caches& caches = Caches::getInstance();
38
39        mTexture = new Texture(caches);
40        mTexture->id = mImage->getTexture();
41        mTexture->width = buffer->getWidth();
42        mTexture->height = buffer->getHeight();
43
44        createEntries(caches, map, count);
45    } else {
46        ALOGW("Could not create atlas image");
47
48        delete mImage;
49        mImage = NULL;
50        mTexture = NULL;
51    }
52}
53
54void AssetAtlas::terminate() {
55    if (mImage) {
56        delete mImage;
57        mImage = NULL;
58
59        delete mTexture;
60        mTexture = NULL;
61
62        for (size_t i = 0; i < mEntries.size(); i++) {
63            delete mEntries.valueAt(i);
64        }
65        mEntries.clear();
66    }
67}
68
69///////////////////////////////////////////////////////////////////////////////
70// Entries
71///////////////////////////////////////////////////////////////////////////////
72
73AssetAtlas::Entry* AssetAtlas::getEntry(SkBitmap* const bitmap) const {
74    ssize_t index = mEntries.indexOfKey(bitmap);
75    return index >= 0 ? mEntries.valueAt(index) : NULL;
76}
77
78Texture* AssetAtlas::getEntryTexture(SkBitmap* const bitmap) const {
79    ssize_t index = mEntries.indexOfKey(bitmap);
80    return index >= 0 ? mEntries.valueAt(index)->texture : NULL;
81}
82
83/**
84 * Delegates changes to wrapping and filtering to the base atlas texture
85 * instead of applying the changes to the virtual textures.
86 */
87struct DelegateTexture: public Texture {
88    DelegateTexture(Caches& caches, Texture* delegate): Texture(caches), mDelegate(delegate) { }
89
90    virtual void setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture = false,
91            bool force = false, GLenum renderTarget = GL_TEXTURE_2D) {
92        mDelegate->setWrapST(wrapS, wrapT, bindTexture, force, renderTarget);
93    }
94
95    virtual void setFilterMinMag(GLenum min, GLenum mag, bool bindTexture = false,
96            bool force = false, GLenum renderTarget = GL_TEXTURE_2D) {
97        mDelegate->setFilterMinMag(min, mag, bindTexture, force, renderTarget);
98    }
99private:
100    Texture* const mDelegate;
101}; // struct DelegateTexture
102
103/**
104 * TODO: This method does not take the rotation flag into account
105 */
106void AssetAtlas::createEntries(Caches& caches, int* map, int count) {
107    const float width = float(mTexture->width);
108    const float height = float(mTexture->height);
109
110    for (int i = 0; i < count; ) {
111        SkBitmap* bitmap = (SkBitmap*) map[i++];
112        int x = map[i++];
113        int y = map[i++];
114        bool rotated = map[i++] > 0;
115
116        // Bitmaps should never be null, we're just extra paranoid
117        if (!bitmap) continue;
118
119        const UvMapper mapper(
120                x / width, (x + bitmap->width()) / width,
121                y / height, (y + bitmap->height()) / height);
122
123        Texture* texture = new DelegateTexture(caches, mTexture);
124        Entry* entry = new Entry(bitmap, x, y, rotated, texture, mapper, *this);
125
126        texture->id = mTexture->id;
127        texture->blend = !bitmap->isOpaque();
128        texture->width = bitmap->width();
129        texture->height = bitmap->height();
130        texture->uvMapper = &entry->uvMapper;
131
132        mEntries.add(entry->bitmap, entry);
133    }
134}
135
136}; // namespace uirenderer
137}; // namespace android
138