Creating the jni and java layer to integrate a3d
Change-Id: I438359633bae59bf9188cd2c4664a92ca16c5f37
diff --git a/rsFileA3D.cpp b/rsFileA3D.cpp
index b88f7b0..23c0cf5 100644
--- a/rsFileA3D.cpp
+++ b/rsFileA3D.cpp
@@ -29,11 +29,8 @@
using namespace android;
using namespace android::renderscript;
-
-
-FileA3D::FileA3D()
+FileA3D::FileA3D(Context *rsc) : ObjectBase(rsc)
{
- mRsc = NULL;
mAlloc = NULL;
mData = NULL;
mWriteStream = NULL;
@@ -63,7 +60,110 @@
}
}
-bool FileA3D::load(Context *rsc, FILE *f)
+void FileA3D::parseHeader(IStream *headerStream)
+{
+ mMajorVersion = headerStream->loadU32();
+ mMinorVersion = headerStream->loadU32();
+ uint32_t flags = headerStream->loadU32();
+ mUse64BitOffsets = (flags & 1) != 0;
+
+ LOGE("file open 64bit = %i", mUse64BitOffsets);
+
+ uint32_t numIndexEntries = headerStream->loadU32();
+ for(uint32_t i = 0; i < numIndexEntries; i ++) {
+ A3DIndexEntry *entry = new A3DIndexEntry();
+ headerStream->loadString(&entry->mObjectName);
+ LOGE("Header data, entry name = %s", entry->mObjectName.string());
+ entry->mType = (RsA3DClassID)headerStream->loadU32();
+ if(mUse64BitOffsets){
+ entry->mOffset = headerStream->loadOffset();
+ entry->mLength = headerStream->loadOffset();
+ }
+ else {
+ entry->mOffset = headerStream->loadU32();
+ entry->mLength = headerStream->loadU32();
+ }
+ entry->mRsObj = NULL;
+ mIndex.push(entry);
+ }
+}
+
+bool FileA3D::load(const void *data, size_t length)
+{
+ LOGE("Loading data. Size: %u", length);
+ const uint8_t *localData = (const uint8_t *)data;
+
+ size_t lengthRemaining = length;
+ size_t magicStrLen = 12;
+ if ((length < magicStrLen) ||
+ memcmp(data, "Android3D_ff", magicStrLen)) {
+ return false;
+ }
+
+ localData += magicStrLen;
+ lengthRemaining -= magicStrLen;
+
+ // Next we get our header size
+ uint64_t headerSize = 0;
+ if(lengthRemaining < sizeof(headerSize)) {
+ return false;
+ }
+
+ memcpy(&headerSize, localData, sizeof(headerSize));
+ localData += sizeof(headerSize);
+ lengthRemaining -= sizeof(headerSize);
+
+ LOGE("Loading data, headerSize = %lli", headerSize);
+
+ if(lengthRemaining < headerSize) {
+ return false;
+ }
+
+ uint8_t *headerData = (uint8_t *)malloc(headerSize);
+ if(!headerData) {
+ return false;
+ }
+
+ memcpy(headerData, localData, headerSize);
+
+ // Now open the stream to parse the header
+ IStream headerStream(headerData, false);
+ parseHeader(&headerStream);
+
+ free(headerData);
+
+ localData += headerSize;
+ lengthRemaining -= headerSize;
+
+ if(lengthRemaining < sizeof(mDataSize)) {
+ return false;
+ }
+
+ // Read the size of the data
+ memcpy(&mDataSize, localData, sizeof(mDataSize));
+ localData += sizeof(mDataSize);
+ lengthRemaining -= sizeof(mDataSize);
+
+ LOGE("Loading data, mDataSize = %lli", mDataSize);
+
+ if(lengthRemaining < mDataSize) {
+ return false;
+ }
+
+ // We should know enough to read the file in at this point.
+ mAlloc = malloc(mDataSize);
+ if (!mAlloc) {
+ return false;
+ }
+ mData = (uint8_t *)mAlloc;
+ memcpy(mAlloc, localData, mDataSize);
+
+ mReadStream = new IStream(mData, mUse64BitOffsets);
+
+ return true;
+}
+
+bool FileA3D::load(FILE *f)
{
char magicString[12];
size_t len;
@@ -94,28 +194,9 @@
// Now open the stream to parse the header
IStream headerStream(headerData, false);
+ parseHeader(&headerStream);
- mMajorVersion = headerStream.loadU32();
- mMinorVersion = headerStream.loadU32();
- uint32_t flags = headerStream.loadU32();
- mUse64BitOffsets = (flags & 1) != 0;
-
- LOGE("file open 64bit = %i", mUse64BitOffsets);
-
- uint32_t numIndexEntries = headerStream.loadU32();
- for(uint32_t i = 0; i < numIndexEntries; i ++) {
- A3DIndexEntry *entry = new A3DIndexEntry();
- headerStream.loadString(&entry->mID);
- entry->mType = (A3DClassID)headerStream.loadU32();
- if(mUse64BitOffsets){
- entry->mOffset = headerStream.loadOffset();
- }
- else {
- entry->mOffset = headerStream.loadU32();
- }
- entry->mRsObj = NULL;
- mIndex.push(entry);
- }
+ free(headerData);
// Next thing is the size of the header
len = fread(&mDataSize, 1, sizeof(mDataSize), f);
@@ -138,65 +219,90 @@
mReadStream = new IStream(mData, mUse64BitOffsets);
- mRsc = rsc;
-
LOGE("Header is read an stream initialized");
return true;
}
-size_t FileA3D::getNumLoadedEntries() const {
+size_t FileA3D::getNumIndexEntries() const {
return mIndex.size();
}
-const FileA3D::A3DIndexEntry *FileA3D::getLoadedEntry(size_t index) const {
+const FileA3D::A3DIndexEntry *FileA3D::getIndexEntry(size_t index) const {
if(index < mIndex.size()) {
return mIndex[index];
}
return NULL;
}
-ObjectBase *FileA3D::initializeFromEntry(const FileA3D::A3DIndexEntry *entry) {
+ObjectBase *FileA3D::initializeFromEntry(size_t index) {
+ if(index >= mIndex.size()) {
+ return NULL;
+ }
+
+ FileA3D::A3DIndexEntry *entry = mIndex[index];
if(!entry) {
return NULL;
}
+ if(entry->mRsObj) {
+ entry->mRsObj->incUserRef();
+ return entry->mRsObj;
+ }
+
// Seek to the beginning of object
mReadStream->reset(entry->mOffset);
switch (entry->mType) {
- case A3D_CLASS_ID_UNKNOWN:
+ case RS_A3D_CLASS_ID_UNKNOWN:
return NULL;
- case A3D_CLASS_ID_MESH:
- return Mesh::createFromStream(mRsc, mReadStream);
- case A3D_CLASS_ID_SIMPLE_MESH:
- return SimpleMesh::createFromStream(mRsc, mReadStream);
- case A3D_CLASS_ID_TYPE:
- return Type::createFromStream(mRsc, mReadStream);
- case A3D_CLASS_ID_ELEMENT:
- return Element::createFromStream(mRsc, mReadStream);
- case A3D_CLASS_ID_ALLOCATION:
- return Allocation::createFromStream(mRsc, mReadStream);
- case A3D_CLASS_ID_PROGRAM_VERTEX:
- return ProgramVertex::createFromStream(mRsc, mReadStream);
- case A3D_CLASS_ID_PROGRAM_RASTER:
- return ProgramRaster::createFromStream(mRsc, mReadStream);
- case A3D_CLASS_ID_PROGRAM_FRAGMENT:
- return ProgramFragment::createFromStream(mRsc, mReadStream);
- case A3D_CLASS_ID_PROGRAM_STORE:
- return ProgramStore::createFromStream(mRsc, mReadStream);
- case A3D_CLASS_ID_SAMPLER:
- return Sampler::createFromStream(mRsc, mReadStream);
- case A3D_CLASS_ID_ANIMATION:
- return Animation::createFromStream(mRsc, mReadStream);
- case A3D_CLASS_ID_LIGHT:
- return Light::createFromStream(mRsc, mReadStream);
- case A3D_CLASS_ID_ADAPTER_1D:
- return Adapter1D::createFromStream(mRsc, mReadStream);
- case A3D_CLASS_ID_ADAPTER_2D:
- return Adapter2D::createFromStream(mRsc, mReadStream);
- case A3D_CLASS_ID_SCRIPT_C:
+ case RS_A3D_CLASS_ID_MESH:
+ entry->mRsObj = Mesh::createFromStream(mRSC, mReadStream);
+ break;
+ case RS_A3D_CLASS_ID_SIMPLE_MESH:
+ entry->mRsObj = SimpleMesh::createFromStream(mRSC, mReadStream);
+ break;
+ case RS_A3D_CLASS_ID_TYPE:
+ entry->mRsObj = Type::createFromStream(mRSC, mReadStream);
+ break;
+ case RS_A3D_CLASS_ID_ELEMENT:
+ entry->mRsObj = Element::createFromStream(mRSC, mReadStream);
+ break;
+ case RS_A3D_CLASS_ID_ALLOCATION:
+ entry->mRsObj = Allocation::createFromStream(mRSC, mReadStream);
+ break;
+ case RS_A3D_CLASS_ID_PROGRAM_VERTEX:
+ entry->mRsObj = ProgramVertex::createFromStream(mRSC, mReadStream);
+ break;
+ case RS_A3D_CLASS_ID_PROGRAM_RASTER:
+ entry->mRsObj = ProgramRaster::createFromStream(mRSC, mReadStream);
+ break;
+ case RS_A3D_CLASS_ID_PROGRAM_FRAGMENT:
+ entry->mRsObj = ProgramFragment::createFromStream(mRSC, mReadStream);
+ break;
+ case RS_A3D_CLASS_ID_PROGRAM_STORE:
+ entry->mRsObj = ProgramStore::createFromStream(mRSC, mReadStream);
+ break;
+ case RS_A3D_CLASS_ID_SAMPLER:
+ entry->mRsObj = Sampler::createFromStream(mRSC, mReadStream);
+ break;
+ case RS_A3D_CLASS_ID_ANIMATION:
+ entry->mRsObj = Animation::createFromStream(mRSC, mReadStream);
+ break;
+ case RS_A3D_CLASS_ID_LIGHT:
+ entry->mRsObj = Light::createFromStream(mRSC, mReadStream);
+ break;
+ case RS_A3D_CLASS_ID_ADAPTER_1D:
+ entry->mRsObj = Adapter1D::createFromStream(mRSC, mReadStream);
+ break;
+ case RS_A3D_CLASS_ID_ADAPTER_2D:
+ entry->mRsObj = Adapter2D::createFromStream(mRSC, mReadStream);
+ break;
+ case RS_A3D_CLASS_ID_SCRIPT_C:
return NULL;
}
- return NULL;
+ if(entry->mRsObj) {
+ entry->mRsObj->incUserRef();
+ }
+ return entry->mRsObj;
}
bool FileA3D::writeFile(const char *filename)
@@ -226,14 +332,17 @@
uint32_t writeIndexSize = mWriteIndex.size();
headerStream.addU32(writeIndexSize);
for(uint32_t i = 0; i < writeIndexSize; i ++) {
- headerStream.addString(&mWriteIndex[i]->mID);
+ headerStream.addString(&mWriteIndex[i]->mObjectName);
headerStream.addU32((uint32_t)mWriteIndex[i]->mType);
if(mUse64BitOffsets){
headerStream.addOffset(mWriteIndex[i]->mOffset);
+ headerStream.addOffset(mWriteIndex[i]->mLength);
}
else {
uint32_t offset = (uint32_t)mWriteIndex[i]->mOffset;
headerStream.addU32(offset);
+ offset = (uint32_t)mWriteIndex[i]->mLength;
+ headerStream.addU32(offset);
}
}
@@ -273,26 +382,93 @@
mWriteStream = new OStream(initialStreamSize, false);
}
A3DIndexEntry *indexEntry = new A3DIndexEntry();
- indexEntry->mID.setTo(obj->getName());
+ indexEntry->mObjectName.setTo(obj->getName());
indexEntry->mType = obj->getClassId();
indexEntry->mOffset = mWriteStream->getPos();
- indexEntry->mRsObj = (void*)obj;
+ indexEntry->mRsObj = obj;
mWriteIndex.push(indexEntry);
obj->serialize(mWriteStream);
+ indexEntry->mLength = mWriteStream->getPos() - indexEntry->mOffset;
+ mWriteStream->align(4);
}
namespace android {
namespace renderscript {
+void rsi_FileA3DGetNumIndexEntries(Context *rsc, int32_t *numEntries, RsFile file)
+{
+ FileA3D *fa3d = static_cast<FileA3D *>(file);
+
+ if(fa3d) {
+ *numEntries = fa3d->getNumIndexEntries();
+ }
+ else {
+ *numEntries = 0;
+ }
+}
+
+void rsi_FileA3DGetIndexEntries(Context *rsc, RsFileIndexEntry *fileEntries, uint32_t numEntries, RsFile file)
+{
+ FileA3D *fa3d = static_cast<FileA3D *>(file);
+
+ if(!fa3d) {
+ LOGE("Can't load index entries. No valid file");
+ return;
+ }
+
+ uint32_t numFileEntries = fa3d->getNumIndexEntries();
+ if(numFileEntries != numEntries || numEntries == 0 || fileEntries == NULL) {
+ LOGE("Can't load index entries. Invalid number requested");
+ return;
+ }
+
+ for(uint32_t i = 0; i < numFileEntries; i ++) {
+ const FileA3D::A3DIndexEntry *entry = fa3d->getIndexEntry(i);
+ fileEntries[i].classID = entry->getType();
+ fileEntries[i].objectName = entry->getObjectName().string();
+ }
+
+}
+
+RsObjectBase rsi_FileA3DGetEntryByIndex(Context *rsc, uint32_t index, RsFile file)
+{
+ FileA3D *fa3d = static_cast<FileA3D *>(file);
+ if(!fa3d) {
+ LOGE("Can't load entry. No valid file");
+ return NULL;
+ }
+
+ ObjectBase *obj = fa3d->initializeFromEntry(index);
+ LOGE("Returning object with name %s", obj->getName());
+
+ return obj;
+}
+
+RsFile rsi_FileA3DCreateFromAssetStream(Context *rsc, const void *data, uint32_t len)
+{
+ if (data == NULL) {
+ LOGE("File load failed. Asset stream is NULL");
+ return NULL;
+ }
+
+ FileA3D *fa3d = new FileA3D(rsc);
+
+ fa3d->load(data, len);
+ fa3d->incUserRef();
+
+ return fa3d;
+}
+
RsFile rsi_FileOpen(Context *rsc, char const *path, unsigned int len)
{
- FileA3D *fa3d = new FileA3D;
+ FileA3D *fa3d = new FileA3D(rsc);
FILE *f = fopen("/sdcard/test.a3d", "rb");
if (f) {
- fa3d->load(rsc, f);
+ fa3d->load(f);
fclose(f);
+ fa3d->incUserRef();
return fa3d;
}
delete fa3d;