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

Commit ebd52610 authored by John Reck's avatar John Reck
Browse files

Don't preload textures for AssetAtlas

Bug: 18317479

RenderNode::prepareSubTree calls prefetchAndMarkInUse
on every bitmapResoruce in the DisplayList. However,
this resulted in textures being uploaded for bitmaps
that would be drawn from the AssetAtlas instead.

To fix this we teach TextureCache about the AssetAtlas
so that calls to TextureCache return the Texture from
AssetAtlas if it exists. Thus usage of AssetAtlas
is now purely to allow for further optimizations via
draw merging instead of a requirement to get
any benefit at all.

Change-Id: I65282fa05bac46f4e93822b3467ffa0261ccf200
parent fa3f4314
Loading
Loading
Loading
Loading
+16 −19
Original line number Diff line number Diff line
@@ -36,39 +36,37 @@ void AssetAtlas::init(sp<GraphicBuffer> buffer, int64_t* map, int count) {
    ATRACE_NAME("AssetAtlas::init");

    mImage = new Image(buffer);

    if (mImage->getTexture()) {
        if (!mTexture) {
            Caches& caches = Caches::getInstance();

            mTexture = new Texture(caches);
        mTexture->id = mImage->getTexture();
            mTexture->width = buffer->getWidth();
            mTexture->height = buffer->getHeight();

            createEntries(caches, map, count);
        }
    } else {
        ALOGW("Could not create atlas image");

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

    mGenerationId++;
    updateTextureId();
}

void AssetAtlas::terminate() {
    if (mImage) {
        delete mImage;
        mImage = NULL;
        updateTextureId();
    }
}

        delete mTexture;
        mTexture = NULL;

void AssetAtlas::updateTextureId() {
    mTexture->id = mImage ? mImage->getTexture() : 0;
    for (size_t i = 0; i < mEntries.size(); i++) {
            delete mEntries.valueAt(i);
        }
        mEntries.clear();
        AssetAtlas::Entry* entry = mEntries.valueAt(i);
        entry->texture->id = mTexture->id;
    }
}

@@ -133,7 +131,6 @@ void AssetAtlas::createEntries(Caches& caches, int64_t* map, int count) {
                y / height, (y + bitmap->height()) / height);

        Texture* texture = new DelegateTexture(caches, mTexture);
        texture->id = mTexture->id;
        texture->blend = !bitmap->isOpaque();
        texture->width = bitmap->width();
        texture->height = bitmap->height();
+3 −11
Original line number Diff line number Diff line
@@ -106,7 +106,7 @@ public:
        friend class AssetAtlas;
    };

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

@@ -130,7 +130,7 @@ public:
     * After calling this method, the width, height
     * and texture are set to 0.
     */
    ANDROID_API void terminate();
    void terminate();

    /**
     * Returns the width of this atlas in pixels.
@@ -168,21 +168,13 @@ public:
     */
    Texture* getEntryTexture(const SkBitmap* bitmap) const;

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

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

    Texture* mTexture;
    Image* mImage;

    uint32_t mGenerationId;

    const bool mBlendKey;
    const bool mOpaqueKey;

