Carousel performance improvements.

This change disables depth and changes the background bitmap
for the test case to 256x256 instead of 512x512. With these
two changes, Carousel consistently achieves 87fps with no
background and 78fps with. Both tests were with sync-to-vblank
disabled.

It also cleans up the program store names to have more
meaningful names as we add new states.

Upload after rebase.

Change-Id: I6008fbd89fbe924dbea10792b3f787fe69586fa0
diff --git a/carousel/java/com/android/ex/carousel/CarouselController.java b/carousel/java/com/android/ex/carousel/CarouselController.java
index f28d3f5..fc53642 100644
--- a/carousel/java/com/android/ex/carousel/CarouselController.java
+++ b/carousel/java/com/android/ex/carousel/CarouselController.java
@@ -66,7 +66,7 @@
     private int mVisibleDetails = DEFAULT_VISIBLE_DETAIL_COUNT;
     private int mPrefetchCardCount = DEFAULT_PREFETCH_CARD_COUNT;
     private int mDetailTextureAlignment = DEFAULT_DETAIL_ALIGNMENT;
-    private boolean mDrawCardsWithBlending = true;
+    private boolean mForceBlendCardsWithZ = false;
     private boolean mDrawRuler = true;
     private float mStartAngle;
     private float mCarouselRotationAngle;
@@ -103,7 +103,7 @@
         setVisibleDetails(mVisibleDetails);
         setPrefetchCardCount(mPrefetchCardCount);
         setDetailTextureAlignment(mDetailTextureAlignment);
-        setDrawCardsWithBlending(mDrawCardsWithBlending);
+        setForceBlendCardsWithZ(mForceBlendCardsWithZ);
         setDrawRuler(mDrawRuler);
         setCallback(mCarouselCallback);
         setDefaultBitmap(mDefaultBitmap);
@@ -231,16 +231,17 @@
     }
 
     /**
-     * Set whether blending is enabled while drawing the card textures. This should be true when
-     * translucent cards need to be supported, and false when all cards are fully opaque. Setting
-     * to false provides a performance boost.
+     * Set whether depth is enabled while blending. Generally, this is discouraged because
+     * it causes bad artifacts. Careful attention to geometry and alpha transparency of
+     * textures can mitigate much of this. Geometry for an individual item must be drawn
+     * back-to-front, for example.
      *
-     * @param enabled True to enable blending, and false to disable it.
+     * @param enabled True to enable depth while blending, and false to disable it.
      */
