Merge "Fix ilogb's return type"
diff --git a/driver/runtime/rs_structs.h b/driver/runtime/rs_structs.h
index 40f740a..b57a2c8 100644
--- a/driver/runtime/rs_structs.h
+++ b/driver/runtime/rs_structs.h
@@ -242,8 +242,10 @@
             uint32_t *lodDimX;
             uint32_t *lodDimY;
             uint32_t *lodDimZ;
-            uint32_t *lodOffset;
+            uint32_t *arrays;
             uint32_t lodCount;
+            uint32_t dimYuv;
+            uint32_t arrayCount;
             bool faces;
         } state;
     } mHal;
diff --git a/rs.spec b/rs.spec
index 22c53b9..183ae8b 100644
--- a/rs.spec
+++ b/rs.spec
@@ -43,6 +43,12 @@
     ret RsType
 }
 
+TypeCreate2 {
+    direct
+    param const RsTypeCreateParams *dat
+    ret RsType
+}
+
 AllocationCreateTyped {
     direct
     param RsType vtype
diff --git a/rsCppUtils.h b/rsCppUtils.h
index 7f1d58c..8b49056 100644
--- a/rsCppUtils.h
+++ b/rsCppUtils.h
@@ -63,7 +63,7 @@
 
 static inline nsecs_t systemTime(int clock)
 {
-#if defined(HAVE_POSIX_CLOCKS)
+#if defined(__linux__)
     static const clockid_t clocks[] = {
             CLOCK_REALTIME,
             CLOCK_MONOTONIC,
diff --git a/rsFont.cpp b/rsFont.cpp
index 2f09384..8f39ca9 100644
--- a/rsFont.cpp
+++ b/rsFont.cpp
@@ -519,8 +519,7 @@
     const char *ebn1[] = { "Color", "Gamma" };
     const Element *ebe1[] = {colorElem.get(), gammaElem.get()};
     ObjectBaseRef<const Element> constInput = Element::create(mRSC, 2, ebe1, ebn1);
-
-    ObjectBaseRef<Type> inputType = Type::getTypeRef(mRSC, constInput.get(), 1, 0, 0, false, false, 0);
+    ObjectBaseRef<Type> inputType = Type::getTypeRef(mRSC, constInput.get(), 1);
 
     uintptr_t tmp[4];
     tmp[0] = RS_PROGRAM_PARAM_CONSTANT;
@@ -557,9 +556,7 @@
     // We will allocate a texture to initially hold 32 character bitmaps
     mCacheHeight = 256;
     mCacheWidth = 1024;
-    ObjectBaseRef<Type> texType = Type::getTypeRef(mRSC, alphaElem.get(),
-                                                   mCacheWidth, mCacheHeight,
-                                                   0, false, false, 0);
+    ObjectBaseRef<Type> texType = Type::getTypeRef(mRSC, alphaElem.get(), mCacheWidth, mCacheHeight);
 
     mCacheBuffer = new uint8_t[mCacheWidth * mCacheHeight];
 
@@ -597,8 +594,7 @@
 void FontState::initVertexArrayBuffers() {
     // Now lets write index data
     ObjectBaseRef<const Element> indexElem = Element::createRef(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1);
-    uint32_t numIndicies = mMaxNumberOfQuads * 6;
-    ObjectBaseRef<Type> indexType = Type::getTypeRef(mRSC, indexElem.get(), numIndicies, 0, 0, false, false, 0);
+    ObjectBaseRef<Type> indexType = Type::getTypeRef(mRSC, indexElem.get(), mMaxNumberOfQuads * 6);
 
     Allocation *indexAlloc = Allocation::createAllocation(mRSC, indexType.get(),
                                                           RS_ALLOCATION_USAGE_SCRIPT |
@@ -628,9 +624,7 @@
     const Element *ebe1[] = {posElem.get(), texElem.get()};
     ObjectBaseRef<const Element> vertexDataElem = Element::create(mRSC, 2, ebe1, ebn1);
 
-    ObjectBaseRef<Type> vertexDataType = Type::getTypeRef(mRSC, vertexDataElem.get(),
-                                                          mMaxNumberOfQuads * 4,
-                                                          0, 0, false, false, 0);
+    ObjectBaseRef<Type> vertexDataType = Type::getTypeRef(mRSC, vertexDataElem.get(), mMaxNumberOfQuads * 4);
 
     Allocation *vertexAlloc = Allocation::createAllocation(mRSC, vertexDataType.get(),
                                                            RS_ALLOCATION_USAGE_SCRIPT);
diff --git a/rsInternalDefines.h b/rsInternalDefines.h
index 57cb72a..678e6c8 100644
--- a/rsInternalDefines.h
+++ b/rsInternalDefines.h
@@ -199,6 +199,24 @@
 
 
 
+// Structure for rs.spec functions
+
+typedef struct {
+    RsElement e;
+    uint32_t dimX;
+    uint32_t dimY;
+    uint32_t dimZ;
+    bool mipmaps;
+    bool faces;
+    uint32_t yuv;
+    uint32_t array0;
+    uint32_t array1;
+    uint32_t array2;
+    uint32_t array3;
+} RsTypeCreateParams;
+
+
+
 #ifdef __cplusplus
 };
 #endif
diff --git a/rsProgramFragment.cpp b/rsProgramFragment.cpp
index 7af6738..071f57e 100644
--- a/rsProgramFragment.cpp
+++ b/rsProgramFragment.cpp
@@ -109,7 +109,7 @@
     const Element *eins[] = {colorElem.get()};
     ObjectBaseRef<const Element> constInput = Element::create(rsc, 1, eins, enames);
 
-    ObjectBaseRef<Type> inputType = Type::getTypeRef(rsc, constInput.get(), 1, 0, 0, false, false, 0);
+    ObjectBaseRef<Type> inputType = Type::getTypeRef(rsc, constInput.get(), 1);
 
     uintptr_t tmp[2];
     tmp[0] = RS_PROGRAM_PARAM_CONSTANT;
diff --git a/rsProgramVertex.cpp b/rsProgramVertex.cpp
index baf1fff..3492f63 100644
--- a/rsProgramVertex.cpp
+++ b/rsProgramVertex.cpp
@@ -183,7 +183,7 @@
     const Element *ebe2[] = {f4Elem.get(), f4Elem.get(), f3Elem.get(), f2Elem.get()};
     ObjectBaseRef<const Element> attrElem = Element::create(rsc, 4, ebe2, ebn2);
 
-    ObjectBaseRef<Type> inputType = Type::getTypeRef(rsc, constInput.get(), 1, 0, 0, false, false, 0);
+    ObjectBaseRef<Type> inputType = Type::getTypeRef(rsc, constInput.get(), 1);
 
     const char *shaderString =
             RS_SHADER_INTERNAL
diff --git a/rsType.cpp b/rsType.cpp
index c0cda91..39c91cd 100644
--- a/rsType.cpp
+++ b/rsType.cpp
@@ -62,6 +62,9 @@
         delete [] mHal.state.lodDimY;
         delete [] mHal.state.lodDimZ;
     }
+    if (mHal.state.arrayCount > 0) {
+        delete [] mHal.state.arrays;
+    }
     mElement.clear();
     memset(&mHal, 0, sizeof(mHal));
 }
@@ -192,12 +195,14 @@
         return nullptr;
     }
 
-    uint32_t x = stream->loadU32();
-    uint32_t y = stream->loadU32();
-    uint32_t z = stream->loadU32();
-    uint8_t lod = stream->loadU8();
-    uint8_t faces = stream->loadU8();
-    Type *type = Type::getType(rsc, elem, x, y, z, lod != 0, faces !=0, 0);
+    RsTypeCreateParams p;
+    memset(&p, 0, sizeof(p));
+    p.dimX = stream->loadU32();
+    p.dimY = stream->loadU32();
+    p.dimZ = stream->loadU32();
+    p.mipmaps = stream->loadU8();
+    p.faces = stream->loadU8();
+    Type *type = Type::getType(rsc, elem, &p, sizeof(p));
     elem->decUserRef();
 
     delete [] name;
@@ -222,8 +227,7 @@
 }
 
 ObjectBaseRef<Type> Type::getTypeRef(Context *rsc, const Element *e,
-                                     uint32_t dimX, uint32_t dimY, uint32_t dimZ,
-                                     bool dimLOD, bool dimFaces, uint32_t dimYuv) {
+                                     const RsTypeCreateParams *params, size_t len) {
     ObjectBaseRef<Type> returnRef;
 
     TypeState * stc = &rsc->mStateType;
@@ -232,12 +236,16 @@
     for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
         Type *t = stc->mTypes[ct];
         if (t->getElement() != e) continue;
-        if (t->getDimX() != dimX) continue;
-        if (t->getDimY() != dimY) continue;
-        if (t->getDimZ() != dimZ) continue;
-        if (t->getDimLOD() != dimLOD) continue;
-        if (t->getDimFaces() != dimFaces) continue;
-        if (t->getDimYuv() != dimYuv) continue;
+        if (t->getDimX() != params->dimX) continue;
+        if (t->getDimY() != params->dimY) continue;
+        if (t->getDimZ() != params->dimZ) continue;
+        if (t->getDimLOD() != params->mipmaps) continue;
+        if (t->getDimFaces() != params->faces) continue;
+        if (t->getDimYuv() != params->yuv) continue;
+        if (t->getArray(0) != params->array0) continue;
+        if (t->getArray(1) != params->array1) continue;
+        if (t->getArray(2) != params->array2) continue;
+        if (t->getArray(3) != params->array3) continue;
         returnRef.set(t);
         ObjectBase::asyncUnlock();
         return returnRef;
@@ -258,14 +266,28 @@
     ALOGE("pointer for type.drv: %p", &nt->mHal.drv);
 #endif
 
-    nt->mDimLOD = dimLOD;
+    nt->mDimLOD = params->mipmaps;
     returnRef.set(nt);
     nt->mElement.set(e);
-    nt->mHal.state.dimX = dimX;
-    nt->mHal.state.dimY = dimY;
-    nt->mHal.state.dimZ = dimZ;
-    nt->mHal.state.faces = dimFaces;
-    nt->mHal.state.dimYuv = dimYuv;
+    nt->mHal.state.dimX = params->dimX;
+    nt->mHal.state.dimY = params->dimY;
+    nt->mHal.state.dimZ = params->dimZ;
+    nt->mHal.state.faces = params->faces;
+    nt->mHal.state.dimYuv = params->yuv;
+
+    nt->mHal.state.arrayCount = 0;
+    if (params->array0 > 0) nt->mHal.state.arrayCount ++;
+    if (params->array1 > 0) nt->mHal.state.arrayCount ++;
+    if (params->array2 > 0) nt->mHal.state.arrayCount ++;
+    if (params->array3 > 0) nt->mHal.state.arrayCount ++;
+    if (nt->mHal.state.arrayCount > 0) {
+        nt->mHal.state.arrays = new uint32_t[nt->mHal.state.arrayCount];
+        if (params->array0 > 0) nt->mHal.state.arrays[0] = params->array0;
+        if (params->array1 > 1) nt->mHal.state.arrays[1] = params->array1;
+        if (params->array2 > 2) nt->mHal.state.arrays[2] = params->array2;
+        if (params->array3 > 3) nt->mHal.state.arrays[3] = params->array3;
+    }
+
     nt->compute();
 
     ObjectBase::asyncLock();
@@ -276,15 +298,27 @@
 }
 
 ObjectBaseRef<Type> Type::cloneAndResize1D(Context *rsc, uint32_t dimX) const {
-    return getTypeRef(rsc, mElement.get(), dimX,
-                      getDimY(), getDimZ(), getDimLOD(), getDimFaces(), getDimYuv());
+    RsTypeCreateParams p;
+    memset(&p, 0, sizeof(p));
+    p.dimX = dimX;
+    p.dimY = getDimY();
+    p.dimZ = getDimZ();
+    p.mipmaps = getDimLOD();
+    return getTypeRef(rsc, mElement.get(), &p, sizeof(p));
 }
 
 ObjectBaseRef<Type> Type::cloneAndResize2D(Context *rsc,
                               uint32_t dimX,
                               uint32_t dimY) const {
-    return getTypeRef(rsc, mElement.get(), dimX, dimY,
-                      getDimZ(), getDimLOD(), getDimFaces(), getDimYuv());
+    RsTypeCreateParams p;
+    memset(&p, 0, sizeof(p));
+    p.dimX = dimX;
+    p.dimY = dimY;
+    p.dimZ = getDimZ();
+    p.mipmaps = getDimLOD();
+    p.faces = getDimFaces();
+    p.yuv = getDimYuv();
+    return getTypeRef(rsc, mElement.get(), &p, sizeof(p));
 }
 
 
