AssetAtlas.cpp revision ebd52610cfeff6e557fde284a7e1efc5e6438285
13b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy/* 23b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * Copyright (C) 2013 The Android Open Source Project 33b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * 43b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * Licensed under the Apache License, Version 2.0 (the "License"); 53b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * you may not use this file except in compliance with the License. 63b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * You may obtain a copy of the License at 73b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * 83b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * http://www.apache.org/licenses/LICENSE-2.0 93b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * 103b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * Unless required by applicable law or agreed to in writing, software 113b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * distributed under the License is distributed on an "AS IS" BASIS, 123b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * See the License for the specific language governing permissions and 143b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * limitations under the License. 153b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy */ 163b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 1755b6f95ee4ace96c97508bcd14483fb4e9dbeaa0Romain Guy#define LOG_TAG "OpenGLRenderer" 1855b6f95ee4ace96c97508bcd14483fb4e9dbeaa0Romain Guy 193b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#include "AssetAtlas.h" 208aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy#include "Caches.h" 213b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 223b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#include <GLES2/gl2ext.h> 233b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 243b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guynamespace android { 253b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guynamespace uirenderer { 263b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 273b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy/////////////////////////////////////////////////////////////////////////////// 283b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy// Lifecycle 293b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy/////////////////////////////////////////////////////////////////////////////// 303b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 3117ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhatvoid AssetAtlas::init(sp<GraphicBuffer> buffer, int64_t* map, int count) { 32877cfe0e32a845d5a58252b8a6e1f54f95b4379cRomain Guy if (mImage) { 333b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy return; 343b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 353b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 36fbc8df03e498baf47ff1a5e05e182f1bcd60c770John Reck ATRACE_NAME("AssetAtlas::init"); 37fbc8df03e498baf47ff1a5e05e182f1bcd60c770John Reck 38877cfe0e32a845d5a58252b8a6e1f54f95b4379cRomain Guy mImage = new Image(buffer); 39a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy if (mImage->getTexture()) { 40ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck if (!mTexture) { 41ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck Caches& caches = Caches::getInstance(); 42ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck mTexture = new Texture(caches); 43ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck mTexture->width = buffer->getWidth(); 44ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck mTexture->height = buffer->getHeight(); 45ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck createEntries(caches, map, count); 46ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck } 47877cfe0e32a845d5a58252b8a6e1f54f95b4379cRomain Guy } else { 48d5207b2eb9ba520da822d61ff78b539842fc5255Romain Guy ALOGW("Could not create atlas image"); 49877cfe0e32a845d5a58252b8a6e1f54f95b4379cRomain Guy delete mImage; 50d5207b2eb9ba520da822d61ff78b539842fc5255Romain Guy mImage = NULL; 513b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 5255b6f95ee4ace96c97508bcd14483fb4e9dbeaa0Romain Guy 53ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck updateTextureId(); 543b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy} 553b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 563b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyvoid AssetAtlas::terminate() { 57877cfe0e32a845d5a58252b8a6e1f54f95b4379cRomain Guy if (mImage) { 58877cfe0e32a845d5a58252b8a6e1f54f95b4379cRomain Guy delete mImage; 59d5207b2eb9ba520da822d61ff78b539842fc5255Romain Guy mImage = NULL; 60ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck updateTextureId(); 61ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck } 62ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck} 633b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 64a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy 65ebd52610cfeff6e557fde284a7e1efc5e6438285John Reckvoid AssetAtlas::updateTextureId() { 66ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck mTexture->id = mImage ? mImage->getTexture() : 0; 67ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck for (size_t i = 0; i < mEntries.size(); i++) { 68ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck AssetAtlas::Entry* entry = mEntries.valueAt(i); 69ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck entry->texture->id = mTexture->id; 703b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 713b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy} 723b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 733b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy/////////////////////////////////////////////////////////////////////////////// 743b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy// Entries 753b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy/////////////////////////////////////////////////////////////////////////////// 763b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 77d218a92c0afb8c0d98135b20b52ac87236e1c935Chris CraikAssetAtlas::Entry* AssetAtlas::getEntry(const SkBitmap* bitmap) const { 783b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy ssize_t index = mEntries.indexOfKey(bitmap); 793b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy return index >= 0 ? mEntries.valueAt(index) : NULL; 803b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy} 813b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 82d218a92c0afb8c0d98135b20b52ac87236e1c935Chris CraikTexture* AssetAtlas::getEntryTexture(const SkBitmap* bitmap) const { 833b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy ssize_t index = mEntries.indexOfKey(bitmap); 84a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy return index >= 0 ? mEntries.valueAt(index)->texture : NULL; 853b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy} 863b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 873b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy/** 88a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy * Delegates changes to wrapping and filtering to the base atlas texture 89a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy * instead of applying the changes to the virtual textures. 90a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy */ 91a404e16e4933857464046d763ed7629cd0c86cbfRomain Guystruct DelegateTexture: public Texture { 928aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy DelegateTexture(Caches& caches, Texture* delegate): Texture(caches), mDelegate(delegate) { } 93a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy 94a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy virtual void setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture = false, 95a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy bool force = false, GLenum renderTarget = GL_TEXTURE_2D) { 96a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy mDelegate->setWrapST(wrapS, wrapT, bindTexture, force, renderTarget); 97a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy } 98a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy 99a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy virtual void setFilterMinMag(GLenum min, GLenum mag, bool bindTexture = false, 100a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy bool force = false, GLenum renderTarget = GL_TEXTURE_2D) { 101a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy mDelegate->setFilterMinMag(min, mag, bindTexture, force, renderTarget); 102a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy } 1037f6d6b0370df4b5a9e0f45bffc31ea6caeeb509dRomain Guy 104a404e16e4933857464046d763ed7629cd0c86cbfRomain Guyprivate: 105a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy Texture* const mDelegate; 106a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy}; // struct DelegateTexture 107a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy 108a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy/** 1093b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * TODO: This method does not take the rotation flag into account 1103b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy */ 11117ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhatvoid AssetAtlas::createEntries(Caches& caches, int64_t* map, int count) { 112a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy const float width = float(mTexture->width); 113a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy const float height = float(mTexture->height); 114a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy 1153b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy for (int i = 0; i < count; ) { 11617ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(map[i++]); 11717ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat // NOTE: We're converting from 64 bit signed values to 32 bit 11817ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat // signed values. This is guaranteed to be safe because the "x" 11917ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat // and "y" coordinate values are guaranteed to be representable 12017ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat // with 32 bits. The array is 64 bits wide so that it can carry 12117ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat // pointers on 64 bit architectures. 12217ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat const int x = static_cast<int>(map[i++]); 12317ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat const int y = static_cast<int>(map[i++]); 1243b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy bool rotated = map[i++] > 0; 1253b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 1263b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy // Bitmaps should never be null, we're just extra paranoid 1273b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy if (!bitmap) continue; 1283b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 1293b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy const UvMapper mapper( 130a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy x / width, (x + bitmap->width()) / width, 131a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy y / height, (y + bitmap->height()) / height); 132a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy 1338aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy Texture* texture = new DelegateTexture(caches, mTexture); 134a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy texture->blend = !bitmap->isOpaque(); 135a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy texture->width = bitmap->width(); 136a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy texture->height = bitmap->height(); 1377f6d6b0370df4b5a9e0f45bffc31ea6caeeb509dRomain Guy 1387f6d6b0370df4b5a9e0f45bffc31ea6caeeb509dRomain Guy Entry* entry = new Entry(bitmap, x, y, rotated, texture, mapper, *this); 139a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy texture->uvMapper = &entry->uvMapper; 1403b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 1413b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy mEntries.add(entry->bitmap, entry); 1423b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 1433b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy} 1443b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 1453b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy}; // namespace uirenderer 1463b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy}; // namespace android 147