+// Contains basically the same data as InputState, but does not hold on to
+// a reference to the frames. This is important so that we can release them
+// without having to wait for Lua's GC.
+struct InputStateInfo {
+ InputStateInfo(const InputState& input_state);
+
+ unsigned last_width[MAX_CARDS], last_height[MAX_CARDS];
+};
+
+InputStateInfo::InputStateInfo(const InputState &input_state)
+{
+ for (unsigned signal_num = 0; signal_num < MAX_CARDS; ++signal_num) {
+ BufferedFrame frame = input_state.buffered_frames[signal_num][0];
+ if (frame.frame == nullptr) {
+ last_width[signal_num] = last_height[signal_num] = 0;
+ continue;
+ }
+ const PBOFrameAllocator::Userdata *userdata = (const PBOFrameAllocator::Userdata *)frame.frame->userdata;
+ last_width[signal_num] = userdata->last_width[frame.field_number];
+ last_height[signal_num] = userdata->last_height[frame.field_number];
+ }
+}
+
+class LuaRefWithDeleter {
+public:
+ LuaRefWithDeleter(mutex *m, lua_State *L, int ref) : m(m), L(L), ref(ref) {}
+ ~LuaRefWithDeleter() {
+ unique_lock<mutex> lock(*m);
+ luaL_unref(L, LUA_REGISTRYINDEX, ref);
+ }
+ int get() const { return ref; }
+
+private:
+ LuaRefWithDeleter(const LuaRefWithDeleter &) = delete;
+
+ mutex *m;
+ lua_State *L;
+ int ref;
+};