Put the label into the same texture as the icon.
diff --git a/src/com/android/launcher2/AllAppsView.java b/src/com/android/launcher2/AllAppsView.java
index 8d24ea3..37ec15c 100644
--- a/src/com/android/launcher2/AllAppsView.java
+++ b/src/com/android/launcher2/AllAppsView.java
@@ -125,15 +125,11 @@
         public static final int ALLOC_PARAMS = 0;
         public static final int ALLOC_STATE = 1;
         public static final int ALLOC_ICON_IDS = 3;
-        public static final int ALLOC_LABEL_IDS = 4;
 
         public static final int COLUMNS_PER_PAGE = 4;
         public static final int ROWS_PER_PAGE = 4;
 
-        public static final int ICON_WIDTH_PX = 64;
         public static final int ICON_TEXTURE_WIDTH_PX = 128;
-
-        public static final int ICON_HEIGHT_PX = 64;
         public static final int ICON_TEXTURE_HEIGHT_PX = 128;
 
         public int SCREEN_WIDTH_PX;
@@ -571,15 +567,18 @@
                 && mCurrentIconIndex >= 0 && mCurrentIconIndex < mAllAppsList.size()) {
             ApplicationInfo app = mAllAppsList.get(mCurrentIconIndex);
 
-            // We don't really have an accurate location to use.  This will do.
-            int screenX = mMotionDownRawX - (mDefines.ICON_WIDTH_PX / 2);
-            int screenY = mMotionDownRawY - mDefines.ICON_HEIGHT_PX;
+            Bitmap bmp = Utilities.extractIconFromTexture(app.iconBitmap, getContext());
 
-            int left = (mDefines.ICON_TEXTURE_WIDTH_PX - mDefines.ICON_WIDTH_PX) / 2;
-            int top = (mDefines.ICON_TEXTURE_HEIGHT_PX - mDefines.ICON_HEIGHT_PX) / 2;
-            mDragController.startDrag(app.iconBitmap, screenX, screenY,
-                    left, top, mDefines.ICON_WIDTH_PX, mDefines.ICON_HEIGHT_PX,
-                    this, app, DragController.DRAG_ACTION_COPY);
+            final int w = bmp.getWidth();
+            final int h = bmp.getHeight();
+
+            // We don't really have an accurate location to use.  This will do.
+            int screenX = mMotionDownRawX - (w / 2);
+            int screenY = mMotionDownRawY - h;
+
+            mDragController.startDrag(bmp, screenX, screenY,
+                    0, 0, w, h, this, app, DragController.DRAG_ACTION_COPY);
+            bmp.recycle();
 
             mLauncher.closeAllApps(true);
         }
@@ -787,10 +786,6 @@
         private Allocation[] mIcons;
         private int[] mIconIds;
         private Allocation mAllocIconIds;
-
-        private Allocation[] mLabels;
-        private int[] mLabelIds;
-        private Allocation mAllocLabelIds;
         private Allocation mSelectedIcon;
 
         private int[] mTouchYBorders;
@@ -883,7 +878,7 @@
                 float maxAngle = 3.14f * 0.16f;
                 float l = 1.f;
 
-                l = 1 - ((ct-5) * 0.10f);
+                l = 1 - ((ct-7) * 0.10f);
                 if (ct > 7) {
                     angle = maxAngle * (ct - 7) * 0.2f;
                     angle = Math.min(angle, maxAngle);
@@ -949,8 +944,8 @@
             Sampler nearest = sb.create();
 
             ProgramFragment.Builder bf = new ProgramFragment.Builder(mRS, null, null);
-            //mPFColor = bf.create();
-            //mPFColor.setName("PFColor");
+            mPFColor = bf.create();
+            mPFColor.setName("PFColor");
 
             bf.setTexEnable(true, 0);
             bf.setTexEnvMode(ProgramFragment.EnvMode.MODULATE, 0);
@@ -1040,7 +1035,6 @@
             mScript.bindAllocation(mParams.mAlloc, Defines.ALLOC_PARAMS);
             mScript.bindAllocation(mState.mAlloc, Defines.ALLOC_STATE);
             mScript.bindAllocation(mAllocIconIds, Defines.ALLOC_ICON_IDS);
-            mScript.bindAllocation(mAllocLabelIds, Defines.ALLOC_LABEL_IDS);
 
             mRS.contextBindRootScript(mScript);
         }
