summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author John Reck <jreck@google.com> 2014-12-10 16:47:36 -0800
committer John Reck <jreck@google.com> 2014-12-10 17:07:41 -0800
commitebd52610cfeff6e557fde284a7e1efc5e6438285 (patch)
tree6e371646828e9074579fe91f869954a67f48e93a
parentfa3f43145ac1af62ed063d3cd7ba1c30a81bb3fd (diff)
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
-rw-r--r--libs/hwui/AssetAtlas.cpp35
-rw-r--r--libs/hwui/AssetAtlas.h14
-rw-r--r--libs/hwui/Caches.cpp2
-rw-r--r--libs/hwui/Caches.h2
-rw-r--r--libs/hwui/DisplayListOp.h58
-rwxr-xr-xlibs/hwui/OpenGLRenderer.cpp6
-rw-r--r--libs/hwui/RenderState.cpp2
-rw-r--r--libs/hwui/RenderState.h4
-rw-r--r--libs/hwui/TextureCache.cpp16
-rw-r--r--libs/hwui/TextureCache.h6
-rw-r--r--libs/hwui/renderthread/EglManager.cpp3
11 files changed, 75 insertions, 73 deletions
diff --git a/libs/hwui/AssetAtlas.cpp b/libs/hwui/AssetAtlas.cpp
index e5a93bde191b..c6de53594b0f 100644
--- a/libs/hwui/AssetAtlas.cpp
+++ b/libs/hwui/AssetAtlas.cpp
@@ -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()) {
- Caches& caches = Caches::getInstance();
-
- mTexture = new Texture(caches);
- mTexture->id = mImage->getTexture();
- mTexture->width = buffer->getWidth();
- mTexture->height = buffer->getHeight();
-
- createEntries(caches, map, count);
+ if (!mTexture) {
+ Caches& caches = Caches::getInstance();
+ mTexture = new Texture(caches);
+ 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;
- for (size_t i = 0; i < mEntries.size(); i++) {
- delete mEntries.valueAt(i);
- }
- mEntries.clear();
+void AssetAtlas::updateTextureId() {
+ mTexture->id = mImage ? mImage->getTexture() : 0;
+ for (size_t i = 0; i < mEntries.size(); i++) {
+ 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();
diff --git a/libs/hwui/AssetAtlas.h b/libs/hwui/AssetAtlas.h
index 2ec556e0e3a9..fffd7401e608 100644
--- a/libs/hwui/AssetAtlas.h
+++ b/libs/hwui/AssetAtlas.h
@@ -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;
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 6453206eac3d..4bbe6edf7296 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -237,8 +237,6 @@ void Caches::terminate() {
programCache.clear();
currentProgram = NULL;
- assetAtlas.terminate();
-
patchCache.clear();
clearGarbage();
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index e338686a245b..2e179af8eecc 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -348,8 +348,6 @@ public:
Dither dither;
Stencil stencil;
- AssetAtlas assetAtlas;
-
bool gpuPixelBuffersEnabled;
// Debug methods
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 96e76d0d4101..8a5e21d3f456 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -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;
};
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 075f2c509b24..62fdb93d73d5 100755
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2049,7 +2049,7 @@ status_t OpenGLRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, i
}
mCaches.activeTexture(0);
- Texture* texture = mCaches.assetAtlas.getEntryTexture(bitmap);
+ Texture* texture = mRenderState.assetAtlas().getEntryTexture(bitmap);
const UvMapper& mapper(getMapper(texture));
for (int32_t y = 0; y < meshHeight; y++) {
@@ -2232,7 +2232,7 @@ status_t OpenGLRenderer::drawPatch(const SkBitmap* bitmap, const Res_png_9patch*
return DrawGlInfo::kStatusDone;
}
- AssetAtlas::Entry* entry = mCaches.assetAtlas.getEntry(bitmap);
+ AssetAtlas::Entry* entry = mRenderState.assetAtlas().getEntry(bitmap);
const Patch* mesh = mCaches.patchCache.get(entry, bitmap->width(), bitmap->height(),
right - left, bottom - top, patch);
@@ -3028,7 +3028,7 @@ const SkPaint* OpenGLRenderer::filterPaint(const SkPaint* paint) {
///////////////////////////////////////////////////////////////////////////////
Texture* OpenGLRenderer::getTexture(const SkBitmap* bitmap) {
- Texture* texture = mCaches.assetAtlas.getEntryTexture(bitmap);
+ Texture* texture = mRenderState.assetAtlas().getEntryTexture(bitmap);
if (!texture) {
return mCaches.textureCache.get(bitmap);
}
diff --git a/libs/hwui/RenderState.cpp b/libs/hwui/RenderState.cpp
index a8cf26f0d5da..d1f5f4e0fdd2 100644
--- a/libs/hwui/RenderState.cpp
+++ b/libs/hwui/RenderState.cpp
@@ -38,6 +38,7 @@ void RenderState::onGLContextCreated() {
mCaches = &Caches::getInstance();
mCaches->init();
mCaches->setRenderState(this);
+ mCaches->textureCache.setAssetAtlas(&mAssetAtlas);
}
void RenderState::onGLContextDestroyed() {
@@ -72,6 +73,7 @@ void RenderState::onGLContextDestroyed() {
LOG_ALWAYS_FATAL("%d layers have survived gl context destruction", size);
}
*/
+ mAssetAtlas.terminate();
}
void RenderState::setViewport(GLsizei width, GLsizei height) {
diff --git a/libs/hwui/RenderState.h b/libs/hwui/RenderState.h
index afeef950d5cd..1ecfb1cf7c6c 100644
--- a/libs/hwui/RenderState.h
+++ b/libs/hwui/RenderState.h
@@ -23,6 +23,7 @@
#include <private/hwui/DrawGlInfo.h>
+#include "AssetAtlas.h"
#include "Caches.h"
#include "utils/Macros.h"
@@ -73,6 +74,8 @@ public:
// more thinking...
void postDecStrong(VirtualLightRefBase* object);
+ AssetAtlas& assetAtlas() { return mAssetAtlas; }
+
private:
friend class renderthread::RenderThread;
friend class Caches;
@@ -86,6 +89,7 @@ private:
renderthread::RenderThread& mRenderThread;
Caches* mCaches;
+ AssetAtlas mAssetAtlas;
std::set<const Layer*> mActiveLayers;
std::set<renderthread::CanvasContext*> mRegisteredContexts;
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 5bad2fc43e6f..63454d8ef7c9 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -24,6 +24,7 @@
#include <utils/Mutex.h>
+#include "AssetAtlas.h"
#include "Caches.h"
#include "TextureCache.h"
#include "Properties.h"
@@ -39,7 +40,7 @@ namespace uirenderer {
TextureCache::TextureCache():
mCache(LruCache<uint32_t, Texture*>::kUnlimitedCapacity),
mSize(0), mMaxSize(MB(DEFAULT_TEXTURE_CACHE_SIZE)),
- mFlushRate(DEFAULT_TEXTURE_CACHE_FLUSH_RATE) {
+ mFlushRate(DEFAULT_TEXTURE_CACHE_FLUSH_RATE), mAssetAtlas(0) {
char property[PROPERTY_VALUE_MAX];
if (property_get(PROPERTY_TEXTURE_CACHE_SIZE, property, NULL) > 0) {
INIT_LOGD(" Setting texture cache size to %sMB", property);
@@ -62,7 +63,7 @@ TextureCache::TextureCache():
TextureCache::TextureCache(uint32_t maxByteSize):
mCache(LruCache<uint32_t, Texture*>::kUnlimitedCapacity),
- mSize(0), mMaxSize(maxByteSize) {
+ mSize(0), mMaxSize(maxByteSize), mAssetAtlas(0) {
init();
}
@@ -124,6 +125,10 @@ void TextureCache::operator()(uint32_t&, Texture*& texture) {
// Caching
///////////////////////////////////////////////////////////////////////////////
+void TextureCache::setAssetAtlas(AssetAtlas* assetAtlas) {
+ mAssetAtlas = assetAtlas;
+}
+
void TextureCache::resetMarkInUse() {
LruCache<uint32_t, Texture*>::Iterator iter(mCache);
while (iter.next()) {
@@ -143,6 +148,13 @@ bool TextureCache::canMakeTextureFromBitmap(const SkBitmap* bitmap) {
// Returns a prepared Texture* that either is already in the cache or can fit
// in the cache (and is thus added to the cache)
Texture* TextureCache::getCachedTexture(const SkBitmap* bitmap) {
+ if (CC_LIKELY(mAssetAtlas)) {
+ AssetAtlas::Entry* entry = mAssetAtlas->getEntry(bitmap);
+ if (CC_UNLIKELY(entry)) {
+ return entry->texture;
+ }
+ }
+
Texture* texture = mCache.get(bitmap->pixelRef()->getStableID());
if (!texture) {
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index 3e94d1f4781b..cf8d1349dc50 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -44,6 +44,8 @@ namespace uirenderer {
// Classes
///////////////////////////////////////////////////////////////////////////////
+class AssetAtlas;
+
/**
* A simple LRU texture cache. The cache has a maximum size expressed in bytes.
* Any texture added to the cache causing the cache to grow beyond the maximum
@@ -123,6 +125,8 @@ public:
*/
void setFlushRate(float flushRate);
+ void setAssetAtlas(AssetAtlas* assetAtlas);
+
private:
bool canMakeTextureFromBitmap(const SkBitmap* bitmap);
@@ -155,6 +159,8 @@ private:
Vector<uint32_t> mGarbage;
mutable Mutex mLock;
+
+ AssetAtlas* mAssetAtlas;
}; // class TextureCache
}; // namespace uirenderer
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 378cf618a26f..8fb1b1011aa5 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -175,7 +175,8 @@ void EglManager::setTextureAtlas(const sp<GraphicBuffer>& buffer,
void EglManager::initAtlas() {
if (mAtlasBuffer.get()) {
- Caches::getInstance().assetAtlas.init(mAtlasBuffer, mAtlasMap, mAtlasMapSize);
+ mRenderThread.renderState().assetAtlas().init(mAtlasBuffer,
+ mAtlasMap, mAtlasMapSize);
}
}