-    public void setDrawCardsWithBlending(boolean enabled) {
-        mDrawCardsWithBlending = enabled;
+    public void setForceBlendCardsWithZ(boolean enabled) {
+        mForceBlendCardsWithZ = enabled;
         if (mRenderScript != null) {
-            mRenderScript.setDrawCardsWithBlending(enabled);
+            mRenderScript.setForceBlendCardsWithZ(enabled);
         }
     }
 
@@ -406,7 +407,9 @@
 
     /**
      * This geometry will be shown when no geometry has been loaded for a given slot. If not set,
-     * a quad will be drawn in its place. It is shared for all cards.
+     * a quad will be drawn in its place. It is shared for all cards. If something other than
+     * simple planar geometry is used, consider enabling depth test with
+     * {@link CarouselController#setForceBlendCardsWithZ(boolean)}
      *
      * @param mesh
      */
@@ -419,7 +422,9 @@
 
     /**
      * This is an intermediate version of the object to show while geometry is loading. If not set,
-     * a quad will be drawn in its place.  It is shared for all cards.
+     * a quad will be drawn in its place.  It is shared for all cards. If something other than
+     * simple planar geometry is used, consider enabling depth test with
+     * {@link CarouselView#setForceBlendCardsWithZ(boolean)}
      *
      * @param mesh
      */
diff --git a/carousel/java/com/android/ex/carousel/CarouselRS.java b/carousel/java/com/android/ex/carousel/CarouselRS.java
index efa6ff6..dee79e5 100644
--- a/carousel/java/com/android/ex/carousel/CarouselRS.java
+++ b/carousel/java/com/android/ex/carousel/CarouselRS.java
@@ -19,6 +19,8 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.renderscript.*;
+import android.renderscript.ProgramStore.BlendDstFunc;
+import android.renderscript.ProgramStore.BlendSrcFunc;
 import android.renderscript.RenderScript.RSMessage;
 import android.util.Log;
 
@@ -56,9 +58,10 @@
     private ScriptC_carousel mScript;
     private ScriptField_Card mCards;
     private ScriptField_FragmentShaderConstants_s mFSConst;
-    private ProgramStore mProgramStore;
-    private ProgramStore mProgramStoreOpaque;
-    private ProgramStore mProgramStoreDetail;
+    private ProgramStore mProgramStoreAlphaZ;
+    private ProgramStore mProgramStoreAlphaNoZ;
+    private ProgramStore mProgramStoreNoAlphaZ;
+    private ProgramStore mProgramStoreNoAlphaNoZ;
     private ProgramFragment mSingleTextureFragmentProgram;
     private ProgramFragment mMultiTextureFragmentProgram;
     private ProgramVertex mVertexProgram;
@@ -315,22 +318,40 @@
     }
 
     private void initProgramStore() {
-        ProgramStore.Builder programStoreBuilder = new ProgramStore.Builder(mRS, null, null);
-        programStoreBuilder.setDepthFunc(ProgramStore.DepthFunc.LESS);
-        programStoreBuilder.setBlendFunc(ProgramStore.BlendSrcFunc.ONE,
-                ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA);
-        programStoreBuilder.setDitherEnable(true);
-        programStoreBuilder.setDepthMask(true);
-        mProgramStore = programStoreBuilder.create();
-        mScript.set_programStore(mProgramStore);
+        final boolean dither = true;
+        mProgramStoreAlphaZ = new ProgramStore.Builder(mRS)
+                .setBlendFunc(ProgramStore.BlendSrcFunc.ONE,
+                        ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA)
+                .setDitherEnable(dither)
+                .setDepthFunc(ProgramStore.DepthFunc.LESS)
+                .setDepthMask(true)
+                .create();
+        mScript.set_programStoreAlphaZ(mProgramStoreAlphaZ);
 
-        programStoreBuilder.setBlendFunc(ProgramStore.BlendSrcFunc.ONE,
-                ProgramStore.BlendDstFunc.ZERO);
-        mProgramStoreOpaque = programStoreBuilder.create();
-        mScript.set_programStoreOpaque(mProgramStoreOpaque);
+        mProgramStoreAlphaNoZ = new ProgramStore.Builder(mRS)
+                .setBlendFunc(ProgramStore.BlendSrcFunc.ONE,
+                        ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA)
+                .setDitherEnable(dither)
+                .setDepthFunc(ProgramStore.DepthFunc.ALWAYS)
+                .setDepthMask(false)
+                .create();
+        mScript.set_programStoreAlphaNoZ(mProgramStoreAlphaNoZ);
 
-        mProgramStoreDetail = ProgramStore.BLEND_ALPHA_DEPTH_NO_DEPTH(mRS);
-        mScript.set_programStoreDetail(mProgramStoreDetail);
+        mProgramStoreNoAlphaZ = new ProgramStore.Builder(mRS)
+                .setBlendFunc(ProgramStore.BlendSrcFunc.ONE, ProgramStore.BlendDstFunc.ZERO)
+                .setDitherEnable(dither)
+                .setDepthFunc(ProgramStore.DepthFunc.LESS)
+                .setDepthMask(true)
+                .create();
+        mScript.set_programStoreNoAlphaZ(mProgramStoreNoAlphaZ);
+
+        mProgramStoreNoAlphaNoZ = new ProgramStore.Builder(mRS)
+                .setBlendFunc(ProgramStore.BlendSrcFunc.ONE, ProgramStore.BlendDstFunc.ZERO)
+                .setDitherEnable(dither)
+                .setDepthFunc(ProgramStore.DepthFunc.ALWAYS)
+                .setDepthMask(false)
+                .create();
+        mScript.set_programStoreNoAlphaNoZ(mProgramStoreNoAlphaNoZ);
     }
 
     public void createCards(int count)
@@ -371,8 +392,8 @@
         mScript.set_detailTextureAlignment(alignment);
     }
 
