Add updateDetailTexture to allow updating detail textures
Change-Id: Id0d3146142bc7019523c038cacbfffb71db56594
diff --git a/carousel/java/com/android/ex/carousel/CarouselController.java b/carousel/java/com/android/ex/carousel/CarouselController.java
index 09e51ca..68b2f7c 100644
--- a/carousel/java/com/android/ex/carousel/CarouselController.java
+++ b/carousel/java/com/android/ex/carousel/CarouselController.java
@@ -320,6 +320,22 @@
}
/**
+ * Sets the specified detail texture as invalid. If eraseCurrent is true, the texture will be
+ * immediately cleared from view and an invalidate handler will be called. If eraseCurrent is
+ * false, a replacement texture will be requested, and the old texture will be left in place
+ * in the meantime.
+ * @param n the card to invalidate the detail texture for
+ * @param eraseCurrent whether to erase the current texture
+ */
+ public void invalidateDetailTexture(int n, boolean eraseCurrent) {
+ if (mRenderScript != null && mRS != null) {
+ if (DBG) Log.v(TAG, "invalidateDetailTexture(" + n + ")");
+ mRenderScript.invalidateDetailTexture(n, false);
+ if (DBG) Log.v(TAG, "done");
+ }
+ }
+
+ /**
* Sets the bitmap to show on a card when the card draws the very first time.
* Generally, this bitmap will only be seen during the first few frames of startup
* or when the number of cards are changed. It can be ignored in most cases,
diff --git a/carousel/java/com/android/ex/carousel/CarouselRS.java b/carousel/java/com/android/ex/carousel/CarouselRS.java
index a4e7ef3..b0f208d 100644
--- a/carousel/java/com/android/ex/carousel/CarouselRS.java
+++ b/carousel/java/com/android/ex/carousel/CarouselRS.java
@@ -19,8 +19,6 @@
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;
@@ -552,6 +550,27 @@
}
}
+ void invalidateDetailTexture(int n, boolean eraseCurrent)
+ {
+ if (n < 0) throw new IllegalArgumentException("Index cannot be negative");
+
+ synchronized(this) {
+ ScriptField_Card.Item item = mCards.get(n);
+ if (item == null) {
+ throw new IllegalStateException("invalidateDetailTexture without an existing card");
+ }
+ if (eraseCurrent && item.detailTexture != null) {
+ if (DBG) Log.v(TAG, "unloading texture " + n);
+ // Don't wait for GC to free native memory.
+ // Only works if textures are not shared.
+ item.detailTexture.destroy();
+ item.detailTexture = null;
+ }
+ mCards.set(item, n, false); // This is primarily used for reference counting.
+ mScript.invoke_invalidateDetailTexture(n, eraseCurrent);
+ }
+ }
+
public void setGeometry(int n, Mesh geometry)
{
if (n < 0) throw new IllegalArgumentException("Index cannot be negative");
diff --git a/carousel/java/com/android/ex/carousel/carousel.rs b/carousel/java/com/android/ex/carousel/carousel.rs
index 99da954..bb846ce 100644
--- a/carousel/java/com/android/ex/carousel/carousel.rs
+++ b/carousel/java/com/android/ex/carousel/carousel.rs
@@ -73,6 +73,8 @@
enum {
STATE_INVALID = 0, // item hasn't been loaded
STATE_LOADING, // we've requested an item but are waiting for it to load
+ STATE_STALE, // we have an old item, but should request an update
+ STATE_UPDATING, // we've requested an update, and will display the old one in the meantime
STATE_LOADED // item was delivered
};
@@ -190,8 +192,8 @@
#pragma rs export_func(createCards, copyCards, lookAt, setRadius)
#pragma rs export_func(doStart, doStop, doMotion, doLongPress)
-#pragma rs export_func(setTexture, setGeometry, setDetailTexture, debugCamera)
-#pragma rs export_func(setCarouselRotationAngle)
+#pragma rs export_func(setTexture, setGeometry, setDetailTexture, invalidateDetailTexture)
+#pragma rs export_func(debugCamera, setCarouselRotationAngle)
// Local variables
static float bias; // rotation bias, in radians. Used for animation and dragging.
@@ -435,12 +437,26 @@
{
if (n < 0 || n >= cardCount) return;
rsSetObject(&cards[n].detailTexture, texture);
+ if (cards[n].detailTextureState != STATE_STALE &&
+ cards[n].detailTextureState != STATE_UPDATING) {
+ cards[n].detailTextureTimeStamp = rsUptimeMillis();
+ }
cards[n].detailTextureOffset.x = offx;
cards[n].detailTextureOffset.y = offy;
cards[n].detailLineOffset.x = loffx;
cards[n].detailLineOffset.y = loffy;
cards[n].detailTextureState = (texture.p != 0) ? STATE_LOADED : STATE_INVALID;
- cards[n].detailTextureTimeStamp = rsUptimeMillis();
+}
+
+void invalidateDetailTexture(int n, bool eraseCurrent)
+{
+ if (n < 0 || n >= cardCount) return;
+ if (eraseCurrent) {
+ cards[n].detailTextureState = STATE_INVALID;
+ rsClearObject(&cards[n].detailTexture);
+ } else {
+ cards[n].detailTextureState = STATE_STALE;
+ }
}
void setGeometry(int n, rs_mesh geometry)
@@ -645,7 +661,10 @@
for (int i = cardCount-1; i >= 0; --i) {
if (cards[i].cardVisible) {
- if (cards[i].detailTextureState == STATE_LOADED && cards[i].detailTexture.p != 0) {
+ const int state = cards[i].detailTextureState;
+ const bool isLoaded = (state == STATE_LOADED) || (state == STATE_STALE) ||
+ (state == STATE_UPDATING);
+ if (isLoaded && cards[i].detailTexture.p != 0) {
const float lineWidth = rsAllocationGetDimX(detailLineTexture);
// Compute position in screen space of top corner or bottom corner of card
@@ -1379,6 +1398,14 @@
} else {
if (debugTextureLoading) rsDebug("Couldn't send CMD_REQUEST_DETAIL_TEXTURE", 0);
}
+ } else if (cards[i].detailTextureState == STATE_STALE) {
+ data[0] = i;
+ bool enqueued = rsSendToClient(CMD_REQUEST_DETAIL_TEXTURE, data, sizeof(data));
+ if (enqueued) {
+ cards[i].detailTextureState = STATE_UPDATING;
+ } else {
+ if (debugTextureLoading) rsDebug("Couldn't send CMD_REQUEST_DETAIL_TEXTURE", 0);
+ }
}
// request geometry from client if not loaded
if (cards[i].geometryState == STATE_INVALID) {