@@ -335,7 +369,20 @@
                      uint32_t dimY, uint32_t dimZ, bool mipmaps, bool faces, uint32_t yuv) {
     Element *e = static_cast<Element *>(_e);
 
-    return Type::getType(rsc, e, dimX, dimY, dimZ, mipmaps, faces, yuv);
+    RsTypeCreateParams p;
+    memset(&p, 0, sizeof(p));
+    p.dimX = dimX;
+    p.dimY = dimY;
+    p.dimZ = dimZ;
+    p.mipmaps = mipmaps;
+    p.faces = faces;
+    p.yuv = yuv;
+    return Type::getType(rsc, e, &p, sizeof(p));
+}
+
+RsType rsi_TypeCreate2(Context *rsc, const RsTypeCreateParams *p, size_t len) {
+    Element *e = static_cast<Element *>(p->e);
+    return Type::getType(rsc, e, p, len);
 }
 
 }
diff --git a/rsType.h b/rsType.h
index 86d6ece..445f4ff 100644
--- a/rsType.h
+++ b/rsType.h
@@ -26,13 +26,15 @@
  * CAUTION
  *
  * Any layout changes for this class may require a corresponding change to be
- * made to frameworks/compile/libbcc/lib/ScriptCRT/rs_core.c, which contains
+ * made to frameworks/rs/driver/runtime/rs_structs.h, which contains
  * a partial copy of the information below.
  *
  *****************************************************************************/
 
 class Type : public ObjectBase {
 public:
+    const static uint32_t mMaxArrays = 4;
+
     struct Hal {
         mutable void *drv;
 
@@ -47,9 +49,10 @@
             uint32_t *lodDimX;
             uint32_t *lodDimY;
             uint32_t *lodDimZ;
-            uint32_t *_unused;
+            uint32_t *arrays;
             uint32_t lodCount;
             uint32_t dimYuv;
+            uint32_t arrayCount;
             bool faces;
         };
         State state;
@@ -71,6 +74,12 @@
     bool getDimLOD() const {return mDimLOD;}
     bool getDimFaces() const {return mHal.state.faces;}
     uint32_t getDimYuv() const {return mHal.state.dimYuv;}
+    uint32_t getArray(uint32_t idx) const {
+        if (idx < mHal.state.arrayCount) {
+            return mHal.state.arrays[idx];
+        }
+        return 0;
+    }
 
     uint32_t getLODDimX(uint32_t lod) const {
         rsAssert(lod < mHal.state.lodCount);
@@ -100,17 +109,23 @@
     ObjectBaseRef<Type> cloneAndResize2D(Context *rsc, uint32_t dimX, uint32_t dimY) const;
 
     static ObjectBaseRef<Type> getTypeRef(Context *rsc, const Element *e,
-                                          uint32_t dimX, uint32_t dimY, uint32_t dimZ,
-                                          bool dimLOD, bool dimFaces, uint32_t dimYuv);
+                                          const RsTypeCreateParams *params, size_t len);
 
     static Type* getType(Context *rsc, const Element *e,
-                         uint32_t dimX, uint32_t dimY, uint32_t dimZ,
-                         bool dimLOD, bool dimFaces, uint32_t yuv) {
-        ObjectBaseRef<Type> type = getTypeRef(rsc, e, dimX, dimY, dimZ, dimLOD, dimFaces, yuv);
+                         const RsTypeCreateParams *params, size_t len) {
+        ObjectBaseRef<Type> type = getTypeRef(rsc, e, params, len);
         type->incUserRef();
         return type.get();
     }
 
+    static ObjectBaseRef<Type> getTypeRef(Context *rsc, const Element *e, uint32_t dimX, uint32_t dimY = 0) {
+        RsTypeCreateParams p;
+        memset(&p, 0, sizeof(p));
+        p.dimX = dimX;
+        p.dimY = dimY;
+        return getTypeRef(rsc, e, &p, sizeof(p));
+    }
+
     void incRefs(const void *ptr, size_t ct, size_t startOff = 0) const;
     void decRefs(const void *ptr, size_t ct, size_t startOff = 0) const;
     virtual void callUpdateCacheObject(const Context *rsc, void *dstObj) const;