@@ -1071,16 +1065,15 @@
             mIconIds = new int[allocCount];
             mAllocIconIds = Allocation.createSized(mRS, Element.USER_I32(mRS), allocCount);
 
-            mLabels = new Allocation[count];
-            mLabelIds = new int[allocCount];
-            mAllocLabelIds = Allocation.createSized(mRS, Element.USER_I32(mRS), allocCount);
-
             Element ie8888 = Element.RGBA_8888(mRS);
 
             mState.iconCount = count;
+            long before = SystemClock.uptimeMillis();
             for (int i=0; i < mState.iconCount; i++) {
                 createAppIconAllocations(i, list.get(i));
             }
+            long after = SystemClock.uptimeMillis();
+            //Log.d(TAG, "createAppIconAllocations took " + (after-before) + "ms");
             if (mHasSurface) {
                 for (int i=0; i < mState.iconCount; i++) {
                     uploadAppIcon(i, list.get(i));
@@ -1123,18 +1116,11 @@
         }
 
         private void createAppIconAllocations(int index, ApplicationInfo item) {
-            mIcons[index] = Allocation.createFromBitmap(mRS, item.iconBitmap,
-                    Element.RGBA_8888(mRS), true);
-            frameBitmapAllocMips(mIcons[index], item.iconBitmap.getWidth(),
-                    item.iconBitmap.getHeight());
-
-            mLabels[index] = Allocation.createFromBitmap(mRS, item.titleBitmap,
-                    Element.RGBA_8888(mRS), true);
-            frameBitmapAllocMips(mLabels[index], item.titleBitmap.getWidth(),
-                    item.titleBitmap.getHeight());
+            Bitmap bitmap = item.iconBitmap;
+            mIcons[index] = Allocation.createFromBitmap(mRS, bitmap, Element.RGBA_8888(mRS), true);
+            frameBitmapAllocMips(mIcons[index], bitmap.getWidth(), bitmap.getHeight());
 
             mIconIds[index] = mIcons[index].getID();
-            mLabelIds[index] = mLabels[index].getID();
         }
 
         private void uploadAppIcon(int index, ApplicationInfo item) {
@@ -1145,7 +1131,6 @@
                     + " item=" + item);
             }
             mIcons[index].uploadToTexture(0);
