0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-21 22:22:43 -05:00

Merge pull request #5235 from penpot/azazeln28-handle-webgl-context

🎉 Handle WebGL Context
This commit is contained in:
Belén Albeza 2024-11-08 09:38:45 +01:00 committed by GitHub
commit 7b196e1ca5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 125 additions and 16 deletions

View file

@ -0,0 +1,17 @@
(ns app.main.data.render-wasm
(:require
[potok.v2.core :as ptk]))
(defn context-lost
[]
(ptk/reify ::context-lost
ptk/UpdateEvent
(update [_ state]
(update state :render-state #(assoc % :lost true)))))
(defn context-restored
[]
(ptk/reify ::context-restored
ptk/UpdateEvent
(update [_ state]
(update state :render-state #(dissoc % :lost)))))

View file

@ -116,6 +116,12 @@
;; ---- Workspace refs ;; ---- Workspace refs
(def render-state
(l/derived :render-state st/state))
(def render-context-lost?
(l/derived :lost render-state))
(def workspace-local (def workspace-local
(l/derived :workspace-local st/state)) (l/derived :workspace-local st/state))

View file

@ -111,6 +111,8 @@
modifiers (mf/deref refs/workspace-modifiers) modifiers (mf/deref refs/workspace-modifiers)
text-modifiers (mf/deref refs/workspace-text-modifier) text-modifiers (mf/deref refs/workspace-text-modifier)
render-context-lost? (mf/deref refs/render-context-lost?)
objects-modified (mf/with-memo [base-objects text-modifiers modifiers] objects-modified (mf/with-memo [base-objects text-modifiers modifiers]
(apply-modifiers-to-selected selected base-objects text-modifiers modifiers)) (apply-modifiers-to-selected selected base-objects text-modifiers modifiers))
@ -175,6 +177,8 @@
mode-inspect? (= options-mode :inspect) mode-inspect? (= options-mode :inspect)
on-render-restore-context #(.reload js/location)
on-click (actions/on-click hover selected edition drawing-path? drawing-tool space? selrect z?) on-click (actions/on-click hover selected edition drawing-path? drawing-tool space? selrect z?)
on-context-menu (actions/on-context-menu hover hover-ids read-only?) on-context-menu (actions/on-context-menu hover hover-ids read-only?)
on-double-click (actions/on-double-click hover hover-ids hover-top-frame-id drawing-path? base-objects edition drawing-tool z? read-only?) on-double-click (actions/on-double-click hover hover-ids hover-top-frame-id drawing-path? base-objects edition drawing-tool z? read-only?)
@ -277,9 +281,9 @@
(p/fmap (fn [ready?] (p/fmap (fn [ready?]
(when ready? (when ready?
(reset! canvas-init? true) (reset! canvas-init? true)
(render.wasm/assign-canvas canvas))))) (render.wasm/setup-canvas canvas)))))
(fn [] (fn []
(render.wasm/clear-canvas)))) (render.wasm/dispose-canvas canvas))))
(mf/with-effect [objects-modified canvas-init?] (mf/with-effect [objects-modified canvas-init?]
(when @canvas-init? (when @canvas-init?
@ -635,4 +639,11 @@
{:objects base-objects {:objects base-objects
:zoom zoom :zoom zoom
:vbox vbox :vbox vbox
:bottom-padding (when palete-size (+ palete-size 8))}]]]]])) :bottom-padding (when palete-size (+ palete-size 8))}]]]]
(when render-context-lost?
[:div {:id "context-lost" :class (stl/css :context-lost)}
[:h1 "GL Error Screen"]
[:button
{:on-click on-render-restore-context}
"Restore context"]])]))

View file

@ -35,3 +35,13 @@
right: 0; right: 0;
z-index: 10; z-index: 10;
} }
.context-lost {
position: fixed;
inset: 0;
z-index: 100;
background-color: rgba(0, 0, 0, 0.5);
display: grid;
place-items: center;
cursor: default;
}

View file

@ -11,6 +11,10 @@
[app.common.files.helpers :as cfh] [app.common.files.helpers :as cfh]
[app.common.types.shape.impl] [app.common.types.shape.impl]
[app.config :as cf] [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]
[promesa.core :as p])) [promesa.core :as p]))
(def enabled? (def enabled?
@ -82,29 +86,67 @@
:stencil true :stencil true
:alpha true}) :alpha true})
(defn clear-canvas (defn init-skia
[] [canvas]
;; TODO: perform corresponding cleaning (let [init-fn (unchecked-get internal-module "_init")
) state (init-fn (.-width ^js canvas)
(.-height ^js canvas))]
(set! internal-gpu-state state)))
(defn assign-canvas ;; 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]
;; 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
[canvas] [canvas]
(let [gl (unchecked-get internal-module "GL") (let [gl (unchecked-get internal-module "GL")
init-fn (unchecked-get internal-module "_init")
context (.getContext ^js canvas "webgl2" canvas-options) context (.getContext ^js canvas "webgl2" canvas-options)
;; Register the context with emscripten ;; Register the context with emscripten
handle (.registerContext ^js gl context #js {"majorVersion" 2}) handle (.registerContext ^js gl context #js {"majorVersion" 2})
_ (.makeContextCurrent ^js gl handle) _ (.makeContextCurrent ^js gl handle)]
;; Initialize Skia (when (dbg/enabled? :gl-context)
state (init-fn (.-width ^js canvas) (init-debug-webgl-context-state context))
(.-height ^js canvas))]
(.addEventListener canvas "webglcontextlost" on-webgl-context)
(.addEventListener canvas "webglcontextrestored" on-webgl-context)
(set! (.-width canvas) (.-clientWidth ^js canvas)) (set! (.-width canvas) (.-clientWidth ^js canvas))
(set! (.-height canvas) (.-clientHeight ^js canvas)) (set! (.-height canvas) (.-clientHeight ^js canvas))
(set! internal-gpu-state state)))
(init-skia canvas)))
(defonce module (defonce module
(->> (js/dynamicImport "/js/render_wasm.js") (->> (js/dynamicImport "/js/render_wasm.js")

View file

@ -89,7 +89,10 @@
:display-touched :display-touched
;; Show some visual indicators for bool shape ;; Show some visual indicators for bool shape
:bool-shapes}) :bool-shapes
;; Show some information about the WebGL context.
:gl-context})
(defn enable! (defn enable!
[option] [option]

18
render-wasm/Cargo.lock generated
View file

@ -96,6 +96,22 @@ version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "emscripten-functions"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62c026cc030b24957ca45d9555f9fa241d6b3a01d725cd98a25924de249b840a"
dependencies = [
"cc",
"emscripten-functions-sys",
]
[[package]]
name = "emscripten-functions-sys"
version = "4.1.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65715a5f07b03636d7cd5508a45d1b62486840cb7d91a66564a73f1d7aa70b79"
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.1" version = "1.0.1"
@ -370,6 +386,8 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
name = "render" name = "render"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"emscripten-functions",
"emscripten-functions-sys",
"gl", "gl",
"skia-safe", "skia-safe",
] ]

View file

@ -11,6 +11,8 @@ name = "render_wasm"
path = "src/main.rs" path = "src/main.rs"
[dependencies] [dependencies]
emscripten-functions = "0.2.3"
emscripten-functions-sys = "4.1.67"
gl = "0.14.0" gl = "0.14.0"
skia-safe = { version = "0.78.2", features = ["gl"] } skia-safe = { version = "0.78.2", features = ["gl"] }