RSInfo.cpp revision 688e4c0dd73c273551f517fa85a08b40dd63eacc
1326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams/*
2a04e30dbb5ab11592b03666bb3d102070759c58eAlex Sakhartchouk * Copyright 2012, The Android Open Source Project
3326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams *
4326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * Licensed under the Apache License, Version 2.0 (the "License");
5326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * you may not use this file except in compliance with the License.
6326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * You may obtain a copy of the License at
7326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams *
8326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams *     http://www.apache.org/licenses/LICENSE-2.0
9326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams *
10326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * Unless required by applicable law or agreed to in writing, software
11326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * distributed under the License is distributed on an "AS IS" BASIS,
12326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * See the License for the specific language governing permissions and
14326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams * limitations under the License.
15326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams */
16326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
17326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams//#define LOG_NDEBUG 0
18326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include "bcc/Renderscript/RSInfo.h"
19326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
205ae678f2e68e25bd74cdc408df354c3b6fe481bfMathias Agopian#include <dlfcn.h>
21326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
22158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams#include <cstring>
23158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams#include <new>
247bf29ddc35450d8064541c42c99a1f48be6cf0ddJason Sams#include <string>
25158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams
2676371fff76412fd020e24ddb8bf1ddb5c75f0ed1Joe Onorato#include "bcc/Support/FileBase.h"
2776371fff76412fd020e24ddb8bf1ddb5c75f0ed1Joe Onorato#include "bcc/Support/Log.h"
28158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams
298d957fa762eff6c03a93ddea9405d9575665f1ecJason Sams#include <cutils/properties.h>
308d957fa762eff6c03a93ddea9405d9575665f1ecJason Sams
31158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Samsusing namespace bcc;
32326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
33326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsconst char RSInfo::LibBCCPath[] = "/system/lib/libbcc.so";
34326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsconst char RSInfo::LibRSPath[] = "/system/lib/libRS.so";
35fb03a22ad2adadc1ff50a8b50d43ad7fcc3fa6edJason Samsconst char RSInfo::LibCLCorePath[] = "/system/lib/libclcore.bc";
36ca3f09c0924e9515901dfd47fa5f95385d53cf80Stephen Hines#if defined(ARCH_ARM_HAVE_NEON)
37326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsconst char RSInfo::LibCLCoreNEONPath[] = "/system/lib/libclcore_neon.bc";
38afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk#endif
396b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Sams
406b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Samsconst uint8_t *RSInfo::LibBCCSHA1 = NULL;
416b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Samsconst uint8_t *RSInfo::LibRSSHA1 = NULL;
424b3de47071d875faaa7d419d050a464b09538797Jason Samsconst uint8_t *RSInfo::LibCLCoreSHA1 = NULL;
435c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams#if defined(ARCH_ARM_HAVE_NEON)
444b3de47071d875faaa7d419d050a464b09538797Jason Samsconst uint8_t *RSInfo::LibCLCoreNEONSHA1 = NULL;
455c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams#endif
466b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Sams
476b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Samsbool RSInfo::LoadBuiltInSHA1Information() {
486b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Sams#ifdef TARGET_BUILD
495c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams  if (LibBCCSHA1 != NULL) {
50326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams    // Loaded before.
51326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams    return true;
52afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk  }
534c5f99e3d27a0487878435010a23f37b2e9d721bJason Sams
544b3de47071d875faaa7d419d050a464b09538797Jason Sams  void *h = ::dlopen("/system/lib/libbcc.sha1.so", RTLD_LAZY | RTLD_NOW);
5533b6e3b91329080e5cdd0b8fdbcd3e6a906032aeJason Sams  if (h == NULL) {
5633b6e3b91329080e5cdd0b8fdbcd3e6a906032aeJason Sams    ALOGE("Failed to load SHA-1 information from shared library '"
5760709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams          "/system/lib/libbcc.sha1.so'! (%s)", ::dlerror());
5860709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams    return false;
59c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams  }
60c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams
61c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams  LibBCCSHA1 = reinterpret_cast<const uint8_t *>(::dlsym(h, "libbcc_so_SHA1"));
62c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams  LibRSSHA1 = reinterpret_cast<const uint8_t *>(::dlsym(h, "libRS_so_SHA1"));
63c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams  LibCLCoreSHA1 =
64c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams      reinterpret_cast<const uint8_t *>(::dlsym(h, "libclcore_bc_SHA1"));
65c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams#if defined(ARCH_ARM_HAVE_NEON)
6660709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams  LibCLCoreNEONSHA1 =
6760709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams      reinterpret_cast<const uint8_t *>(::dlsym(h, "libclcore_neon_bc_SHA1"));
6860709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams#endif
69c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams
70c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams  return true;
71c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams#else  // TARGET_BUILD
72c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams  return false;
73c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams#endif  // TARGET_BUILD
74c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams}
75c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams
7660709257bbdeb0c50f39b9c8969dc76264d6e142Jason Samsandroid::String8 RSInfo::GetPath(const FileBase &pFile) {
7760709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams  android::String8 result(pFile.getName().c_str());
7833b6e3b91329080e5cdd0b8fdbcd3e6a906032aeJason Sams  result.append(".info");
79afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk  return result;
8060709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams}
811030893d9b99b72468034da13df025bda479bb97Jason Sams
82c61346b91434307c5003029017b54ce9c49112beJason Sams#define PRINT_DEPENDENCY(PREFIX, N, X) \
83c9d43db4d216b01b13aebfdb31d5615909591b33Jason Sams        ALOGV("\t" PREFIX "Source name: %s, "                                 \
841030893d9b99b72468034da13df025bda479bb97Jason Sams                          "SHA-1: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"   \
851030893d9b99b72468034da13df025bda479bb97Jason Sams                                 "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",  \
86afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk              (N), (X)[ 0], (X)[ 1], (X)[ 2], (X)[ 3], (X)[ 4], (X)[ 5],      \
872dca84dd6c07992f78ad050177975f16486dd77eJason Sams                   (X)[ 6], (X)[ 7], (X)[ 8], (X)[ 9], (X)[10], (X)[11],      \
888c401effb0837155fc39ca0364f57a882d127d38Jason Sams                   (X)[12], (X)[13], (X)[14], (X)[15], (X)[16], (X)[17],      \
89c61346b91434307c5003029017b54ce9c49112beJason Sams                   (X)[18], (X)[19]);
908cfdd24fec22080b72266d33f61befc4a98b77c6Jason Sams
9124371d93cdb6999971c4058f78974da3c3d5fc64Jason Samsbool RSInfo::CheckDependency(const RSInfo &pInfo,
9224371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams                             const char *pInputFilename,
93cfb1d11ce6826fce7241d316d8b7dcab661f63a6Jason Sams                             const DependencyTableTy &pDeps) {
94afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk  // Built-in dependencies are libbcc.so, libRS.so and libclcore.bc plus
9524371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams  // libclcore_neon.bc if NEON is available on the target device.
9624371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams#if !defined(ARCH_ARM_HAVE_NEON)
9724371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams  static const unsigned NumBuiltInDependencies = 3;
9824371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams#else
99cfb1d11ce6826fce7241d316d8b7dcab661f63a6Jason Sams  static const unsigned NumBuiltInDependencies = 4;
100afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk#endif
10124371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams
10224371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams  LoadBuiltInSHA1Information();
10324371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams
10424371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams  if (pInfo.mDependencyTable.size() != (pDeps.size() + NumBuiltInDependencies)) {
105cfb1d11ce6826fce7241d316d8b7dcab661f63a6Jason Sams    ALOGD("Number of dependencies recorded mismatch (%lu v.s. %lu) in %s!",
106afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk          static_cast<unsigned long>(pInfo.mDependencyTable.size()),
10724371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams          static_cast<unsigned long>(pDeps.size()), pInputFilename);
1081d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams    return false;
1091d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams  } else {
11024371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams    // Built-in dependencies always go first.
111c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk    const std::pair<const char *, const uint8_t *> &cache_libbcc_dep =
112c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk        pInfo.mDependencyTable[0];
113c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk    const std::pair<const char *, const uint8_t *> &cache_libRS_dep =
11424371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams        pInfo.mDependencyTable[1];
11524371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams    const std::pair<const char *, const uint8_t *> &cache_libclcore_dep =
11624371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams        pInfo.mDependencyTable[2];
117afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk#if defined(ARCH_ARM_HAVE_NEON)
1181d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams    const std::pair<const char *, const uint8_t *> &cache_libclcore_neon_dep =
1191d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams        pInfo.mDependencyTable[3];
120c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk#endif
121c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk
122c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk    // Check libbcc.so.
123c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk    if (::memcmp(cache_libbcc_dep.second, LibBCCSHA1, SHA1_DIGEST_LENGTH) != 0) {
124afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        ALOGD("Cache %s is dirty due to %s has been updated.", pInputFilename,
125c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk              LibBCCPath);
126c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk        PRINT_DEPENDENCY("current - ", LibBCCPath, LibBCCSHA1);
127c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk        PRINT_DEPENDENCY("cache - ", cache_libbcc_dep.first,
128c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk                                     cache_libbcc_dep.second);
129c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk        return false;
1301d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams    }
1311d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams
132afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    // Check libRS.so.
13324371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams    if (::memcmp(cache_libRS_dep.second, LibRSSHA1, SHA1_DIGEST_LENGTH) != 0) {
13424371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams        ALOGD("Cache %s is dirty due to %s has been updated.", pInputFilename,
13524371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams              LibRSPath);
13624371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams        PRINT_DEPENDENCY("current - ", LibRSPath, LibRSSHA1);
13724371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams        PRINT_DEPENDENCY("cache - ", cache_libRS_dep.first,
13824371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams                                     cache_libRS_dep.second);
139afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        return false;
14024371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams    }
14124371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams
14224371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams    // Check libclcore.bc.
14324371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams    if (::memcmp(cache_libclcore_dep.second, LibCLCoreSHA1,
1441d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                 SHA1_DIGEST_LENGTH) != 0) {
1452dca84dd6c07992f78ad050177975f16486dd77eJason Sams        ALOGD("Cache %s is dirty due to %s has been updated.", pInputFilename,
1462dca84dd6c07992f78ad050177975f16486dd77eJason Sams              LibRSPath);
1472dca84dd6c07992f78ad050177975f16486dd77eJason Sams        PRINT_DEPENDENCY("current - ", LibCLCorePath, LibCLCoreSHA1);
14824371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams        PRINT_DEPENDENCY("cache - ", cache_libclcore_dep.first,
1492dca84dd6c07992f78ad050177975f16486dd77eJason Sams                                     cache_libclcore_dep.second);
1502dca84dd6c07992f78ad050177975f16486dd77eJason Sams        return false;
15164cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk    }
1522dca84dd6c07992f78ad050177975f16486dd77eJason Sams
1532dca84dd6c07992f78ad050177975f16486dd77eJason Sams#if defined(ARCH_ARM_HAVE_NEON)
1542dca84dd6c07992f78ad050177975f16486dd77eJason Sams    // Check libclcore_neon.bc if NEON is available.
1552dca84dd6c07992f78ad050177975f16486dd77eJason Sams    if (::memcmp(cache_libclcore_neon_dep.second, LibCLCoreNEONSHA1,
156c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk                 SHA1_DIGEST_LENGTH) != 0) {
157c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk        ALOGD("Cache %s is dirty due to %s has been updated.", pInputFilename,
1582dca84dd6c07992f78ad050177975f16486dd77eJason Sams              LibRSPath);
159326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams        PRINT_DEPENDENCY("current - ", LibCLCoreNEONPath, LibCLCoreNEONSHA1);
160326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams        PRINT_DEPENDENCY("cache - ", cache_libclcore_neon_dep.first,
161afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk                                     cache_libclcore_neon_dep.second);
162900f1616bf33c7ba13cf2a737832a95bcd176388Jason Sams        return false;
163721acc495b859c6d884725a4f9b5523583dd11c7Jason Sams    }
164c19ff0177a7a0dadfc01b1990f822354fdc95991Alex Sakhartchouk#endif
165721acc495b859c6d884725a4f9b5523583dd11c7Jason Sams
166c19ff0177a7a0dadfc01b1990f822354fdc95991Alex Sakhartchouk    for (unsigned i = 0; i < pDeps.size(); i++) {
167c19ff0177a7a0dadfc01b1990f822354fdc95991Alex Sakhartchouk      const std::pair<const char *, const uint8_t *> &cache_dep =
168a2cf755a28a1e7ffff2955df656d714f40e4d715Jason Sams          pInfo.mDependencyTable[i + NumBuiltInDependencies];
169326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
170326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams      if ((::strcmp(pDeps[i].first, cache_dep.first) != 0) ||
171889fe50e7aaebed8cb8284b16a0e51e64e8a3a9cAlex Sakhartchouk          (::memcmp(pDeps[i].second, cache_dep.second,
172721acc495b859c6d884725a4f9b5523583dd11c7Jason Sams                    SHA1_DIGEST_LENGTH) != 0)) {
173889fe50e7aaebed8cb8284b16a0e51e64e8a3a9cAlex Sakhartchouk        ALOGD("Cache %s is dirty due to the source it dependends on has been "
174889fe50e7aaebed8cb8284b16a0e51e64e8a3a9cAlex Sakhartchouk              "changed:", pInputFilename);
175afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        PRINT_DEPENDENCY("given - ", pDeps[i].first, pDeps[i].second);
17676371fff76412fd020e24ddb8bf1ddb5c75f0ed1Joe Onorato        PRINT_DEPENDENCY("cache - ", cache_dep.first, cache_dep.second);
1771fddd90849deaae89b546ff492c345d485bbce42Jason Sams        return false;
17876371fff76412fd020e24ddb8bf1ddb5c75f0ed1Joe Onorato      }
17976371fff76412fd020e24ddb8bf1ddb5c75f0ed1Joe Onorato    }
180326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams  }
181afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk
1820cae59f7d8dd63d1bf0ca4abedecb4cfa3ab1921Alex Sakhartchouk  return true;
183c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk}
184ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk
185ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex SakhartchoukRSInfo::RSInfo(size_t pStringPoolSize) : mStringPool(NULL) {
18609c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk  ::memset(&mHeader, 0, sizeof(mHeader));
1870cae59f7d8dd63d1bf0ca4abedecb4cfa3ab1921Alex Sakhartchouk
1881809bde133e0d66f06cea65887d9ceb3c70f8b95Alex Sakhartchouk  ::memcpy(mHeader.magic, RSINFO_MAGIC, sizeof(mHeader.magic));
1891809bde133e0d66f06cea65887d9ceb3c70f8b95Alex Sakhartchouk  ::memcpy(mHeader.version, RSINFO_VERSION, sizeof(mHeader.version));
19009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
191ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk  mHeader.headerSize = sizeof(mHeader);
192c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk
1930cae59f7d8dd63d1bf0ca4abedecb4cfa3ab1921Alex Sakhartchouk  mHeader.dependencyTable.itemSize = sizeof(rsinfo::DependencyTableItem);
19409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk  mHeader.pragmaList.itemSize = sizeof(rsinfo::PragmaItem);
195c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk  mHeader.objectSlotList.itemSize = sizeof(rsinfo::ObjectSlotItem);
1960cae59f7d8dd63d1bf0ca4abedecb4cfa3ab1921Alex Sakhartchouk  mHeader.exportVarNameList.itemSize = sizeof(rsinfo::ExportVarNameItem);
1971809bde133e0d66f06cea65887d9ceb3c70f8b95Alex Sakhartchouk  mHeader.exportFuncNameList.itemSize = sizeof(rsinfo::ExportFuncNameItem);
198ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk  mHeader.exportForeachFuncList.itemSize = sizeof(rsinfo::ExportForeachFuncItem);
1990cae59f7d8dd63d1bf0ca4abedecb4cfa3ab1921Alex Sakhartchouk
2000cae59f7d8dd63d1bf0ca4abedecb4cfa3ab1921Alex Sakhartchouk  if (pStringPoolSize > 0) {
201afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    mHeader.strPoolSize = pStringPoolSize;
20283c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    mStringPool = new (std::nothrow) char [ mHeader.strPoolSize ];
20383c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    if (mStringPool == NULL) {
20483c451a4ef4388e002482e383d488ca9b7b7600dJason Sams      ALOGE("Out of memory when allocate memory for string pool in RSInfo "
20583c451a4ef4388e002482e383d488ca9b7b7600dJason Sams            "constructor (size: %u)!", mHeader.strPoolSize);
20683c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    }
20783c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  }
20883c451a4ef4388e002482e383d488ca9b7b7600dJason Sams}
20983c451a4ef4388e002482e383d488ca9b7b7600dJason Sams
21083c451a4ef4388e002482e383d488ca9b7b7600dJason SamsRSInfo::~RSInfo() {
21183c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  delete [] mStringPool;
21283c451a4ef4388e002482e383d488ca9b7b7600dJason Sams}
21383c451a4ef4388e002482e383d488ca9b7b7600dJason Sams
21483c451a4ef4388e002482e383d488ca9b7b7600dJason Samsbool RSInfo::layout(off_t initial_offset) {
21583c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  mHeader.dependencyTable.offset = initial_offset +
21683c451a4ef4388e002482e383d488ca9b7b7600dJason Sams                                   mHeader.headerSize +
217d3e7107c60ce06d637d83fa0db783ecdd0ad534cJason Sams                                   mHeader.strPoolSize;
21883c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  mHeader.dependencyTable.count = mDependencyTable.size();
21983c451a4ef4388e002482e383d488ca9b7b7600dJason Sams
22083c451a4ef4388e002482e383d488ca9b7b7600dJason Sams#define AFTER(_list) ((_list).offset + (_list).itemSize * (_list).count)
22183c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  mHeader.pragmaList.offset = AFTER(mHeader.dependencyTable);
22283c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  mHeader.pragmaList.count = mPragmas.size();
22383c451a4ef4388e002482e383d488ca9b7b7600dJason Sams
224d3e7107c60ce06d637d83fa0db783ecdd0ad534cJason Sams  mHeader.objectSlotList.offset = AFTER(mHeader.pragmaList);
225d3e7107c60ce06d637d83fa0db783ecdd0ad534cJason Sams  mHeader.objectSlotList.count = mObjectSlots.size();
226d3e7107c60ce06d637d83fa0db783ecdd0ad534cJason Sams
227d3e7107c60ce06d637d83fa0db783ecdd0ad534cJason Sams  mHeader.exportVarNameList.offset = AFTER(mHeader.objectSlotList);
228d3e7107c60ce06d637d83fa0db783ecdd0ad534cJason Sams  mHeader.exportVarNameList.count = mExportVarNames.size();
22983c451a4ef4388e002482e383d488ca9b7b7600dJason Sams
23083c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  mHeader.exportFuncNameList.offset = AFTER(mHeader.exportVarNameList);
23183c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  mHeader.exportFuncNameList.count = mExportFuncNames.size();
23283c451a4ef4388e002482e383d488ca9b7b7600dJason Sams
23383c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  mHeader.exportForeachFuncList.offset = AFTER(mHeader.exportFuncNameList);
23483c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  mHeader.exportForeachFuncList.count = mExportForeachFuncs.size();
23583c451a4ef4388e002482e383d488ca9b7b7600dJason Sams#undef AFTER
23683c451a4ef4388e002482e383d488ca9b7b7600dJason Sams
23783c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  return true;
23883c451a4ef4388e002482e383d488ca9b7b7600dJason Sams}
239da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk
24083c451a4ef4388e002482e383d488ca9b7b7600dJason Samsvoid RSInfo::dump() const {
24183c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  // Hide the codes to save the code size when debugging is disabled.
24283c451a4ef4388e002482e383d488ca9b7b7600dJason Sams#if !LOG_NDEBUG
24383c451a4ef4388e002482e383d488ca9b7b7600dJason Sams
24483c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  // Dump header
24583c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  ALOGV("RSInfo Header:");
24683c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  ALOGV("\tIs threadable: %s", ((mHeader.isThreadable) ? "true" : "false"));
2477257c7ee4b66f00c43d9235f3ac600061ae79968Alex Sakhartchouk  ALOGV("\tHeader size: %u", mHeader.headerSize);
24883c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  ALOGV("\tString pool size: %u", mHeader.strPoolSize);
24983c451a4ef4388e002482e383d488ca9b7b7600dJason Sams
25083c451a4ef4388e002482e383d488ca9b7b7600dJason Sams#define DUMP_LIST_HEADER(_name, _header) do { \
25183c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  ALOGV(_name ":"); \
25283c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  ALOGV("\toffset: %u", (_header).offset);  \
25383c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  ALOGV("\t# of item: %u", (_header).count);  \
25483c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  ALOGV("\tsize of each item: %u", (_header).itemSize); \
25583c451a4ef4388e002482e383d488ca9b7b7600dJason Sams} while (false)
25683c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  DUMP_LIST_HEADER("Dependency table", mHeader.dependencyTable);
25783c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  for (DependencyTableTy::const_iterator dep_iter = mDependencyTable.begin(),
25883c451a4ef4388e002482e383d488ca9b7b7600dJason Sams          dep_end = mDependencyTable.end(); dep_iter != dep_end; dep_iter++) {
25983c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    PRINT_DEPENDENCY("", dep_iter->first, dep_iter->second);
26083c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  }
26183c451a4ef4388e002482e383d488ca9b7b7600dJason Sams
26283c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  DUMP_LIST_HEADER("Pragma list", mHeader.pragmaList);
26383c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  for (PragmaListTy::const_iterator pragma_iter = mPragmas.begin(),
26483c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        pragma_end = mPragmas.end(); pragma_iter != pragma_end; pragma_iter++) {
26583c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    ALOGV("\tkey: %s, value: %s", pragma_iter->first, pragma_iter->second);
26683c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  }
26783c451a4ef4388e002482e383d488ca9b7b7600dJason Sams
26883c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  DUMP_LIST_HEADER("RS object slots", mHeader.objectSlotList);
26983c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  for (ObjectSlotListTy::const_iterator slot_iter = mObjectSlots.begin(),
27083c451a4ef4388e002482e383d488ca9b7b7600dJason Sams          slot_end = mObjectSlots.end(); slot_iter != slot_end; slot_iter++) {
27183c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    ALOGV("slot: %u", *slot_iter);
27283c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  }
27383c451a4ef4388e002482e383d488ca9b7b7600dJason Sams
27483c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  DUMP_LIST_HEADER("RS export variables", mHeader.exportVarNameList);
27583c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  for (ExportVarNameListTy::const_iterator var_iter = mExportVarNames.begin(),
27683c451a4ef4388e002482e383d488ca9b7b7600dJason Sams          var_end = mExportVarNames.end(); var_iter != var_end; var_iter++) {
27783c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    ALOGV("name: %s", *var_iter);
27883c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  }
27983c451a4ef4388e002482e383d488ca9b7b7600dJason Sams
28083c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  DUMP_LIST_HEADER("RS export functions", mHeader.exportFuncNameList);
28183c451a4ef4388e002482e383d488ca9b7b7600dJason Sams  for (ExportFuncNameListTy::const_iterator func_iter = mExportFuncNames.begin(),
28283c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        func_end = mExportFuncNames.end(); func_iter != func_end; func_iter++) {
283326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams    ALOGV("name: %s", *func_iter);
284326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams  }
285741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams
286249d453869cca82dcb57123f6d1c8df3ca9f4372Jason Sams  DUMP_LIST_HEADER("RS foreach list", mHeader.exportForeachFuncList);
2872e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams  for (ExportForeachFuncListTy::const_iterator
288741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams          foreach_iter = mExportForeachFuncs.begin(),
289741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams          foreach_end = mExportForeachFuncs.end(); foreach_iter != foreach_end;
290741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams          foreach_iter++) {
291741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams    ALOGV("name: %s, signature: %05x", foreach_iter->first,
292741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams                                       foreach_iter->second);
293741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams  }
294741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams#undef DUMP_LIST_HEADER
295741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams
296741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams#endif // LOG_NDEBUG
297741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams  return;
298741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams}
299741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams
300da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchoukconst char *RSInfo::getStringFromPool(rsinfo::StringIndexTy pStrIdx) const {
301741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams  // String pool uses direct indexing. Ensure that the pStrIdx is within the
302249d453869cca82dcb57123f6d1c8df3ca9f4372Jason Sams  // range.
303cf912de17f1e086ccea707d8607a3d2eda56b98fJason Sams  if (pStrIdx >= mHeader.strPoolSize) {
304741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams    ALOGE("String index #%u is out of range in string pool (size: %u)!",
305741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams          pStrIdx, mHeader.strPoolSize);
306afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    return NULL;
307158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams  }
308158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams  return &mStringPool[ pStrIdx ];
309158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams}
310158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams
3112dca84dd6c07992f78ad050177975f16486dd77eJason Samsrsinfo::StringIndexTy RSInfo::getStringIdxInPool(const char *pStr) const {
312158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams  // Assume we are on the flat memory architecture (i.e., the memory space is
313158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams  // continuous.)
314158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams  if ((mStringPool + mHeader.strPoolSize) < pStr) {
315158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams    ALOGE("String %s does not in the string pool!", pStr);
316158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams    return rsinfo::gInvalidStringIndex;
317158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams  }
318158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams  return (pStr - mStringPool);
319158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams}
320158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams
3217bf29ddc35450d8064541c42c99a1f48be6cf0ddJason SamsRSInfo::FloatPrecision RSInfo::getFloatPrecisionRequirement() const {
322158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams  // Check to see if we have any FP precision-related pragmas.
323158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams  std::string relaxed_pragma("rs_fp_relaxed");
324158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams  std::string imprecise_pragma("rs_fp_imprecise");
325afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk  std::string full_pragma("rs_fp_full");
3265c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams  bool relaxed_pragma_seen = false;
327326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams  bool imprecise_pragma_seen = false;
328326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams  RSInfo::FloatPrecision result = FP_Full;
32986f1b23aaaf9b8822a009d8c3e585e46768abb6aJason Sams
330e514b45de8561fbc6ef6770845102ca10b0a69d7Jason Sams  for (PragmaListTy::const_iterator pragma_iter = mPragmas.begin(),
331a2cf755a28a1e7ffff2955df656d714f40e4d715Jason Sams           pragma_end = mPragmas.end(); pragma_iter != pragma_end;
3327b3e9bd825901e33661e3c385e3e7c6f40ca6000Alex Sakhartchouk       pragma_iter++) {
3335c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams    const char *pragma_key = pragma_iter->first;
3345c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams    if (!relaxed_pragma.compare(pragma_key)) {
335afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk      if (relaxed_pragma_seen || imprecise_pragma_seen) {
3365c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams        ALOGE("Multiple float precision pragmas specified!");
3375c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams      }
3385c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams      relaxed_pragma_seen = true;
3395c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams    } else if (!imprecise_pragma.compare(pragma_key)) {
3405c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams      if (relaxed_pragma_seen || imprecise_pragma_seen) {
3415c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams        ALOGE("Multiple float precision pragmas specified!");
3425c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams      }
3435c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams      imprecise_pragma_seen = true;
344afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    }
3455c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams  }
3465c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams
3471a4efa363916977ef9aeab756725b3bdc880a15bJason Sams  // Imprecise is selected over Relaxed precision.
3481a4efa363916977ef9aeab756725b3bdc880a15bJason Sams  // In the absence of both, we stick to the default Full precision.
3495c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams  if (imprecise_pragma_seen) {
3505c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams    result = FP_Imprecise;
3516b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Sams  } else if (relaxed_pragma_seen) {
3526b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Sams    result = FP_Relaxed;
3536b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Sams  }
3546b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Sams
3556b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Sams  // Provide an override for precsion via adb shell setprop
356a2cf755a28a1e7ffff2955df656d714f40e4d715Jason Sams  // adb shell setprop debug.rs.precision rs_fp_full
3576b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Sams  // adb shell setprop debug.rs.precision rs_fp_relaxed
358326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams  // adb shell setprop debug.rs.precision rs_fp_imprecise
359a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams  char precision_prop_buf[PROPERTY_VALUE_MAX];
360a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams  property_get("debug.rs.precision", precision_prop_buf, "");
361a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams
362fb03a22ad2adadc1ff50a8b50d43ad7fcc3fa6edJason Sams  if (precision_prop_buf[0]) {
363fb03a22ad2adadc1ff50a8b50d43ad7fcc3fa6edJason Sams    if (!relaxed_pragma.compare(precision_prop_buf)) {
364fb03a22ad2adadc1ff50a8b50d43ad7fcc3fa6edJason Sams      ALOGI("Switching to RS FP relaxed mode via setprop");
365e57691037aea219562ac686429b4b98202aab7bcJason Sams      result = FP_Relaxed;
366a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams    } else if (!imprecise_pragma.compare(precision_prop_buf)) {
367a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams      ALOGI("Switching to RS FP imprecise mode via setprop");
368a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams      result = FP_Imprecise;
3695c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams    } else if (!full_pragma.compare(precision_prop_buf)) {
370a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams      ALOGI("Switching to RS FP full mode via setprop");
371a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams      result = FP_Full;
3727257c7ee4b66f00c43d9235f3ac600061ae79968Alex Sakhartchouk    }
373992a0b70d8fd7a14f0c57bc3c7e16c1f269a6609Jason Sams  }
37424371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams
375a891933b4c5ab1b63103add167269cfc404c2adfJason Sams  return result;
3765086938044e0a9b6b1138f915d0d252fe046e102Jason Sams}
377a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams