rsFileA3D.cpp revision a5597fcd411badad50c1345b3eca26453da45bbb
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
26using namespace android;
27using namespace android::renderscript;
28
29
30
31FileA3D::FileA3D()
32{
33    mRsc = NULL;
34}
35
36FileA3D::~FileA3D()
37{
38}
39
40bool 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
106bool 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
136bool 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
214FileA3D::IO::IO(const uint8_t *buf, bool use64)
215{
216    mData = buf;
217    mPos = 0;
218    mUse64 = use64;
219}
220
221uint64_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
233void 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
243void FileA3D::processChunk_Mesh(Context *rsc, IO *io, A3DIndexEntry *ie)
244{
245    Mesh * m = new Mesh;
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
258void 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    uint32_t bits = io->loadU8();
265    p->mType = (RsPrimitive)io->loadU8();
266
267    p->mVerticies = (Mesh::Verticies_t *)mIndex[vertIdx].mRsObj;
268
269    p->mIndicies = new uint16_t[p->mIndexCount];
270    for (uint32_t ct = 0; ct < p->mIndexCount; ct++) {
271        switch(bits) {
272        case 8:
273            p->mIndicies[ct] = io->loadU8();
274            break;
275        case 16:
276            p->mIndicies[ct] = io->loadU16();
277            break;
278        case 32:
279            p->mIndicies[ct] = io->loadU32();
280            break;
281        }
282    }
283
284    ie->mRsObj = p;
285}
286
287void FileA3D::processChunk_Verticies(Context *rsc, IO *io, A3DIndexEntry *ie)
288{
289    Mesh::Verticies_t *cv = new Mesh::Verticies_t;
290    cv->mAllocationCount = io->loadU32();
291    cv->mAllocations = new Allocation *[cv->mAllocationCount];
292    for (uint32_t ct = 0; ct < cv->mAllocationCount; ct++) {
293        uint32_t i = io->loadU32();
294        cv->mAllocations[ct] = (Allocation *)mIndex[i].mRsObj;
295    }
296    ie->mRsObj = cv;
297}
298
299void FileA3D::processChunk_Element(Context *rsc, IO *io, A3DIndexEntry *ie)
300{
301    LOGE("processChunk_Element ie %p", ie);
302    rsi_ElementBegin(rsc);
303
304    uint32_t count = io->loadU32();
305    LOGE("processChunk_Element count %i", count);
306    while (count--) {
307        RsDataKind dk = (RsDataKind)io->loadU8();
308        RsDataType dt = (RsDataType)io->loadU8();
309        uint32_t bits = io->loadU8();
310        bool isNorm = io->loadU8() != 0;
311        LOGE("  %i %i %i %i", dk, dt, bits, isNorm);
312        rsi_ElementAdd(rsc, dk, dt, isNorm, bits);
313    }
314    LOGE("processChunk_Element create");
315    ie->mRsObj = rsi_ElementCreate(rsc);
316}
317
318void FileA3D::processChunk_ElementSource(Context *rsc, IO *io, A3DIndexEntry *ie)
319{
320    uint32_t index = io->loadU32();
321    uint32_t count = io->loadU32();
322
323    RsElement e = (RsElement)mIndex[index].mRsObj;
324
325    RsAllocation a = rsi_AllocationCreateSized(rsc, e, count);
326    Allocation * alloc = static_cast<Allocation *>(a);
327
328    float * data = (float *)alloc->getPtr();
329    while(count--) {
330        *data = io->loadF();
331        data++;
332    }
333    ie->mRsObj = alloc;
334}
335
336namespace android {
337namespace renderscript {
338
339
340RsFile rsi_FileOpen(Context *rsc, char const *path, unsigned int len)
341{
342    FileA3D *fa3d = new FileA3D;
343
344    FILE *f = fopen("/sdcard/test.a3d", "rb");
345    if (f) {
346        fa3d->load(rsc, f);
347        fclose(f);
348        return fa3d;
349    }
350    delete fa3d;
351    return NULL;
352}
353
354
355}
356}
357