diff options
-rw-r--r-- | core/java/android/view/ThreadedRenderer.java | 28 | ||||
-rwxr-xr-x | core/jni/android/graphics/Bitmap.cpp | 8 | ||||
-rw-r--r-- | graphics/java/android/graphics/Bitmap.java | 10 | ||||
-rw-r--r-- | libs/hwui/AssetAtlas.cpp | 22 | ||||
-rw-r--r-- | libs/hwui/AssetAtlas.h | 62 | ||||
-rw-r--r-- | services/core/java/com/android/server/AssetAtlasService.java | 98 |
6 files changed, 103 insertions, 125 deletions
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index 5017a38..25c5127 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -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); diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp index 7a934bd..5c95f8a 100755 --- a/core/jni/android/graphics/Bitmap.cpp +++ b/core/jni/android/graphics/Bitmap.cpp @@ -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) diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index e2f7799..76d6edf 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -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); } diff --git a/libs/hwui/AssetAtlas.cpp b/libs/hwui/AssetAtlas.cpp index 4d2e3a0..882826e 100644 --- a/libs/hwui/AssetAtlas.cpp +++ b/libs/hwui/AssetAtlas.cpp @@ -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); } } diff --git a/libs/hwui/AssetAtlas.h b/libs/hwui/AssetAtlas.h index 1772eff..17c5281 100644 --- a/libs/hwui/AssetAtlas.h +++ b/libs/hwui/AssetAtlas.h @@ -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 @@ -80,11 +64,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 diff --git a/services/core/java/com/android/server/AssetAtlasService.java b/services/core/java/com/android/server/AssetAtlasService.java index 9e28b64..26f4232 100644 --- a/services/core/java/com/android/server/AssetAtlasService.java +++ b/services/core/java/com/android/server/AssetAtlasService.java @@ -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(); - - 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; - } + final long startRender = System.nanoTime(); + final int count = mBitmaps.size(); - 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; } - } - - final long endRender = System.nanoTime(); - result = nUploadAtlas(buffer, mAtlasBitmap); - 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)); + 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; } + } - } finally { - releaseCanvas(canvas); + final long endRender = System.nanoTime(); + releaseCanvas(canvas, atlasBitmap); + result = nUploadAtlas(buffer, atlasBitmap); + atlasBitmap.recycle(); + 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)); } 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; } } |