Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a404e16e authored by Romain Guy's avatar Romain Guy
Browse files

Make sure atlas antries can correctly filter/wrap textures

The virtual textures would each have their own values for wrapping
and filtering which could lead to conflict and/or extraneous GL
commands being issued.

Change-Id: I64cb59a03e598f46bf645bd1d30fccfa63a07431
parent 64770d16
Loading
Loading
Loading
Loading
+44 −16
Original line number Diff line number Diff line
@@ -31,11 +31,12 @@ void AssetAtlas::init(sp<GraphicBuffer> buffer, int* map, int count) {
    }

    mImage = new Image(buffer);
    mTexture = mImage->getTexture();

    if (mTexture) {
        mWidth = buffer->getWidth();
        mHeight = buffer->getHeight();
    if (mImage->getTexture()) {
        mTexture = new Texture();
        mTexture->id = mImage->getTexture();
        mTexture->width = buffer->getWidth();
        mTexture->height = buffer->getHeight();

        createEntries(map, count);
    } else {
@@ -43,6 +44,7 @@ void AssetAtlas::init(sp<GraphicBuffer> buffer, int* map, int count) {

        delete mImage;
        mImage = NULL;
        mTexture = NULL;
    }
}

@@ -51,12 +53,13 @@ void AssetAtlas::terminate() {
        delete mImage;
        mImage = NULL;

        delete mTexture;
        mTexture = NULL;

        for (size_t i = 0; i < mEntries.size(); i++) {
            delete mEntries.valueAt(i);
        }
        mEntries.clear();

        mWidth = mHeight = 0;
    }
}

@@ -71,13 +74,36 @@ AssetAtlas::Entry* AssetAtlas::getEntry(SkBitmap* const bitmap) const {

Texture* AssetAtlas::getEntryTexture(SkBitmap* const bitmap) const {
    ssize_t index = mEntries.indexOfKey(bitmap);
    return index >= 0 ? &mEntries.valueAt(index)->texture : NULL;
    return index >= 0 ? mEntries.valueAt(index)->texture : NULL;
}

/**
 * Delegates changes to wrapping and filtering to the base atlas texture
 * instead of applying the changes to the virtual textures.
 */
struct DelegateTexture: public Texture {
    DelegateTexture(Texture* delegate): Texture(), mDelegate(delegate) { }

    virtual void setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture = false,
            bool force = false, GLenum renderTarget = GL_TEXTURE_2D) {
        mDelegate->setWrapST(wrapS, wrapT, bindTexture, force, renderTarget);
    }

    virtual void setFilterMinMag(GLenum min, GLenum mag, bool bindTexture = false,
            bool force = false, GLenum renderTarget = GL_TEXTURE_2D) {
        mDelegate->setFilterMinMag(min, mag, bindTexture, force, renderTarget);
    }
private:
    Texture* const mDelegate;
}; // struct DelegateTexture

/**
 * TODO: This method does not take the rotation flag into account
 */
