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