rsFileA3D.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. /*
  2. * Copyright (C) 2009 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "rsContext.h"
  17. #include "rsFileA3D.h"
  18. #include "rsMesh.h"
  19. #include "rsAnimation.h"
  20. #include "rs.h"
  21. #include <inttypes.h>
  22. namespace android {
  23. namespace renderscript {
  24. FileA3D::FileA3D(Context *rsc) : ObjectBase(rsc) {
  25. mAlloc = nullptr;
  26. mData = nullptr;
  27. mWriteStream = nullptr;
  28. mReadStream = nullptr;
  29. mMajorVersion = 0;
  30. mMinorVersion = 1;
  31. mDataSize = 0;
  32. }
  33. FileA3D::~FileA3D() {
  34. for (size_t i = 0; i < mIndex.size(); i ++) {
  35. delete mIndex[i];
  36. }
  37. for (size_t i = 0; i < mWriteIndex.size(); i ++) {
  38. delete mWriteIndex[i];
  39. }
  40. if (mWriteStream) {
  41. delete mWriteStream;
  42. }
  43. if (mReadStream) {
  44. delete mReadStream;
  45. }
  46. if (mAlloc) {
  47. free(mAlloc);
  48. }
  49. }
  50. void FileA3D::parseHeader(IStream *headerStream) {
  51. mMajorVersion = headerStream->loadU32();
  52. mMinorVersion = headerStream->loadU32();
  53. uint32_t flags = headerStream->loadU32();
  54. mUse64BitOffsets = (flags & 1) != 0;
  55. uint32_t numIndexEntries = headerStream->loadU32();
  56. for (uint32_t i = 0; i < numIndexEntries; i ++) {
  57. A3DIndexEntry *entry = new A3DIndexEntry();
  58. entry->mObjectName = headerStream->loadString();
  59. //ALOGV("Header data, entry name = %s", entry->mObjectName.string());
  60. entry->mType = (RsA3DClassID)headerStream->loadU32();
  61. if (mUse64BitOffsets){
  62. entry->mOffset = headerStream->loadOffset();
  63. entry->mLength = headerStream->loadOffset();
  64. } else {
  65. entry->mOffset = headerStream->loadU32();
  66. entry->mLength = headerStream->loadU32();
  67. }
  68. entry->mRsObj = nullptr;
  69. mIndex.push_back(entry);
  70. }
  71. }
  72. bool FileA3D::load(Asset *asset) {
  73. return false;
  74. }
  75. bool FileA3D::load(const void *data, size_t length) {
  76. const uint8_t *localData = (const uint8_t *)data;
  77. size_t lengthRemaining = length;
  78. size_t magicStrLen = 12;
  79. if ((length < magicStrLen) ||
  80. memcmp(data, "Android3D_ff", magicStrLen)) {
  81. return false;
  82. }
  83. localData += magicStrLen;
  84. lengthRemaining -= magicStrLen;
  85. // Next we get our header size
  86. uint64_t headerSize = 0;
  87. if (lengthRemaining < sizeof(headerSize)) {
  88. return false;
  89. }
  90. memcpy(&headerSize, localData, sizeof(headerSize));
  91. localData += sizeof(headerSize);
  92. lengthRemaining -= sizeof(headerSize);
  93. if (lengthRemaining < headerSize) {
  94. return false;
  95. }
  96. // Now open the stream to parse the header
  97. IStream headerStream(localData, false);
  98. parseHeader(&headerStream);
  99. localData += headerSize;
  100. lengthRemaining -= headerSize;
  101. if (lengthRemaining < sizeof(mDataSize)) {
  102. return false;
  103. }
  104. // Read the size of the data
  105. memcpy(&mDataSize, localData, sizeof(mDataSize));
  106. localData += sizeof(mDataSize);
  107. lengthRemaining -= sizeof(mDataSize);
  108. if (lengthRemaining < mDataSize) {
  109. return false;
  110. }
  111. // We should know enough to read the file in at this point.
  112. mData = (uint8_t *)localData;
  113. mReadStream = new IStream(mData, mUse64BitOffsets);
  114. return true;
  115. }
  116. bool FileA3D::load(FILE *f) {
  117. char magicString[12];
  118. size_t len;
  119. ALOGV("file open 1");
  120. len = fread(magicString, 1, 12, f);
  121. if ((len != 12) ||
  122. memcmp(magicString, "Android3D_ff", 12)) {
  123. return false;
  124. }
  125. // Next thing is the size of the header
  126. uint64_t headerSize = 0;
  127. len = fread(&headerSize, 1, sizeof(headerSize), f);
  128. if (len != sizeof(headerSize) || headerSize == 0) {
  129. return false;
  130. }
  131. uint8_t *headerData = (uint8_t *)malloc(headerSize);
  132. if (!headerData) {
  133. return false;
  134. }
  135. len = fread(headerData, 1, headerSize, f);
  136. if (len != headerSize) {
  137. free(headerData);
  138. return false;
  139. }
  140. // Now open the stream to parse the header
  141. IStream headerStream(headerData, false);
  142. parseHeader(&headerStream);
  143. free(headerData);
  144. // Next thing is the size of the header
  145. len = fread(&mDataSize, 1, sizeof(mDataSize), f);
  146. if (len != sizeof(mDataSize) || mDataSize == 0) {
  147. return false;
  148. }
  149. ALOGV("file open size = %" PRIi64, mDataSize);
  150. // We should know enough to read the file in at this point.
  151. mAlloc = malloc(mDataSize);
  152. if (!mAlloc) {
  153. return false;
  154. }
  155. mData = (uint8_t *)mAlloc;
  156. len = fread(mAlloc, 1, mDataSize, f);
  157. if (len != mDataSize) {
  158. return false;
  159. }
  160. mReadStream = new IStream(mData, mUse64BitOffsets);
  161. ALOGV("Header is read an stream initialized");
  162. return true;
  163. }
  164. size_t FileA3D::getNumIndexEntries() const {
  165. return mIndex.size();
  166. }
  167. FileA3D::A3DIndexEntry::~A3DIndexEntry() {
  168. delete[] mObjectName;
  169. }
  170. const FileA3D::A3DIndexEntry *FileA3D::getIndexEntry(size_t index) const {
  171. if (index < mIndex.size()) {
  172. return mIndex[index];
  173. }
  174. return nullptr;
  175. }
  176. ObjectBase *FileA3D::initializeFromEntry(size_t index) {
  177. if (index >= mIndex.size()) {
  178. return nullptr;
  179. }
  180. FileA3D::A3DIndexEntry *entry = mIndex[index];
  181. if (!entry) {
  182. return nullptr;
  183. }
  184. if (entry->mRsObj) {
  185. entry->mRsObj->incUserRef();
  186. return entry->mRsObj;
  187. }
  188. // Seek to the beginning of object
  189. mReadStream->reset(entry->mOffset);
  190. switch (entry->mType) {
  191. case RS_A3D_CLASS_ID_UNKNOWN:
  192. return nullptr;
  193. case RS_A3D_CLASS_ID_MESH:
  194. entry->mRsObj = Mesh::createFromStream(mRSC, mReadStream);
  195. break;
  196. case RS_A3D_CLASS_ID_TYPE:
  197. entry->mRsObj = Type::createFromStream(mRSC, mReadStream);
  198. break;
  199. case RS_A3D_CLASS_ID_ELEMENT:
  200. entry->mRsObj = Element::createFromStream(mRSC, mReadStream);
  201. break;
  202. case RS_A3D_CLASS_ID_ALLOCATION:
  203. entry->mRsObj = Allocation::createFromStream(mRSC, mReadStream);
  204. break;
  205. case RS_A3D_CLASS_ID_PROGRAM_VERTEX:
  206. //entry->mRsObj = ProgramVertex::createFromStream(mRSC, mReadStream);
  207. break;
  208. case RS_A3D_CLASS_ID_PROGRAM_RASTER:
  209. //entry->mRsObj = ProgramRaster::createFromStream(mRSC, mReadStream);
  210. break;
  211. case RS_A3D_CLASS_ID_PROGRAM_FRAGMENT:
  212. //entry->mRsObj = ProgramFragment::createFromStream(mRSC, mReadStream);
  213. break;
  214. case RS_A3D_CLASS_ID_PROGRAM_STORE:
  215. //entry->mRsObj = ProgramStore::createFromStream(mRSC, mReadStream);
  216. break;
  217. case RS_A3D_CLASS_ID_SAMPLER:
  218. //entry->mRsObj = Sampler::createFromStream(mRSC, mReadStream);
  219. break;
  220. case RS_A3D_CLASS_ID_ANIMATION:
  221. //entry->mRsObj = Animation::createFromStream(mRSC, mReadStream);
  222. break;
  223. case RS_A3D_CLASS_ID_ADAPTER_1D:
  224. //entry->mRsObj = Adapter1D::createFromStream(mRSC, mReadStream);
  225. break;
  226. case RS_A3D_CLASS_ID_ADAPTER_2D:
  227. //entry->mRsObj = Adapter2D::createFromStream(mRSC, mReadStream);
  228. break;
  229. case RS_A3D_CLASS_ID_SCRIPT_C:
  230. break;
  231. case RS_A3D_CLASS_ID_SCRIPT_KERNEL_ID:
  232. break;
  233. case RS_A3D_CLASS_ID_SCRIPT_INVOKE_ID:
  234. break;
  235. case RS_A3D_CLASS_ID_SCRIPT_FIELD_ID:
  236. break;
  237. case RS_A3D_CLASS_ID_SCRIPT_METHOD_ID:
  238. break;
  239. case RS_A3D_CLASS_ID_SCRIPT_GROUP:
  240. break;
  241. case RS_A3D_CLASS_ID_CLOSURE:
  242. break;
  243. case RS_A3D_CLASS_ID_SCRIPT_GROUP2:
  244. break;
  245. }
  246. if (entry->mRsObj) {
  247. entry->mRsObj->incUserRef();
  248. }
  249. return entry->mRsObj;
  250. }
  251. bool FileA3D::writeFile(const char *filename) {
  252. if (!mWriteStream) {
  253. ALOGE("No objects to write\n");
  254. return false;
  255. }
  256. if (mWriteStream->getPos() == 0) {
  257. ALOGE("No objects to write\n");
  258. return false;
  259. }
  260. FILE *writeHandle = fopen(filename, "wbe");
  261. if (!writeHandle) {
  262. ALOGE("Couldn't open the file for writing\n");
  263. return false;
  264. }
  265. // Open a new stream to make writing the header easier
  266. OStream headerStream(5*1024, false);
  267. headerStream.addU32(mMajorVersion);
  268. headerStream.addU32(mMinorVersion);
  269. uint32_t is64Bit = 0;
  270. headerStream.addU32(is64Bit);
  271. uint32_t writeIndexSize = mWriteIndex.size();
  272. headerStream.addU32(writeIndexSize);
  273. for (uint32_t i = 0; i < writeIndexSize; i ++) {
  274. headerStream.addString(mWriteIndex[i]->mObjectName);
  275. headerStream.addU32((uint32_t)mWriteIndex[i]->mType);
  276. if (mUse64BitOffsets){
  277. headerStream.addOffset(mWriteIndex[i]->mOffset);
  278. headerStream.addOffset(mWriteIndex[i]->mLength);
  279. } else {
  280. uint32_t offset = (uint32_t)mWriteIndex[i]->mOffset;
  281. headerStream.addU32(offset);
  282. offset = (uint32_t)mWriteIndex[i]->mLength;
  283. headerStream.addU32(offset);
  284. }
  285. }
  286. // Write our magic string so we know we are reading the right file
  287. fwrite(A3D_MAGIC_KEY, sizeof(char), strlen(A3D_MAGIC_KEY), writeHandle);
  288. // Store the size of the header to make it easier to parse when we read it
  289. uint64_t headerSize = headerStream.getPos();
  290. fwrite(&headerSize, sizeof(headerSize), 1, writeHandle);
  291. // Now write our header
  292. fwrite(headerStream.getPtr(), sizeof(uint8_t), headerStream.getPos(), writeHandle);
  293. // Now write the size of the data part of the file for easier parsing later
  294. uint64_t fileDataSize = mWriteStream->getPos();
  295. fwrite(&fileDataSize, sizeof(fileDataSize), 1, writeHandle);
  296. fwrite(mWriteStream->getPtr(), sizeof(uint8_t), mWriteStream->getPos(), writeHandle);
  297. int status = fclose(writeHandle);
  298. if (status != 0) {
  299. ALOGE("Couldn't close file\n");
  300. return false;
  301. }
  302. return true;
  303. }
  304. void FileA3D::appendToFile(Context *con, ObjectBase *obj) {
  305. if (!obj) {
  306. return;
  307. }
  308. if (!mWriteStream) {
  309. const uint64_t initialStreamSize = 256*1024;
  310. mWriteStream = new OStream(initialStreamSize, false);
  311. }
  312. A3DIndexEntry *indexEntry = new A3DIndexEntry();
  313. indexEntry->mObjectName = rsuCopyString(obj->getName());
  314. indexEntry->mType = obj->getClassId();
  315. indexEntry->mOffset = mWriteStream->getPos();
  316. indexEntry->mRsObj = obj;
  317. mWriteIndex.push_back(indexEntry);
  318. obj->serialize(con, mWriteStream);
  319. indexEntry->mLength = mWriteStream->getPos() - indexEntry->mOffset;
  320. mWriteStream->align(4);
  321. }
  322. } // namespace renderscript
  323. } // namespace android