-            mLabels[index].uploadToTexture(0);
         }
 
         /**
@@ -1157,21 +1142,13 @@
             int[] iconIds = new int[count];
             mAllocIconIds = Allocation.createSized(mRS, Element.USER_I32(mRS), count);
 
-            Allocation[] labels = new Allocation[count];
-            int[] labelIds = new int[count];
-            mAllocLabelIds = Allocation.createSized(mRS, Element.USER_I32(mRS), count);
-
             final int oldCount = mRollo.mState.iconCount;
 
             System.arraycopy(mIcons, 0, icons, 0, oldCount);
             System.arraycopy(mIconIds, 0, iconIds, 0, oldCount);
-            System.arraycopy(mLabels, 0, labels, 0, oldCount);
-            System.arraycopy(mLabelIds, 0, labelIds, 0, oldCount);
 
             mIcons = icons;
             mIconIds = iconIds;
-            mLabels = labels;
-            mLabelIds = labelIds;
         }
 
         /**
@@ -1183,8 +1160,6 @@
 
             System.arraycopy(mIcons, index, mIcons, dest, count);
             System.arraycopy(mIconIds, index, mIconIds, dest, count);
-            System.arraycopy(mLabels, index, mLabels, dest, count);
-            System.arraycopy(mLabelIds, index, mLabelIds, dest, count);
 
             createAppIconAllocations(index, item);
 
@@ -1206,16 +1181,12 @@
 
             System.arraycopy(mIcons, src, mIcons, index, count);
             System.arraycopy(mIconIds, src, mIconIds, index, count);
-            System.arraycopy(mLabels, src, mLabels, index, count);
-            System.arraycopy(mLabelIds, src, mLabelIds, index, count);
 
             mRollo.mState.iconCount--;
             final int last = mState.iconCount;
 
             mIcons[last] = null;
             mIconIds[last] = 0;
-            mLabels[last] = null;
-            mLabelIds[last] = 0;
         }
 
         /**
@@ -1225,11 +1196,9 @@
             mRS.contextBindRootScript(null);
 
             mAllocIconIds.data(mIconIds);
-            mAllocLabelIds.data(mLabelIds);
 
             if (mScript != null) { // this happens when we init it
                 mScript.bindAllocation(mAllocIconIds, Defines.ALLOC_ICON_IDS);
-                mScript.bindAllocation(mAllocLabelIds, Defines.ALLOC_LABEL_IDS);
             }
 
             mState.save();
@@ -1344,7 +1313,7 @@
                 ApplicationInfo info = mAllAppsList.get(index);
                 Bitmap selectionBitmap = mSelectionBitmap;
 
-                Utilities.drawSelectedAllAppsBitmap(mSelectionCanvas,
+                Utilities.drawSelectedAllAppsBitmap(mSelectionCanvas, selectionBitmap,
                         selectionBitmap.getWidth(), selectionBitmap.getHeight(),
                         pressed == SELECTED_PRESSED, info.iconBitmap);
 
@@ -1399,10 +1368,6 @@
                 Log.d(TAG, "mRollo.mIconIds.length=" + mIconIds.length);
             }
             Log.d(TAG, "mRollo.mIconIds=" +  Arrays.toString(mIconIds));
-            if (mLabelIds != null) {
-                Log.d(TAG, "mRollo.mLabelIds.length=" + mLabelIds.length);
-            }
-            Log.d(TAG, "mRollo.mLabelIds=" +  Arrays.toString(mLabelIds));
             Log.d(TAG, "mRollo.mTouchXBorders=" +  Arrays.toString(mTouchXBorders));
             Log.d(TAG, "mRollo.mTouchYBorders=" +  Arrays.toString(mTouchYBorders));
             Log.d(TAG, "mRollo.mHasSurface=" + mHasSurface);
diff --git a/src/com/android/launcher2/AppInfoCache.java b/src/com/android/launcher2/AppInfoCache.java
index a2d9830..e81168e 100644
--- a/src/com/android/launcher2/AppInfoCache.java
+++ b/src/com/android/launcher2/AppInfoCache.java
@@ -168,10 +168,13 @@
             application.title = info.activityInfo.name;
         }
 
+        // TODO: turn this on in froyo, not enough time for testing in mr3
+        //if (application.iconBitmap != null) {
+        //    application.iconBitmap.recycle();
+        //}
         application.iconBitmap = Utilities.createAllAppsBitmap(
-                info.activityInfo.loadIcon(packageManager), context);
-
-        application.titleBitmap = bubble.createTextBitmap(application.title.toString());
+                info.activityInfo.loadIcon(packageManager),
+                application.title.toString(), bubble, context);
     }
 }
 
diff --git a/src/com/android/launcher2/ApplicationInfo.java b/src/com/android/launcher2/ApplicationInfo.java
index 0fe84e7..ae0e219 100644
--- a/src/com/android/launcher2/ApplicationInfo.java
+++ b/src/com/android/launcher2/ApplicationInfo.java
@@ -37,11 +37,6 @@
     CharSequence title;
 
     /**
-     * A bitmap of the application's text in the bubble.
-     */
-    Bitmap titleBitmap;
-
-    /**
      * The intent used to start the application.
      */
     Intent intent;
