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