• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
FileA3D()31 FileA3D::FileA3D()
32 {
33     mRsc = NULL;
34 }
35 
~FileA3D()36 FileA3D::~FileA3D()
37 {
38 }
39 
load(Context * rsc,FILE * f)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 
processIndex(Context * rsc,A3DIndexEntry * ie)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 
process(Context * rsc)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 
IO(const uint8_t * buf,bool use64)214 FileA3D::IO::IO(const uint8_t *buf, bool use64)
215 {
216     mData = buf;
217     mPos = 0;
218     mUse64 = use64;
219 }
220 
loadOffset()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 
loadString(String8 * s)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 
processChunk_Mesh(Context * rsc,IO * io,A3DIndexEntry * ie)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 
processChunk_Primitive(Context * rsc,IO * io,A3DIndexEntry * ie)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 
processChunk_Verticies(Context * rsc,IO * io,A3DIndexEntry * ie)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 
processChunk_Element(Context * rsc,IO * io,A3DIndexEntry * ie)325 void FileA3D::processChunk_Element(Context *rsc, IO *io, A3DIndexEntry *ie)
326 {
327     rsi_ElementBegin(rsc);
328 
329     uint32_t count = io->loadU32();
330     LOGE("processChunk_Element count %i", count);
331     while (count--) {
332         RsDataKind dk = (RsDataKind)io->loadU8();
333         RsDataType dt = (RsDataType)io->loadU8();
334         uint32_t bits = io->loadU8();
335         bool isNorm = io->loadU8() != 0;
336         LOGE("  %i %i %i %i", dk, dt, bits, isNorm);
337         rsi_ElementAdd(rsc, dk, dt, isNorm, bits, 0);
338     }
339     LOGE("processChunk_Element create");
340     ie->mRsObj = rsi_ElementCreate(rsc);
341 }
342 
processChunk_ElementSource(Context * rsc,IO * io,A3DIndexEntry * ie)343 void FileA3D::processChunk_ElementSource(Context *rsc, IO *io, A3DIndexEntry *ie)
344 {
345     uint32_t index = io->loadU32();
346     uint32_t count = io->loadU32();
347 
348     LOGE("processChunk_ElementSource count %i, index %i", count, index);
349 
350     RsElement e = (RsElement)mIndex[index].mRsObj;
351 
352     RsAllocation a = rsi_AllocationCreateSized(rsc, e, count);
353     Allocation * alloc = static_cast<Allocation *>(a);
354 
355     float * data = (float *)alloc->getPtr();
356     while(count--) {
357         *data = io->loadF();
358         LOGE("  %f", *data);
359         data++;
360     }
361     ie->mRsObj = alloc;
362 }
363 
364 namespace android {
365 namespace renderscript {
366 
367 
rsi_FileOpen(Context * rsc,char const * path,unsigned int len)368 RsFile rsi_FileOpen(Context *rsc, char const *path, unsigned int len)
369 {
370     FileA3D *fa3d = new FileA3D;
371 
372     FILE *f = fopen("/sdcard/test.a3d", "rb");
373     if (f) {
374         fa3d->load(rsc, f);
375         fclose(f);
376         return fa3d;
377     }
378     delete fa3d;
379     return NULL;
380 }
381 
382 
383 }
384 }
385