🎉 Save shape data in rust memory

This commit is contained in:
Alejandro Alonso 2024-11-12 11:09:50 +01:00
parent 48909dc3c4
commit 65ee2f9081
13 changed files with 479 additions and 297 deletions

View file

@ -9,12 +9,10 @@
(:require
[app.common.data.macros :as dm]
[app.common.files.helpers :as cfh]
[app.common.types.shape.impl]
[app.common.types.shape.impl :as ctsi]
[app.common.uuid :as uuid]
[app.config :as cf]
[app.main.data.render-wasm :as drw]
[app.main.store :as st]
[app.util.debug :as dbg]
[app.util.dom :as dom]
[app.util.object :as obj]
[promesa.core :as p]))
(def enabled?
@ -23,7 +21,6 @@
(set! app.common.types.shape.impl/enabled-wasm-ready-shape enabled?)
(defonce internal-module #js {})
(defonce internal-gpu-state #js {})
;; TODO: remove the `take` once we have the dynamic data structure in Rust
(def xform
@ -31,49 +28,70 @@
(remove cfh/root?)
(take 2048)))
;; Size in number of f32 values that represents the shape selrect (
(def rect-size 4)
(defn create-shape
[id]
(let [buffer (uuid/uuid->u32 id)]
(._create_shape ^js internal-module (aget buffer 0) (aget buffer 1) (aget buffer 2) (aget buffer 3))))
(defn use-shape
[id]
(let [buffer (uuid/uuid->u32 id)]
(._use_shape ^js internal-module (aget buffer 0) (aget buffer 1) (aget buffer 2) (aget buffer 3))))
(defn set-shape-selrect
[selrect]
(let [x1 (:x1 selrect)
y1 (:y1 selrect)
x2 (:x2 selrect)
y2 (:y2 selrect)]
(._set_shape_selrect ^js internal-module x1 y1 x2 y2)))
(defn set-shape-transform
[transform]
(let [a (:a transform)
b (:b transform)
c (:c transform)
d (:d transform)
e (:e transform)
f (:f transform)]
(._set_shape_transform ^js internal-module a b c d e f)))
(defn set-shape-rotation
[rotation]
(._set_shape_rotation ^js internal-module rotation))
(defn set-shape-x
[x]
(._set_shape_x ^js internal-module x))
(defn set-shape-y
[y]
(._set_shape_y ^js internal-module y))
(defn set-objects
[objects]
;; FIXME: maybe change the name of `_shapes_buffer` (?)
(let [get-shapes-buffer-ptr
(unchecked-get internal-module "_shapes_buffer")
heap
(unchecked-get internal-module "HEAPF32")
shapes
(into [] xform (vals objects))
total-shapes
(count shapes)
heap-offset
(get-shapes-buffer-ptr)
heap-size
(* rect-size total-shapes)
mem
(js/Float32Array. (.-buffer heap)
heap-offset
heap-size)]
(let [shapes (into [] xform (vals objects))
total-shapes (count shapes)]
(loop [index 0]
(when (< index total-shapes)
(let [shape (nth shapes index)]
(.set ^js mem (.-buffer shape) (* index rect-size))
(let [shape (nth shapes index)
id (dm/get-prop shape :id)
selrect (dm/get-prop shape :selrect)
rotation (dm/get-prop shape :rotation)
transform (dm/get-prop shape :transform)]
(use-shape id)
(set-shape-selrect selrect)
(set-shape-rotation rotation)
(set-shape-transform transform)
(recur (inc index)))))))
(defn draw-objects
[zoom vbox]
(let [draw-all-shapes (unchecked-get internal-module "_draw_all_shapes")]
(js/requestAnimationFrame
(fn []
(let [pan-x (- (dm/get-prop vbox :x))
pan-y (- (dm/get-prop vbox :y))]
(draw-all-shapes internal-gpu-state zoom pan-x pan-y))))))
(js/requestAnimationFrame
(fn []
(let [pan-x (- (dm/get-prop vbox :x))
pan-y (- (dm/get-prop vbox :y))]
(._draw_all_shapes ^js internal-module zoom pan-x pan-y)))))
(defn cancel-draw
[frame-id]
@ -86,67 +104,28 @@
:stencil true
:alpha true})
(defn init-skia
[canvas]
(let [init-fn (unchecked-get internal-module "_init")
state (init-fn (.-width ^js canvas)
(.-height ^js canvas))]
(set! internal-gpu-state state)))
;; NOTE: This function can be called externally
;; by the button in the context lost component (shown
;; in viewport-wasm) or called internally by
;; on-webgl-context
(defn restore-canvas
[canvas]
(st/emit! (drw/context-restored))
;; We need to reinitialize skia when the
;; context is restored.
(init-skia canvas))
;; Handles both events: webglcontextlost and
;; webglcontextrestored
(defn on-webgl-context
[event]
(dom/prevent-default event)
(if (= (.-type event) "webglcontextlost")
(st/emit! (drw/context-lost))
(restore-canvas (dom/get-target event))))
(defn dispose-canvas
[canvas]
(defn clear-canvas
[]
;; TODO: perform corresponding cleaning
(.removeEventListener canvas "webglcontextlost" on-webgl-context)
(.removeEventListener canvas "webglcontextrestored" on-webgl-context))
)
(defn init-debug-webgl-context-state
[context]
(let [context-extension (.getExtension ^js context "WEBGL_lose_context")
info-extension (.getExtension ^js context "WEBGL_debug_renderer_info")]
(set! (.-penpotGL js/window) #js {:context context-extension
:renderer info-extension})
(js/console.log "WEBGL_lose_context" context-extension)
(js/console.log "WEBGL_debug_renderer_info" info-extension)))
(defn setup-canvas
(defn assign-canvas
[canvas]
(let [gl (unchecked-get internal-module "GL")
init-fn (unchecked-get internal-module "_init")
context (.getContext ^js canvas "webgl2" canvas-options)
;; Register the context with emscripten
handle (.registerContext ^js gl context #js {"majorVersion" 2})
_ (.makeContextCurrent ^js gl handle)]
(when (dbg/enabled? :gl-context)
(init-debug-webgl-context-state context))
(.addEventListener canvas "webglcontextlost" on-webgl-context)
(.addEventListener canvas "webglcontextrestored" on-webgl-context)
handle (.registerContext ^js gl context #js {"majorVersion" 2})]
(.makeContextCurrent ^js gl handle)
;; Initialize Skia
(init-fn (.-width ^js canvas)
(.-height ^js canvas))
(set! (.-width canvas) (.-clientWidth ^js canvas))
(set! (.-height canvas) (.-clientHeight ^js canvas))
(init-skia canvas)))
(obj/set! js/window "shape_list" (fn [] ((unchecked-get internal-module "_shape_list"))))))
(defonce module
(->> (js/dynamicImport "/js/render_wasm.js")
@ -159,3 +138,9 @@
(p/merr (fn [cause]
(js/console.error cause)
(p/resolved false)))))
(set! app.common.types.shape.impl/wasm-create-shape create-shape)
(set! app.common.types.shape.impl/wasm-use-shape use-shape)
(set! app.common.types.shape.impl/wasm-set-shape-selrect set-shape-selrect)
(set! app.common.types.shape.impl/wasm-set-shape-transform set-shape-transform)
(set! app.common.types.shape.impl/wasm-set-shape-rotation set-shape-rotation)