void AssetAtlas::createEntries(int* map, int count) {
    const float width = float(mTexture->width);
    const float height = float(mTexture->height);

    for (int i = 0; i < count; ) {
        SkBitmap* bitmap = (SkBitmap*) map[i++];
        int x = map[i++];
@@ -88,15 +114,17 @@ void AssetAtlas::createEntries(int* map, int count) {
        if (!bitmap) continue;

        const UvMapper mapper(
                x / (float) mWidth, (x + bitmap->width()) / (float) mWidth,
                y / (float) mHeight, (y + bitmap->height()) / (float) mHeight);

        Entry* entry = new Entry(bitmap, x, y, rotated, mapper, *this);
        entry->texture.id = mTexture;
        entry->texture.blend = !bitmap->isOpaque();
        entry->texture.width = bitmap->width();
        entry->texture.height = bitmap->height();
        entry->texture.uvMapper = &entry->uvMapper;
                x / width, (x + bitmap->width()) / width,
                y / height, (y + bitmap->height()) / height);

        Texture* texture = new DelegateTexture(mTexture);
        Entry* entry = new Entry(bitmap, x, y, rotated, texture, mapper, *this);

        texture->id = mTexture->id;
        texture->blend = !bitmap->isOpaque();
        texture->width = bitmap->width();
        texture->height = bitmap->height();
        texture->uvMapper = &entry->uvMapper;

        mEntries.add(entry->bitmap, entry);
    }
+19 −17
Original line number Diff line number Diff line
@@ -64,6 +64,13 @@ public:
         */
        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.
@@ -75,22 +82,20 @@ public:
         */
        const AssetAtlas& atlas;

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

    private:
        Entry(SkBitmap* bitmap, int x, int y, bool rotated,
                const UvMapper& mapper, const AssetAtlas& atlas):
                bitmap(bitmap), x(x), y(y), rotated(rotated), uvMapper(mapper), atlas(atlas) { }
                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(): mWidth(0), mHeight(0), mTexture(0), mImage(NULL) { }
    AssetAtlas(): mTexture(NULL), mImage(NULL) { }
    ~AssetAtlas() { terminate(); }

    /**
@@ -120,7 +125,7 @@ public:
     * Can return 0 if the atlas is not initialized.
     */
    uint32_t getWidth() const {
        return mWidth;
        return mTexture ? mTexture->width : 0;
    }

    /**
@@ -128,7 +133,7 @@ public:
     * Can return 0 if the atlas is not initialized.
     */
    uint32_t getHeight() const {
        return mHeight;
        return mTexture ? mTexture->height : 0;
    }

    /**
@@ -136,7 +141,7 @@ public:
     * Can return 0 if the atlas is not initialized.
     */
    GLuint getTexture() const {
        return mTexture;
        return mTexture ? mTexture->id : 0;
    }

    /**
@@ -154,10 +159,7 @@ public:
private:
    void createEntries(int* map, int count);

    uint32_t mWidth;
    uint32_t mHeight;

    GLuint mTexture;
    Texture* mTexture;
    Image* mImage;

    KeyedVector<SkBitmap*, Entry*> mEntries;
+1 −1
Original line number Diff line number Diff line
@@ -2352,7 +2352,7 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,

    if (CC_LIKELY(mesh && mesh->verticesCount > 0)) {
        mCaches.activeTexture(0);
        Texture* texture = entry ? &entry->texture : mCaches.textureCache.get(bitmap);
        Texture* texture = entry ? entry->texture : mCaches.textureCache.get(bitmap);
        if (!texture) return DrawGlInfo::kStatusDone;
        const AutoTexture autoCleanup(texture);

+0 −1
Original line number Diff line number Diff line
@@ -1083,7 +1083,6 @@ private:
    // No-ops start/endTiling when set
    bool mSuppressTiling;


    // If true, this renderer will setup drawing to emulate
    // an increment stencil buffer in the color buffer
    bool mCountOverdraw;
+6 −4
Original line number Diff line number Diff line
@@ -48,13 +48,15 @@ struct Texture {
        uvMapper = NULL;
    }

    virtual ~Texture() { }

    void setWrap(GLenum wrap, bool bindTexture = false, bool force = false,
                GLenum renderTarget = GL_TEXTURE_2D) {
        setWrapST(wrap, wrap, bindTexture, force, renderTarget);
    }

    void setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture = false, bool force = false,
            GLenum renderTarget = GL_TEXTURE_2D) {
    virtual void setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture = false,
            bool force = false, GLenum renderTarget = GL_TEXTURE_2D) {

        if (firstWrap || force || wrapS != this->wrapS || wrapT != this->wrapT) {
            firstWrap = false;
@@ -76,8 +78,8 @@ struct Texture {
        setFilterMinMag(filter, filter, bindTexture, force, renderTarget);
    }

    void setFilterMinMag(GLenum min, GLenum mag, bool bindTexture = false, bool force = false,
            GLenum renderTarget = GL_TEXTURE_2D) {
    virtual void setFilterMinMag(GLenum min, GLenum mag, bool bindTexture = false,
            bool force = false, GLenum renderTarget = GL_TEXTURE_2D) {

        if (firstFilter || force || min != minFilter || mag != magFilter) {
            firstFilter = false;