+0 −2
Original line number Diff line number Diff line
@@ -237,8 +237,6 @@ void Caches::terminate() {
    programCache.clear();
    currentProgram = NULL;

    assetAtlas.terminate();

    patchCache.clear();

    clearGarbage();
+0 −2
Original line number Diff line number Diff line
@@ -348,8 +348,6 @@ public:
    Dither dither;
    Stencil stencil;

    AssetAtlas assetAtlas;

    bool gpuPixelBuffersEnabled;

    // Debug methods
+25 −33
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include "AssetAtlas.h"
#include "DeferredDisplayList.h"
#include "DisplayListRenderer.h"
#include "RenderState.h"
#include "UvMapper.h"
#include "utils/LinearAllocator.h"

@@ -647,24 +648,17 @@ public:
    DrawBitmapOp(const SkBitmap* bitmap, const SkPaint* paint)
            : DrawBoundedOp(0, 0, bitmap->width(), bitmap->height(), paint)
            , mBitmap(bitmap)
            , mAtlas(Caches::getInstance().assetAtlas) {
        mEntry = mAtlas.getEntry(bitmap);
        if (mEntry) {
            mEntryGenerationId = mAtlas.getGenerationId();
            mUvMapper = mEntry->uvMapper;
        }
            , mEntryValid(false), mEntry(NULL) {
    }

    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
        return renderer.drawBitmap(mBitmap, getPaint(renderer));
    }

    AssetAtlas::Entry* getAtlasEntry() {
        // The atlas entry is stale, let's get a new one
        if (mEntry && mEntryGenerationId != mAtlas.getGenerationId()) {
            mEntryGenerationId = mAtlas.getGenerationId();
            mEntry = mAtlas.getEntry(mBitmap);
            mUvMapper = mEntry->uvMapper;
    AssetAtlas::Entry* getAtlasEntry(OpenGLRenderer& renderer) {
        if (!mEntryValid) {
            mEntryValid = true;
            mEntry = renderer.renderState().assetAtlas().getEntry(mBitmap);
        }
        return mEntry;
    }
@@ -700,7 +694,7 @@ public:
            pureTranslate &= state.mMatrix.isPureTranslate();

            Rect texCoords(0, 0, 1, 1);
            ((DrawBitmapOp*) ops[i].op)->mUvMapper.map(texCoords);
            ((DrawBitmapOp*) ops[i].op)->uvMap(renderer, texCoords);

            SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top);
            SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
@@ -729,7 +723,7 @@ public:
    virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
            const DeferredDisplayState& state) {
        deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap;
        deferInfo.mergeId = getAtlasEntry() ?
        deferInfo.mergeId = getAtlasEntry(renderer) ?
                (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;

        // Don't merge non-simply transformed or neg scale ops, SET_TEXTURE doesn't handle rotation
@@ -742,13 +736,17 @@ public:
                (mBitmap->colorType() != kAlpha_8_SkColorType);
    }

    void uvMap(OpenGLRenderer& renderer, Rect& texCoords) {
        if (getAtlasEntry(renderer)) {
            mEntry->uvMapper.map(texCoords);
        }
    }

    const SkBitmap* bitmap() { return mBitmap; }
protected:
    const SkBitmap* mBitmap;
    const AssetAtlas& mAtlas;
    uint32_t mEntryGenerationId;
    bool mEntryValid;
    AssetAtlas::Entry* mEntry;
    UvMapper mUvMapper;
};

class DrawBitmapRectOp : public DrawBoundedOp {
@@ -841,18 +839,13 @@ public:
            float left, float top, float right, float bottom, const SkPaint* paint)
            : DrawBoundedOp(left, top, right, bottom, paint),
            mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(NULL),
            mAtlas(Caches::getInstance().assetAtlas) {
        mEntry = mAtlas.getEntry(bitmap);
        if (mEntry) {
            mEntryGenerationId = mAtlas.getGenerationId();
        }
            mEntryValid(false), mEntry(NULL) {
    };

    AssetAtlas::Entry* getAtlasEntry() {
        // The atlas entry is stale, let's get a new one
        if (mEntry && mEntryGenerationId != mAtlas.getGenerationId()) {
            mEntryGenerationId = mAtlas.getGenerationId();
            mEntry = mAtlas.getEntry(mBitmap);
    AssetAtlas::Entry* getAtlasEntry(OpenGLRenderer& renderer) {
        if (!mEntryValid) {
            mEntryValid = true;
            mEntry = renderer.renderState().assetAtlas().getEntry(mBitmap);
        }
        return mEntry;
    }
@@ -860,7 +853,7 @@ public:
    const Patch* getMesh(OpenGLRenderer& renderer) {
        if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) {
            PatchCache& cache = renderer.getCaches().patchCache;
            mMesh = cache.get(getAtlasEntry(), mBitmap->width(), mBitmap->height(),
            mMesh = cache.get(getAtlasEntry(renderer), mBitmap->width(), mBitmap->height(),
                    mLocalBounds.getWidth(), mLocalBounds.getHeight(), mPatch);
            mGenerationId = cache.getGenerationId();
        }
@@ -942,14 +935,14 @@ public:
            indexCount += opMesh->indexCount;
        }

        return renderer.drawPatches(mBitmap, getAtlasEntry(),
        return renderer.drawPatches(mBitmap, getAtlasEntry(renderer),
                &vertices[0], indexCount, getPaint(renderer));
    }

    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
        // We're not calling the public variant of drawPatch() here
        // This method won't perform the quickReject() since we've already done it at this point
        return renderer.drawPatch(mBitmap, getMesh(renderer), getAtlasEntry(),
        return renderer.drawPatch(mBitmap, getMesh(renderer), getAtlasEntry(renderer),
                mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
                getPaint(renderer));
    }
@@ -964,7 +957,7 @@ public:
    virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
            const DeferredDisplayState& state) {
        deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch;
        deferInfo.mergeId = getAtlasEntry() ? (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
        deferInfo.mergeId = getAtlasEntry(renderer) ? (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap;
        deferInfo.mergeable = state.mMatrix.isPureTranslate() &&
                OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
        deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) && mBitmap->isOpaque();
@@ -977,8 +970,7 @@ private:
    uint32_t mGenerationId;
    const Patch* mMesh;

    const AssetAtlas& mAtlas;
    uint32_t mEntryGenerationId;
    bool mEntryValid;
    AssetAtlas::Entry* mEntry;
};

Loading