AssetAtlas.cpp revision 38e0c32852e3b9d8ca4a9d3791577f52536419cb
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 173b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#include "AssetAtlas.h" 188aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy#include "Caches.h" 192dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudson#include "Image.h" 203b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 213b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#include <GLES2/gl2ext.h> 223b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 233b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guynamespace android { 243b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guynamespace uirenderer { 253b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 263b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy/////////////////////////////////////////////////////////////////////////////// 273b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy// Lifecycle 283b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy/////////////////////////////////////////////////////////////////////////////// 293b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 3017ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhatvoid AssetAtlas::init(sp<GraphicBuffer> buffer, int64_t* map, int count) { 31877cfe0e32a845d5a58252b8a6e1f54f95b4379cRomain Guy if (mImage) { 323b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy return; 333b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 343b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 35fbc8df03e498baf47ff1a5e05e182f1bcd60c770John Reck ATRACE_NAME("AssetAtlas::init"); 36fbc8df03e498baf47ff1a5e05e182f1bcd60c770John Reck 37877cfe0e32a845d5a58252b8a6e1f54f95b4379cRomain Guy mImage = new Image(buffer); 38a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy if (mImage->getTexture()) { 39ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck if (!mTexture) { 40ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck Caches& caches = Caches::getInstance(); 41ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck mTexture = new Texture(caches); 4238e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck mTexture->wrap(mImage->getTexture(), 4338e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck buffer->getWidth(), buffer->getHeight(), GL_RGBA); 44ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck createEntries(caches, map, count); 45ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck } 46877cfe0e32a845d5a58252b8a6e1f54f95b4379cRomain Guy } else { 47d5207b2eb9ba520da822d61ff78b539842fc5255Romain Guy ALOGW("Could not create atlas image"); 4838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck terminate(); 493b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 503b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy} 513b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 523b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyvoid AssetAtlas::terminate() { 5338e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck delete mImage; 5438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck mImage = nullptr; 5538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck delete mTexture; 5638e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck mTexture = nullptr; 5738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck mEntries.clear(); 583b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy} 593b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 603b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy/////////////////////////////////////////////////////////////////////////////// 613b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy// Entries 623b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy/////////////////////////////////////////////////////////////////////////////// 633b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 6415c3f19a445b8df575911a16e8a6dba755a084b5Chris CraikAssetAtlas::Entry* AssetAtlas::getEntry(const SkPixelRef* pixelRef) const { 6538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck auto result = mEntries.find(pixelRef); 6638e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck return result != mEntries.end() ? result->second.get() : nullptr; 673b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy} 683b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 6915c3f19a445b8df575911a16e8a6dba755a084b5Chris CraikTexture* AssetAtlas::getEntryTexture(const SkPixelRef* pixelRef) const { 7038e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck auto result = mEntries.find(pixelRef); 7138e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck return result != mEntries.end() ? result->second->texture : nullptr; 723b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy} 733b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 743b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy/** 75a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy * Delegates changes to wrapping and filtering to the base atlas texture 76a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy * instead of applying the changes to the virtual textures. 77a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy */ 78a404e16e4933857464046d763ed7629cd0c86cbfRomain Guystruct DelegateTexture: public Texture { 7938e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck DelegateTexture(Caches& caches, Texture* delegate) 8038e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck : Texture(caches), mDelegate(delegate) { } 81a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy 82a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy virtual void setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture = false, 83d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik bool force = false, GLenum renderTarget = GL_TEXTURE_2D) override { 84a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy mDelegate->setWrapST(wrapS, wrapT, bindTexture, force, renderTarget); 85a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy } 86a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy 87a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy virtual void setFilterMinMag(GLenum min, GLenum mag, bool bindTexture = false, 88d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik bool force = false, GLenum renderTarget = GL_TEXTURE_2D) override { 89a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy mDelegate->setFilterMinMag(min, mag, bindTexture, force, renderTarget); 90a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy } 917f6d6b0370df4b5a9e0f45bffc31ea6caeeb509dRomain Guy 92a404e16e4933857464046d763ed7629cd0c86cbfRomain Guyprivate: 93a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy Texture* const mDelegate; 94a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy}; // struct DelegateTexture 95a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy 9617ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhatvoid AssetAtlas::createEntries(Caches& caches, int64_t* map, int count) { 9738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck const float width = float(mTexture->width()); 9838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck const float height = float(mTexture->height()); 99a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy 1003b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy for (int i = 0; i < count; ) { 101c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck SkPixelRef* pixelRef = reinterpret_cast<SkPixelRef*>(map[i++]); 10217ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat // NOTE: We're converting from 64 bit signed values to 32 bit 10317ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat // signed values. This is guaranteed to be safe because the "x" 10417ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat // and "y" coordinate values are guaranteed to be representable 10517ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat // with 32 bits. The array is 64 bits wide so that it can carry 10617ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat // pointers on 64 bit architectures. 10717ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat const int x = static_cast<int>(map[i++]); 10817ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat const int y = static_cast<int>(map[i++]); 1093b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 1103b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy // Bitmaps should never be null, we're just extra paranoid 111c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck if (!pixelRef) continue; 1123b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 1133b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy const UvMapper mapper( 114c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck x / width, (x + pixelRef->info().width()) / width, 115c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck y / height, (y + pixelRef->info().height()) / height); 116a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy 1178aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy Texture* texture = new DelegateTexture(caches, mTexture); 118c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck texture->blend = !SkAlphaTypeIsOpaque(pixelRef->info().alphaType()); 11938e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck texture->wrap(mTexture->id(), pixelRef->info().width(), 12038e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck pixelRef->info().height(), mTexture->format()); 1217f6d6b0370df4b5a9e0f45bffc31ea6caeeb509dRomain Guy 12238e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck std::unique_ptr<Entry> entry(new Entry(pixelRef, texture, mapper, *this)); 123a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy texture->uvMapper = &entry->uvMapper; 1243b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 12538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck mEntries.emplace(entry->pixelRef, std::move(entry)); 1263b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy } 1273b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy} 1283b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy 1293b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy}; // namespace uirenderer 1303b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy}; // namespace android 131