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