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(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 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 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 311void 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 325void 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 343void 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 364namespace android { 365namespace renderscript { 366 367 368RsFile 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