Home | History | Annotate | Line # | Download | only in decode
      1 /* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
      2 
      3 /*
      4  * Copyright (C) 2014 Rob Clark <robclark (at) freedesktop.org>
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the next
     14  * paragraph) shall be included in all copies or substantial portions of the
     15  * Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     23  * SOFTWARE.
     24  *
     25  * Authors:
     26  *    Rob Clark <robclark (at) freedesktop.org>
     27  */
     28 
     29 #define LUA_COMPAT_APIINTCASTS
     30 
     31 #include <assert.h>
     32 #include <lauxlib.h>
     33 #include <lua.h>
     34 #include <lualib.h>
     35 #include <stdio.h>
     36 #include <stdlib.h>
     37 #include <string.h>
     38 
     39 #include "cffdec.h"
     40 #include "rnnutil.h"
     41 #include "script.h"
     42 
     43 static lua_State *L;
     44 
     45 #if 0
     46 #define DBG(fmt, ...)                                                          \
     47    do {                                                                        \
     48       printf(" ** %s:%d ** " fmt "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__); \
     49    } while (0)
     50 #else
     51 #define DBG(fmt, ...)                                                          \
     52    do {                                                                        \
     53    } while (0)
     54 #endif
     55 
     56 /* An rnn based decoder, which can either be decoding current register
     57  * values, or domain based decoding of a pm4 packet.
     58  *
     59  */
     60 struct rnndec {
     61    struct rnn base;
     62 
     63    /* for pm4 packet decoding: */
     64    uint32_t sizedwords;
     65    uint32_t *dwords;
     66 };
     67 
     68 static inline struct rnndec *
     69 to_rnndec(struct rnn *rnn)
     70 {
     71    return (struct rnndec *)rnn;
     72 }
     73 
     74 static uint32_t
     75 rnn_val(struct rnn *rnn, uint32_t regbase)
     76 {
     77    struct rnndec *rnndec = to_rnndec(rnn);
     78 
     79    if (!rnndec->sizedwords) {
     80       return reg_val(regbase);
     81    } else if (regbase < rnndec->sizedwords) {
     82       return rnndec->dwords[regbase];
     83    } else {
     84       // XXX throw an error
     85       return -1;
     86    }
     87 }
     88 
     89 /* does not return */
     90 static void
     91 error(const char *fmt)
     92 {
     93    fprintf(stderr, fmt, lua_tostring(L, -1));
     94    exit(1);
     95 }
     96 
     97 /*
     98  * An enum type that can be used as string or number:
     99  */
    100 
    101 struct rnndenum {
    102    const char *str;
    103    int val;
    104 };
    105 
    106 static int
    107 l_meta_rnn_enum_tostring(lua_State *L)
    108 {
    109    struct rnndenum *e = lua_touserdata(L, 1);
    110    if (e->str) {
    111       lua_pushstring(L, e->str);
    112    } else {
    113       char buf[32];
    114       sprintf(buf, "%u", e->val);
    115       lua_pushstring(L, buf);
    116    }
    117    return 1;
    118 }
    119 
    120 /* so, this doesn't actually seem to be implemented yet, but hopefully
    121  * some day lua comes to it's senses
    122  */
    123 static int
    124 l_meta_rnn_enum_tonumber(lua_State *L)
    125 {
    126    struct rnndenum *e = lua_touserdata(L, 1);
    127    lua_pushinteger(L, e->val);
    128    return 1;
    129 }
    130 
    131 static const struct luaL_Reg l_meta_rnn_enum[] = {
    132    {"__tostring", l_meta_rnn_enum_tostring},
    133    {"__tonumber", l_meta_rnn_enum_tonumber},
    134    {NULL, NULL} /* sentinel */
    135 };
    136 
    137 static void
    138 pushenum(struct lua_State *L, int val, struct rnnenum *info)
    139 {
    140    struct rnndenum *e = lua_newuserdata(L, sizeof(*e));
    141 
    142    e->val = val;
    143    e->str = NULL;
    144 
    145    for (int i = 0; i < info->valsnum; i++) {
    146       if (info->vals[i]->valvalid && (info->vals[i]->value == val)) {
    147          e->str = info->vals[i]->name;
    148          break;
    149       }
    150    }
    151 
    152    luaL_newmetatable(L, "rnnmetaenum");
    153    luaL_setfuncs(L, l_meta_rnn_enum, 0);
    154    lua_pop(L, 1);
    155 
    156    luaL_setmetatable(L, "rnnmetaenum");
    157 }
    158 
    159 /* Expose rnn decode to script environment as "rnn" library:
    160  */
    161 
    162 struct rnndoff {
    163    struct rnn *rnn;
    164    struct rnndelem *elem;
    165    uint64_t offset;
    166 };
    167 
    168 static void
    169 push_rnndoff(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
    170              uint64_t offset)
    171 {
    172    struct rnndoff *rnndoff = lua_newuserdata(L, sizeof(*rnndoff));
    173    rnndoff->rnn = rnn;
    174    rnndoff->elem = elem;
    175    rnndoff->offset = offset;
    176 }
    177 
    178 static int l_rnn_etype_array(lua_State *L, struct rnn *rnn,
    179                              struct rnndelem *elem, uint64_t offset);
    180 static int l_rnn_etype_reg(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
    181                            uint64_t offset);
    182 
    183 static int
    184 pushdecval(struct lua_State *L, struct rnn *rnn, uint32_t regval,
    185            struct rnntypeinfo *info)
    186 {
    187    union rnndecval val;
    188    switch (rnn_decodelem(rnn, info, regval, &val)) {
    189    case RNN_TTYPE_ENUM:
    190    case RNN_TTYPE_INLINE_ENUM:
    191       pushenum(L, val.i, info->eenum);
    192       return 1;
    193    case RNN_TTYPE_INT:
    194       lua_pushinteger(L, val.i);
    195       return 1;
    196    case RNN_TTYPE_UINT:
    197    case RNN_TTYPE_HEX:
    198       lua_pushunsigned(L, val.u);
    199       return 1;
    200    case RNN_TTYPE_FLOAT:
    201       lua_pushnumber(L, val.f);
    202       return 1;
    203    case RNN_TTYPE_BOOLEAN:
    204       lua_pushboolean(L, val.u);
    205       return 1;
    206    case RNN_TTYPE_INVALID:
    207    default:
    208       return 0;
    209    }
    210 }
    211 
    212 static int
    213 l_rnn_etype(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
    214             uint64_t offset)
    215 {
    216    int ret;
    217    uint32_t regval;
    218    DBG("elem=%p (%d), offset=%lu", elem, elem->type, offset);
    219    switch (elem->type) {
    220    case RNN_ETYPE_REG:
    221       /* if a register has no bitfields, just return
    222        * the raw value:
    223        */
    224       regval = rnn_val(rnn, offset);
    225       regval <<= elem->typeinfo.shr;
    226       ret = pushdecval(L, rnn, regval, &elem->typeinfo);
    227       if (ret)
    228          return ret;
    229       return l_rnn_etype_reg(L, rnn, elem, offset);
    230    case RNN_ETYPE_ARRAY:
    231       return l_rnn_etype_array(L, rnn, elem, offset);
    232    default:
    233       /* hmm.. */
    234       printf("unhandled type: %d\n", elem->type);
    235       return 0;
    236    }
    237 }
    238 
    239 /*
    240  * Struct Object:
    241  * To implement stuff like 'RB_MRT[n].CONTROL' we need a struct-object
    242  * to represent the current array index (ie. 'RB_MRT[n]')
    243  */
    244 
    245 static int
    246 l_rnn_struct_meta_index(lua_State *L)
    247 {
    248    struct rnndoff *rnndoff = lua_touserdata(L, 1);
    249    const char *name = lua_tostring(L, 2);
    250    struct rnndelem *elem = rnndoff->elem;
    251    int i;
    252 
    253    for (i = 0; i < elem->subelemsnum; i++) {
    254       struct rnndelem *subelem = elem->subelems[i];
    255       if (!strcmp(name, subelem->name)) {
    256          return l_rnn_etype(L, rnndoff->rnn, subelem,
    257                             rnndoff->offset + subelem->offset);
    258       }
    259    }
    260 
    261    return 0;
    262 }
    263 
    264 static const struct luaL_Reg l_meta_rnn_struct[] = {
    265    {"__index", l_rnn_struct_meta_index}, {NULL, NULL} /* sentinel */
    266 };
    267 
    268 static int
    269 l_rnn_etype_struct(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
    270                    uint64_t offset)
    271 {
    272    push_rnndoff(L, rnn, elem, offset);
    273 
    274    luaL_newmetatable(L, "rnnmetastruct");
    275    luaL_setfuncs(L, l_meta_rnn_struct, 0);
    276    lua_pop(L, 1);
    277 
    278    luaL_setmetatable(L, "rnnmetastruct");
    279 
    280    return 1;
    281 }
    282 
    283 /*
    284  * Array Object:
    285  */
    286 
    287 static int
    288 l_rnn_array_meta_index(lua_State *L)
    289 {
    290    struct rnndoff *rnndoff = lua_touserdata(L, 1);
    291    int idx = lua_tointeger(L, 2);
    292    struct rnndelem *elem = rnndoff->elem;
    293    uint64_t offset = rnndoff->offset + (elem->stride * idx);
    294 
    295    DBG("rnndoff=%p, idx=%d, numsubelems=%d", rnndoff, idx,
    296        rnndoff->elem->subelemsnum);
    297 
    298    /* if just a single sub-element, it is directly a register,
    299     * otherwise we need to accumulate the array index while
    300     * we wait for the register name within the array..
    301     */
    302    if (elem->subelemsnum == 1) {
    303       return l_rnn_etype(L, rnndoff->rnn, elem->subelems[0], offset);
    304    } else {
    305       return l_rnn_etype_struct(L, rnndoff->rnn, elem, offset);
    306    }
    307 
    308    return 0;
    309 }
    310 
    311 static const struct luaL_Reg l_meta_rnn_array[] = {
    312    {"__index", l_rnn_array_meta_index}, {NULL, NULL} /* sentinel */
    313 };
    314 
    315 static int
    316 l_rnn_etype_array(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
    317                   uint64_t offset)
    318 {
    319    push_rnndoff(L, rnn, elem, offset);
    320 
    321    luaL_newmetatable(L, "rnnmetaarray");
    322    luaL_setfuncs(L, l_meta_rnn_array, 0);
    323    lua_pop(L, 1);
    324 
    325    luaL_setmetatable(L, "rnnmetaarray");
    326 
    327    return 1;
    328 }
    329 
    330 /*
    331  * Register element:
    332  */
    333 
    334 static int
    335 l_rnn_reg_meta_index(lua_State *L)
    336 {
    337    struct rnndoff *rnndoff = lua_touserdata(L, 1);
    338    const char *name = lua_tostring(L, 2);
    339    struct rnndelem *elem = rnndoff->elem;
    340    struct rnntypeinfo *info = &elem->typeinfo;
    341    struct rnnbitfield **bitfields;
    342    int bitfieldsnum;
    343    int i;
    344 
    345    switch (info->type) {
    346    case RNN_TTYPE_BITSET:
    347       bitfields = info->ebitset->bitfields;
    348       bitfieldsnum = info->ebitset->bitfieldsnum;
    349       break;
    350    case RNN_TTYPE_INLINE_BITSET:
    351       bitfields = info->bitfields;
    352       bitfieldsnum = info->bitfieldsnum;
    353       break;
    354    default:
    355       printf("invalid register type: %d\n", info->type);
    356       return 0;
    357    }
    358 
    359    for (i = 0; i < bitfieldsnum; i++) {
    360       struct rnnbitfield *bf = bitfields[i];
    361       if (!strcmp(name, bf->name)) {
    362          uint32_t regval = rnn_val(rnndoff->rnn, rnndoff->offset);
    363 
    364          regval &= typeinfo_mask(&bf->typeinfo);
    365          regval >>= bf->typeinfo.low;
    366          regval <<= bf->typeinfo.shr;
    367 
    368          DBG("name=%s, info=%p, subelemsnum=%d, type=%d, regval=%x", name, info,
    369              rnndoff->elem->subelemsnum, bf->typeinfo.type, regval);
    370 
    371          return pushdecval(L, rnndoff->rnn, regval, &bf->typeinfo);
    372       }
    373    }
    374 
    375    printf("invalid member: %s\n", name);
    376    return 0;
    377 }
    378 
    379 static int
    380 l_rnn_reg_meta_tostring(lua_State *L)
    381 {
    382    struct rnndoff *rnndoff = lua_touserdata(L, 1);
    383    uint32_t regval = rnn_val(rnndoff->rnn, rnndoff->offset);
    384    struct rnndecaddrinfo *info = rnn_reginfo(rnndoff->rnn, rnndoff->offset);
    385    char *decoded;
    386    if (info && info->typeinfo) {
    387       decoded = rnndec_decodeval(rnndoff->rnn->vc, info->typeinfo, regval);
    388    } else {
    389       asprintf(&decoded, "%08x", regval);
    390    }
    391    lua_pushstring(L, decoded);
    392    free(decoded);
    393    if (info) {
    394       free(info->name);
    395       free(info);
    396    }
    397    return 1;
    398 }
    399 
    400 static int
    401 l_rnn_reg_meta_tonumber(lua_State *L)
    402 {
    403    struct rnndoff *rnndoff = lua_touserdata(L, 1);
    404    uint32_t regval = rnn_val(rnndoff->rnn, rnndoff->offset);
    405 
    406    regval <<= rnndoff->elem->typeinfo.shr;
    407 
    408    lua_pushnumber(L, regval);
    409    return 1;
    410 }
    411 
    412 static const struct luaL_Reg l_meta_rnn_reg[] = {
    413    {"__index", l_rnn_reg_meta_index},
    414    {"__tostring", l_rnn_reg_meta_tostring},
    415    {"__tonumber", l_rnn_reg_meta_tonumber},
    416    {NULL, NULL} /* sentinel */
    417 };
    418 
    419 static int
    420 l_rnn_etype_reg(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
    421                 uint64_t offset)
    422 {
    423    push_rnndoff(L, rnn, elem, offset);
    424 
    425    luaL_newmetatable(L, "rnnmetareg");
    426    luaL_setfuncs(L, l_meta_rnn_reg, 0);
    427    lua_pop(L, 1);
    428 
    429    luaL_setmetatable(L, "rnnmetareg");
    430 
    431    return 1;
    432 }
    433 
    434 /*
    435  *
    436  */
    437 
    438 static int
    439 l_rnn_meta_index(lua_State *L)
    440 {
    441    struct rnn *rnn = lua_touserdata(L, 1);
    442    const char *name = lua_tostring(L, 2);
    443    struct rnndelem *elem;
    444 
    445    elem = rnn_regelem(rnn, name);
    446    if (!elem)
    447       return 0;
    448 
    449    return l_rnn_etype(L, rnn, elem, elem->offset);
    450 }
    451 
    452 static int
    453 l_rnn_meta_gc(lua_State *L)
    454 {
    455    // TODO
    456    // struct rnn *rnn = lua_touserdata(L, 1);
    457    // rnn_deinit(rnn);
    458    return 0;
    459 }
    460 
    461 static const struct luaL_Reg l_meta_rnn[] = {
    462    {"__index", l_rnn_meta_index},
    463    {"__gc", l_rnn_meta_gc},
    464    {NULL, NULL} /* sentinel */
    465 };
    466 
    467 static int
    468 l_rnn_init(lua_State *L)
    469 {
    470    const char *gpuname = lua_tostring(L, 1);
    471    struct rnndec *rnndec = lua_newuserdata(L, sizeof(*rnndec));
    472    _rnn_init(&rnndec->base, 0);
    473    rnn_load(&rnndec->base, gpuname);
    474    rnndec->sizedwords = 0;
    475 
    476    luaL_newmetatable(L, "rnnmeta");
    477    luaL_setfuncs(L, l_meta_rnn, 0);
    478    lua_pop(L, 1);
    479 
    480    luaL_setmetatable(L, "rnnmeta");
    481 
    482    return 1;
    483 }
    484 
    485 static int
    486 l_rnn_enumname(lua_State *L)
    487 {
    488    struct rnn *rnn = lua_touserdata(L, 1);
    489    const char *name = lua_tostring(L, 2);
    490    uint32_t val = (uint32_t)lua_tonumber(L, 3);
    491    lua_pushstring(L, rnn_enumname(rnn, name, val));
    492    return 1;
    493 }
    494 
    495 static int
    496 l_rnn_regname(lua_State *L)
    497 {
    498    struct rnn *rnn = lua_touserdata(L, 1);
    499    uint32_t regbase = (uint32_t)lua_tonumber(L, 2);
    500    lua_pushstring(L, rnn_regname(rnn, regbase, 1));
    501    return 1;
    502 }
    503 
    504 static int
    505 l_rnn_regval(lua_State *L)
    506 {
    507    struct rnn *rnn = lua_touserdata(L, 1);
    508    uint32_t regbase = (uint32_t)lua_tonumber(L, 2);
    509    uint32_t regval = (uint32_t)lua_tonumber(L, 3);
    510    struct rnndecaddrinfo *info = rnn_reginfo(rnn, regbase);
    511    char *decoded;
    512    if (info && info->typeinfo) {
    513       decoded = rnndec_decodeval(rnn->vc, info->typeinfo, regval);
    514    } else {
    515       asprintf(&decoded, "%08x", regval);
    516    }
    517    lua_pushstring(L, decoded);
    518    free(decoded);
    519    if (info) {
    520       free(info->name);
    521       free(info);
    522    }
    523    return 1;
    524 }
    525 
    526 static const struct luaL_Reg l_rnn[] = {
    527    {"init", l_rnn_init},
    528    {"enumname", l_rnn_enumname},
    529    {"regname", l_rnn_regname},
    530    {"regval", l_rnn_regval},
    531    {NULL, NULL} /* sentinel */
    532 };
    533 
    534 /* Expose the register state to script enviroment as a "regs" library:
    535  */
    536 
    537 static int
    538 l_reg_written(lua_State *L)
    539 {
    540    uint32_t regbase = (uint32_t)lua_tonumber(L, 1);
    541    lua_pushnumber(L, reg_written(regbase));
    542    return 1;
    543 }
    544 
    545 static int
    546 l_reg_lastval(lua_State *L)
    547 {
    548    uint32_t regbase = (uint32_t)lua_tonumber(L, 1);
    549    lua_pushnumber(L, reg_lastval(regbase));
    550    return 1;
    551 }
    552 
    553 static int
    554 l_reg_val(lua_State *L)
    555 {
    556    uint32_t regbase = (uint32_t)lua_tonumber(L, 1);
    557    lua_pushnumber(L, reg_val(regbase));
    558    return 1;
    559 }
    560 
    561 static const struct luaL_Reg l_regs[] = {
    562    {"written", l_reg_written},
    563    {"lastval", l_reg_lastval},
    564    {"val", l_reg_val},
    565    {NULL, NULL} /* sentinel */
    566 };
    567 
    568 /* Expose API to lookup snapshot buffers:
    569  */
    570 
    571 uint64_t gpubaseaddr(uint64_t gpuaddr);
    572 unsigned hostlen(uint64_t gpuaddr);
    573 
    574 /* given address, return base-address of buffer: */
    575 static int
    576 l_bo_base(lua_State *L)
    577 {
    578    uint64_t addr = (uint64_t)lua_tonumber(L, 1);
    579    lua_pushnumber(L, gpubaseaddr(addr));
    580    return 1;
    581 }
    582 
    583 /* given address, return the remaining size of the buffer: */
    584 static int
    585 l_bo_size(lua_State *L)
    586 {
    587    uint64_t addr = (uint64_t)lua_tonumber(L, 1);
    588    lua_pushnumber(L, hostlen(addr));
    589    return 1;
    590 }
    591 
    592 static const struct luaL_Reg l_bos[] = {
    593    {"base", l_bo_base}, {"size", l_bo_size}, {NULL, NULL} /* sentinel */
    594 };
    595 
    596 static void
    597 openlib(const char *lib, const luaL_Reg *reg)
    598 {
    599    lua_newtable(L);
    600    luaL_setfuncs(L, reg, 0);
    601    lua_setglobal(L, lib);
    602 }
    603 
    604 /* called at start to load the script: */
    605 int
    606 script_load(const char *file)
    607 {
    608    int ret;
    609 
    610    assert(!L);
    611 
    612    L = luaL_newstate();
    613    luaL_openlibs(L);
    614    openlib("bos", l_bos);
    615    openlib("regs", l_regs);
    616    openlib("rnn", l_rnn);
    617 
    618    ret = luaL_loadfile(L, file);
    619    if (ret)
    620       error("%s\n");
    621 
    622    ret = lua_pcall(L, 0, LUA_MULTRET, 0);
    623    if (ret)
    624       error("%s\n");
    625 
    626    return 0;
    627 }
    628 
    629 /* called at start of each cmdstream file: */
    630 void
    631 script_start_cmdstream(const char *name)
    632 {
    633    if (!L)
    634       return;
    635 
    636    lua_getglobal(L, "start_cmdstream");
    637 
    638    /* if no handler just ignore it: */
    639    if (!lua_isfunction(L, -1)) {
    640       lua_pop(L, 1);
    641       return;
    642    }
    643 
    644    lua_pushstring(L, name);
    645 
    646    /* do the call (1 arguments, 0 result) */
    647    if (lua_pcall(L, 1, 0, 0) != 0)
    648       error("error running function `f': %s\n");
    649 }
    650 
    651 /* called at each DRAW_INDX, calls script drawidx fxn to process
    652  * the current state
    653  */
    654 void
    655 script_draw(const char *primtype, uint32_t nindx)
    656 {
    657    if (!L)
    658       return;
    659 
    660    lua_getglobal(L, "draw");
    661 
    662    /* if no handler just ignore it: */
    663    if (!lua_isfunction(L, -1)) {
    664       lua_pop(L, 1);
    665       return;
    666    }
    667 
    668    lua_pushstring(L, primtype);
    669    lua_pushnumber(L, nindx);
    670 
    671    /* do the call (2 arguments, 0 result) */
    672    if (lua_pcall(L, 2, 0, 0) != 0)
    673       error("error running function `f': %s\n");
    674 }
    675 
    676 static int
    677 l_rnn_meta_dom_index(lua_State *L)
    678 {
    679    struct rnn *rnn = lua_touserdata(L, 1);
    680    uint32_t offset = (uint32_t)lua_tonumber(L, 2);
    681    struct rnndelem *elem;
    682 
    683    /* TODO might be nicer if the arg isn't a number, to search the domain
    684     * for matching bitfields.. so that the script could do something like
    685     * 'pkt.WIDTH' insteadl of 'pkt[1].WIDTH', ie. not have to remember the
    686     * offset of the dword containing the bitfield..
    687     */
    688 
    689    elem = rnn_regoff(rnn, offset);
    690    if (!elem)
    691       return 0;
    692 
    693    return l_rnn_etype(L, rnn, elem, elem->offset);
    694 }
    695 
    696 /*
    697  * A wrapper object for rnndomain based decoding of an array of dwords
    698  * (ie. for pm4 packet decoding).  Mostly re-uses the register-value
    699  * decoding for the individual dwords and bitfields.
    700  */
    701 
    702 static int
    703 l_rnn_meta_dom_gc(lua_State *L)
    704 {
    705    // TODO
    706    // struct rnn *rnn = lua_touserdata(L, 1);
    707    // rnn_deinit(rnn);
    708    return 0;
    709 }
    710 
    711 static const struct luaL_Reg l_meta_rnn_dom[] = {
    712    {"__index", l_rnn_meta_dom_index},
    713    {"__gc", l_rnn_meta_dom_gc},
    714    {NULL, NULL} /* sentinel */
    715 };
    716 
    717 /* called to general pm4 packet decoding, such as texture/sampler state
    718  */
    719 void
    720 script_packet(uint32_t *dwords, uint32_t sizedwords, struct rnn *rnn,
    721               struct rnndomain *dom)
    722 {
    723    if (!L)
    724       return;
    725 
    726    lua_getglobal(L, dom->name);
    727 
    728    /* if no handler for the packet, just ignore it: */
    729    if (!lua_isfunction(L, -1)) {
    730       lua_pop(L, 1);
    731       return;
    732    }
    733 
    734    struct rnndec *rnndec = lua_newuserdata(L, sizeof(*rnndec));
    735 
    736    rnndec->base = *rnn;
    737    rnndec->base.dom[0] = dom;
    738    rnndec->base.dom[1] = NULL;
    739    rnndec->dwords = dwords;
    740    rnndec->sizedwords = sizedwords;
    741 
    742    luaL_newmetatable(L, "rnnmetadom");
    743    luaL_setfuncs(L, l_meta_rnn_dom, 0);
    744    lua_pop(L, 1);
    745 
    746    luaL_setmetatable(L, "rnnmetadom");
    747 
    748    lua_pushnumber(L, sizedwords);
    749 
    750    if (lua_pcall(L, 2, 0, 0) != 0)
    751       error("error running function `f': %s\n");
    752 }
    753 
    754 /* helper to call fxn that takes and returns void: */
    755 static void
    756 simple_call(const char *name)
    757 {
    758    if (!L)
    759       return;
    760 
    761    lua_getglobal(L, name);
    762 
    763    /* if no handler just ignore it: */
    764    if (!lua_isfunction(L, -1)) {
    765       lua_pop(L, 1);
    766       return;
    767    }
    768 
    769    /* do the call (0 arguments, 0 result) */
    770    if (lua_pcall(L, 0, 0, 0) != 0)
    771       error("error running function `f': %s\n");
    772 }
    773 
    774 /* called at end of each cmdstream file: */
    775 void
    776 script_end_cmdstream(void)
    777 {
    778    simple_call("end_cmdstream");
    779 }
    780 
    781 /* called at start of submit/issueibcmds: */
    782 void
    783 script_start_submit(void)
    784 {
    785    simple_call("start_submit");
    786 }
    787 
    788 /* called at end of submit/issueibcmds: */
    789 void
    790 script_end_submit(void)
    791 {
    792    simple_call("end_submit");
    793 }
    794 
    795 /* called after last cmdstream file: */
    796 void
    797 script_finish(void)
    798 {
    799    if (!L)
    800       return;
    801 
    802    simple_call("finish");
    803 
    804    lua_close(L);
    805    L = NULL;
    806 }
    807