@@ -52,7 +47,7 @@
     Drawable icon;
 
     /**
-     * A bitmap version of the application icon.
+     * What we show in all apps, including the text.
      */
     Bitmap iconBitmap;
 
@@ -149,9 +144,9 @@
             ArrayList<ApplicationInfo> list) {
         Log.d(tag, label + " size=" + list.size());
         for (ApplicationInfo info: list) {
-            Log.d(tag, "   title=\"" + info.title + "\" titleBitmap=" + info.titleBitmap
-                    + " icon=" + info.icon + " iconBitmap=" + info.iconBitmap
-                    + " filtered=" + info.filtered + " customIcon=" + info.customIcon);
+            Log.d(tag, "   title=\"" + info.title + "\" icon=" + info.icon
+                    + " iconBitmap=" + info.iconBitmap + " filtered=" + info.filtered
+                    + " customIcon=" + info.customIcon);
         }
     }
 }
diff --git a/src/com/android/launcher2/Utilities.java b/src/com/android/launcher2/Utilities.java
index 55cb509..2dfba43 100644
--- a/src/com/android/launcher2/Utilities.java
+++ b/src/com/android/launcher2/Utilities.java
@@ -52,6 +52,10 @@
     private static int sIconTextureWidth = -1;
     private static int sIconTextureHeight = -1;
 
+    private static int sTitleMargin = -1;
+    private static float sBlurRadius = -1;
+    private static Rect sIconTextureRect;
+
     private static final Paint sPaint = new Paint();
     private static final Paint sBlurPaint = new Paint();
     private static final Paint sGlowColorPressedPaint = new Paint();
@@ -175,7 +179,8 @@
      * Returns a bitmap suitable for the all apps view.  The bitmap will be a power
      * of two sized ARGB_8888 bitmap that can be used as a gl texture.
      */
