rsFileA3D.cpp revision fb6b614bcea88a587a7ea4530be45ff0ffa0210e
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#ifndef ANDROID_RS_BUILD_FOR_HOST
19#include "rsContext.h"
20#else
21#include "rsContextHostStub.h"
22#endif
23
24#include "rsFileA3D.h"
25
26#include "rsMesh.h"
27#include "rsAnimation.h"
28
29using namespace android;
30using namespace android::renderscript;
31
32
33
34FileA3D::FileA3D()
35{
36    mRsc = NULL;
37    mAlloc = NULL;
38    mData = NULL;
39    mWriteStream = NULL;
40    mReadStream = NULL;
41
42    mMajorVersion = 0;
43    mMinorVersion = 1;
44    mDataSize = 0;
45}
46
47FileA3D::~FileA3D()
48{
49    for(size_t i = 0; i < mIndex.size(); i ++) {
50        delete mIndex[i];
51    }
52    for(size_t i = 0; i < mWriteIndex.size(); i ++) {
53        delete mWriteIndex[i];
54    }
55    if(mWriteStream) {
56        delete mWriteStream;
57    }
58    if(mReadStream) {
59        delete mWriteStream;
60    }
61    if(mAlloc) {
62        free(mAlloc);
63    }
64}
65
66bool FileA3D::load(Context *rsc, FILE *f)
67{
68    char magicString[12];
69    size_t len;
70
71    LOGE("file open 1");
72    len = fread(magicString, 1, 12, f);
73    if ((len != 12) ||
74        memcmp(magicString, "Android3D_ff", 12)) {
75        return false;
76    }
77
78    // Next thing is the size of the header
79    uint64_t headerSize = 0;
80    len = fread(&headerSize, 1, sizeof(headerSize), f);
81    if (len != sizeof(headerSize) || headerSize == 0) {
82        return false;
83    }
84
85    uint8_t *headerData = (uint8_t *)malloc(headerSize);
86    if(!headerData) {
87        return false;
88    }
89
90    len = fread(headerData, 1, headerSize, f);
91    if (len != headerSize) {
92        return false;
93    }
94
95    // Now open the stream to parse the header
96    IStream headerStream(headerData, false);
97
98    mMajorVersion = headerStream.loadU32();
99    mMinorVersion = headerStream.loadU32();
100    uint32_t flags = headerStream.loadU32();
101    mUse64BitOffsets = (flags & 1) != 0;
102
103    LOGE("file open 64bit = %i", mUse64BitOffsets);
104
105    uint32_t numIndexEntries = headerStream.loadU32();
106    for(uint32_t i = 0; i < numIndexEntries; i ++) {
107        A3DIndexEntry *entry = new A3DIndexEntry();
108        headerStream.loadString(&entry->mID);
109        entry->mType = (A3DClassID)headerStream.loadU32();
110        if(mUse64BitOffsets){
111            entry->mOffset = headerStream.loadOffset();
112        }
113        else {
114            entry->mOffset = headerStream.loadU32();
115        }
116        entry->mRsObj = NULL;
117        mIndex.push(entry);
118    }
119
120    // Next thing is the size of the header
121    len = fread(&mDataSize, 1, sizeof(mDataSize), f);
122    if (len != sizeof(mDataSize) || mDataSize == 0) {
123        return false;
124    }
125
126    LOGE("file open size = %lli", mDataSize);
127
128    // We should know enough to read the file in at this point.
129    mAlloc = malloc(mDataSize);
130    if (!mAlloc) {
131        return false;
132    }
133    mData = (uint8_t *)mAlloc;
134    len = fread(mAlloc, 1, mDataSize, f);
135    if (len != mDataSize) {
136        return false;
137    }
138
139    mReadStream = new IStream(mData, mUse64BitOffsets);
140
141    mRsc = rsc;
142
143    LOGE("Header is read an stream initialized");
144    return true;
145}
146
147size_t FileA3D::getNumLoadedEntries() const {
148    return mIndex.size();
149}
150
151const FileA3D::A3DIndexEntry *FileA3D::getLoadedEntry(size_t index) const {
152    if(index < mIndex.size()) {
153        return mIndex[index];
154    }
155    return NULL;
156}
157
158ObjectBase *FileA3D::initializeFromEntry(const FileA3D::A3DIndexEntry *entry) {
159    if(!entry) {
160        return NULL;
161    }
162
163    // Seek to the beginning of object
164    mReadStream->reset(entry->mOffset);
165    switch (entry->mType) {
166        case A3D_CLASS_ID_UNKNOWN:
167            return NULL;
168        case A3D_CLASS_ID_MESH:
169            return Mesh::createFromStream(mRsc, mReadStream);
170        case A3D_CLASS_ID_SIMPLE_MESH:
171            return SimpleMesh::createFromStream(mRsc, mReadStream);
172        case A3D_CLASS_ID_TYPE:
173            return Type::createFromStream(mRsc, mReadStream);
174        case A3D_CLASS_ID_ELEMENT:
175            return Element::createFromStream(mRsc, mReadStream);
176        case A3D_CLASS_ID_ALLOCATION:
177            return Allocation::createFromStream(mRsc, mReadStream);
178        case A3D_CLASS_ID_PROGRAM_VERTEX:
179            return ProgramVertex::createFromStream(mRsc, mReadStream);
180        case A3D_CLASS_ID_PROGRAM_RASTER:
181            return ProgramRaster::createFromStream(mRsc, mReadStream);
182        case A3D_CLASS_ID_PROGRAM_FRAGMENT:
183            return ProgramFragment::createFromStream(mRsc, mReadStream);
184        case A3D_CLASS_ID_PROGRAM_STORE:
185            return ProgramStore::createFromStream(mRsc, mReadStream);
186        case A3D_CLASS_ID_SAMPLER:
187            return Sampler::createFromStream(mRsc, mReadStream);
188        case A3D_CLASS_ID_ANIMATION:
189            return Animation::createFromStream(mRsc, mReadStream);
190        case A3D_CLASS_ID_LIGHT:
191            return Light::createFromStream(mRsc, mReadStream);
192        case A3D_CLASS_ID_ADAPTER_1D:
193            return Adapter1D::createFromStream(mRsc, mReadStream);
194        case A3D_CLASS_ID_ADAPTER_2D:
195            return Adapter2D::createFromStream(mRsc, mReadStream);
196        case A3D_CLASS_ID_SCRIPT_C:
197            return NULL;
198    }
199    return NULL;
200}
201
202bool FileA3D::writeFile(const char *filename)
203{
204    if(!mWriteStream) {
205        LOGE("No objects to write\n");
206        return false;
207    }
208    if(mWriteStream->getPos() == 0) {
209        LOGE("No objects to write\n");
210        return false;
211    }
212
213    FILE *writeHandle = fopen(filename, "wb");
214    if(!writeHandle) {
215        LOGE("Couldn't open the file for writing\n");
216        return false;
217    }
218
219    // Open a new stream to make writing the header easier
220    OStream headerStream(5*1024, false);
221    headerStream.addU32(mMajorVersion);
222    headerStream.addU32(mMinorVersion);
223    uint32_t is64Bit = 0;
224    headerStream.addU32(is64Bit);
225
226    uint32_t writeIndexSize = mWriteIndex.size();
227    headerStream.addU32(writeIndexSize);
228    for(uint32_t i = 0; i < writeIndexSize; i ++) {
229        headerStream.addString(&mWriteIndex[i]->mID);
230        headerStream.addU32((uint32_t)mWriteIndex[i]->mType);
231        if(mUse64BitOffsets){
232            headerStream.addOffset(mWriteIndex[i]->mOffset);
233        }
234        else {
235            uint32_t offset = (uint32_t)mWriteIndex[i]->mOffset;
236            headerStream.addU32(offset);
237        }
238    }
239
240    // Write our magic string so we know we are reading the right file
241    String8 magicString(A3D_MAGIC_KEY);
242    fwrite(magicString.string(), sizeof(char), magicString.size(), writeHandle);
243
244    // Store the size of the header to make it easier to parse when we read it
245    uint64_t headerSize = headerStream.getPos();
246    fwrite(&headerSize, sizeof(headerSize), 1, writeHandle);
247
248    // Now write our header
249    fwrite(headerStream.getPtr(), sizeof(uint8_t), headerStream.getPos(), writeHandle);
250
251    // Now write the size of the data part of the file for easier parsing later
252    uint64_t fileDataSize = mWriteStream->getPos();
253    fwrite(&fileDataSize, sizeof(fileDataSize), 1, writeHandle);
254
255    fwrite(mWriteStream->getPtr(), sizeof(uint8_t), mWriteStream->getPos(), writeHandle);
256
257    int status = fclose(writeHandle);
258
259    if(status != 0) {
260        LOGE("Couldn't close file\n");
261        return false;
262    }
263
264    return true;
265}
266
267void FileA3D::appendToFile(ObjectBase *obj) {
268    if(!obj) {
269        return;
270    }
271    if(!mWriteStream) {
272        const uint64_t initialStreamSize = 256*1024;
273        mWriteStream = new OStream(initialStreamSize, false);
274    }
275    A3DIndexEntry *indexEntry = new A3DIndexEntry();
276    indexEntry->mID.setTo(obj->getName());
277    indexEntry->mType = obj->getClassId();
278    indexEntry->mOffset = mWriteStream->getPos();
279    indexEntry->mRsObj = (void*)obj;
280    mWriteIndex.push(indexEntry);
281    obj->serialize(mWriteStream);
282}
283
284namespace android {
285namespace renderscript {
286
287
288RsFile rsi_FileOpen(Context *rsc, char const *path, unsigned int len)
289{
290    FileA3D *fa3d = new FileA3D;
291
292    FILE *f = fopen("/sdcard/test.a3d", "rb");
293    if (f) {
294        fa3d->load(rsc, f);
295        fclose(f);
296        return fa3d;
297    }
298    delete fa3d;
299    return NULL;
300}
301
302
303}
304}
305