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