-    static Bitmap createAllAppsBitmap(Drawable icon, Context context) {
+    static Bitmap createAllAppsBitmap(Drawable icon, String title, BubbleText bubble,
+            Context context) {
         synchronized (sCanvas) { // we share the statics :-(
             if (sIconWidth == -1) {
                 initStatics(context);
@@ -217,8 +222,8 @@
             }
 
             // no intrinsic size --> use default size
-            int textureWidth = sIconTextureWidth;
-            int textureHeight = sIconTextureHeight;
+            final int textureWidth = sIconTextureWidth;
+            final int textureHeight = sIconTextureHeight;
 
             final Bitmap bitmap = Bitmap.createBitmap(textureWidth, textureHeight,
                     Bitmap.Config.ARGB_8888);
@@ -226,7 +231,7 @@
             canvas.setBitmap(bitmap);
 
             final int left = (textureWidth-width) / 2;
-            final int top = (textureHeight-height) / 2;
+            final int top = sIconTextureRect.top;
 
             if (false) {
                 // draw a big box for the icon for debugging
@@ -242,12 +247,34 @@
             icon.draw(canvas);
             icon.setBounds(sOldBounds);
 
+            if (title != null) {
+                bubble.drawText(canvas, title);
+            }
+
             return bitmap;
         }
     }
 
-    static void drawSelectedAllAppsBitmap(Canvas dest, int destWidth, int destHeight,
-            boolean pressed, Bitmap src) {
+    static Bitmap extractIconFromTexture(Bitmap src, Context context) {
+        synchronized (sCanvas) { // we share the statics :-(
+            if (sIconWidth == -1) {
+                initStatics(context);
+            }
+            final Bitmap bitmap = Bitmap.createBitmap(sIconWidth, sIconHeight,
+                    Bitmap.Config.ARGB_8888);
+            final Canvas canvas = sCanvas;
+            canvas.setBitmap(bitmap);
+
+            Rect r = new Rect(0, 0, sIconWidth, sIconHeight);
+            canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+            canvas.drawBitmap(src, sIconTextureRect, r, sEmptyPaint);
+
+            return bitmap;
+        }
+    }
+
+    static void drawSelectedAllAppsBitmap(Canvas dest, Bitmap destBitmap,
+            int destWidth, int destHeight, boolean pressed, Bitmap src) {
         synchronized (sCanvas) { // we share the statics :-(
             if (sIconWidth == -1) {
                 // We can't have gotten to here without src being initialized, which
@@ -257,12 +284,14 @@
             }
 
             dest.drawColor(0, PorterDuff.Mode.CLEAR);
-            
+            dest.drawBitmap(src, sIconTextureRect, sIconTextureRect, sEmptyPaint);
+
             int[] xy = new int[2];
-            Bitmap mask = src.extractAlpha(sBlurPaint, xy);
+            Bitmap mask = destBitmap.extractAlpha(sBlurPaint, xy);
 
             float px = (destWidth - src.getWidth()) / 2;
             float py = (destHeight - src.getHeight()) / 2;
+            dest.drawColor(0, PorterDuff.Mode.CLEAR);
             dest.drawBitmap(mask, px + xy[0], py + xy[1],
                     pressed ? sGlowColorPressedPaint : sGlowColorFocusedPaint);
 
@@ -341,6 +370,12 @@
         sIconWidth = sIconHeight = (int) resources.getDimension(android.R.dimen.app_icon_size);
         sIconTextureWidth = sIconTextureHeight = roundToPow2(sIconWidth);
 
+        sTitleMargin = (int)(1 * density);
+        sBlurRadius = 5 * density;
+        final int left = (sIconTextureWidth-sIconWidth)/2;
+        final int top = (int)(sBlurRadius) + 1;
+        sIconTextureRect = new Rect(left, top, left+sIconWidth, top+sIconHeight);
+
         sBlurPaint.setMaskFilter(new BlurMaskFilter(5 * density, BlurMaskFilter.Blur.NORMAL));
         sGlowColorPressedPaint.setColor(0xffffc300);
         sGlowColorPressedPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30));
@@ -364,60 +399,65 @@
         private int mBitmapHeight;
 
         BubbleText(Context context) {
-            final Resources resources = context.getResources();
+            synchronized (sCanvas) { // we share the statics :-(
+                if (sIconWidth == -1) {
+                    initStatics(context);
+                }
+                final Resources resources = context.getResources();
 
-            final float scale = resources.getDisplayMetrics().density;
+                final float scale = resources.getDisplayMetrics().density;
 
-            final float paddingLeft = 5.0f * scale;
-            final float paddingRight = 5.0f * scale;
-            final float cellWidth = resources.getDimension(R.dimen.workspace_cell_width);
-            final float bubbleWidth = cellWidth - paddingLeft - paddingRight;
-            mBubblePadding = 3.0f * scale;
+                final float paddingLeft = 5.0f * scale;
+                final float paddingRight = 5.0f * scale;
+                final float cellWidth = resources.getDimension(R.dimen.workspace_cell_width);
+                final float bubbleWidth = cellWidth - paddingLeft - paddingRight;
+                mBubblePadding = 3.0f * scale;
 
-            RectF bubbleRect = mBubbleRect;
-            bubbleRect.left = 0;
-            bubbleRect.top = 0;
-            bubbleRect.right = (int)(bubbleWidth+0.5f);
+                RectF bubbleRect = mBubbleRect;
+                bubbleRect.left = 0;
+                bubbleRect.top = 0;
+                bubbleRect.right = (int)(bubbleWidth+0.5f);
 
-            mTextWidth = bubbleWidth - mBubblePadding - mBubblePadding;
+                mTextWidth = bubbleWidth - mBubblePadding - mBubblePadding;
 
-            Paint rectPaint = new Paint();
-            rectPaint.setColor(0xff000000);
-            rectPaint.setAntiAlias(true);
+                Paint rectPaint = new Paint();
+                rectPaint.setColor(0xff000000);
+                rectPaint.setAntiAlias(true);
 
-            TextPaint textPaint = mTextPaint = new TextPaint();
-            textPaint.setTypeface(Typeface.DEFAULT);
-            textPaint.setTextSize(13*scale);
-            textPaint.setColor(0xffffffff);
-            textPaint.setAntiAlias(true);
-            if (TEXT_BURN) {
-                textPaint.setShadowLayer(8, 0, 0, 0xff000000);
-            }
+                TextPaint textPaint = mTextPaint = new TextPaint();
+                textPaint.setTypeface(Typeface.DEFAULT);
+                textPaint.setTextSize(13*scale);
+                //textPaint.setColor(0xff00ff00);
+                textPaint.setColor(0xffffffff);
+                textPaint.setAntiAlias(true);
+                if (TEXT_BURN) {
+                    textPaint.setShadowLayer(8, 0, 0, 0xff000000);
+                }
 
-            float ascent = -textPaint.ascent();
-            float descent = textPaint.descent();
-            float leading = 0.0f;//(ascent+descent) * 0.1f;
-            mLeading = (int)(leading + 0.5f);
-            mFirstLineY = (int)(leading + ascent + 0.5f);
-            mLineHeight = (int)(leading + ascent + descent + 0.5f);
+                final int iconTop = (int)(sBlurRadius) + 1;
+                final int iconBottom = iconTop + sIconHeight;
 
-            mBitmapWidth = roundToPow2((int)(mBubbleRect.width() + 0.5f));
-            mBitmapHeight = roundToPow2((int)((MAX_LINES * mLineHeight) + leading + 0.5f));
+                float ascent = -textPaint.ascent();
+                float descent = textPaint.descent();
+                float leading = -1.0f;//(ascent+descent) * 0.1f;
+                mLeading = (int)(leading + 0.5f);
+                mFirstLineY = (int)(iconBottom + sTitleMargin + ascent + 0.5f);
+                mLineHeight = (int)(leading + ascent + descent + 0.5f);
 
-            mBubbleRect.offsetTo((mBitmapWidth-mBubbleRect.width())/2, 0);
+                mBitmapWidth = roundToPow2((int)(mBubbleRect.width() + 0.5f));
+                mBitmapHeight = roundToPow2((int)((MAX_LINES * mLineHeight) + leading + 0.5f));
 
-            if (false) {
-                Log.d(TAG, "mBitmapWidth=" + mBitmapWidth + " mBitmapHeight="
-                        + mBitmapHeight + " w=" + ((int)(mBubbleRect.width() + 0.5f))
-                        + " h=" + ((int)((MAX_LINES * mLineHeight) + leading + 0.5f)));
+                mBubbleRect.offsetTo((mBitmapWidth-mBubbleRect.width())/2, 0);
+
+                if (false) {
+                    Log.d(TAG, "mBitmapWidth=" + mBitmapWidth + " mBitmapHeight="
+                            + mBitmapHeight + " w=" + ((int)(mBubbleRect.width() + 0.5f))
+                            + " h=" + ((int)((MAX_LINES * mLineHeight) + leading + 0.5f)));
+                }
             }
         }
 
-        /** You own the bitmap after this and you must call recycle on it. */
-        Bitmap createTextBitmap(String text) {
-            Bitmap b = Bitmap.createBitmap(mBitmapWidth, mBitmapHeight, Bitmap.Config.ARGB_8888);
-            Canvas c = new Canvas(b);
-
+        void drawText(Canvas c, String text) {
             StaticLayout layout = new StaticLayout(text, mTextPaint, (int)mTextWidth,
                     Alignment.ALIGN_CENTER, 1, 0, true);
             int lineCount = layout.getLineCount();
@@ -438,8 +478,6 @@
                 c.drawText(text.substring(layout.getLineStart(i), layout.getLineEnd(i)),
                         x, y, mTextPaint);
             }
-
-            return b;
         }
 
         private int height(int lineCount) {