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", __func__, __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 rnn_reginfo_free(info);
397 return 1;
398 }
399
400 static int
l_rnn_reg_meta_tonumber(lua_State * L)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
l_rnn_etype_reg(lua_State * L,struct rnn * rnn,struct rnndelem * elem,uint64_t offset)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
l_rnn_meta_index(lua_State * L)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
l_rnn_meta_gc(lua_State * L)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
l_rnn_init(lua_State * L)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
l_rnn_enumname(lua_State * L)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
l_rnn_regname(lua_State * L)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
l_rnn_regval(lua_State * L)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 rnn_reginfo_free(info);
520 return 1;
521 }
522
523 static const struct luaL_Reg l_rnn[] = {
524 {"init", l_rnn_init},
525 {"enumname", l_rnn_enumname},
526 {"regname", l_rnn_regname},
527 {"regval", l_rnn_regval},
528 {NULL, NULL} /* sentinel */
529 };
530
531 /* Expose the register state to script enviroment as a "regs" library:
532 */
533
534 static int
l_reg_written(lua_State * L)535 l_reg_written(lua_State *L)
536 {
537 uint32_t regbase = (uint32_t)lua_tonumber(L, 1);
538 lua_pushnumber(L, reg_written(regbase));
539 return 1;
540 }
541
542 static int
l_reg_lastval(lua_State * L)543 l_reg_lastval(lua_State *L)
544 {
545 uint32_t regbase = (uint32_t)lua_tonumber(L, 1);
546 lua_pushnumber(L, reg_lastval(regbase));
547 return 1;
548 }
549
550 static int
l_reg_val(lua_State * L)551 l_reg_val(lua_State *L)
552 {
553 uint32_t regbase = (uint32_t)lua_tonumber(L, 1);
554 lua_pushnumber(L, reg_val(regbase));
555 return 1;
556 }
557
558 static const struct luaL_Reg l_regs[] = {
559 {"written", l_reg_written},
560 {"lastval", l_reg_lastval},
561 {"val", l_reg_val},
562 {NULL, NULL} /* sentinel */
563 };
564
565 /* Expose API to lookup snapshot buffers:
566 */
567
568 uint64_t gpubaseaddr(uint64_t gpuaddr);
569 unsigned hostlen(uint64_t gpuaddr);
570
571 /* given address, return base-address of buffer: */
572 static int
l_bo_base(lua_State * L)573 l_bo_base(lua_State *L)
574 {
575 uint64_t addr = (uint64_t)lua_tonumber(L, 1);
576 lua_pushnumber(L, gpubaseaddr(addr));
577 return 1;
578 }
579
580 /* given address, return the remaining size of the buffer: */
581 static int
l_bo_size(lua_State * L)582 l_bo_size(lua_State *L)
583 {
584 uint64_t addr = (uint64_t)lua_tonumber(L, 1);
585 lua_pushnumber(L, hostlen(addr));
586 return 1;
587 }
588
589 static const struct luaL_Reg l_bos[] = {
590 {"base", l_bo_base}, {"size", l_bo_size}, {NULL, NULL} /* sentinel */
591 };
592
593 static void
openlib(const char * lib,const luaL_Reg * reg)594 openlib(const char *lib, const luaL_Reg *reg)
595 {
596 lua_newtable(L);
597 luaL_setfuncs(L, reg, 0);
598 lua_setglobal(L, lib);
599 }
600
601 /* called at start to load the script: */
602 int
script_load(const char * file)603 script_load(const char *file)
604 {
605 int ret;
606
607 assert(!L);
608
609 L = luaL_newstate();
610 luaL_openlibs(L);
611 openlib("bos", l_bos);
612 openlib("regs", l_regs);
613 openlib("rnn", l_rnn);
614
615 ret = luaL_loadfile(L, file);
616 if (ret)
617 error("%s\n");
618
619 ret = lua_pcall(L, 0, LUA_MULTRET, 0);
620 if (ret)
621 error("%s\n");
622
623 return 0;
624 }
625
626 /* called at start of each cmdstream file: */
627 void
script_start_cmdstream(const char * name)628 script_start_cmdstream(const char *name)
629 {
630 if (!L)
631 return;
632
633 lua_getglobal(L, "start_cmdstream");
634
635 /* if no handler just ignore it: */
636 if (!lua_isfunction(L, -1)) {
637 lua_pop(L, 1);
638 return;
639 }
640
641 lua_pushstring(L, name);
642
643 /* do the call (1 arguments, 0 result) */
644 if (lua_pcall(L, 1, 0, 0) != 0)
645 error("error running function `f': %s\n");
646 }
647
648 /* called at each DRAW_INDX, calls script drawidx fxn to process
649 * the current state
650 */
651 void
script_draw(const char * primtype,uint32_t nindx)652 script_draw(const char *primtype, uint32_t nindx)
653 {
654 if (!L)
655 return;
656
657 lua_getglobal(L, "draw");
658
659 /* if no handler just ignore it: */
660 if (!lua_isfunction(L, -1)) {
661 lua_pop(L, 1);
662 return;
663 }
664
665 lua_pushstring(L, primtype);
666 lua_pushnumber(L, nindx);
667
668 /* do the call (2 arguments, 0 result) */
669 if (lua_pcall(L, 2, 0, 0) != 0)
670 error("error running function `f': %s\n");
671 }
672
673 static int
l_rnn_meta_dom_index(lua_State * L)674 l_rnn_meta_dom_index(lua_State *L)
675 {
676 struct rnn *rnn = lua_touserdata(L, 1);
677 uint32_t offset = (uint32_t)lua_tonumber(L, 2);
678 struct rnndelem *elem;
679
680 /* TODO might be nicer if the arg isn't a number, to search the domain
681 * for matching bitfields.. so that the script could do something like
682 * 'pkt.WIDTH' insteadl of 'pkt[1].WIDTH', ie. not have to remember the
683 * offset of the dword containing the bitfield..
684 */
685
686 elem = rnn_regoff(rnn, offset);
687 if (!elem)
688 return 0;
689
690 return l_rnn_etype(L, rnn, elem, elem->offset);
691 }
692
693 /*
694 * A wrapper object for rnndomain based decoding of an array of dwords
695 * (ie. for pm4 packet decoding). Mostly re-uses the register-value
696 * decoding for the individual dwords and bitfields.
697 */
698
699 static int
l_rnn_meta_dom_gc(lua_State * L)700 l_rnn_meta_dom_gc(lua_State *L)
701 {
702 // TODO
703 // struct rnn *rnn = lua_touserdata(L, 1);
704 // rnn_deinit(rnn);
705 return 0;
706 }
707
708 static const struct luaL_Reg l_meta_rnn_dom[] = {
709 {"__index", l_rnn_meta_dom_index},
710 {"__gc", l_rnn_meta_dom_gc},
711 {NULL, NULL} /* sentinel */
712 };
713
714 /* called to general pm4 packet decoding, such as texture/sampler state
715 */
716 void
script_packet(uint32_t * dwords,uint32_t sizedwords,struct rnn * rnn,struct rnndomain * dom)717 script_packet(uint32_t *dwords, uint32_t sizedwords, struct rnn *rnn,
718 struct rnndomain *dom)
719 {
720 if (!L)
721 return;
722
723 lua_getglobal(L, dom->name);
724
725 /* if no handler for the packet, just ignore it: */
726 if (!lua_isfunction(L, -1)) {
727 lua_pop(L, 1);
728 return;
729 }
730
731 struct rnndec *rnndec = lua_newuserdata(L, sizeof(*rnndec));
732
733 rnndec->base = *rnn;
734 rnndec->base.dom[0] = dom;
735 rnndec->base.dom[1] = NULL;
736 rnndec->dwords = dwords;
737 rnndec->sizedwords = sizedwords;
738
739 luaL_newmetatable(L, "rnnmetadom");
740 luaL_setfuncs(L, l_meta_rnn_dom, 0);
741 lua_pop(L, 1);
742
743 luaL_setmetatable(L, "rnnmetadom");
744
745 lua_pushnumber(L, sizedwords);
746
747 if (lua_pcall(L, 2, 0, 0) != 0)
748 error("error running function `f': %s\n");
749 }
750
751 /* helper to call fxn that takes and returns void: */
752 static void
simple_call(const char * name)753 simple_call(const char *name)
754 {
755 if (!L)
756 return;
757
758 lua_getglobal(L, name);
759
760 /* if no handler just ignore it: */
761 if (!lua_isfunction(L, -1)) {
762 lua_pop(L, 1);
763 return;
764 }
765
766 /* do the call (0 arguments, 0 result) */
767 if (lua_pcall(L, 0, 0, 0) != 0)
768 error("error running function `f': %s\n");
769 }
770
771 /* called at end of each cmdstream file: */
772 void
script_end_cmdstream(void)773 script_end_cmdstream(void)
774 {
775 simple_call("end_cmdstream");
776 }
777
778 /* called at start of submit/issueibcmds: */
779 void
script_start_submit(void)780 script_start_submit(void)
781 {
782 simple_call("start_submit");
783 }
784
785 /* called at end of submit/issueibcmds: */
786 void
script_end_submit(void)787 script_end_submit(void)
788 {
789 simple_call("end_submit");
790 }
791
792 /* called after last cmdstream file: */
793 void
script_finish(void)794 script_finish(void)
795 {
796 if (!L)
797 return;
798
799 simple_call("finish");
800
801 lua_close(L);
802 L = NULL;
803 }
804