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#ifndef ANDROID_HWUI_ASSET_ATLAS_H
183b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#define ANDROID_HWUI_ASSET_ATLAS_H
193b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
2038e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck#include "Texture.h"
2138e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck#include "UvMapper.h"
223b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
233b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#include <cutils/compiler.h>
2438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck#include <GLES2/gl2.h>
2538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck#include <ui/GraphicBuffer.h>
263b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#include <SkBitmap.h>
273b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
2838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck#include <memory>
2938e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck#include <unordered_map>
303b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
313b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guynamespace android {
323b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guynamespace uirenderer {
333b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
348aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guyclass Caches;
352dc236b2bae13b9a0ed9b3f7320502aecd7983b3Tom Hudsonclass Image;
368aa195d7081b889f3a7b1f426cbd8556377aae5eRomain Guy
373b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy/**
383b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * An asset atlas holds a collection of framework bitmaps in a single OpenGL
393b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * texture. Each bitmap is associated with a location, defined in pixels,
403b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * inside the atlas. The atlas is generated by the framework and bound as
413b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy * an external texture using the EGLImageKHR extension.
423b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy */
433b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyclass AssetAtlas {
443b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guypublic:
453b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    /**
46a039182d6157bc0487df4ad8e373685c9dd7d662John Reck     * Entry representing the texture and uvMapper of a PixelRef in the
47a039182d6157bc0487df4ad8e373685c9dd7d662John Reck     * atlas
483b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     */
49c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck    class Entry {
50c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck    public:
51a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy        /*
52a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy         * A "virtual texture" object that represents the texture
53a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy         * this entry belongs to. This texture should never be
54a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy         * modified.
55a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy         */
56a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy        Texture* texture;
57a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy
583b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        /**
593b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy         * Maps texture coordinates in the [0..1] range into the
603b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy         * correct range to sample this entry from the atlas.
613b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy         */
623b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        const UvMapper uvMapper;
633b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
643b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        /**
657f6d6b0370df4b5a9e0f45bffc31ea6caeeb509dRomain Guy         * Unique identifier used to merge bitmaps and 9-patches stored
667f6d6b0370df4b5a9e0f45bffc31ea6caeeb509dRomain Guy         * in the atlas.
677f6d6b0370df4b5a9e0f45bffc31ea6caeeb509dRomain Guy         */
687f6d6b0370df4b5a9e0f45bffc31ea6caeeb509dRomain Guy        const void* getMergeId() const {
697f6d6b0370df4b5a9e0f45bffc31ea6caeeb509dRomain Guy            return texture->blend ? &atlas.mBlendKey : &atlas.mOpaqueKey;
707f6d6b0370df4b5a9e0f45bffc31ea6caeeb509dRomain Guy        }
717f6d6b0370df4b5a9e0f45bffc31ea6caeeb509dRomain Guy
7238e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck        ~Entry() {
7338e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck            delete texture;
7438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck        }
7538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck
763b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    private:
77c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck        /**
78c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck         * The pixel ref that generated this atlas entry.
79c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck         */
80c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck        SkPixelRef* pixelRef;
81c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck
82c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck        /**
83c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck         * Atlas this entry belongs to.
84c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck         */
85c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck        const AssetAtlas& atlas;
86c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck
87a039182d6157bc0487df4ad8e373685c9dd7d662John Reck        Entry(SkPixelRef* pixelRef, Texture* texture, const UvMapper& mapper,
88a039182d6157bc0487df4ad8e373685c9dd7d662John Reck                    const AssetAtlas& atlas)
89c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck                : texture(texture)
90c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck                , uvMapper(mapper)
91c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck                , pixelRef(pixelRef)
92c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck                , atlas(atlas) {
937f6d6b0370df4b5a9e0f45bffc31ea6caeeb509dRomain Guy        }
94a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy
953b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy        friend class AssetAtlas;
963b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    };
973b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
98e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik    AssetAtlas(): mTexture(nullptr), mImage(nullptr),
997f6d6b0370df4b5a9e0f45bffc31ea6caeeb509dRomain Guy            mBlendKey(true), mOpaqueKey(false) { }
1003b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    ~AssetAtlas() { terminate(); }
1013b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
1023b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    /**
1033b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * Initializes the atlas with the specified buffer and
1043b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * map. The buffer is a gralloc'd texture that will be
1053b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * used as an EGLImage. The map is a list of SkBitmap*
106a039182d6157bc0487df4ad8e373685c9dd7d662John Reck     * and their (x, y) positions
1073b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     *
1083b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * This method returns immediately if the atlas is already
1093b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * initialized. To re-initialize the atlas, you must
1103b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * first call terminate().
1113b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     */
11217ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat    ANDROID_API void init(sp<GraphicBuffer> buffer, int64_t* map, int count);
1133b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
1143b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    /**
1153b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * Destroys the atlas texture. This object can be
1163b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * re-initialized after calling this method.
1173b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     *
1183b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * After calling this method, the width, height
1193b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * and texture are set to 0.
1203b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     */
121ebd52610cfeff6e557fde284a7e1efc5e6438285John Reck    void terminate();
1223b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
1233b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    /**
1243b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * Returns the width of this atlas in pixels.
1253b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * Can return 0 if the atlas is not initialized.
1263b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     */
1273b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    uint32_t getWidth() const {
12838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck        return mTexture ? mTexture->width() : 0;
1293b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    }
1303b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
1313b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    /**
1323b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * Returns the height of this atlas in pixels.
1333b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * Can return 0 if the atlas is not initialized.
1343b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     */
1353b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    uint32_t getHeight() const {
13638e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck        return mTexture ? mTexture->height() : 0;
1373b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    }
1383b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
1393b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    /**
1403b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * Returns the OpenGL name of the texture backing this atlas.
1413b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * Can return 0 if the atlas is not initialized.
1423b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     */
1433b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    GLuint getTexture() const {
14438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck        return mTexture ? mTexture->id() : 0;
1453b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    }
1463b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
1473b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    /**
1483b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * Returns the entry in the atlas associated with the specified
14915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik     * pixelRef. If the pixelRef is not in the atlas, return NULL.
1503b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     */
15115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik    Entry* getEntry(const SkPixelRef* pixelRef) const;
1523b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
1533b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy    /**
1543b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     * Returns the texture for the atlas entry associated with the
15515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik     * specified pixelRef. If the pixelRef is not in the atlas, return NULL.
1563b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy     */
15715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik    Texture* getEntryTexture(const SkPixelRef* pixelRef) const;
1583b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
1593b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guyprivate:
16017ab38f8a87bc90eab11373f878f220ce3031de6Ashok Bhat    void createEntries(Caches& caches, int64_t* map, int count);
1613b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
162a404e16e4933857464046d763ed7629cd0c86cbfRomain Guy    Texture* mTexture;
163877cfe0e32a845d5a58252b8a6e1f54f95b4379cRomain Guy    Image* mImage;
1643b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
1657f6d6b0370df4b5a9e0f45bffc31ea6caeeb509dRomain Guy    const bool mBlendKey;
1667f6d6b0370df4b5a9e0f45bffc31ea6caeeb509dRomain Guy    const bool mOpaqueKey;
1677f6d6b0370df4b5a9e0f45bffc31ea6caeeb509dRomain Guy
16838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck    std::unordered_map<const SkPixelRef*, std::unique_ptr<Entry>> mEntries;
1693b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy}; // class AssetAtlas
1703b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
1713b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy}; // namespace uirenderer
1723b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy}; // namespace android
1733b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy
1743b748a44c6bd2ea05fe16839caf73dbe50bd7ae9Romain Guy#endif // ANDROID_HWUI_ASSET_ATLAS_H
175