Home | History | Annotate | Download | only in rs
      1 
      2 /*
      3  * Copyright (C) 2009 The Android Open Source Project
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 #include "rsContext.h"
     19 
     20 
     21 #include <utils/String8.h>
     22 #include "rsFileA3D.h"
     23 
     24 #include "rsMesh.h"
     25 
     26 using namespace android;
     27 using namespace android::renderscript;
     28 
     29 
     30 
     31 FileA3D::FileA3D()
     32 {
     33     mRsc = NULL;
     34 }
     35 
     36 FileA3D::~FileA3D()
     37 {
     38 }
     39 
     40 bool FileA3D::load(Context *rsc, FILE *f)
     41 {
     42     char magicString[12];
     43     size_t len;
     44 
     45     LOGE("file open 1");
     46     len = fread(magicString, 1, 12, f);
     47     if ((len != 12) ||
     48         memcmp(magicString, "Android3D_ff", 12)) {
     49         return false;
     50     }
     51 
     52     LOGE("file open 2");
     53     len = fread(&mMajorVersion, 1, sizeof(mMajorVersion), f);
     54     if (len != sizeof(mMajorVersion)) {
     55         return false;
     56     }
     57 
     58     LOGE("file open 3");
     59     len = fread(&mMinorVersion, 1, sizeof(mMinorVersion), f);
     60     if (len != sizeof(mMinorVersion)) {
     61         return false;
     62     }
     63 
     64     LOGE("file open 4");
     65     uint32_t flags;
     66     len = fread(&flags, 1, sizeof(flags), f);
     67     if (len != sizeof(flags)) {
     68         return false;
     69     }
     70     mUse64BitOffsets = (flags & 1) != 0;
     71 
     72     LOGE("file open 64bit = %i", mUse64BitOffsets);
     73 
     74     if (mUse64BitOffsets) {
     75         len = fread(&mDataSize, 1, sizeof(mDataSize), f);
     76         if (len != sizeof(mDataSize)) {
     77             return false;
     78         }
     79     } else {
     80         uint32_t tmp;
     81         len = fread(&tmp, 1, sizeof(tmp), f);
     82         if (len != sizeof(tmp)) {
     83             return false;
     84         }
     85         mDataSize = tmp;
     86     }
     87 
     88     LOGE("file open size = %lli", mDataSize);
     89 
     90     // We should know enough to read the file in at this point.
     91     fseek(f, SEEK_SET, 0);
     92     mAlloc= malloc(mDataSize);
     93     if (!mAlloc) {
     94         return false;
     95     }
     96     mData = (uint8_t *)mAlloc;
     97     len = fread(mAlloc, 1, mDataSize, f);
     98     if (len != mDataSize) {
     99         return false;
    100     }
    101 
    102     LOGE("file start processing");
    103     return process(rsc);
    104 }
    105 
    106 bool FileA3D::processIndex(Context *rsc, A3DIndexEntry *ie)
    107 {
    108     bool ret = false;
    109     IO io(mData + ie->mOffset, mUse64BitOffsets);
    110 
    111     LOGE("process index, type %i", ie->mType);
    112 
    113     switch(ie->mType) {
    114     case CHUNK_ELEMENT:
    115         processChunk_Element(rsc, &io, ie);
    116         break;
    117     case CHUNK_ELEMENT_SOURCE:
    118         processChunk_ElementSource(rsc, &io, ie);
    119         break;
    120     case CHUNK_VERTICIES:
    121         processChunk_Verticies(rsc, &io, ie);
    122         break;
    123     case CHUNK_MESH:
    124         processChunk_Mesh(rsc, &io, ie);
    125         break;
    126     case CHUNK_PRIMITIVE:
    127         processChunk_Primitive(rsc, &io, ie);
    128         break;
    129     default:
    130         LOGE("FileA3D Unknown chunk type");
    131         break;
    132     }
    133     return (ie->mRsObj != NULL);
    134 }
    135 
    136 bool FileA3D::process(Context *rsc)
    137 {
    138     LOGE("process");
    139     IO io(mData + 12, mUse64BitOffsets);
    140     bool ret = true;
    141 
    142     // Build the index first
    143     LOGE("process 1");
    144     io.loadU32(); // major version, already loaded
    145     io.loadU32(); // minor version, already loaded
    146     LOGE("process 2");
    147 
    148     io.loadU32();  // flags
    149     io.loadOffset(); // filesize, already loaded.
    150     LOGE("process 4");
    151     uint64_t mIndexOffset = io.loadOffset();
    152     uint64_t mStringOffset = io.loadOffset();
    153 
    154     LOGE("process mIndexOffset= 0x%016llx", mIndexOffset);
    155     LOGE("process mStringOffset= 0x%016llx", mStringOffset);
    156 
    157     IO index(mData + mIndexOffset, mUse64BitOffsets);
    158     IO stringTable(mData + mStringOffset, mUse64BitOffsets);
    159 
    160     uint32_t stringEntryCount = stringTable.loadU32();
    161     LOGE("stringEntryCount %i", stringEntryCount);
    162     mStrings.setCapacity(stringEntryCount);
    163     mStringIndexValues.setCapacity(stringEntryCount);
    164     if (stringEntryCount) {
    165         uint32_t stringType = stringTable.loadU32();
    166         LOGE("stringType %i", stringType);
    167         rsAssert(stringType==0);
    168         for (uint32_t ct = 0; ct < stringEntryCount; ct++) {
    169             uint64_t offset = stringTable.loadOffset();
    170             LOGE("string offset 0x%016llx", offset);
    171             IO tmp(mData + offset, mUse64BitOffsets);
    172             String8 s;
    173             tmp.loadString(&s);
    174             LOGE("string %s", s.string());
    175             mStrings.push(s);
    176         }
    177     }
    178 
    179     LOGE("strings done");
    180     uint32_t indexEntryCount = index.loadU32();
    181     LOGE("index count %i", indexEntryCount);
    182     mIndex.setCapacity(indexEntryCount);
    183     for (uint32_t ct = 0; ct < indexEntryCount; ct++) {
    184         A3DIndexEntry e;
    185         uint32_t stringIndex = index.loadU32();
    186         LOGE("index %i", ct);
    187         LOGE("  string index %i", stringIndex);
    188         e.mType = (A3DChunkType)index.loadU32();
    189         LOGE("  type %i", e.mType);
    190         e.mOffset = index.loadOffset();
    191         LOGE("  offset 0x%016llx", e.mOffset);
    192 
    193         if (stringIndex && (stringIndex < mStrings.size())) {
    194             e.mID = mStrings[stringIndex];
    195             mStringIndexValues.editItemAt(stringIndex) = ct;
    196             LOGE("  id %s", e.mID.string());
    197         }
    198 
    199         mIndex.push(e);
    200     }
    201     LOGE("index done");
    202 
    203     // At this point the index should be fully populated.
    204     // We can now walk though it and load all the objects.
    205     for (uint32_t ct = 0; ct < indexEntryCount; ct++) {
    206         LOGE("processing index entry %i", ct);
    207         processIndex(rsc, &mIndex.editItemAt(ct));
    208     }
    209 
    210     return ret;
    211 }
    212 
    213 
    214 FileA3D::IO::IO(const uint8_t *buf, bool use64)
    215 {
    216     mData = buf;
    217     mPos = 0;
    218     mUse64 = use64;
    219 }
    220 
    221 uint64_t FileA3D::IO::loadOffset()
    222 {
    223     uint64_t tmp;
    224     if (mUse64) {
    225         mPos = (mPos + 7) & (~7);
    226         tmp = reinterpret_cast<const uint64_t *>(&mData[mPos])[0];
    227         mPos += sizeof(uint64_t);
    228         return tmp;
    229     }
    230     return loadU32();
    231 }
    232 
    233 void FileA3D::IO::loadString(String8 *s)
    234 {
    235     LOGE("loadString");
    236     uint32_t len = loadU32();
    237     LOGE("loadString len %i", len);
    238     s->setTo((const char *)&mData[mPos], len);
    239     mPos += len;
    240 }
    241 
    242 
    243 void FileA3D::processChunk_Mesh(Context *rsc, IO *io, A3DIndexEntry *ie)
    244 {
    245     Mesh * m = new Mesh(rsc);
    246 
    247     m->mPrimitivesCount = io->loadU32();
    248     m->mPrimitives = new Mesh::Primitive_t *[m->mPrimitivesCount];
    249 
    250     for (uint32_t ct = 0; ct < m->mPrimitivesCount; ct++) {
    251         uint32_t index = io->loadU32();
    252 
    253         m->mPrimitives[ct] = (Mesh::Primitive_t *)mIndex[index].mRsObj;
    254     }
    255     ie->mRsObj = m;
    256 }
    257 
    258 void FileA3D::processChunk_Primitive(Context *rsc, IO *io, A3DIndexEntry *ie)
    259 {
    260     Mesh::Primitive_t * p = new Mesh::Primitive_t;
    261 
    262     p->mIndexCount = io->loadU32();
    263     uint32_t vertIdx = io->loadU32();
    264     p->mRestartCounts = io->loadU16();
    265     uint32_t bits = io->loadU8();
    266     p->mType = (RsPrimitive)io->loadU8();
    267 
    268     LOGE("processChunk_Primitive count %i, bits %i", p->mIndexCount, bits);
    269 
    270     p->mVerticies = (Mesh::Verticies_t *)mIndex[vertIdx].mRsObj;
    271 
    272     p->mIndicies = new uint16_t[p->mIndexCount];
    273     for (uint32_t ct = 0; ct < p->mIndexCount; ct++) {
    274         switch(bits) {
    275         case 8:
    276             p->mIndicies[ct] = io->loadU8();
    277             break;
    278         case 16:
    279             p->mIndicies[ct] = io->loadU16();
    280             break;
    281         case 32:
    282             p->mIndicies[ct] = io->loadU32();
    283             break;
    284         }
    285         LOGE("  idx %i", p->mIndicies[ct]);
    286     }
    287 
    288     if (p->mRestartCounts) {
    289         p->mRestarts = new uint16_t[p->mRestartCounts];
    290         for (uint32_t ct = 0; ct < p->mRestartCounts; ct++) {
    291             switch(bits) {
    292             case 8:
    293                 p->mRestarts[ct] = io->loadU8();
    294                 break;
    295             case 16:
    296                 p->mRestarts[ct] = io->loadU16();
    297                 break;
    298             case 32:
    299                 p->mRestarts[ct] = io->loadU32();
    300                 break;
    301             }
    302             LOGE("  idx %i", p->mRestarts[ct]);
    303         }
    304     } else {
    305         p->mRestarts = NULL;
    306     }
    307 
    308     ie->mRsObj = p;
    309 }
    310 
    311 void FileA3D::processChunk_Verticies(Context *rsc, IO *io, A3DIndexEntry *ie)
    312 {
    313     Mesh::Verticies_t *cv = new Mesh::Verticies_t;
    314     cv->mAllocationCount = io->loadU32();
    315     cv->mAllocations = new Allocation *[cv->mAllocationCount];
    316     LOGE("processChunk_Verticies count %i", cv->mAllocationCount);
    317     for (uint32_t ct = 0; ct < cv->mAllocationCount; ct++) {
    318         uint32_t i = io->loadU32();
    319         cv->mAllocations[ct] = (Allocation *)mIndex[i].mRsObj;
    320         LOGE("  idx %i", i);
    321     }
    322     ie->mRsObj = cv;
    323 }
    324 
    325 void FileA3D::processChunk_Element(Context *rsc, IO *io, A3DIndexEntry *ie)
    326 {
    327     /*
    328     rsi_ElementBegin(rsc);
    329 
    330     uint32_t count = io->loadU32();
    331     LOGE("processChunk_Element count %i", count);
    332     while (count--) {
    333         RsDataKind dk = (RsDataKind)io->loadU8();
    334         RsDataType dt = (RsDataType)io->loadU8();
    335         uint32_t bits = io->loadU8();
    336         bool isNorm = io->loadU8() != 0;
    337         LOGE("  %i %i %i %i", dk, dt, bits, isNorm);
    338         rsi_ElementAdd(rsc, dk, dt, isNorm, bits, 0);
    339     }
    340     LOGE("processChunk_Element create");
    341     ie->mRsObj = rsi_ElementCreate(rsc);
    342     */
    343 }
    344 
    345 void FileA3D::processChunk_ElementSource(Context *rsc, IO *io, A3DIndexEntry *ie)
    346 {
    347     uint32_t index = io->loadU32();
    348     uint32_t count = io->loadU32();
    349 
    350     LOGE("processChunk_ElementSource count %i, index %i", count, index);
    351 
    352     RsElement e = (RsElement)mIndex[index].mRsObj;
    353 
    354     RsAllocation a = rsi_AllocationCreateSized(rsc, e, count);
    355     Allocation * alloc = static_cast<Allocation *>(a);
    356 
    357     float * data = (float *)alloc->getPtr();
    358     while(count--) {
    359         *data = io->loadF();
    360         LOGE("  %f", *data);
    361         data++;
    362     }
    363     ie->mRsObj = alloc;
    364 }
    365 
    366 namespace android {
    367 namespace renderscript {
    368 
    369 
    370 RsFile rsi_FileOpen(Context *rsc, char const *path, unsigned int len)
    371 {
    372     FileA3D *fa3d = new FileA3D;
    373 
    374     FILE *f = fopen("/sdcard/test.a3d", "rb");
    375     if (f) {
    376         fa3d->load(rsc, f);
    377         fclose(f);
    378         return fa3d;
    379     }
    380     delete fa3d;
    381     return NULL;
    382 }
    383 
    384 
    385 }
    386 }
    387