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