am 1641c0cb: Merge "Move AssetAtlas off of SkBitmap*" into mnc-dev
* commit '1641c0cb0b6baf313c82846fe4f64007078c604f': Move AssetAtlas off of SkBitmap*
This commit is contained in:
@@ -460,8 +460,6 @@ public class ThreadedRenderer extends HardwareRenderer {
|
||||
if (buffer != null) {
|
||||
long[] map = atlas.getMap();
|
||||
if (map != null) {
|
||||
// TODO Remove after fixing b/15425820
|
||||
validateMap(context, map);
|
||||
nSetAtlas(renderProxy, buffer, map);
|
||||
}
|
||||
// If IAssetAtlas is not the same class as the IBinder
|
||||
@@ -476,32 +474,6 @@ public class ThreadedRenderer extends HardwareRenderer {
|
||||
Log.w(LOG_TAG, "Could not acquire atlas", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void validateMap(Context context, long[] map) {
|
||||
Log.d("Atlas", "Validating map...");
|
||||
HashSet<Long> preloadedPointers = new HashSet<Long>();
|
||||
|
||||
// We only care about drawables that hold bitmaps
|
||||
final Resources resources = context.getResources();
|
||||
final LongSparseArray<Drawable.ConstantState> drawables = resources.getPreloadedDrawables();
|
||||
|
||||
final int count = drawables.size();
|
||||
ArrayList<Bitmap> tmpList = new ArrayList<Bitmap>();
|
||||
for (int i = 0; i < count; i++) {
|
||||
drawables.valueAt(i).addAtlasableBitmaps(tmpList);
|
||||
for (int j = 0; j < tmpList.size(); j++) {
|
||||
preloadedPointers.add(tmpList.get(j).getSkBitmap());
|
||||
}
|
||||
tmpList.clear();
|
||||
}
|
||||
|
||||
for (int i = 0; i < map.length; i += 4) {
|
||||
if (!preloadedPointers.contains(map[i])) {
|
||||
Log.w("Atlas", String.format("Pointer 0x%X, not in getPreloadedDrawables?", map[i]));
|
||||
map[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static native void setupShadersDiskCache(String cacheFile);
|
||||
|
||||
@@ -857,6 +857,13 @@ static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapHandle) {
|
||||
bitmap->unlockPixels();
|
||||
}
|
||||
|
||||
static jlong Bitmap_refPixelRef(JNIEnv* env, jobject, jlong bitmapHandle) {
|
||||
SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
|
||||
SkPixelRef* pixelRef = bitmap ? bitmap->pixelRef() : nullptr;
|
||||
SkSafeRef(pixelRef);
|
||||
return reinterpret_cast<jlong>(pixelRef);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static JNINativeMethod gBitmapMethods[] = {
|
||||
@@ -896,6 +903,7 @@ static JNINativeMethod gBitmapMethods[] = {
|
||||
(void*)Bitmap_copyPixelsFromBuffer },
|
||||
{ "nativeSameAs", "(JJ)Z", (void*)Bitmap_sameAs },
|
||||
{ "nativePrepareToDraw", "(J)V", (void*)Bitmap_prepareToDraw },
|
||||
{ "nativeRefPixelRef", "(J)J", (void*)Bitmap_refPixelRef },
|
||||
};
|
||||
|
||||
int register_android_graphics_Bitmap(JNIEnv* env)
|
||||
|
||||
@@ -1573,6 +1573,15 @@ public final class Bitmap implements Parcelable {
|
||||
return mSkBitmapPtr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refs the underlying SkPixelRef and returns a pointer to it.
|
||||
*
|
||||
* @hide
|
||||
* */
|
||||
public final long refSkPixelRef() {
|
||||
return nativeRefPixelRef(mSkBitmapPtr);
|
||||
}
|
||||
|
||||
private static class BitmapFinalizer {
|
||||
private long mNativeBitmap;
|
||||
|
||||
@@ -1661,4 +1670,5 @@ public final class Bitmap implements Parcelable {
|
||||
private static native boolean nativeHasMipMap(long nativeBitmap);
|
||||
private static native void nativeSetHasMipMap(long nativeBitmap, boolean hasMipMap);
|
||||
private static native boolean nativeSameAs(long nativeBitmap0, long nativeBitmap1);
|
||||
private static native long nativeRefPixelRef(long nativeBitmap);
|
||||
}
|
||||
|
||||
@@ -82,12 +82,12 @@ void AssetAtlas::updateTextureId() {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AssetAtlas::Entry* AssetAtlas::getEntry(const SkBitmap* bitmap) const {
|
||||
ssize_t index = mEntries.indexOfKey(bitmap);
|
||||
ssize_t index = mEntries.indexOfKey(bitmap->pixelRef());
|
||||
return index >= 0 ? mEntries.valueAt(index) : nullptr;
|
||||
}
|
||||
|
||||
Texture* AssetAtlas::getEntryTexture(const SkBitmap* bitmap) const {
|
||||
ssize_t index = mEntries.indexOfKey(bitmap);
|
||||
ssize_t index = mEntries.indexOfKey(bitmap->pixelRef());
|
||||
return index >= 0 ? mEntries.valueAt(index)->texture : nullptr;
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ void AssetAtlas::createEntries(Caches& caches, int64_t* map, int count) {
|
||||
const float height = float(mTexture->height);
|
||||
|
||||
for (int i = 0; i < count; ) {
|
||||
SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(map[i++]);
|
||||
SkPixelRef* pixelRef = reinterpret_cast<SkPixelRef*>(map[i++]);
|
||||
// NOTE: We're converting from 64 bit signed values to 32 bit
|
||||
// signed values. This is guaranteed to be safe because the "x"
|
||||
// and "y" coordinate values are guaranteed to be representable
|
||||
@@ -131,21 +131,21 @@ void AssetAtlas::createEntries(Caches& caches, int64_t* map, int count) {
|
||||
bool rotated = map[i++] > 0;
|
||||
|
||||
// Bitmaps should never be null, we're just extra paranoid
|
||||
if (!bitmap) continue;
|
||||
if (!pixelRef) continue;
|
||||
|
||||
const UvMapper mapper(
|
||||
x / width, (x + bitmap->width()) / width,
|
||||
y / height, (y + bitmap->height()) / height);
|
||||
x / width, (x + pixelRef->info().width()) / width,
|
||||
y / height, (y + pixelRef->info().height()) / height);
|
||||
|
||||
Texture* texture = new DelegateTexture(caches, mTexture);
|
||||
texture->blend = !bitmap->isOpaque();
|
||||
texture->width = bitmap->width();
|
||||
texture->height = bitmap->height();
|
||||
texture->blend = !SkAlphaTypeIsOpaque(pixelRef->info().alphaType());
|
||||
texture->width = pixelRef->info().width();
|
||||
texture->height = pixelRef->info().height();
|
||||
|
||||
Entry* entry = new Entry(bitmap, x, y, rotated, texture, mapper, *this);
|
||||
Entry* entry = new Entry(pixelRef, x, y, rotated, texture, mapper, *this);
|
||||
texture->uvMapper = &entry->uvMapper;
|
||||
|
||||
mEntries.add(entry->bitmap, entry);
|
||||
mEntries.add(entry->pixelRef, entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,24 +48,8 @@ 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;
|
||||
|
||||
class Entry {
|
||||
public:
|
||||
/*
|
||||
* A "virtual texture" object that represents the texture
|
||||
* this entry belongs to. This texture should never be
|
||||
@@ -79,11 +63,6 @@ public:
|
||||
*/
|
||||
const UvMapper uvMapper;
|
||||
|
||||
/**
|
||||
* Atlas this entry belongs to.
|
||||
*/
|
||||
const AssetAtlas& atlas;
|
||||
|
||||
/**
|
||||
* Unique identifier used to merge bitmaps and 9-patches stored
|
||||
* in the atlas.
|
||||
@@ -93,10 +72,37 @@ public:
|
||||
}
|
||||
|
||||
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) {
|
||||
/**
|
||||
* The pixel ref that generated this atlas entry.
|
||||
*/
|
||||
SkPixelRef* pixelRef;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Atlas this entry belongs to.
|
||||
*/
|
||||
const AssetAtlas& atlas;
|
||||
|
||||
Entry(SkPixelRef* pixelRef, int x, int y, bool rotated,
|
||||
Texture* texture, const UvMapper& mapper, const AssetAtlas& atlas)
|
||||
: texture(texture)
|
||||
, uvMapper(mapper)
|
||||
, pixelRef(pixelRef)
|
||||
, x(x)
|
||||
, y(y)
|
||||
, rotated(rotated)
|
||||
, atlas(atlas) {
|
||||
}
|
||||
|
||||
~Entry() {
|
||||
@@ -178,7 +184,7 @@ private:
|
||||
const bool mBlendKey;
|
||||
const bool mOpaqueKey;
|
||||
|
||||
KeyedVector<const SkBitmap*, Entry*> mEntries;
|
||||
KeyedVector<const SkPixelRef*, Entry*> mEntries;
|
||||
}; // class AssetAtlas
|
||||
|
||||
}; // namespace uirenderer
|
||||
|
||||
@@ -199,8 +199,6 @@ public class AssetAtlasService extends IAssetAtlas.Stub {
|
||||
private final ArrayList<Bitmap> mBitmaps;
|
||||
private final int mPixelCount;
|
||||
|
||||
private Bitmap mAtlasBitmap;
|
||||
|
||||
Renderer(ArrayList<Bitmap> bitmaps, int pixelCount) {
|
||||
mBitmaps = bitmaps;
|
||||
mPixelCount = pixelCount;
|
||||
@@ -255,8 +253,9 @@ public class AssetAtlasService extends IAssetAtlas.Stub {
|
||||
|
||||
// We always render the atlas into a bitmap. This bitmap is then
|
||||
// uploaded into the GraphicBuffer using OpenGL to swizzle the content
|
||||
final Canvas canvas = acquireCanvas(buffer.getWidth(), buffer.getHeight());
|
||||
if (canvas == null) return false;
|
||||
final Bitmap atlasBitmap = Bitmap.createBitmap(
|
||||
buffer.getWidth(), buffer.getHeight(), Bitmap.Config.ARGB_8888);
|
||||
final Canvas canvas = new Canvas(atlasBitmap);
|
||||
|
||||
final Atlas.Entry entry = new Atlas.Entry();
|
||||
|
||||
@@ -265,73 +264,58 @@ public class AssetAtlasService extends IAssetAtlas.Stub {
|
||||
int mapIndex = 0;
|
||||
|
||||
boolean result = false;
|
||||
try {
|
||||
final long startRender = System.nanoTime();
|
||||
final int count = mBitmaps.size();
|
||||
final long startRender = System.nanoTime();
|
||||
final int count = mBitmaps.size();
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
final Bitmap bitmap = mBitmaps.get(i);
|
||||
if (atlas.pack(bitmap.getWidth(), bitmap.getHeight(), entry) != null) {
|
||||
// We have more bitmaps to pack than the current configuration
|
||||
// says, we were most likely not able to detect a change in the
|
||||
// list of preloaded drawables, abort and delete the configuration
|
||||
if (mapIndex >= mAtlasMap.length) {
|
||||
deleteDataFile();
|
||||
break;
|
||||
}
|
||||
|
||||
canvas.save();
|
||||
canvas.translate(entry.x, entry.y);
|
||||
if (entry.rotated) {
|
||||
canvas.translate(bitmap.getHeight(), 0.0f);
|
||||
canvas.rotate(90.0f);
|
||||
}
|
||||
canvas.drawBitmap(bitmap, 0.0f, 0.0f, null);
|
||||
canvas.restore();
|
||||
atlasMap[mapIndex++] = bitmap.getSkBitmap();
|
||||
atlasMap[mapIndex++] = entry.x;
|
||||
atlasMap[mapIndex++] = entry.y;
|
||||
atlasMap[mapIndex++] = entry.rotated ? 1 : 0;
|
||||
for (int i = 0; i < count; i++) {
|
||||
final Bitmap bitmap = mBitmaps.get(i);
|
||||
if (atlas.pack(bitmap.getWidth(), bitmap.getHeight(), entry) != null) {
|
||||
// We have more bitmaps to pack than the current configuration
|
||||
// says, we were most likely not able to detect a change in the
|
||||
// list of preloaded drawables, abort and delete the configuration
|
||||
if (mapIndex >= mAtlasMap.length) {
|
||||
deleteDataFile();
|
||||
break;
|
||||
}
|
||||
|
||||
canvas.save();
|
||||
canvas.translate(entry.x, entry.y);
|
||||
if (entry.rotated) {
|
||||
canvas.translate(bitmap.getHeight(), 0.0f);
|
||||
canvas.rotate(90.0f);
|
||||
}
|
||||
canvas.drawBitmap(bitmap, 0.0f, 0.0f, null);
|
||||
canvas.restore();
|
||||
atlasMap[mapIndex++] = bitmap.refSkPixelRef();
|
||||
atlasMap[mapIndex++] = entry.x;
|
||||
atlasMap[mapIndex++] = entry.y;
|
||||
atlasMap[mapIndex++] = entry.rotated ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
final long endRender = System.nanoTime();
|
||||
result = nUploadAtlas(buffer, mAtlasBitmap);
|
||||
final long endRender = System.nanoTime();
|
||||
releaseCanvas(canvas, atlasBitmap);
|
||||
result = nUploadAtlas(buffer, atlasBitmap);
|
||||
atlasBitmap.recycle();
|
||||
final long endUpload = System.nanoTime();
|
||||
|
||||
final long endUpload = System.nanoTime();
|
||||
if (DEBUG_ATLAS) {
|
||||
float renderDuration = (endRender - startRender) / 1000.0f / 1000.0f;
|
||||
float uploadDuration = (endUpload - endRender) / 1000.0f / 1000.0f;
|
||||
Log.d(LOG_TAG, String.format("Rendered atlas in %.2fms (%.2f+%.2fms)",
|
||||
renderDuration + uploadDuration, renderDuration, uploadDuration));
|
||||
}
|
||||
|
||||
} finally {
|
||||
releaseCanvas(canvas);
|
||||
if (DEBUG_ATLAS) {
|
||||
float renderDuration = (endRender - startRender) / 1000.0f / 1000.0f;
|
||||
float uploadDuration = (endUpload - endRender) / 1000.0f / 1000.0f;
|
||||
Log.d(LOG_TAG, String.format("Rendered atlas in %.2fms (%.2f+%.2fms)",
|
||||
renderDuration + uploadDuration, renderDuration, uploadDuration));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Canvas for the specified buffer. If {@link #DEBUG_ATLAS_TEXTURE}
|
||||
* is turned on, the returned Canvas will render into a local bitmap that
|
||||
* will then be saved out to disk for debugging purposes.
|
||||
* @param width
|
||||
* @param height
|
||||
*/
|
||||
private Canvas acquireCanvas(int width, int height) {
|
||||
mAtlasBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
return new Canvas(mAtlasBitmap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the canvas used to render into the buffer. Calling this method
|
||||
* will release any resource previously acquired. If {@link #DEBUG_ATLAS_TEXTURE}
|
||||
* is turend on, calling this method will write the content of the atlas
|
||||
* to disk in /data/system/atlas.png for debugging.
|
||||
*/
|
||||
private void releaseCanvas(Canvas canvas) {
|
||||
private void releaseCanvas(Canvas canvas, Bitmap atlasBitmap) {
|
||||
canvas.setBitmap(null);
|
||||
if (DEBUG_ATLAS_TEXTURE) {
|
||||
|
||||
@@ -340,7 +324,7 @@ public class AssetAtlasService extends IAssetAtlas.Stub {
|
||||
|
||||
try {
|
||||
FileOutputStream out = new FileOutputStream(dataFile);
|
||||
mAtlasBitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
|
||||
atlasBitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
|
||||
out.close();
|
||||
} catch (FileNotFoundException e) {
|
||||
// Ignore
|
||||
@@ -348,8 +332,6 @@ public class AssetAtlasService extends IAssetAtlas.Stub {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
mAtlasBitmap.recycle();
|
||||
mAtlasBitmap = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user