checkpoint animations

Change-Id: I14ef05bf56470565e4b0cb706f9fb358cdcb42ff
diff --git a/Android.mk b/Android.mk
index 98464a0..7b61504 100644
--- a/Android.mk
+++ b/Android.mk
@@ -76,6 +76,7 @@
 LOCAL_SRC_FILES:= \
 	rsAdapter.cpp \
 	rsAllocation.cpp \
+	rsAnimation.cpp \
 	rsComponent.cpp \
 	rsContext.cpp \
 	rsDevice.cpp \
diff --git a/RenderScript.h b/RenderScript.h
index d280f50..7415ba9 100644
--- a/RenderScript.h
+++ b/RenderScript.h
@@ -30,6 +30,7 @@
 typedef void * RsAdapter1D;
 typedef void * RsAdapter2D;
 typedef void * RsAllocation;
+typedef void * RsAnimation;
 typedef void * RsContext;
 typedef void * RsDevice;
 typedef void * RsElement;
@@ -205,7 +206,27 @@
 enum RsError {
     RS_ERROR_NONE,
     RS_ERROR_BAD_SHADER,
-    RS_ERROR_BAD_SCRIPT
+    RS_ERROR_BAD_SCRIPT,
+    RS_ERROR_BAD_VALUE,
+    RS_ERROR_OUT_OF_MEMORY
+};
+
+enum RsAnimationInterpolation {
+    RS_ANIMATION_INTERPOLATION_STEP,
+    RS_ANIMATION_INTERPOLATION_LINEAR,
+    RS_ANIMATION_INTERPOLATION_BEZIER,
+    RS_ANIMATION_INTERPOLATION_CARDINAL,
+    RS_ANIMATION_INTERPOLATION_HERMITE,
+    RS_ANIMATION_INTERPOLATION_BSPLINE
+};
+
+enum RsAnimationEdge {
+    RS_ANIMATION_EDGE_UNDEFINED,
+    RS_ANIMATION_EDGE_CONSTANT,
+    RS_ANIMATION_EDGE_GRADIENT,
+    RS_ANIMATION_EDGE_CYCLE,
+    RS_ANIMATION_EDGE_OSCILLATE,
+    RS_ANIMATION_EDGE_CYLE_RELATIVE
 };
 
 #ifndef NO_RS_FUNCS
diff --git a/rs.spec b/rs.spec
index cb9937c..08aa369 100644
--- a/rs.spec
+++ b/rs.spec
@@ -480,3 +480,13 @@
 	param uint32_t slot
 	}
 
+AnimationCreate {
+	param const float *inValues
+	param const float *outValues
+	param uint32_t valueCount
+	param RsAnimationInterpolation interp
+	param RsAnimationEdge pre
+	param RsAnimationEdge post
+	ret RsAnimation
+	}
+
diff --git a/rsAllocation.cpp b/rsAllocation.cpp
index 4e8278d..e5ff1d7 100644
--- a/rsAllocation.cpp
+++ b/rsAllocation.cpp
@@ -170,6 +170,7 @@
         glGenerateMipmap(GL_TEXTURE_2D);
     }
 
+    rsc->checkError("Allocation::uploadToTexture");
 }
 
 void Allocation::deferedUploadToBufferObject(const Context *rsc)
@@ -201,6 +202,7 @@
     glBindBuffer(GL_ARRAY_BUFFER, mBufferID);
     glBufferData(GL_ARRAY_BUFFER, mType->getSizeBytes(), getPtr(), GL_DYNAMIC_DRAW);
     glBindBuffer(GL_ARRAY_BUFFER, 0);
+    rsc->checkError("Allocation::uploadToBufferObject");
 }
 
 void Allocation::uploadCheck(const Context *rsc)
