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
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 *
to_rnndec(struct rnn * rnn)69 to_rnndec(struct rnn *rnn)
70 {
71 return (struct rnndec *)rnn;
72 }
73
74 static uint32_t
rnn_val(struct rnn * rnn,uint32_t regbase)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
error(const char * fmt)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
l_meta_rnn_enum_tostring(lua_State * L)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
l_meta_rnn_enum_tonumber(lua_State * L)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
pushenum(struct lua_State * L,int val,struct rnnenum * info)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
push_rnndoff(lua_State * L,struct rnn * rnn,struct rnndelem * elem,uint64_t offset)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
pushdecval(struct lua_State * L,struct rnn * rnn,uint32_t regval,struct rnntypeinfo * info)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
l_rnn_etype(lua_State * L,struct rnn * rnn,struct rnndelem * elem,uint64_t offset)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
l_rnn_struct_meta_index(lua_State * L)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
l_rnn_etype_struct(lua_State * L,struct rnn * rnn,struct rnndelem * elem,uint64_t offset)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
l_rnn_array_meta_index(lua_State * L)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
l_rnn_etype_array(lua_State * L,struct rnn * rnn,struct rnndelem * elem,uint64_t offset)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
l_rnn_reg_meta_index(lua_State * L)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
l_rnn_reg_meta_tostring(lua_State * L)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
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 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
l_reg_written(lua_State * L)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
l_reg_lastval(lua_State * L)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
l_reg_val(lua_State * L)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
l_bo_base(lua_State * L)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
l_bo_size(lua_State * L)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
openlib(const char * lib,const luaL_Reg * reg)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
script_load(const char * file)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
script_start_cmdstream(const char * name)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
script_draw(const char * primtype,uint32_t nindx)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
l_rnn_meta_dom_index(lua_State * L)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
l_rnn_meta_dom_gc(lua_State * L)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
script_packet(uint32_t * dwords,uint32_t sizedwords,struct rnn * rnn,struct rnndomain * dom)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
simple_call(const char * name)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
script_end_cmdstream(void)776 script_end_cmdstream(void)
777 {
778 simple_call("end_cmdstream");
779 }
780
781 /* called at start of submit/issueibcmds: */
782 void
script_start_submit(void)783 script_start_submit(void)
784 {
785 simple_call("start_submit");
786 }
787
788 /* called at end of submit/issueibcmds: */
789 void
script_end_submit(void)790 script_end_submit(void)
791 {
792 simple_call("end_submit");
793 }
794
795 /* called after last cmdstream file: */
796 void
script_finish(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