1st cut of a3d file loader.
diff --git a/rsFileA3D.cpp b/rsFileA3D.cpp
new file mode 100644
index 0000000..f669417
--- /dev/null
+++ b/rsFileA3D.cpp
@@ -0,0 +1,356 @@
+
+/*
+ * 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 <utils/String8.h>
+#include "rsFileA3D.h"
+
+#include "rsMesh.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+
+
+FileA3D::FileA3D()
+{
+    mRsc = NULL;
+}
+
+FileA3D::~FileA3D()
+{
+}
+
+bool FileA3D::load(Context *rsc, FILE *f)
+{
+    char magicString[12];
+    size_t len;
+
+    LOGE("file open 1");
+    len = fread(magicString, 1, 12, f);
+    if ((len != 12) ||
+        memcmp(magicString, "Android3D_ff", 12)) {
+        return false;
+    }
+
+    LOGE("file open 2");
+    len = fread(&mMajorVersion, 1, sizeof(mMajorVersion), f);
+    if (len != sizeof(mMajorVersion)) {
+        return false;
+    }
+
+    LOGE("file open 3");
+    len = fread(&mMinorVersion, 1, sizeof(mMinorVersion), f);
+    if (len != sizeof(mMinorVersion)) {
+        return false;
+    }
+
+    LOGE("file open 4");
+    uint32_t flags;
+    len = fread(&flags, 1, sizeof(flags), f);
+    if (len != sizeof(flags)) {
+        return false;
+    }
+    mUse64BitOffsets = (flags & 1) != 0;
+
+    LOGE("file open 64bit = %i", mUse64BitOffsets);
+
+    if (mUse64BitOffsets) {
+        len = fread(&mDataSize, 1, sizeof(mDataSize), f);
+        if (len != sizeof(mDataSize)) {
+            return false;
+        }
+    } else {
+        uint32_t tmp;
+        len = fread(&tmp, 1, sizeof(tmp), f);
+        if (len != sizeof(tmp)) {
+            return false;
+        }
+        mDataSize = tmp;
+    }
+
+    LOGE("file open size = %lli", mDataSize);
+
+    // We should know enough to read the file in at this point.
+    fseek(f, SEEK_SET, 0);
+    mAlloc= malloc(mDataSize);
+    if (!mAlloc) {
+        return false;
+    }
+    mData = (uint8_t *)mAlloc;
+    len = fread(mAlloc, 1, mDataSize, f);
+    if (len != mDataSize) {
+        return false;
+    }
+
+    LOGE("file start processing");
+    return process(rsc);
+}
+
+bool FileA3D::processIndex(Context *rsc, A3DIndexEntry *ie)
+{
+    bool ret = false;
+    IO io(mData + ie->mOffset, mUse64BitOffsets);
+
+    LOGE("process index, type %i", ie->mType);
+
+    switch(ie->mType) {
+    case CHUNK_ELEMENT:
+        processChunk_Element(rsc, &io, ie);
+        break;
+    case CHUNK_ELEMENT_SOURCE:
+        processChunk_ElementSource(rsc, &io, ie);
+        break;
+    case CHUNK_VERTICIES:
+        processChunk_Verticies(rsc, &io, ie);
+        break;
+    case CHUNK_MESH:
+        processChunk_Mesh(rsc, &io, ie);
+        break;
+    case CHUNK_PRIMITIVE:
+        processChunk_Primitive(rsc, &io, ie);
+        break;
+    default:
+        LOGE("FileA3D Unknown chunk type");
+        break;
+    }
+    return (ie->mRsObj != NULL);
+}
+
+bool FileA3D::process(Context *rsc)
+{
+    LOGE("process");
+    IO io(mData + 12, mUse64BitOffsets);
+    bool ret = true;
+
+    // Build the index first
+    LOGE("process 1");
+    io.loadU32(); // major version, already loaded
+    io.loadU32(); // minor version, already loaded
+    LOGE("process 2");
+
+    io.loadU32();  // flags
+    io.loadOffset(); // filesize, already loaded.
+    LOGE("process 4");
+    uint64_t mIndexOffset = io.loadOffset();
+    uint64_t mStringOffset = io.loadOffset();
+
+    LOGE("process mIndexOffset= 0x%016llx", mIndexOffset);
+    LOGE("process mStringOffset= 0x%016llx", mStringOffset);
+
+    IO index(mData + mIndexOffset, mUse64BitOffsets);
+    IO stringTable(mData + mStringOffset, mUse64BitOffsets);
+
+    uint32_t stringEntryCount = stringTable.loadU32();
+    LOGE("stringEntryCount %i", stringEntryCount);
+    mStrings.setCapacity(stringEntryCount);
+    mStringIndexValues.setCapacity(stringEntryCount);
+    if (stringEntryCount) {
+        uint32_t stringType = stringTable.loadU32();
+        LOGE("stringType %i", stringType);
+        rsAssert(stringType==0);
+        for (uint32_t ct = 0; ct < stringEntryCount; ct++) {
+            uint64_t offset = stringTable.loadOffset();
+            LOGE("string offset 0x%016llx", offset);
+            IO tmp(mData + offset, mUse64BitOffsets);
+            String8 s;
+            tmp.loadString(&s);
+            LOGE("string %s", s.string());
+            mStrings.push(s);
+        }
+    }
+
+    LOGE("strings done");
+    uint32_t indexEntryCount = index.loadU32();
+    LOGE("index count %i", indexEntryCount);
+    mIndex.setCapacity(indexEntryCount);
+    for (uint32_t ct = 0; ct < indexEntryCount; ct++) {
+        A3DIndexEntry e;
+        uint32_t stringIndex = index.loadU32();
+        LOGE("index %i", ct);
+        LOGE("  string index %i", stringIndex);
+        e.mType = (A3DChunkType)index.loadU32();
+        LOGE("  type %i", e.mType);
+        e.mOffset = index.loadOffset();
+        LOGE("  offset 0x%016llx", e.mOffset);
+
+        if (stringIndex && (stringIndex < mStrings.size())) {
+            e.mID = mStrings[stringIndex];
+            mStringIndexValues.editItemAt(stringIndex) = ct;
+            LOGE("  id %s", e.mID.string());
+        }
+
+        mIndex.push(e);
+    }
+    LOGE("index done");
+
+    // At this point the index should be fully populated.
+    // We can now walk though it and load all the objects.
+    for (uint32_t ct = 0; ct < indexEntryCount; ct++) {
+        LOGE("processing index entry %i", ct);
+        processIndex(rsc, &mIndex.editItemAt(ct));
+    }
+
+    return ret;
+}
+
+
+FileA3D::IO::IO(const uint8_t *buf, bool use64)
+{
+    mData = buf;
+    mPos = 0;
+    mUse64 = use64;
+}
+
+uint64_t FileA3D::IO::loadOffset()
+{
+    uint64_t tmp;
+    if (mUse64) {
+        mPos = (mPos + 7) & (~7);
+        tmp = reinterpret_cast<const uint64_t *>(&mData[mPos])[0];
+        mPos += sizeof(uint64_t);
+        return tmp;
+    }
+    return loadU32();
+}
+
+void FileA3D::IO::loadString(String8 *s)
+{
+    LOGE("loadString");
+    uint32_t len = loadU32();
+    LOGE("loadString len %i", len);
+    s->setTo((const char *)&mData[mPos], len);
+    mPos += len;
+}
+
+
+void FileA3D::processChunk_Mesh(Context *rsc, IO *io, A3DIndexEntry *ie)
+{
+    Mesh * m = new Mesh;
+
+    m->mPrimitivesCount = io->loadU32();
+    m->mPrimitives = new Mesh::Primitive_t *[m->mPrimitivesCount];
+
+    for (uint32_t ct = 0; ct < m->mPrimitivesCount; ct++) {
+        uint32_t index = io->loadU32();
+
+        m->mPrimitives[ct] = (Mesh::Primitive_t *)mIndex[index].mRsObj;
+    }
+    ie->mRsObj = m;
+}
+
+void FileA3D::processChunk_Primitive(Context *rsc, IO *io, A3DIndexEntry *ie)
+{
+    Mesh::Primitive_t * p = new Mesh::Primitive_t;
+
+    p->mIndexCount = io->loadU32();
+    uint32_t vertIdx = io->loadU32();
+    uint32_t bits = io->loadU8();
+    p->mType = (RsPrimitive)io->loadU8();
+
+    p->mVerticies = (Mesh::Verticies_t *)mIndex[vertIdx].mRsObj;
+
+    p->mIndicies = new uint16_t[p->mIndexCount];
+    for (uint32_t ct = 0; ct < p->mIndexCount; ct++) {
+        switch(bits) {
+        case 8:
+            p->mIndicies[ct] = io->loadU8();
+            break;
+        case 16:
+            p->mIndicies[ct] = io->loadU16();
+            break;
+        case 32:
+            p->mIndicies[ct] = io->loadU32();
+            break;
+        }
+    }
+
+    ie->mRsObj = p;
+}
+
+void FileA3D::processChunk_Verticies(Context *rsc, IO *io, A3DIndexEntry *ie)
+{
+    Mesh::Verticies_t *cv = new Mesh::Verticies_t;
+    cv->mAllocationCount = io->loadU32();
+    cv->mAllocations = new Allocation *[cv->mAllocationCount];
+    for (uint32_t ct = 0; ct < cv->mAllocationCount; ct++) {
+        uint32_t i = io->loadU32();
+        cv->mAllocations[ct] = (Allocation *)mIndex[i].mRsObj;
+    }
+    ie->mRsObj = cv;
+}
+
+void FileA3D::processChunk_Element(Context *rsc, IO *io, A3DIndexEntry *ie)
+{
+    LOGE("processChunk_Element ie %p", ie);
+    rsi_ElementBegin(rsc);
+
+    uint32_t count = io->loadU32();
+    LOGE("processChunk_Element count %i", count);
+    while (count--) {
+        RsDataKind dk = (RsDataKind)io->loadU8();
+        RsDataType dt = (RsDataType)io->loadU8();
+        uint32_t bits = io->loadU8();
+        bool isNorm = io->loadU8() != 0;
+        LOGE("  %i %i %i %i", dk, dt, bits, isNorm);
+        rsi_ElementAdd(rsc, dk, dt, isNorm, bits);
+    }
+    LOGE("processChunk_Element create");
+    ie->mRsObj = rsi_ElementCreate(rsc);
+}
+
+void FileA3D::processChunk_ElementSource(Context *rsc, IO *io, A3DIndexEntry *ie)
+{
+    uint32_t index = io->loadU32();
+    uint32_t count = io->loadU32();
+
+    RsElement e = (RsElement)mIndex[index].mRsObj;
+
+    RsAllocation a = rsi_AllocationCreateSized(rsc, e, count);
+    Allocation * alloc = static_cast<Allocation *>(a);
+
+    float * data = (float *)alloc->getPtr();
+    while(count--) {
+        *data = io->loadF();
+        data++;
+    }
+    ie->mRsObj = alloc;
+}
+
+namespace android {
+namespace renderscript {
+
+
+RsFile rsi_FileOpen(Context *rsc, char const *path, unsigned int len)
+{
+    FileA3D *fa3d = new FileA3D;
+
+    FILE *f = fopen("/sdcard/test.a3d", "rb");
+    if (f) {
+        fa3d->load(rsc, f);
+        fclose(f);
+        return fa3d;
+    }
+    delete fa3d;
+    return NULL;
+}
+
+
+}
+}