-    public void setDrawCardsWithBlending(boolean enabled) {
-        mScript.set_drawCardsWithBlending(enabled);
+    public void setForceBlendCardsWithZ(boolean enabled) {
+        mScript.set_forceBlendCardsWithZ(enabled);
     }
 
     public void setDrawRuler(boolean drawRuler) {
diff --git a/carousel/java/com/android/ex/carousel/CarouselView.java b/carousel/java/com/android/ex/carousel/CarouselView.java
index 2223bd1..950c39c 100644
--- a/carousel/java/com/android/ex/carousel/CarouselView.java
+++ b/carousel/java/com/android/ex/carousel/CarouselView.java
@@ -149,6 +149,7 @@
     @Override
     public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
         super.surfaceChanged(holder, format, w, h);
+        // setZOrderOnTop(true);
         mController.onSurfaceChanged();
     }
 
@@ -234,7 +235,7 @@
 
     /**
      * Sets how detail textures are aligned with respect to the card.
-     * 
+     *
      * @param alignment a bitmask of DetailAlignment flags.
      */
     public void setDetailTextureAlignment(int alignment) {
@@ -242,14 +243,15 @@
     }
 
     /**
-     * Set whether blending is enabled while drawing the card textures. This should be true when
-     * translucent cards need to be supported, and false when all cards are fully opaque. Setting
-     * to false provides a performance boost.
+     * Set whether depth is enabled while blending. Generally, this is discouraged because
+     * it causes bad artifacts. Careful attention to geometry and alpha transparency of
+     * textures can mitigate much of this. For example, geometry for an item must be drawn
+     * back-to-front if any edges overlap.
      *
-     * @param enabled True to enable blending, and false to disable it.
+     * @param enabled True to enable depth while blending, and false to disable it.
      */
-    public void setDrawCardsWithBlending(boolean enabled) {
-        mController.setDrawCardsWithBlending(enabled);
+    public void setForceBlendCardsWithZ(boolean enabled) {
+        mController.setForceBlendCardsWithZ(enabled);
     }
 
     /**
@@ -380,7 +382,9 @@
 
     /**
      * This geometry will be shown when no geometry has been loaded for a given slot. If not set,
-     * a quad will be drawn in its place. It is shared for all cards.
+     * a quad will be drawn in its place. It is shared for all cards. If something other than
+     * simple planar geometry is used, consider enabling depth test with
+     * {@link CarouselView#setForceBlendCardsWithZ(boolean)}
      *
      * @param mesh
      */
@@ -390,7 +394,9 @@
 
     /**
      * This is an intermediate version of the object to show while geometry is loading. If not set,
-     * a quad will be drawn in its place.  It is shared for all cards.
+     * a quad will be drawn in its place.  It is shared for all cards. If something other than
+     * simple planar geometry is used, consider enabling depth test with
+     * {@link CarouselView#setForceBlendCardsWithZ(boolean)}
      *
      * @param mesh
      */
diff --git a/carousel/java/com/android/ex/carousel/carousel.rs b/carousel/java/com/android/ex/carousel/carousel.rs
index 83483f4..2bcf946 100644
--- a/carousel/java/com/android/ex/carousel/carousel.rs
+++ b/carousel/java/com/android/ex/carousel/carousel.rs
@@ -147,7 +147,7 @@
 int visibleDetailCount; // number of visible detail textures to show
 int prefetchCardCount; // how many cards to keep in memory
 int detailTextureAlignment; // How to align detail texture with respect to card
-bool drawCardsWithBlending; // Enable blending while drawing cards (for translucent card textures)
+bool forceBlendCardsWithZ; // Enable depth buffer while blending
 bool drawRuler; // whether to draw a ruler from the card to the detail texture
 float radius; // carousel radius. Cards will be centered on a circle with this radius
 float cardRotation; // rotation of card in XY plane relative to Z=1
@@ -159,9 +159,10 @@
 float rezInCardCount; // this controls how rapidly distant card textures will be rez-ed in
 float detailFadeRate; // rate at which details fade as they move into the distance
 float4 backgroundColor;
-rs_program_store programStore;
-rs_program_store programStoreOpaque;
-rs_program_store programStoreDetail;
+rs_program_store programStoreAlphaZ;
+rs_program_store programStoreAlphaNoZ;
+rs_program_store programStoreNoAlphaZ;
+rs_program_store programStoreNoAlphaNoZ;
 rs_program_fragment singleTextureFragmentProgram;
 rs_program_fragment multiTextureFragmentProgram;
 rs_program_vertex vertexProgram;
@@ -1410,7 +1411,11 @@
     }
 
     rsgBindProgramFragment(singleTextureFragmentProgram);
-    rsgBindProgramStore(programStoreOpaque);
+    // rsgClearDepth() currently follows the value of glDepthMask(), so it's disabled when
+    // the mask is disabled. We may want to change the following to always draw w/o Z for
+    // the background if we can guarantee the depth buffer will get cleared and
+    // there's a performance advantage.
+    rsgBindProgramStore(forceBlendCardsWithZ ? programStoreNoAlphaZ : programStoreNoAlphaNoZ);
     drawBackground();
 
     updateCameraMatrix(rsgGetWidth(), rsgGetHeight());
@@ -1428,13 +1433,13 @@
     updateCardResources(currentTime);
 
     // Draw cards opaque only if requested, and always draw detail textures with blending.
-    if (drawCardsWithBlending) {
-        rsgBindProgramStore(programStore);
+    if (forceBlendCardsWithZ) {
+        rsgBindProgramStore(programStoreAlphaZ);
     } else {
-        // programStoreOpaque is already bound
+        rsgBindProgramStore(programStoreAlphaNoZ);
     }
     stillAnimating |= drawCards(currentTime);
-    rsgBindProgramStore(programStoreDetail);
+    rsgBindProgramStore(programStoreAlphaNoZ);
     stillAnimating |= drawDetails(currentTime);
 
     if (stillAnimating != animating) {
diff --git a/carousel/test/res/drawable/border.png b/carousel/test/res/drawable/border.png
index ad025f5..723b5a0 100644
--- a/carousel/test/res/drawable/border.png
+++ b/carousel/test/res/drawable/border.png
Binary files differ
diff --git a/carousel/test/res/layout/carousel_test.xml b/carousel/test/res/layout/carousel_test.xml
new file mode 100644
index 0000000..86aa2e2
--- /dev/null
+++ b/carousel/test/res/layout/carousel_test.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="100dip"
+        android:background="#ff800000"
+        android:visibility="gone"/>
+
+    <com.android.carouseltest.MyCarouselView
+        android:id="@+id/carousel"
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:layout_gravity="center">
+    </com.android.carouseltest.MyCarouselView>
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="100dip"
+        android:background="#ff008000"
+        android:visibility="gone"/>
+
+</LinearLayout>
diff --git a/carousel/test/src/com/android/carouseltest/CarouselTestActivity.java b/carousel/test/src/com/android/carouseltest/CarouselTestActivity.java
index 6f7b846..dfc377a 100644
--- a/carousel/test/src/com/android/carouseltest/CarouselTestActivity.java
+++ b/carousel/test/src/com/android/carouseltest/CarouselTestActivity.java
@@ -122,8 +122,9 @@
         super.onCreate(savedInstanceState);
 
         mController = new CarouselController();
-        mView = new MyCarouselView(this, mController);
-        mView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
+        setContentView(R.layout.carousel_test);
+        mView = (CarouselView) findViewById(R.id.carousel);
+        mView.getHolder().setFormat(PixelFormat.RGBA_8888);
         mPaint.setColor(0xffffffff);
         final Resources res = getResources();
 
@@ -155,8 +156,6 @@
                 flags, PixelFormat.TRANSLUCENT);
         getWindow().setAttributes(lp);
         */
-
-        setContentView(mView);
     }
 
     @Override
diff --git a/carousel/test/src/com/android/carouseltest/MusicDemoActivity.java b/carousel/test/src/com/android/carouseltest/MusicDemoActivity.java
index 915fd55..b473b31 100644
--- a/carousel/test/src/com/android/carouseltest/MusicDemoActivity.java
+++ b/carousel/test/src/com/android/carouseltest/MusicDemoActivity.java
@@ -96,6 +96,7 @@
         mView.setDefaultGeometry(mView.loadGeometry(CD_GEOMETRY));
         mView.setFadeInDuration(250);
         mView.setRezInCardCount(3.0f);
+        mView.setForceBlendCardsWithZ(false);
     }
 
     @Override