C++程序  |  196行  |  5.21 KB

/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_HWUI_ASSET_ATLAS_H
#define ANDROID_HWUI_ASSET_ATLAS_H

#include <GLES2/gl2.h>

#include <ui/GraphicBuffer.h>

#include <utils/KeyedVector.h>

#include <cutils/compiler.h>

#include <SkBitmap.h>

#include "Image.h"
#include "Texture.h"
#include "UvMapper.h"

namespace android {
namespace uirenderer {

class Caches;

/**
 * An asset atlas holds a collection of framework bitmaps in a single OpenGL
 * texture. Each bitmap is associated with a location, defined in pixels,
 * inside the atlas. The atlas is generated by the framework and bound as
 * an external texture using the EGLImageKHR extension.
 */
class AssetAtlas {
public:
    /**
     * Entry representing the position and rotation of a
     * bitmap inside the atlas.
     */
    struct Entry {
        /**
         * The bitmap that generated this atlas entry.
         */
        SkBitmap* bitmap;

        /**
         * Location of the bitmap inside the atlas, in pixels.
         */
        int x;
        int y;

        /**
         * If set, the bitmap is rotated 90 degrees (clockwise)
         * inside the atlas.
         */
        bool rotated;

        /*
         * A "virtual texture" object that represents the texture
         * this entry belongs to. This texture should never be
         * modified.
         */
        Texture* texture;

        /**
         * Maps texture coordinates in the [0..1] range into the
         * correct range to sample this entry from the atlas.
         */
        const UvMapper uvMapper;

        /**
         * Atlas this entry belongs to.
         */
        const AssetAtlas& atlas;

        /**
         * Unique identifier used to merge bitmaps and 9-patches stored
         * in the atlas.
         */
        const void* getMergeId() const {
            return texture->blend ? &atlas.mBlendKey : &atlas.mOpaqueKey;
        }

    private:
        Entry(SkBitmap* bitmap, int x, int y, bool rotated,
                Texture* texture, const UvMapper& mapper, const AssetAtlas& atlas):
                bitmap(bitmap), x(x), y(y), rotated(rotated),
                texture(texture), uvMapper(mapper), atlas(atlas) {
        }

        ~Entry() {
            delete texture;
        }

        friend class AssetAtlas;
    };

    AssetAtlas(): mTexture(NULL), mImage(NULL), mGenerationId(0),
            mBlendKey(true), mOpaqueKey(false) { }
    ~AssetAtlas() { terminate(); }

    /**
     * Initializes the atlas with the specified buffer and
     * map. The buffer is a gralloc'd texture that will be
     * used as an EGLImage. The map is a list of SkBitmap*
     * and their (x, y) positions as well as their rotation
     * flags.
     *
     * This method returns immediately if the atlas is already
     * initialized. To re-initialize the atlas, you must
     * first call terminate().
     */
    ANDROID_API void init(sp<GraphicBuffer> buffer, int* map, int count);

    /**
     * Destroys the atlas texture. This object can be
     * re-initialized after calling this method.
     *
     * After calling this method, the width, height
     * and texture are set to 0.
     */
    ANDROID_API void terminate();

    /**
     * Returns the width of this atlas in pixels.
     * Can return 0 if the atlas is not initialized.
     */
    uint32_t getWidth() const {
        return mTexture ? mTexture->width : 0;
    }

    /**
     * Returns the height of this atlas in pixels.
     * Can return 0 if the atlas is not initialized.
     */
    uint32_t getHeight() const {
        return mTexture ? mTexture->height : 0;
    }

    /**
     * Returns the OpenGL name of the texture backing this atlas.
     * Can return 0 if the atlas is not initialized.
     */
    GLuint getTexture() const {
        return mTexture ? mTexture->id : 0;
    }

    /**
     * Returns the entry in the atlas associated with the specified
     * bitmap. If the bitmap is not in the atlas, return NULL.
     */
    Entry* getEntry(SkBitmap* const bitmap) const;

    /**
     * Returns the texture for the atlas entry associated with the
     * specified bitmap. If the bitmap is not in the atlas, return NULL.
     */
    Texture* getEntryTexture(SkBitmap* const bitmap) const;

    /**
     * Returns the current generation id of the atlas.
     */
    uint32_t getGenerationId() const {
        return mGenerationId;
    }

private:
    void createEntries(Caches& caches, int* map, int count);

    Texture* mTexture;
    Image* mImage;

    uint32_t mGenerationId;

    const bool mBlendKey;
    const bool mOpaqueKey;

    KeyedVector<SkBitmap*, Entry*> mEntries;
}; // class AssetAtlas

}; // namespace uirenderer
}; // namespace android

#endif // ANDROID_HWUI_ASSET_ATLAS_H