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 24void 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 42void 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 77void 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 85void 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 95void 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 119void 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 strcpy(t, api->name); 124 if (strlen(prefix) == 0) { 125 if (t[0] > 'A' && t[0] < 'Z') { 126 t[0] -= 'A' - 'a'; 127 } 128 } 129 fprintf(f, " (* %s%s) (", prefix, api->name); 130 } else { 131 fprintf(f, " %s%s (", prefix, api->name); 132 } 133 if (!api->nocontext) { 134 if (addContext) { 135 fprintf(f, "Context *"); 136 } else { 137 fprintf(f, "RsContext rsc"); 138 } 139 } 140 printArgList(f, api, !api->nocontext); 141 fprintf(f, ")"); 142} 143 144void printFuncDecls(FILE *f, const char *prefix, int addContext, int externC) { 145 int ct; 146 for (ct=0; ct < apiCount; ct++) { 147 if (externC) { 148 fprintf(f, "extern \"C\" "); 149 } 150 printFuncDecl(f, &apis[ct], prefix, addContext, 0); 151 fprintf(f, ";\n"); 152 } 153 fprintf(f, "\n\n"); 154} 155 156void printPlaybackFuncs(FILE *f, const char *prefix) { 157 int ct; 158 for (ct=0; ct < apiCount; ct++) { 159 if (apis[ct].direct) { 160 continue; 161 } 162 163 fprintf(f, "void %s%s (Context *, const void *);\n", prefix, apis[ct].name); 164 } 165} 166 167static int hasInlineDataPointers(const ApiEntry * api) { 168 int ret = 0; 169 int ct; 170 if (api->sync || api->ret.typeName[0]) { 171 return 0; 172 } 173 for (ct=0; ct < api->paramCount; ct++) { 174 const VarType *vt = &api->params[ct]; 175 176 if (!vt->isConst && vt->ptrLevel) { 177 // Non-const pointers cannot be inlined. 178 return 0; 179 } 180 if (vt->ptrLevel > 1) { 181 // not handled yet. 182 return 0; 183 } 184 185 if (vt->isConst && vt->ptrLevel) { 186 // Non-const pointers cannot be inlined. 187 ret = 1; 188 } 189 } 190 return ret; 191} 192 193void printApiCpp(FILE *f) { 194 int ct; 195 int ct2; 196 197 fprintf(f, RSG_API_CPP_DOC); 198 199 fprintf(f, "#include \"rsDevice.h\"\n"); 200 fprintf(f, "#include \"rsContext.h\"\n"); 201 fprintf(f, "#include \"rsThreadIO.h\"\n"); 202 fprintf(f, "#include \"rsgApiStructs.h\"\n"); 203 fprintf(f, "#include \"rsgApiFuncDecl.h\"\n"); 204 fprintf(f, "#include \"rsFifo.h\"\n"); 205 fprintf(f, "\n"); 206 fprintf(f, "using namespace android;\n"); 207 fprintf(f, "using namespace android::renderscript;\n"); 208 fprintf(f, "\n"); 209 210 // Generate RS funcs that send messages on the local FIFO. 211 for (ct=0; ct < apiCount; ct++) { 212 int needFlush = 0; 213 const ApiEntry * api = &apis[ct]; 214 215 fprintf(f, "static "); 216 printFuncDecl(f, api, LOCAL_FIFO_PREFIX, 0, 0); 217 fprintf(f, "\n{\n"); 218 if (api->direct) { 219 fprintf(f, " "); 220 if (api->ret.typeName[0]) { 221 fprintf(f, "return "); 222 } 223 fprintf(f, RS_INTERNAL_PREFIX "%s(", api->name); 224 if (!api->nocontext) { 225 fprintf(f, "(Context *)rsc"); 226 } 227 for (ct2=0; ct2 < api->paramCount; ct2++) { 228 const VarType *vt = &api->params[ct2]; 229 if (ct2 > 0 || !api->nocontext) { 230 fprintf(f, ", "); 231 } 232 fprintf(f, "%s", vt->name); 233 } 234 fprintf(f, ");\n"); 235 } else if (api->handcodeApi) { 236 // handle handcode path 237 fprintf(f, " " LOCAL_FIFO_PREFIX "%s_handcode(", api->name); 238 if (!api->nocontext) { 239 fprintf(f, "(Context *)rsc"); 240 } 241 for (ct2=0; ct2 < api->paramCount; ct2++) { 242 const VarType *vt = &api->params[ct2]; 243 if (ct2 > 0 || !api->nocontext) { 244 fprintf(f, ", "); 245 } 246 fprintf(f, "%s", vt->name); 247 } 248 fprintf(f, ");\n"); 249 250 } else { 251 // handle synchronous path 252 fprintf(f, " if (((Context *)rsc)->isSynchronous()) {\n"); 253 fprintf(f, " "); 254 if (api->ret.typeName[0]) { 255 fprintf(f, "return "); 256 } 257 fprintf(f, RS_INTERNAL_PREFIX "%s(", api->name); 258 if (!api->nocontext) { 259 fprintf(f, "(Context *)rsc"); 260 } 261 for (ct2=0; ct2 < api->paramCount; ct2++) { 262 const VarType *vt = &api->params[ct2]; 263 if (ct2 > 0 || !api->nocontext) { 264 fprintf(f, ", "); 265 } 266 fprintf(f, "%s", vt->name); 267 } 268 fprintf(f, ");\n"); 269 if (!api->ret.typeName[0]) { 270 fprintf(f, " return;"); 271 } 272 fprintf(f, " }\n\n"); 273 274 fprintf(f, " ThreadIO *io = &((Context *)rsc)->mIO;\n"); 275 fprintf(f, " const size_t size = sizeof(RS_CMD_%s);\n", api->name); 276 if (hasInlineDataPointers(api)) { 277 fprintf(f, " size_t dataSize = 0;\n"); 278 for (ct2=0; ct2 < api->paramCount; ct2++) { 279 const VarType *vt = &api->params[ct2]; 280 if (vt->isConst && vt->ptrLevel) { 281 fprintf(f, " dataSize += %s_length;\n", vt->name); 282 } 283 } 284 } 285 286 //fprintf(f, " ALOGE(\"add command %s\\n\");\n", api->name); 287 if (hasInlineDataPointers(api)) { 288 fprintf(f, " RS_CMD_%s *cmd = NULL;\n", api->name); 289 fprintf(f, " if (dataSize < io->getMaxInlineSize()) {;\n"); 290 fprintf(f, " cmd = static_cast<RS_CMD_%s *>(io->coreHeader(RS_CMD_ID_%s, dataSize + size));\n", api->name, api->name); 291 fprintf(f, " } else {\n"); 292 fprintf(f, " cmd = static_cast<RS_CMD_%s *>(io->coreHeader(RS_CMD_ID_%s, size));\n", api->name, api->name); 293 fprintf(f, " }\n"); 294 fprintf(f, " uint8_t *payload = (uint8_t *)&cmd[1];\n"); 295 } else { 296 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); 297 } 298 299 for (ct2=0; ct2 < api->paramCount; ct2++) { 300 const VarType *vt = &api->params[ct2]; 301 needFlush += vt->ptrLevel; 302 if (vt->ptrLevel && hasInlineDataPointers(api)) { 303 fprintf(f, " if (%s_length == 0) {\n", vt->name); 304 fprintf(f, " cmd->%s = NULL;\n", vt->name); 305 fprintf(f, " } else if (dataSize < io->getMaxInlineSize()) {\n"); 306 fprintf(f, " memcpy(payload, %s, %s_length);\n", vt->name, vt->name); 307 fprintf(f, " cmd->%s = (", vt->name); 308 printVarType(f, vt); 309 fprintf(f, ")(payload - ((uint8_t *)&cmd[1]));\n"); 310 fprintf(f, " payload += %s_length;\n", vt->name); 311 fprintf(f, " } else {\n"); 312 fprintf(f, " cmd->%s = %s;\n", vt->name, vt->name); 313 fprintf(f, " }\n"); 314 315 } else { 316 fprintf(f, " cmd->%s = %s;\n", vt->name, vt->name); 317 } 318 } 319 if (api->ret.typeName[0] || api->sync) { 320 needFlush = 1; 321 } 322 323 fprintf(f, " io->coreCommit();\n"); 324 if (hasInlineDataPointers(api)) { 325 fprintf(f, " if (dataSize >= io->getMaxInlineSize()) {\n"); 326 fprintf(f, " io->coreGetReturn(NULL, 0);\n"); 327 fprintf(f, " }\n"); 328 } else if (api->ret.typeName[0]) { 329 fprintf(f, "\n "); 330 printVarType(f, &api->ret); 331 fprintf(f, " ret;\n"); 332 fprintf(f, " io->coreGetReturn(&ret, sizeof(ret));\n"); 333 fprintf(f, " return ret;\n"); 334 } else if (needFlush) { 335 fprintf(f, " io->coreGetReturn(NULL, 0);\n"); 336 } 337 } 338 fprintf(f, "};\n\n"); 339 } 340 341 fprintf(f, "\n"); 342 343 for (ct=0; ct < apiCount; ct++) { 344 int needFlush = 0; 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 374void 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 465void yylex(); 466 467int 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, "r"); 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, "w"); 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