AssetAtlas.cpp revision 59cf734f9ee8fa0154d199f0f36779a6ffe0dfb5
1affc150dc44fab1911775a49636d0ce85333b634Zonr Chang/*
2affc150dc44fab1911775a49636d0ce85333b634Zonr Chang * Copyright (C) 2013 The Android Open Source Project
3affc150dc44fab1911775a49636d0ce85333b634Zonr Chang *
4affc150dc44fab1911775a49636d0ce85333b634Zonr Chang * Licensed under the Apache License, Version 2.0 (the "License");
5affc150dc44fab1911775a49636d0ce85333b634Zonr Chang * you may not use this file except in compliance with the License.
6affc150dc44fab1911775a49636d0ce85333b634Zonr Chang * You may obtain a copy of the License at
7affc150dc44fab1911775a49636d0ce85333b634Zonr Chang *
8affc150dc44fab1911775a49636d0ce85333b634Zonr Chang *      http://www.apache.org/licenses/LICENSE-2.0
937b74a387bb3993387029859c2d9d051c41c724eStephen Hines *
1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines * Unless required by applicable law or agreed to in writing, software
11affc150dc44fab1911775a49636d0ce85333b634Zonr Chang * distributed under the License is distributed on an "AS IS" BASIS,
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines * See the License for the specific language governing permissions and
1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines * limitations under the License.
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines */
16affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
17affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#define LOG_TAG "OpenGLRenderer"
18affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
19affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include "AssetAtlas.h"
20affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include "Caches.h"
2137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "Image.h"
2237b74a387bb3993387029859c2d9d051c41c724eStephen Hines
23affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <GLES2/gl2ext.h>
24affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
25affc150dc44fab1911775a49636d0ce85333b634Zonr Changnamespace android {
26affc150dc44fab1911775a49636d0ce85333b634Zonr Changnamespace uirenderer {
2722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
28affc150dc44fab1911775a49636d0ce85333b634Zonr Chang///////////////////////////////////////////////////////////////////////////////
29affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// Lifecycle
30affc150dc44fab1911775a49636d0ce85333b634Zonr Chang///////////////////////////////////////////////////////////////////////////////
31affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
32affc150dc44fab1911775a49636d0ce85333b634Zonr Changvoid AssetAtlas::init(sp<GraphicBuffer> buffer, int64_t* map, int count) {
3337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (mImage) {
34affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        return;
35affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
36affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
37affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    ATRACE_NAME("AssetAtlas::init");
38affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
39affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    mImage = new Image(buffer);
4022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (mImage->getTexture()) {
4122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        if (!mTexture) {
42affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            Caches& caches = Caches::getInstance();
4337b74a387bb3993387029859c2d9d051c41c724eStephen Hines            mTexture = new Texture(caches);
44affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            mTexture->width = buffer->getWidth();
45affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            mTexture->height = buffer->getHeight();
46affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            createEntries(caches, map, count);
47affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        }
4837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else {
49affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        ALOGW("Could not create atlas image");
5037b74a387bb3993387029859c2d9d051c41c724eStephen Hines        delete mImage;
51        mImage = NULL;
52    }
53
54    updateTextureId();
55}
56
57void AssetAtlas::terminate() {
58    if (mImage) {
59        delete mImage;
60        mImage = NULL;
61        updateTextureId();
62    }
63}
64
65
66void AssetAtlas::updateTextureId() {
67    mTexture->id = mImage ? mImage->getTexture() : 0;
68    for (size_t i = 0; i < mEntries.size(); i++) {
69        AssetAtlas::Entry* entry = mEntries.valueAt(i);
70        entry->texture->id = mTexture->id;
71    }
72}
73
74///////////////////////////////////////////////////////////////////////////////
75// Entries
76///////////////////////////////////////////////////////////////////////////////
77
78AssetAtlas::Entry* AssetAtlas::getEntry(const SkBitmap* bitmap) const {
79    ssize_t index = mEntries.indexOfKey(bitmap);
80    return index >= 0 ? mEntries.valueAt(index) : NULL;
81}
82
83Texture* AssetAtlas::getEntryTexture(const SkBitmap* bitmap) const {
84    ssize_t index = mEntries.indexOfKey(bitmap);
85    return index >= 0 ? mEntries.valueAt(index)->texture : NULL;
86}
87
88/**
89 * Delegates changes to wrapping and filtering to the base atlas texture
90 * instead of applying the changes to the virtual textures.
91 */
92struct DelegateTexture: public Texture {
93    DelegateTexture(Caches& caches, Texture* delegate): Texture(caches), mDelegate(delegate) { }
94
95    virtual void setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture = false,
96            bool force = false, GLenum renderTarget = GL_TEXTURE_2D) {
97        mDelegate->setWrapST(wrapS, wrapT, bindTexture, force, renderTarget);
98    }
99
100    virtual void setFilterMinMag(GLenum min, GLenum mag, bool bindTexture = false,
101            bool force = false, GLenum renderTarget = GL_TEXTURE_2D) {
102        mDelegate->setFilterMinMag(min, mag, bindTexture, force, renderTarget);
103    }
104
105private:
106    Texture* const mDelegate;
107}; // struct DelegateTexture
108
109/**
110 * TODO: This method does not take the rotation flag into account
111 */
112void AssetAtlas::createEntries(Caches& caches, int64_t* map, int count) {
113    const float width = float(mTexture->width);
114    const float height = float(mTexture->height);
115
116    for (int i = 0; i < count; ) {
117        SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(map[i++]);
118        // NOTE: We're converting from 64 bit signed values to 32 bit
119        // signed values. This is guaranteed to be safe because the "x"
120        // and "y" coordinate values are guaranteed to be representable
121        // with 32 bits. The array is 64 bits wide so that it can carry
122        // pointers on 64 bit architectures.
123        const int x = static_cast<int>(map[i++]);
124        const int y = static_cast<int>(map[i++]);
125        bool rotated = map[i++] > 0;
126
127        // Bitmaps should never be null, we're just extra paranoid
128        if (!bitmap) continue;
129
130        const UvMapper mapper(
131                x / width, (x + bitmap->width()) / width,
132                y / height, (y + bitmap->height()) / height);
133
134        Texture* texture = new DelegateTexture(caches, mTexture);
135        texture->blend = !bitmap->isOpaque();
136        texture->width = bitmap->width();
137        texture->height = bitmap->height();
138
139        Entry* entry = new Entry(bitmap, x, y, rotated, texture, mapper, *this);
140        texture->uvMapper = &entry->uvMapper;
141
142        mEntries.add(entry->bitmap, entry);
143    }
144}
145
146}; // namespace uirenderer
147}; // namespace android
148