From 2ead48d3dd79b7fe43753ed26c94e7488bc657de Mon Sep 17 00:00:00 2001
From: Serge Bazanski <q3k@q3k.org>
Date: Mon, 12 Jun 2023 13:06:52 +0200
Subject: [PATCH] sim: support for new gfx and input apis

---
 sim/fakes/ctx.py      | 19 +++++++------
 sim/fakes/hardware.py | 62 +++++++++++++++++++++++++++++++++----------
 2 files changed, 59 insertions(+), 22 deletions(-)

diff --git a/sim/fakes/ctx.py b/sim/fakes/ctx.py
index d9f809ac4c..9854100496 100644
--- a/sim/fakes/ctx.py
+++ b/sim/fakes/ctx.py
@@ -57,6 +57,9 @@ class Wasm:
         BRGA8 = 5
         return fb, self._i.exports.ctx_new_for_framebuffer(fb, width, height, width * 4, BRGA8)
 
+    def ctx_new_drawlist(self, width, height):
+        return self._i.exports.ctx_new_drawlist(width, height)
+
     def ctx_apply_transform(self, ctx, *args):
         args = [float(a) for a in args]
         return self._i.exports.ctx_apply_transform(ctx, *args)
@@ -72,6 +75,12 @@ class Wasm:
         self.free(p)
         return res
 
+    def ctx_destroy(self, ctx):
+        return self._i.exports.ctx_destroy(ctx)
+
+    def ctx_render_ctx(self, ctx, dctx):
+        return self._i.exports.ctx_render_ctx(ctx, dctx)
+
 _wasm = Wasm()
 
 class Ctx:
@@ -87,19 +96,13 @@ class Ctx:
     END = 'end'
     MIDDLE = 'middle'
 
-    def __init__(self):
-        self._fb, self._ctx = _wasm.ctx_new_for_framebuffer(240, 240)
-        # Place (0, 0) in the center of the screen, mathing what the real badge
-        # software does.
-        _wasm.ctx_apply_transform(self._ctx, 1, 0, 120, 0, 1, 120, 0, 0, 1)
+    def __init__(self, _ctx):
+        self._ctx = _ctx
 
         self.text_align = 'start'
         self.text_baseline = 'alphabetic'
         self.font_size = 10.0
 
-    def _get_fb(self):
-        return _wasm._i.exports.memory.uint8_view(self._fb)
-
     def _emit(self, text):
         _wasm.ctx_parse(self._ctx, text)
 
diff --git a/sim/fakes/hardware.py b/sim/fakes/hardware.py
index b87f6fc74e..27a7538caa 100644
--- a/sim/fakes/hardware.py
+++ b/sim/fakes/hardware.py
@@ -194,11 +194,10 @@ class Simulation:
                 b2 = b / (20 - i)
                 pygame.draw.circle(surface, (r2, g2, b2), (x, y), radius)
 
-    def _render_oled(self, surface):
+    def _render_oled(self, surface, fb):
         surface.fill((0, 0, 0, 0))
         buf = surface.get_buffer()
 
-        fb = get_ctx()._get_fb()
         fb = fb[:240*240*4]
         for y in range(240):
             # Use precalculated row offset to turn OLED disc into square
@@ -263,14 +262,14 @@ class Simulation:
         elif time.time() - self.last_gui_render > d:
             self.render_gui_now()
 
-    def render_display(self):
+    def render_display(self, fb):
         """
         Render the OLED surface from Ctx state.
 
         Afterwards, render_gui_{lazy,now} should still be called to actually
         present the new OLED surface state to the user.
         """
-        self._render_oled(self._oled_surface)
+        self._render_oled(self._oled_surface, fb)
 
     def set_led_rgb(self, ix, r, g, b):
         self.led_state_buf[ix] = (r, g, b)
@@ -297,21 +296,52 @@ def captouch_calibration_active():
     return False
 
 
-_global_ctx = None
-def get_ctx():
-    global _global_ctx
-    import ctx
+import ctx
+
+class FramebufferManager:
+    def __init__(self):
+        self._free = []
+        for _ in range(2):
+            fb, c = ctx._wasm.ctx_new_for_framebuffer(240, 240)
+            ctx._wasm.ctx_apply_transform(c, 1, 0, 120, 0, 1, 120, 0, 0, 1)
+            self._free.append((fb, c))
+    
+    def get(self):
+        if len(self._free) == 0:
+            return None, None
+        fb, ctx = self._free[0]
+        self._free = self._free[1:]
+
+        return fb, ctx
 
-    if _global_ctx is None:
-        _global_ctx = ctx.Ctx()
-    return _global_ctx
+    def put(self, fb, ctx):
+        self._free.append((fb, ctx))
+
+fbm = FramebufferManager()
+
+def get_ctx():
+    dctx = ctx._wasm.ctx_new_drawlist(240, 240)
+    return ctx.Ctx(dctx)
 
 
-def display_update():
+def display_update(subctx):
     _sim.process_events()
-    _sim.render_display()
+    fbp, c = fbm.get()
+    if fbp is None:
+        return
+
+    ctx._wasm.ctx_render_ctx(subctx._ctx, c)
+    ctx._wasm.ctx_destroy(subctx._ctx)
+
+    fb = ctx._wasm._i.exports.memory.uint8_view(fbp)
+    _sim.render_display(fb)
     _sim.render_gui_now()
 
+    fbm.put(fbp, c)
+
+
+def display_pipe_full():
+    return False
 
 def set_led_rgb(ix, r, g, b):
     ix = ((39-ix) + 1 + 32)%40;
@@ -403,4 +433,8 @@ def captouch_get_petal_phi(a):
     return 0
 
 def captouch_get_petal_pad(i, x):
-    return 0
\ No newline at end of file
+    return 0
+
+def freertos_sleep(ms):
+    import _time
+    _time.sleep(ms / 1000.0)
\ No newline at end of file
-- 
GitLab