feat(xteink): expose the panel frame generation over QOM
The wasm front end already tracked panel refreshes; make the counter unconditional and alias it onto the machine so native front ends can redraw on refresh instead of on a timer.
This commit is contained in:
@@ -11,11 +11,21 @@
|
||||
#include "hw/irq.h"
|
||||
#include "hw/display/xteink_x3_eink.h"
|
||||
|
||||
/* Frame Counter - Both the wasm front end and the QMP web UI poll this to redraw only on a real
|
||||
* panel refresh. Only one panel is instantiated per machine, so a single counter suffices. */
|
||||
static uint32_t xteink_frame_generation;
|
||||
|
||||
static void xteink_frame_generation_init(Object *obj)
|
||||
{
|
||||
object_property_add_uint32_ptr(obj, "frame-generation",
|
||||
&xteink_frame_generation,
|
||||
OBJ_PROP_FLAG_READ);
|
||||
}
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten/emscripten.h>
|
||||
|
||||
static QemuConsole *xteink_wasm_console;
|
||||
static uint32_t xteink_wasm_generation;
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE uintptr_t xteink_wasm_framebuffer(void)
|
||||
{
|
||||
@@ -51,17 +61,18 @@ EMSCRIPTEN_KEEPALIVE int xteink_wasm_stride(void)
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE uint32_t xteink_wasm_frame_generation(void)
|
||||
{
|
||||
return qatomic_read(&xteink_wasm_generation);
|
||||
return qatomic_read(&xteink_frame_generation);
|
||||
}
|
||||
|
||||
static void xteink_wasm_frame_updated(QemuConsole *console)
|
||||
static void xteink_frame_updated(QemuConsole *console)
|
||||
{
|
||||
xteink_wasm_console = console;
|
||||
qatomic_inc(&xteink_wasm_generation);
|
||||
qatomic_inc(&xteink_frame_generation);
|
||||
}
|
||||
#else
|
||||
static void xteink_wasm_frame_updated(QemuConsole *console)
|
||||
static void xteink_frame_updated(QemuConsole *console)
|
||||
{
|
||||
qatomic_inc(&xteink_frame_generation);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -73,7 +84,8 @@ static void xteink_wasm_frame_updated(QemuConsole *console)
|
||||
#define CMD_LUT_FIRST 0x20
|
||||
#define CMD_LUT_LAST 0x24
|
||||
|
||||
#define BUSY_TIME_NS (5 * SCALE_MS)
|
||||
/* Mirror a real panel refresh (~1 s): shorter pulses let the completion edge pass before the firmware arms its ISR, costing a 30 s timeout. */
|
||||
#define BUSY_TIME_NS (1000 * SCALE_MS)
|
||||
|
||||
#define XTEINK_X3_LUT_PREFIX_SIZE 13
|
||||
|
||||
@@ -220,7 +232,7 @@ static void xteink_x3_eink_render(XteinkX3EinkState *s)
|
||||
}
|
||||
}
|
||||
|
||||
xteink_wasm_frame_updated(s->console);
|
||||
xteink_frame_updated(s->console);
|
||||
dpy_gfx_update(s->console, 0, 0, XTEINK_X3_HEIGHT, XTEINK_X3_WIDTH);
|
||||
}
|
||||
|
||||
@@ -326,6 +338,7 @@ static void xteink_x3_eink_init(Object *obj)
|
||||
{
|
||||
XteinkX3EinkState *s = XTEINK_X3_EINK(obj);
|
||||
|
||||
xteink_frame_generation_init(obj);
|
||||
s->console = graphic_console_init(DEVICE(s), 0,
|
||||
&xteink_x3_eink_graphics_ops, s);
|
||||
dpy_gfx_replace_surface(s->console,
|
||||
@@ -378,7 +391,7 @@ static void xteink_x4_eink_render(XteinkX4EinkState *s)
|
||||
DisplaySurface *surface = qemu_console_surface(s->console);
|
||||
memset(surface_data(surface), 0xff,
|
||||
surface_stride(surface) * surface_height(surface));
|
||||
xteink_wasm_frame_updated(s->console);
|
||||
xteink_frame_updated(s->console);
|
||||
dpy_gfx_update(s->console, 0, 0, 480, 800);
|
||||
}
|
||||
|
||||
@@ -412,6 +425,7 @@ static void xteink_x4_eink_init(Object *obj)
|
||||
{
|
||||
XteinkX4EinkState *s = XTEINK_X4_EINK(obj);
|
||||
|
||||
xteink_frame_generation_init(obj);
|
||||
s->console = graphic_console_init(DEVICE(s), 0,
|
||||
&xteink_x4_eink_graphics_ops, s);
|
||||
dpy_gfx_replace_surface(s->console, qemu_create_displaysurface(480, 800));
|
||||
|
||||
@@ -868,6 +868,8 @@ static void xteink_machine_init(MachineState *machine)
|
||||
DeviceState *panel = ssi_create_peripheral(ms->spi2.bus,
|
||||
ms->x4 ? TYPE_XTEINK_X4_EINK : TYPE_XTEINK_X3_EINK);
|
||||
qemu_input_handler_register(panel, &xteink_key_handler);
|
||||
object_property_add_alias(OBJECT(machine), "frame-generation",
|
||||
OBJECT(panel), "frame-generation");
|
||||
qdev_connect_gpio_out_named(DEVICE(&ms->gpio), ESP32_GPIO_OUTPUT, 21,
|
||||
qdev_get_gpio_in_named(panel, SSI_GPIO_CS, 0));
|
||||
qdev_connect_gpio_out_named(DEVICE(&ms->gpio), ESP32_GPIO_OUTPUT, 4,
|
||||
|
||||
Reference in New Issue
Block a user