Home | History | Annotate | Download | only in rs
      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         int needFlush = 0;
    346         const ApiEntry * api = &apis[ct];
    347 
    348         fprintf(f, "extern \"C\" ");
    349 
    350         printFuncDecl(f, api, "rs", 0, 0);
    351         fprintf(f, "\n{\n");
    352         fprintf(f, "    ");
    353         if (api->ret.typeName[0]) {
    354             fprintf(f, "return ");
    355         }
    356         fprintf(f, LOCAL_FIFO_PREFIX "%s(", api->name);
    357 
    358         if (!api->nocontext) {
    359             fprintf(f, "(Context *)rsc");
    360         }
    361 
    362         for (ct2=0; ct2 < api->paramCount; ct2++) {
    363             const VarType *vt = &api->params[ct2];
    364             if (ct2 > 0 || !api->nocontext) {
    365                 fprintf(f, ", ");
    366             }
    367             fprintf(f, "%s", vt->name);
    368         }
    369         fprintf(f, ");\n");
    370         fprintf(f, "}\n\n");
    371     }
    372 
    373 }
    374 
    375 void printPlaybackCpp(FILE *f) {
    376     int ct;
    377     int ct2;
    378 
    379     fprintf(f, RSG_API_REPLAY_CPP_DOC);
    380 
    381     fprintf(f, "#include \"rsDevice.h\"\n");
    382     fprintf(f, "#include \"rsContext.h\"\n");
    383     fprintf(f, "#include \"rsThreadIO.h\"\n");
    384     fprintf(f, "#include \"rsgApiStructs.h\"\n");
    385     fprintf(f, "#include \"rsgApiFuncDecl.h\"\n");
    386     fprintf(f, "\n");
    387     fprintf(f, "namespace android {\n");
    388     fprintf(f, "namespace renderscript {\n");
    389     fprintf(f, "\n");
    390 
    391     // Generate functions to play back messages sent from the local FIFO.
    392     for (ct=0; ct < apiCount; ct++) {
    393         const ApiEntry * api = &apis[ct];
    394         int needFlush = 0;
    395 
    396         if (api->direct) {
    397             continue;
    398         }
    399 
    400         fprintf(f, "void " RS_PLAYBACK_PREFIX "%s(Context *con, const void *vp, size_t cmdSizeBytes) {\n", api->name);
    401         fprintf(f, "    const RS_CMD_%s *cmd = static_cast<const RS_CMD_%s *>(vp);\n", api->name, api->name);
    402 
    403         if (hasInlineDataPointers(api)) {
    404             fprintf(f, "    const uint8_t *baseData = 0;\n");
    405             fprintf(f, "    if (cmdSizeBytes != sizeof(RS_CMD_%s)) {\n", api->name);
    406             fprintf(f, "        baseData = &((const uint8_t *)vp)[sizeof(*cmd)];\n");
    407             fprintf(f, "    }\n");
    408         }
    409 
    410         fprintf(f, "    ");
    411         if (api->ret.typeName[0]) {
    412             fprintf(f, "\n    ");
    413             printVarType(f, &api->ret);
    414             fprintf(f, " ret = ");
    415         }
    416         fprintf(f, RS_INTERNAL_PREFIX "%s(con", api->name);
    417         for (ct2=0; ct2 < api->paramCount; ct2++) {
    418             const VarType *vt = &api->params[ct2];
    419             needFlush += vt->ptrLevel;
    420 
    421             if (hasInlineDataPointers(api) && vt->ptrLevel) {
    422                 fprintf(f, ",\n           cmd->%s_length == 0 ? NULL : (const %s *)&baseData[(intptr_t)cmd->%s]",
    423                         vt->name, vt->typeName, vt->name);
    424             } else {
    425                 fprintf(f, ",\n           cmd->%s", vt->name);
    426             }
    427         }
    428         fprintf(f, ");\n");
    429 
    430         if (hasInlineDataPointers(api)) {
    431             fprintf(f, "    size_t totalSize = 0;\n");
    432             for (ct2=0; ct2 < api->paramCount; ct2++) {
    433                 if (api->params[ct2].ptrLevel) {
    434                     fprintf(f, "    totalSize += cmd->%s_length;\n", api->params[ct2].name);
    435                 }
    436             }
    437 
    438             fprintf(f, "    if ((totalSize != 0) && (cmdSizeBytes == sizeof(RS_CMD_%s))) {\n", api->name);
    439             fprintf(f, "        con->mIO.coreSetReturn(NULL, 0);\n");
    440             fprintf(f, "    }\n");
    441         } else if (api->ret.typeName[0]) {
    442             fprintf(f, "    con->mIO.coreSetReturn(&ret, sizeof(ret));\n");
    443         } else if (api->sync || needFlush) {
    444             fprintf(f, "    con->mIO.coreSetReturn(NULL, 0);\n");
    445         }
    446 
    447         fprintf(f, "};\n\n");
    448     }
    449 
    450     // Generate the globally accessible table of playback functions.
    451     fprintf(f, "RsPlaybackLocalFunc gPlaybackFuncs[%i] = {\n", apiCount + 1);
    452     fprintf(f, "    NULL,\n");
    453     for (ct=0; ct < apiCount; ct++) {
    454         if (apis[ct].direct) {
    455             fprintf(f, "    NULL,\n");
    456         } else {
    457             fprintf(f, "    %s%s,\n", RS_PLAYBACK_PREFIX, apis[ct].name);
    458         }
    459     }
    460     fprintf(f, "};\n");
    461 
    462     fprintf(f, "};\n");
    463     fprintf(f, "};\n");
    464 }
    465 
    466 void yylex();
    467 
    468 int main(int argc, char **argv) {
    469     if (argc != 3) {
    470         fprintf(stderr, "usage: %s commandFile outFile\n", argv[0]);
    471         return 1;
    472     }
    473     const char* rsgFile = argv[1];
    474     const char* outFile = argv[2];
    475     FILE* input = fopen(rsgFile, "r");
    476 
    477     char choice = fgetc(input);
    478     fclose(input);
    479 
    480     if (choice < '0' || choice > '3') {
    481         fprintf(stderr, "Uknown command: \'%c\'\n", choice);
    482         return -2;
    483     }
    484 
    485     yylex();
    486     // printf("# of lines = %d\n", num_lines);
    487 
    488     FILE *f = fopen(outFile, "w");
    489 
    490     printFileHeader(f);
    491     switch (choice) {
    492         case '0': // rsgApiStructs.h
    493         {
    494             fprintf(f, "\n");
    495             fprintf(f, "#include \"rsContext.h\"\n");
    496             fprintf(f, "#include \"rsFifo.h\"\n");
    497             fprintf(f, "\n");
    498             fprintf(f, "namespace android {\n");
    499             fprintf(f, "namespace renderscript {\n");
    500             printStructures(f);
    501             printFuncDecls(f, RS_INTERNAL_PREFIX, 1, 0);
    502             printPlaybackFuncs(f, RS_PLAYBACK_PREFIX);
    503             fprintf(f, "typedef void (*RsPlaybackLocalFunc)(Context *, const void *, size_t sizeBytes);\n");
    504             fprintf(f, "extern RsPlaybackLocalFunc gPlaybackFuncs[%i];\n", apiCount + 1);
    505 
    506             fprintf(f, "}\n");
    507             fprintf(f, "}\n");
    508         }
    509         break;
    510 
    511         case '1': // rsgApiFuncDecl.h
    512         {
    513             printFuncDecls(f, "rs", 0, 1);
    514         }
    515         break;
    516 
    517         case '2': // rsgApi.cpp
    518         {
    519             printApiCpp(f);
    520         }
    521         break;
    522 
    523         case '3': // rsgApiReplay.cpp
    524         {
    525             printPlaybackCpp(f);
    526         }
    527         break;
    528     }
    529     fclose(f);
    530     return 0;
    531 }
    532