rsg_generator.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. #include "spec.h"
  2. #include <stdio.h>
  3. #include <string.h>
  4. #define LOCAL_FIFO_PREFIX "LF_"
  5. #define RS_PLAYBACK_PREFIX "rsp_"
  6. #define RS_INTERNAL_PREFIX "rsi_"
  7. #define RSG_API_CPP_DOC \
  8. "/*\n" \
  9. " * rsgApi.cpp\n" \
  10. " * This file implements the functions responsible for sending messages\n" \
  11. " * to the RS driver layer. The messages are sent through a FIFO that is\n" \
  12. " * shared between the process's caller threads and driver thread.\n" \
  13. " */\n\n"
  14. #define RSG_API_REPLAY_CPP_DOC \
  15. "/*\n" \
  16. " * rsgApiReplay.cpp\n" \
  17. " * This file implements the functions responsible for reading messages\n" \
  18. " * sent to the RS driver layer.\n" \
  19. " */\n\n"
  20. void printFileHeader(FILE *f) {
  21. fprintf(f, "/*\n");
  22. fprintf(f, " * Copyright (C) 2015 The Android Open Source Project\n");
  23. fprintf(f, " *\n");
  24. fprintf(f, " * Licensed under the Apache License, Version 2.0 (the \"License\");\n");
  25. fprintf(f, " * you may not use this file except in compliance with the License.\n");
  26. fprintf(f, " * You may obtain a copy of the License at\n");
  27. fprintf(f, " *\n");
  28. fprintf(f, " * http://www.apache.org/licenses/LICENSE-2.0\n");
  29. fprintf(f, " *\n");
  30. fprintf(f, " * Unless required by applicable law or agreed to in writing, software\n");
  31. fprintf(f, " * distributed under the License is distributed on an \"AS IS\" BASIS,\n");
  32. fprintf(f, " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n");
  33. fprintf(f, " * See the License for the specific language governing permissions and\n");
  34. fprintf(f, " * limitations under the License.\n");
  35. fprintf(f, " */\n\n");
  36. }
  37. void printVarType(FILE *f, const VarType *vt) {
  38. int ct;
  39. if (vt->isConst) {
  40. fprintf(f, "const ");
  41. }
  42. switch (vt->type) {
  43. case 0:
  44. fprintf(f, "void");
  45. break;
  46. case 1:
  47. fprintf(f, "int%i_t", vt->bits);
  48. break;
  49. case 2:
  50. fprintf(f, "uint%i_t", vt->bits);
  51. break;
  52. case 3:
  53. if (vt->bits == 32)
  54. fprintf(f, "float");
  55. else
  56. fprintf(f, "double");
  57. break;
  58. case 4:
  59. fprintf(f, "%s", vt->typeName);
  60. break;
  61. }
  62. if (vt->ptrLevel) {
  63. fprintf(f, " ");
  64. for (ct=0; ct < vt->ptrLevel; ct++) {
  65. fprintf(f, "*");
  66. }
  67. }
  68. }
  69. void printVarTypeAndName(FILE *f, const VarType *vt) {
  70. printVarType(f, vt);
  71. if (vt->name[0]) {
  72. fprintf(f, " %s", vt->name);
  73. }
  74. }
  75. void printArgList(FILE *f, const ApiEntry * api, int assumePrevious) {
  76. int ct;
  77. for (ct=0; ct < api->paramCount; ct++) {
  78. if (ct || assumePrevious) {
  79. fprintf(f, ", ");
  80. }
  81. printVarTypeAndName(f, &api->params[ct]);
  82. }
  83. }
  84. void printStructures(FILE *f) {
  85. int ct;
  86. int ct2;
  87. for (ct=0; ct < apiCount; ct++) {
  88. fprintf(f, "typedef struct RS_CMD_%s_rec RS_CMD_%s;\n", apis[ct].name, apis[ct].name);
  89. }
  90. fprintf(f, "\n");
  91. for (ct=0; ct < apiCount; ct++) {
  92. const ApiEntry * api = &apis[ct];
  93. fprintf(f, "#define RS_CMD_ID_%s %i\n", api->name, ct+1);
  94. fprintf(f, "struct __attribute__((packed)) RS_CMD_%s_rec {\n", api->name);
  95. //fprintf(f, " RsCommandHeader _hdr;\n");
  96. for (ct2=0; ct2 < api->paramCount; ct2++) {
  97. fprintf(f, " ");
  98. printVarTypeAndName(f, &api->params[ct2]);
  99. fprintf(f, ";\n");
  100. }
  101. fprintf(f, "};\n\n");
  102. }
  103. }
  104. void printFuncDecl(FILE *f, const ApiEntry *api, const char *prefix, int addContext, int isFnPtr) {
  105. printVarTypeAndName(f, &api->ret);
  106. if (isFnPtr) {
  107. char t[1024];
  108. strncpy(t, api->name, sizeof(t)-1);
  109. t[sizeof(t)-1] = '\0';
  110. if (strlen(prefix) == 0) {
  111. if (t[0] > 'A' && t[0] < 'Z') {
  112. t[0] -= 'A' - 'a';
  113. }
  114. }
  115. fprintf(f, " (* %s%s) (", prefix, api->name);
  116. } else {
  117. fprintf(f, " %s%s (", prefix, api->name);
  118. }
  119. if (!api->nocontext) {
  120. if (addContext) {
  121. fprintf(f, "Context *");
  122. } else {
  123. fprintf(f, "RsContext rsc");
  124. }
  125. }
  126. printArgList(f, api, !api->nocontext);
  127. fprintf(f, ")");
  128. }
  129. void printFuncDecls(FILE *f, const char *prefix, int addContext, int externC) {
  130. int ct;
  131. for (ct=0; ct < apiCount; ct++) {
  132. if (externC) {
  133. fprintf(f, "extern \"C\" ");
  134. }
  135. printFuncDecl(f, &apis[ct], prefix, addContext, 0);
  136. fprintf(f, ";\n");
  137. }
  138. fprintf(f, "\n\n");
  139. }
  140. void printPlaybackFuncs(FILE *f, const char *prefix) {
  141. int ct;
  142. for (ct=0; ct < apiCount; ct++) {
  143. if (apis[ct].direct) {
  144. continue;
  145. }
  146. fprintf(f, "void %s%s (Context *, const void *);\n", prefix, apis[ct].name);
  147. }
  148. }
  149. static int hasInlineDataPointers(const ApiEntry * api) {
  150. int ret = 0;
  151. int ct;
  152. if (api->sync || api->ret.typeName[0]) {
  153. return 0;
  154. }
  155. for (ct=0; ct < api->paramCount; ct++) {
  156. const VarType *vt = &api->params[ct];
  157. if (!vt->isConst && vt->ptrLevel) {
  158. // Non-const pointers cannot be inlined.
  159. return 0;
  160. }
  161. if (vt->ptrLevel > 1) {
  162. // not handled yet.
  163. return 0;
  164. }
  165. if (vt->isConst && vt->ptrLevel) {
  166. // Non-const pointers cannot be inlined.
  167. ret = 1;
  168. }
  169. }
  170. return ret;
  171. }
  172. void printApiCpp(FILE *f) {
  173. int ct;
  174. int ct2;
  175. fprintf(f, RSG_API_CPP_DOC);
  176. fprintf(f, "#include \"rsDevice.h\"\n");
  177. fprintf(f, "#include \"rsContext.h\"\n");
  178. fprintf(f, "#include \"rsThreadIO.h\"\n");
  179. fprintf(f, "#include \"rsgApiStructs.h\"\n");
  180. fprintf(f, "#include \"rsgApiFuncDecl.h\"\n");
  181. fprintf(f, "#include \"rsFifo.h\"\n");
  182. fprintf(f, "\n");
  183. fprintf(f, "using namespace android; // NOLINT\n");
  184. fprintf(f, "using namespace android::renderscript; // NOLINT\n");
  185. fprintf(f, "\n");
  186. // Generate RS funcs that send messages on the local FIFO.
  187. for (ct=0; ct < apiCount; ct++) {
  188. int needFlush = 0;
  189. const ApiEntry * api = &apis[ct];
  190. fprintf(f, "static ");
  191. printFuncDecl(f, api, LOCAL_FIFO_PREFIX, 0, 0);
  192. fprintf(f, "\n{\n");
  193. if (api->direct) {
  194. fprintf(f, " ");
  195. if (api->ret.typeName[0]) {
  196. fprintf(f, "return ");
  197. }
  198. fprintf(f, RS_INTERNAL_PREFIX "%s(", api->name);
  199. if (!api->nocontext) {
  200. fprintf(f, "(Context *)rsc");
  201. }
  202. for (ct2=0; ct2 < api->paramCount; ct2++) {
  203. const VarType *vt = &api->params[ct2];
  204. if (ct2 > 0 || !api->nocontext) {
  205. fprintf(f, ", ");
  206. }
  207. fprintf(f, "%s", vt->name);
  208. }
  209. fprintf(f, ");\n");
  210. } else if (api->handcodeApi) {
  211. // handle handcode path
  212. fprintf(f, " " LOCAL_FIFO_PREFIX "%s_handcode(", api->name);
  213. if (!api->nocontext) {
  214. fprintf(f, "(Context *)rsc");
  215. }
  216. for (ct2=0; ct2 < api->paramCount; ct2++) {
  217. const VarType *vt = &api->params[ct2];
  218. if (ct2 > 0 || !api->nocontext) {
  219. fprintf(f, ", ");
  220. }
  221. fprintf(f, "%s", vt->name);
  222. }
  223. fprintf(f, ");\n");
  224. } else {
  225. // handle synchronous path
  226. fprintf(f, " if (((Context *)rsc)->isSynchronous()) {\n");
  227. fprintf(f, " ");
  228. if (api->ret.typeName[0]) {
  229. fprintf(f, "return ");
  230. }
  231. fprintf(f, RS_INTERNAL_PREFIX "%s(", api->name);
  232. if (!api->nocontext) {
  233. fprintf(f, "(Context *)rsc");
  234. }
  235. for (ct2=0; ct2 < api->paramCount; ct2++) {
  236. const VarType *vt = &api->params[ct2];
  237. if (ct2 > 0 || !api->nocontext) {
  238. fprintf(f, ", ");
  239. }
  240. fprintf(f, "%s", vt->name);
  241. }
  242. fprintf(f, ");\n");
  243. if (!api->ret.typeName[0]) {
  244. fprintf(f, " return;");
  245. }
  246. fprintf(f, " }\n\n");
  247. fprintf(f, " ThreadIO *io = &((Context *)rsc)->mIO;\n");
  248. fprintf(f, " const size_t size = sizeof(RS_CMD_%s);\n", api->name);
  249. if (hasInlineDataPointers(api)) {
  250. fprintf(f, " size_t dataSize = 0;\n");
  251. for (ct2=0; ct2 < api->paramCount; ct2++) {
  252. const VarType *vt = &api->params[ct2];
  253. if (vt->isConst && vt->ptrLevel) {
  254. fprintf(f, " dataSize += %s_length;\n", vt->name);
  255. }
  256. }
  257. }
  258. //fprintf(f, " ALOGE(\"add command %s\\n\");\n", api->name);
  259. if (hasInlineDataPointers(api)) {
  260. fprintf(f, " RS_CMD_%s *cmd = NULL;\n", api->name);
  261. fprintf(f, " if (dataSize < io->getMaxInlineSize()) {;\n");
  262. fprintf(f, " cmd = static_cast<RS_CMD_%s *>(io->coreHeader(RS_CMD_ID_%s, dataSize + size));\n", api->name, api->name);
  263. fprintf(f, " } else {\n");
  264. fprintf(f, " cmd = static_cast<RS_CMD_%s *>(io->coreHeader(RS_CMD_ID_%s, size));\n", api->name, api->name);
  265. fprintf(f, " }\n");
  266. fprintf(f, " uint8_t *payload = (uint8_t *)&cmd[1];\n");
  267. } else {
  268. fprintf(f, " RS_CMD_%s *cmd = static_cast<RS_CMD_%s *>(io->coreHeader(RS_CMD_ID_%s, size));\n", api->name, api->name, api->name);
  269. }
  270. for (ct2=0; ct2 < api->paramCount; ct2++) {
  271. const VarType *vt = &api->params[ct2];
  272. needFlush += vt->ptrLevel;
  273. if (vt->ptrLevel && hasInlineDataPointers(api)) {
  274. fprintf(f, " if (%s_length == 0) {\n", vt->name);
  275. fprintf(f, " cmd->%s = NULL;\n", vt->name);
  276. fprintf(f, " } else if (dataSize < io->getMaxInlineSize()) {\n");
  277. fprintf(f, " memcpy(payload, %s, %s_length);\n", vt->name, vt->name);
  278. fprintf(f, " cmd->%s = (", vt->name);
  279. printVarType(f, vt);
  280. fprintf(f, ")(payload - ((uint8_t *)&cmd[1]));\n");
  281. fprintf(f, " payload += %s_length;\n", vt->name);
  282. fprintf(f, " } else {\n");
  283. fprintf(f, " cmd->%s = %s;\n", vt->name, vt->name);
  284. fprintf(f, " }\n");
  285. } else {
  286. fprintf(f, " cmd->%s = %s;\n", vt->name, vt->name);
  287. }
  288. }
  289. if (api->ret.typeName[0] || api->sync) {
  290. needFlush = 1;
  291. }
  292. fprintf(f, " io->coreCommit();\n");
  293. if (hasInlineDataPointers(api)) {
  294. fprintf(f, " if (dataSize >= io->getMaxInlineSize()) {\n");
  295. fprintf(f, " io->coreGetReturn(NULL, 0);\n");
  296. fprintf(f, " }\n");
  297. } else if (api->ret.typeName[0]) {
  298. fprintf(f, "\n ");
  299. printVarType(f, &api->ret);
  300. fprintf(f, " ret;\n");
  301. fprintf(f, " io->coreGetReturn(&ret, sizeof(ret));\n");
  302. fprintf(f, " return ret;\n");
  303. } else if (needFlush) {
  304. fprintf(f, " io->coreGetReturn(NULL, 0);\n");
  305. }
  306. }
  307. fprintf(f, "};\n\n");
  308. }
  309. fprintf(f, "\n");
  310. for (ct=0; ct < apiCount; ct++) {
  311. const ApiEntry * api = &apis[ct];
  312. fprintf(f, "extern \"C\" ");
  313. printFuncDecl(f, api, "rs", 0, 0);
  314. fprintf(f, "\n{\n");
  315. fprintf(f, " ");
  316. if (api->ret.typeName[0]) {
  317. fprintf(f, "return ");
  318. }
  319. fprintf(f, LOCAL_FIFO_PREFIX "%s(", api->name);
  320. if (!api->nocontext) {
  321. fprintf(f, "(Context *)rsc");
  322. }
  323. for (ct2=0; ct2 < api->paramCount; ct2++) {
  324. const VarType *vt = &api->params[ct2];
  325. if (ct2 > 0 || !api->nocontext) {
  326. fprintf(f, ", ");
  327. }
  328. fprintf(f, "%s", vt->name);
  329. }
  330. fprintf(f, ");\n");
  331. fprintf(f, "}\n\n");
  332. }
  333. }
  334. void printPlaybackCpp(FILE *f) {
  335. int ct;
  336. int ct2;
  337. fprintf(f, RSG_API_REPLAY_CPP_DOC);
  338. fprintf(f, "#include \"rsDevice.h\"\n");
  339. fprintf(f, "#include \"rsContext.h\"\n");
  340. fprintf(f, "#include \"rsThreadIO.h\"\n");
  341. fprintf(f, "#include \"rsgApiStructs.h\"\n");
  342. fprintf(f, "#include \"rsgApiFuncDecl.h\"\n");
  343. fprintf(f, "\n");
  344. fprintf(f, "namespace android {\n");
  345. fprintf(f, "namespace renderscript {\n");
  346. fprintf(f, "\n");
  347. // Generate functions to play back messages sent from the local FIFO.
  348. for (ct=0; ct < apiCount; ct++) {
  349. const ApiEntry * api = &apis[ct];
  350. int needFlush = 0;
  351. if (api->direct) {
  352. continue;
  353. }
  354. fprintf(f, "void " RS_PLAYBACK_PREFIX "%s(Context *con, const void *vp, size_t cmdSizeBytes) {\n", api->name);
  355. fprintf(f, " const RS_CMD_%s *cmd = static_cast<const RS_CMD_%s *>(vp);\n", api->name, api->name);
  356. if (hasInlineDataPointers(api)) {
  357. fprintf(f, " const uint8_t *baseData = 0;\n");
  358. fprintf(f, " if (cmdSizeBytes != sizeof(RS_CMD_%s)) {\n", api->name);
  359. fprintf(f, " baseData = &((const uint8_t *)vp)[sizeof(*cmd)];\n");
  360. fprintf(f, " }\n");
  361. }
  362. fprintf(f, " ");
  363. if (api->ret.typeName[0]) {
  364. fprintf(f, "\n ");
  365. printVarType(f, &api->ret);
  366. fprintf(f, " ret = ");
  367. }
  368. fprintf(f, RS_INTERNAL_PREFIX "%s(con", api->name);
  369. for (ct2=0; ct2 < api->paramCount; ct2++) {
  370. const VarType *vt = &api->params[ct2];
  371. needFlush += vt->ptrLevel;
  372. if (hasInlineDataPointers(api) && vt->ptrLevel) {
  373. fprintf(f, ",\n cmd->%s_length == 0 ? NULL : (const %s *)&baseData[(intptr_t)cmd->%s]",
  374. vt->name, vt->typeName, vt->name);
  375. } else {
  376. fprintf(f, ",\n cmd->%s", vt->name);
  377. }
  378. }
  379. fprintf(f, ");\n");
  380. if (hasInlineDataPointers(api)) {
  381. fprintf(f, " size_t totalSize = 0;\n");
  382. for (ct2=0; ct2 < api->paramCount; ct2++) {
  383. if (api->params[ct2].ptrLevel) {
  384. fprintf(f, " totalSize += cmd->%s_length;\n", api->params[ct2].name);
  385. }
  386. }
  387. fprintf(f, " if ((totalSize != 0) && (cmdSizeBytes == sizeof(RS_CMD_%s))) {\n", api->name);
  388. fprintf(f, " con->mIO.coreSetReturn(NULL, 0);\n");
  389. fprintf(f, " }\n");
  390. } else if (api->ret.typeName[0]) {
  391. fprintf(f, " con->mIO.coreSetReturn(&ret, sizeof(ret));\n");
  392. } else if (api->sync || needFlush) {
  393. fprintf(f, " con->mIO.coreSetReturn(NULL, 0);\n");
  394. }
  395. fprintf(f, "};\n\n");
  396. }
  397. // Generate the globally accessible table of playback functions.
  398. fprintf(f, "RsPlaybackLocalFunc gPlaybackFuncs[%i] = {\n", apiCount + 1);
  399. fprintf(f, " NULL,\n");
  400. for (ct=0; ct < apiCount; ct++) {
  401. if (apis[ct].direct) {
  402. fprintf(f, " NULL,\n");
  403. } else {
  404. fprintf(f, " %s%s,\n", RS_PLAYBACK_PREFIX, apis[ct].name);
  405. }
  406. }
  407. fprintf(f, "};\n");
  408. fprintf(f, "};\n");
  409. fprintf(f, "};\n");
  410. }
  411. void yylex();
  412. int main(int argc, char **argv) {
  413. if (argc != 3) {
  414. fprintf(stderr, "usage: %s commandFile outFile\n", argv[0]);
  415. return 1;
  416. }
  417. const char* rsgFile = argv[1];
  418. const char* outFile = argv[2];
  419. FILE* input = fopen(rsgFile, "re");
  420. char choice = fgetc(input);
  421. fclose(input);
  422. if (choice < '0' || choice > '3') {
  423. fprintf(stderr, "Uknown command: \'%c\'\n", choice);
  424. return -2;
  425. }
  426. yylex();
  427. // printf("# of lines = %d\n", num_lines);
  428. FILE *f = fopen(outFile, "we");
  429. printFileHeader(f);
  430. switch (choice) {
  431. case '0': // rsgApiStructs.h
  432. {
  433. fprintf(f, "\n");
  434. fprintf(f, "#include \"rsContext.h\"\n");
  435. fprintf(f, "#include \"rsFifo.h\"\n");
  436. fprintf(f, "\n");
  437. fprintf(f, "namespace android {\n");
  438. fprintf(f, "namespace renderscript {\n");
  439. printStructures(f);
  440. printFuncDecls(f, RS_INTERNAL_PREFIX, 1, 0);
  441. printPlaybackFuncs(f, RS_PLAYBACK_PREFIX);
  442. fprintf(f, "typedef void (*RsPlaybackLocalFunc)(Context *, const void *, size_t sizeBytes);\n");
  443. fprintf(f, "extern RsPlaybackLocalFunc gPlaybackFuncs[%i];\n", apiCount + 1);
  444. fprintf(f, "}\n");
  445. fprintf(f, "}\n");
  446. }
  447. break;
  448. case '1': // rsgApiFuncDecl.h
  449. {
  450. printFuncDecls(f, "rs", 0, 1);
  451. }
  452. break;
  453. case '2': // rsgApi.cpp
  454. {
  455. printApiCpp(f);
  456. }
  457. break;
  458. case '3': // rsgApiReplay.cpp
  459. {
  460. printPlaybackCpp(f);
  461. }
  462. break;
  463. }
  464. fclose(f);
  465. return 0;
  466. }