diff --git a/rsAnimation.cpp b/rsAnimation.cpp
new file mode 100644
index 0000000..48c9334
--- /dev/null
+++ b/rsAnimation.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#include "rsContext.h"
+#include "rsAnimation.h"
+
+
+using namespace android;
+using namespace android::renderscript;
+
+/*
+Animation::Animation(Context *rsc) : ObjectBase(rsc)
+{
+    mAllocFile = __FILE__;
+    mAllocLine = __LINE__;
+
+    mValuesInput = NULL;
+    mValuesOutput = NULL;
+    mValueCount = 0;
+    mInterpolation = RS_ANIMATION_INTERPOLATION_STEP;
+    mEdgePre = RS_ANIMATION_EDGE_UNDEFINED;
+    mEdgePost = RS_ANIMATION_EDGE_UNDEFINED;
+    mInputMin = 0;
+    mInputMax = 0;
+}
+
+Animation * Animation::create(Context *rsc,
+                              const float *inValues, const float *outValues,
+                              uint32_t valueCount, RsAnimationInterpolation interp,
+                              RsAnimationEdge pre, RsAnimationEdge post)
+{
+    if (valueCount < 2) {
+        rsc->setError(RS_ERROR_BAD_VALUE, "Animations require more than 2 values.");
+        return NULL;
+    }
+    Animation *a = new Animation(rsc);
+    if (!a) {
+        rsc->setError(RS_ERROR_OUT_OF_MEMORY);
+        return NULL;
+    }
+
+    float *vin = (float *)malloc(valueCount * sizeof(float));
+    float *vout = (float *)malloc(valueCount * sizeof(float));
+    a->mValuesInput = vin;
+    a->mValuesOutput = vout;
+    if (a->mValuesInput == NULL || a->mValuesOutput == NULL) {
+        delete a;
+        rsc->setError(RS_ERROR_OUT_OF_MEMORY);
+        return NULL;
+    }
+
+    a->mEdgePre = pre;
+    a->mEdgePost = post;
+    a->mInterpolation = interp;
+    a->mValueCount = valueCount;
+
+    memcpy(vin, inValues, valueCount * sizeof(float));
+    memcpy(vout, outValues, valueCount * sizeof(float));
+    a->mInputMin = inValues[0];
+    a->mInputMax = inValues[0];
+
+    bool needSort = false;
+    for (uint32_t ct=1; ct < valueCount; ct++) {
+        if (a->mInputMin > vin[ct]) {
+            needSort = true;
+            a->mInputMin = vin[ct];
+        }
+        if (a->mInputMax < vin[ct]) {
+            a->mInputMax = vin[ct];
+        } else {
+            needSort = true;
+        }
+    }
+
+    while (1) {
+        bool changed = false;
+        for (uint32_t ct=1; ct < valueCount; ct++) {
+            if (vin[ct-1] > vin[ct]) {
+                float t = vin[ct-1];
+                vin[ct-1] = vin[ct];
+                vin[ct] = t;
+                t = vout[ct-1];
+                vout[ct-1] = vout[ct];
+                vout[ct] = t;
+                changed = true;
+            }
+        }
+        if (!changed) break;
+    }
+
+    return a;
+}
+*/
+
+
+/////////////////////////////////////////
+//
+
+namespace android {
+namespace renderscript {
+
+RsAnimation rsi_AnimationCreate(Context *rsc,
+                                const float *inValues,
+                                const float *outValues,
+                                uint32_t valueCount,
+                                RsAnimationInterpolation interp,
+                                RsAnimationEdge pre,
+                                RsAnimationEdge post)
+{
+    //LOGE("rsi_ElementCreate %i %i %i %i", dt, dk, norm, vecSize);
+    Animation *a = NULL;//Animation::create(rsc, inValues, outValues, valueCount, interp, pre, post);
+    if (a != NULL) {
+        a->incUserRef();
+    }
+    return (RsAnimation)a;
+}
+
+
+}
+}
+
diff --git a/rsAnimation.h b/rsAnimation.h
new file mode 100644
index 0000000..b8db661
--- /dev/null
+++ b/rsAnimation.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef ANDROID_RS_ANIMATION_H
+#define ANDROID_RS_ANIMATION_H
+
+#include "rsUtils.h"
+#include "rsObjectBase.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+
+class Animation : public ObjectBase
+{
+public:
+    ~Animation();
+
+    static Animation * create(Context *rsc,
+                              const float *inValues, const float *outValues,
+                              uint32_t valueCount, RsAnimationInterpolation,
+                              RsAnimationEdge pre, RsAnimationEdge post);
+
+    float eval(float) const;
+
+
+protected:
+    Animation(Context *rsc);
+
+
+
+    float evalInRange(float) const;
+
+
+
+    const float *mValuesInput;
+    const float *mValuesOutput;
+    uint32_t mValueCount;
+    RsAnimationInterpolation mInterpolation;
+    RsAnimationEdge mEdgePre;
+    RsAnimationEdge mEdgePost;
+
+    // derived
+    float mInputMin;
+    float mInputMax;
+};
+
+
+
+
+}
+}
+#endif //ANDROID_STRUCTURED_ELEMENT_H
+
diff --git a/rsContext.h b/rsContext.h
index 82c3687..24c44d5 100644
--- a/rsContext.h
+++ b/rsContext.h
@@ -161,7 +161,7 @@
     void dumpDebug() const;
     void checkError(const char *) const;
     const char * getError(RsError *);
-    void setError(RsError e, const char *msg);
+    void setError(RsError e, const char *msg = NULL);
 
     mutable const ObjectBase * mObjHead;