more Lwd.t-ification

This commit is contained in:
cqc
2024-05-21 20:15:50 -05:00
parent 5c9c41487c
commit 36fd690e21
2 changed files with 191 additions and 182 deletions

294
ogui.ml
View File

@ -30,6 +30,16 @@ let pp_color : Gv.Color.t Fmt.t =
field "a" (fun (s : Gv.Color.t) -> s.a) float; field "a" (fun (s : Gv.Color.t) -> s.a) float;
]) ])
let lwt_lwd (t : 'a Lwt.t Lwd.t) : 'a Lwd.t Lwt.t =
let root = Lwd.observe t in
Lwd.quick_sample root >>= fun root' ->
let var = Lwd.var root' in
Lwd.set_on_invalidate root (fun _t' ->
Lwt.async (fun () ->
Lwd.quick_sample root >>= fun root' ->
Lwt.return @@ Lwd.set var root'));
Lwt.return (Lwd.get var)
module Margin = struct module Margin = struct
open Gg open Gg
@ -87,124 +97,111 @@ end
module TextBuffer = struct module TextBuffer = struct
type t = { type t = {
mutable path : string list; path : string list Lwd.var;
mutable tree : Store.S.tree; tree : Store.S.tree Lwd.var;
repo : Store.Sync.db Lwt.t; repo : Store.Sync.db Lwt.t;
var : string Lwd.var;
} }
let of_repo ~path ~(repo : Store.Sync.db Lwt.t) : t Lwt.t = let of_repo ~initial_path ~(repo : Store.Sync.db Lwt.t) : t Lwt.t =
let tree = Lwt_main.run (repo >>= Store.S.tree) in repo >>= Store.S.tree >>= fun tree ->
Store.S.Tree.find tree path >>= fun res ->
Lwt.return Lwt.return
{ { path = Lwd.var initial_path; tree = Lwd.var tree; repo }
path;
tree;
repo;
var =
Lwd.var
(match res with
| Some s -> s
| None ->
F.epr "TextBuffer.of_repo: None@.";
"");
}
let of_string ~path ?(repo = None) str = let of_string ~path ?(repo = None) str =
{ {
path; path = Lwd.var path;
tree = Store.S.Tree.singleton path str; tree = Lwd.var @@ Store.S.Tree.singleton path str;
repo = repo =
( Store.S.Repo.v (Irmin_mem.config ()) >>= fun repo' -> ( Store.S.Repo.v (Irmin_mem.config ()) >>= fun repo' ->
Option.value ~default:Store.S.(empty repo') repo ); Option.value ~default:Store.S.(empty repo') repo );
var = Lwd.var str;
} }
let insert_uchar t n uc : t Lwt.t = let insert_uchar { path; tree; _ } n uc : unit Lwt.t =
(* F.epr "TextBuffer.insert_uchar %d %a@." n pp_uchar uc; *) F.epr "TextBuffer.insert_uchar %d %a@." n pp_uchar uc;
match t with let ucbuf = Bytes.create 8 in
| { path; tree; var; _ } as tt -> let uclen = Bytes.set_utf_8_uchar ucbuf 0 uc in
Store.S.Tree.update tree path (function Store.S.Tree.update (Lwd.peek tree) (Lwd.peek path) (function
| Some src -> | Some src ->
let sn = String.length src in let sn = String.length src in
assert (n <= sn); assert (n <= sn);
let ucbuf = Bytes.create 8 in let dst = Bytes.create (sn + uclen) in
let uclen = Bytes.set_utf_8_uchar ucbuf 0 uc in BytesLabels.blit_string ~src ~src_pos:0 ~dst ~dst_pos:0
let dst = Bytes.create (sn + uclen) in ~len:n;
BytesLabels.blit_string ~src ~src_pos:0 ~dst ~dst_pos:0 BytesLabels.blit ~src:ucbuf ~src_pos:0 ~dst ~dst_pos:n
~len:n; ~len:uclen;
BytesLabels.blit ~src:ucbuf ~src_pos:0 ~dst ~dst_pos:n if sn > n + uclen then
~len:uclen; BytesLabels.blit_string ~src ~src_pos:n ~dst
if sn > n + uclen then ~dst_pos:(n + uclen)
BytesLabels.blit_string ~src ~src_pos:n ~dst ~len:(sn - (n + uclen));
~dst_pos:(n + uclen) Some (Bytes.to_string dst)
~len:(sn - (n + uclen)); | None ->
Lwd.set var (Bytes.to_string dst); F.epr "TextBuffer.insert_uchar Tree.update -> Nonep@.";
Some (Lwd.peek var) Some (String.sub (Bytes.to_string ucbuf) 0 uclen))
| None -> None) >>= fun t ->
>>= fun tree -> Lwt.return { tt with tree } Lwd.set tree t;
Lwt.return_unit
let remove t (a, b) : t Lwt.t = let remove { path; tree; _ } (a, b) : unit Lwt.t =
let a, b = (min a b, max a b) in let a, b = (min a b, max a b) in
(* F.epr "TextBuffer.remove (%d, %d)@." a b; *) (* F.epr "TextBuffer.remove (%d, %d)@." a b; *)
match t with Store.S.Tree.update (Lwd.peek tree) (Lwd.peek path) (function
| { path; tree; var; _ } as tt -> | Some src ->
Store.S.Tree.update tree path (function let srcn = String.length src in
| Some src -> assert (max a b <= srcn);
let srcn = String.length src in let dst = Bytes.create (srcn - (b - a)) in
assert (max a b <= srcn); Bytes.blit_string src 0 dst 0 a;
let dst = Bytes.create (srcn - (b - a)) in Bytes.blit_string src b dst a (srcn - b);
Bytes.blit_string src 0 dst 0 a; Some (Bytes.to_string dst)
Bytes.blit_string src b dst a (srcn - b); | v -> v)
Lwd.set var (Bytes.to_string dst); >>= fun t ->
Some (Bytes.to_string dst) Lwd.set tree t;
| v -> v) Lwt.return_unit
>>= fun tree -> Lwt.return { tt with tree }
let remove_uchar t n : t Lwt.t = let remove_uchar { path; tree; _ } n : unit Lwt.t =
(* F.epr "TextBuffer.remove_subset n=%d @." n; *) (* F.epr "TextBuffer.remove_subset n=%d @." n; *)
match t with Store.S.Tree.update (Lwd.peek tree) (Lwd.peek path) (function
| { path; tree; var; _ } as tt -> | Some src ->
Store.S.Tree.update tree path (function let srcn = String.length src in
| Some src -> assert (n < srcn);
let srcn = String.length src in let ucn =
assert (n < srcn); Uchar.utf_decode_length (String.get_utf_8_uchar src n)
let ucn = in
Uchar.utf_decode_length (String.get_utf_8_uchar src n) let dst = Bytes.create (srcn - ucn) in
in Bytes.blit_string src 0 dst 0 n;
let dst = Bytes.create (srcn - ucn) in Bytes.blit_string src (n + ucn) dst n (srcn - n - ucn);
Bytes.blit_string src 0 dst 0 n; Some (Bytes.to_string dst)
Bytes.blit_string src (n + ucn) dst n (srcn - n - ucn); | None ->
Lwd.set var (Bytes.to_string dst); F.epr "TextBuffer.remove_uchar None";
Some (Bytes.to_string dst) None)
| None -> >>= fun t ->
F.epr "TextBuffer.remove_uchar None"; Lwd.set tree t;
None) Lwt.return_unit
>>= fun tree -> Lwt.return { tt with tree }
let fold_string t (f : string -> 'a) : 'a Lwt.t = let fold_string t (f : string -> 'a) : 'a Lwt.t =
match t with match t with
| { path; tree; _ } -> | { path; tree; _ } ->
Store.S.Tree.get tree path >>= fun text -> Lwt.return (f text) Store.S.Tree.get (Lwd.peek tree) (Lwd.peek path)
>>= fun text -> Lwt.return (f text)
let get t = Lwd.get t.var let contents { path; tree; _ } : string Lwt.t =
(try Store.S.Tree.get (Lwd.peek tree) (Lwd.peek path)
let contents { path; tree; _ } = with e ->
(try Store.S.Tree.get tree path with F.epr "TextBuffer.contents %s: %s"
| Not_found | Invalid_argument _ -> (String.concat "/" (Lwd.peek path))
Lwt.return (match e with
@@ F.str | Not_found -> "Not_found"
"print_newline \"/%s: Not_found | Invalid_argument\";;" | Invalid_argument a -> F.str "Invalid_argument %s" a
(String.concat "/" path) | exc -> F.str "Exception: %s" (Printexc.to_string exc));
| exc -> Lwt.return "")
Lwt.return
(F.str "Store.S.Tree.get /%s exception: %s"
(String.concat "/" path)
(Printexc.to_string exc)))
>>= fun text -> Lwt.return text >>= fun text -> Lwt.return text
let get { tree; path; _ } =
Lwd.map2 (Lwd.get tree) (Lwd.get path) ~f:(fun tree path ->
Store.S.Tree.get tree path)
|> lwt_lwd
let length { path; tree; _ } = let length { path; tree; _ } =
Store.S.Tree.get tree path >>= fun text -> Store.S.Tree.get (Lwd.peek tree) (Lwd.peek path) >>= fun text ->
Lwt.return (String.length text) Lwt.return (String.length text)
end end
@ -488,7 +485,8 @@ module TextLayout = struct
record record
[ [
field "text" field "text"
(fun s -> str "path=%s" (String.concat "/" s.text.path)) (fun s ->
str "path=%s" (String.concat "/" (Lwd.peek s.text.path)))
string; string;
field "sections" field "sections"
(fun s -> s.sections) (fun s -> s.sections)
@ -526,9 +524,10 @@ module TextLayout = struct
let cursor_default = { index = 0; last_col = 0 } let cursor_default = { index = 0; last_col = 0 }
let cursor ?(last_col = 0) index : cursor = { index; last_col } let cursor ?(last_col = 0) index : cursor = { index; last_col }
let simple (text : 'a) ?(start = Lwd.pure 0) let simple (text : TextBuffer.t) ?(start = Lwd.pure 0)
?(format = format_default) wrap_width : layout Lwd.t = ?(format = format_default) wrap_width : layout Lwd.t Lwt.t =
Lwd.map2 (TextBuffer.get text) start ~f:(fun str start -> TextBuffer.get text >>= fun str ->
Lwd.map2 start str ~f:(fun start str ->
{ {
layout_default with layout_default with
text; text;
@ -537,6 +536,7 @@ module TextLayout = struct
wrap = wrap =
{ (default_text_wrapping ()) with max_width = wrap_width }; { (default_text_wrapping ()) with max_width = wrap_width };
}) })
|> Lwt.return
let cursor_color = ref (Gv.Color.rgbf ~r:0.5 ~g:0.5 ~b:0.) let cursor_color = ref (Gv.Color.rgbf ~r:0.5 ~g:0.5 ~b:0.)
@ -555,20 +555,11 @@ module TextLayout = struct
(fun (l : section list) sec -> (fun (l : section list) sec ->
let s, e = sec.byte_range in let s, e = sec.byte_range in
l l
@ (if @ (if e < cs || ce < s then [ sec ] else [])
e < cs || ce < s @ (if cs > s && cs <= e then
(* cursor start is after this section or cursor end is before this section *) [ { sec with byte_range = (s, cs) } ]
then [ sec ]
else []) else [])
@ (if @ (if cs <= e && ce >= s then
cs > s
&& cs <= e (* if cursor start is in this section *)
then [ { sec with byte_range = (s, cs) } ]
else [])
@ (if
cs <= e && ce >= s
(* if cursor start is at or before the end this section and cursor end is at or after the beginning of this section *)
then
[ [
{ {
format = format sec.format; format = format sec.format;
@ -577,9 +568,8 @@ module TextLayout = struct
] ]
else []) else [])
@ @
if if ce > s && ce <= e then
ce > s && ce <= e (* if cursor end is in this section *) [ { sec with byte_range = (ce, e) } ]
then [ { sec with byte_range = (ce, e) } ]
else []) else [])
[] layout.sections; [] layout.sections;
} }
@ -595,6 +585,8 @@ module TextLayout = struct
Lwd.map2 mark cursor ~f:(fun m c -> Lwd.map2 mark cursor ~f:(fun m c ->
match m with match m with
| Some m' -> | Some m' ->
F.epr "TextLayout.with_mark inside Lwd.map@.";
with_range ~format (min m' c.index, max m' c.index) l with_range ~format (min m' c.index, max m' c.index) l
| None -> l)) | None -> l))
end end
@ -801,7 +793,7 @@ module TextEdit = struct
let cursor_set (t : t) (index : int) : unit Lwt.t = let cursor_set (t : t) (index : int) : unit Lwt.t =
cursor_update t (Fun.const index) cursor_update t (Fun.const index)
let default_bindings (t : t) (ui : Ui.t) : unit Lwt.t = let default_bindings (t : t) (ui : Ui.t) : unit =
let open GLFW in let open GLFW in
let open Event in let open Event in
let open Ui in let open Ui in
@ -989,14 +981,12 @@ module TextEdit = struct
| None -> Some (Lwd.peek t.cursor).index); | None -> Some (Lwd.peek t.cursor).index);
Lwt.return_unit); Lwt.return_unit);
]); ]);
(* WARN XXX TKTK TODO this is probably "breaking" the lwt context and being used in other calls to Lwt_main.run *) Ui.chrcallback_ref :=
(Ui.chrcallback_ref := fun c ->
fun c -> TextBuffer.insert_uchar t.text (Lwd.peek t.cursor).index c
TextBuffer.insert_uchar t.text (Lwd.peek t.cursor).index c >>= fun _ -> cursor_move t 1
>>= fun _ -> cursor_move t 1 (* This creates a giant stack of calls lol
(* This creates a giant stack of calls lol >>= fun () -> !Ui.chrcallback_ref c *)
>>= fun () -> !Ui.chrcallback_ref c *));
Lwt.return_unit
let multiline ui ?(text_format = TextLayout.format_default) let multiline ui ?(text_format = TextLayout.format_default)
(text : TextBuffer.t) : t = (text : TextBuffer.t) : t =
@ -1024,7 +1014,7 @@ module TextEdit = struct
(* return_key = keyboard_shortcut; *) (* return_key = keyboard_shortcut; *)
} }
in in
Lwt_main.run (default_bindings t ui); default_bindings t ui;
t t
end end
@ -1035,10 +1025,10 @@ module Layout = struct
type frame = { t : t; mutable size : size; style : Style.t } type frame = { t : t; mutable size : size; style : Style.t }
and t = and t =
[ `Box of [ `H | `V | `Z ] * frame list [ `Join of [ `X | `Y | `Z ] * (frame * frame)
| `String of string | `String of string
| `Buffer of TextBuffer.t | `Buffer of TextBuffer.t
| `TextEdit of TextEdit.t * TextLayout.layout Lwd.root | `TextEdit of TextEdit.t * TextLayout.layout
| `None ] | `None ]
and size = [ `Fixed of size2 | `Max | `Min ] and size = [ `Fixed of size2 | `Max | `Min ]
@ -1046,8 +1036,22 @@ module Layout = struct
let frame ?(size = `Max) ?(style = Style.default) t : frame = let frame ?(size = `Max) ?(style = Style.default) t : frame =
{ t; size; style } { t; size; style }
let box d ?style t = frame ?style (`Box (d, t)) let none = frame `None
let hbox, vbox, zbox = (box `H, box `V, box `Z) let join d ?style a b = frame ?style (`Join (d, (a, b)))
let box d ?style =
List.fold_left (fun acc a -> join d ?style a acc) none
(* let hbox, vbox, zbox = (box `X, box `Y, box `Z) *)
let pack_x ?style () = (none, join `X ?style)
let pack_y ?style () = (none, join `Y ?style)
let pack_z ?style () = (none, join `Z ?style)
let hcat ?style = Lwd_utils.reduce (pack_x ?style ())
let vcat ?style = Lwd_utils.reduce (pack_y ?style ())
let zcat ?style = Lwd_utils.reduce (pack_z ?style ())
let hbox ?style = Lwd_utils.pack (pack_x ?style ())
let vbox ?style = Lwd_utils.pack (pack_y ?style ())
let zbox ?style = Lwd_utils.pack (pack_z ?style ())
let textedit_style = let textedit_style =
Style. Style.
@ -1057,23 +1061,26 @@ module Layout = struct
margin = Margin.symmetric 10. 10.; margin = Margin.symmetric 10. 10.;
} }
let textedit ?size ?(style = textedit_style) (t : TextEdit.t) = let textedit ?size ?(style = textedit_style) (t : TextEdit.t) :
frame Lwd.t Lwt.t =
let open TextLayout in let open TextLayout in
F.epr "Layout.textedit@.";
simple t.text ~start:(Lwd.get t.scroll) ~format:t.text_format simple t.text ~start:(Lwd.get t.scroll) ~format:t.text_format
(Option.value ~default:80. t.desired_width) (Option.value ~default:80. t.desired_width)
|> with_cursor (Lwd.get t.cursor) >>= fun layout ->
with_cursor (Lwd.get t.cursor) layout
|> with_mark (Lwd.get t.mark) (Lwd.get t.cursor) |> with_mark (Lwd.get t.mark) (Lwd.get t.cursor)
|> Lwd.observe |> Lwd.map ~f:(fun tl -> frame ?size ~style (`TextEdit (t, tl)))
|> fun root -> frame ?size ~style (`TextEdit (t, root)) |> Lwt.return
let pp_dir ppf (t : [ `H | `V | `Z ]) = let pp_dir ppf (t : [ `X | `Y | `Z ]) =
F.pf ppf "%s" F.pf ppf "%s"
(match t with `H -> "`H" | `V -> "`V" | `Z -> "`Z") (match t with `X -> "`X" | `Y -> "`Y" | `Z -> "`Z")
let pp_t ppf (t : t) = let pp_t ppf (t : t) =
F.pf ppf "%s" F.pf ppf "%s"
(match t with (match t with
| `Box (d, _) -> F.str "`Box %a" pp_dir d | `Join (d, _) -> F.str "`Join %a" pp_dir d
| `Buffer _ -> "`Buffer" | `Buffer _ -> "`Buffer"
| `TextEdit _ -> "`TextEdit" | `TextEdit _ -> "`TextEdit"
| `String s -> F.str "`String %s" s | `String s -> F.str "`String %s" s
@ -1131,9 +1138,9 @@ module Painter = struct
Text.set_size t ~size:font_size; Text.set_size t ~size:font_size;
Text.set_align t ~align:Align.(left lor top) Text.set_align t ~align:Align.(left lor top)
let text_layout (t : Gv.t) (rect : box2) (te : TextEdit.t) let text_layout (t : Gv.t) (rect : box2)
(layout : TextLayout.layout Lwd.root) : box2 Lwt.t = ((te, layout) : TextEdit.t * TextLayout.layout) : box2 Lwt.t =
let g = Lwd.quick_sample layout in let g = layout in
let line_height = let line_height =
Option.value ~default:(Gv.Text.metrics t).line_height Option.value ~default:(Gv.Text.metrics t).line_height
g.line_height g.line_height
@ -1141,7 +1148,8 @@ module Painter = struct
let max_rows = Int.of_float (Box2.h rect /. line_height) in let max_rows = Int.of_float (Box2.h rect /. line_height) in
Lwd.set te.rows max_rows; Lwd.set te.rows max_rows;
let lines = Gv.Text.make_empty_rows max_rows in let lines = Gv.Text.make_empty_rows max_rows in
TextBuffer.contents g.text >>= fun contents -> Store.S.Tree.get (Lwd.peek te.text.tree) (Lwd.peek te.text.path)
>>= fun contents ->
let contents_len = String.length contents in let contents_len = String.length contents in
let row_count = let row_count =
Gv.Text.break_lines t ~break_width:(Box2.w rect) ~max_rows Gv.Text.break_lines t ~break_width:(Box2.w rect) ~max_rows
@ -1202,20 +1210,20 @@ module Painter = struct
box2 Lwt.t = box2 Lwt.t =
let box' = Margin.inner style.margin box in let box' = Margin.inner style.margin box in
(match t with (match t with
| `Box (dir, ll) -> | `Join (dir, (a, b)) ->
Lwt_list.fold_left_s Lwt_list.fold_left_s
(fun (c : box2) f -> (fun (c : box2) f ->
layout c ui f >>= fun r -> layout c ui f >>= fun r ->
let c' = let c' =
Box2.( Box2.(
match dir with match dir with
| `V -> of_pts (V2.v (minx c) (maxy r)) (max c) | `X -> of_pts (V2.v (minx c) (maxy r)) (max c)
| `H -> of_pts (V2.v (maxx r) (miny c)) (max c) | `Y -> of_pts (V2.v (maxx r) (miny c)) (max c)
| `Z -> box) | `Z -> box)
in in
Lwt.return c') Lwt.return c')
box' ll box' [ a; b ]
| `TextEdit (t, root) -> text_layout ui.gv box' t root | `TextEdit tt -> text_layout ui.gv box' tt
| _ -> Lwt.return box) | _ -> Lwt.return box)
>>= fun r -> >>= fun r ->
let r' = let r' =

View File

@ -38,7 +38,7 @@ let load_fonts vg =
Gv.Text.add_fallback vg ~name:"sans-bold" ~fallback:"emoji"; Gv.Text.add_fallback vg ~name:"sans-bold" ~fallback:"emoji";
Gv.Text.set_font_face vg ~name:"mono" Gv.Text.set_font_face vg ~name:"mono"
let () = let main =
GLFW.init (); GLFW.init ();
at_exit GLFW.terminate; at_exit GLFW.terminate;
let _res = GLFWExtras.glfwSetErrorCallback errorcb in let _res = GLFWExtras.glfwSetErrorCallback errorcb in
@ -99,24 +99,24 @@ let () =
|> ignore; |> ignore;
F.pr "oplevel.ml: building initial page@."; F.pr "oplevel.ml: building initial page@.";
TextBuffer.of_repo
~initial_path:[ ".config"; "init.ml" ]
~repo:rootrepo
>>= fun tb_init ->
Layout.textedit (TextEdit.multiline ui tb_init) >>= fun te_init ->
let page = let page =
Lwd.var Layout.(
Layout.( vbox
vbox ~style:
~style: Style.{ default with margin = Margin.symmetric 10.0 10.0 }
Style.{ default with margin = Margin.symmetric 10.0 10.0 } [
[ te_init;
textedit (*textedit
(TextEdit.multiline ui (TextEdit.multiline ui
(Lwt_main.run (TextBuffer.of_repo ~path:[ "README" ] ~repo:rootrepo)); *)
(TextBuffer.of_repo ])
~path:[ ".config"; "init.ml" ]
~repo:rootrepo)));
(*textedit
(TextEdit.multiline ui
(TextBuffer.of_repo ~path:[ "README" ] ~repo:rootrepo)); *)
])
in in
let page_root = Lwd.observe page in
let open GLFW in let open GLFW in
let open Event in let open Event in
@ -131,7 +131,23 @@ let () =
let period_min = 1.0 /. 30. in let period_min = 1.0 /. 30. in
let t = GLFW.getTime () |> ref in let t = GLFW.getTime () |> ref in
let render page = let render root =
let page = Lwd.quick_sample root in
let win_w, win_h = GLFW.getWindowSize ~window in
let width, height = (float win_w, float win_h) in
let box = Gg.(Box2.v V2.zero Size2.(v width (height -. 20.))) in
Gv.begin_frame ctx ~width ~height ~device_ratio:1.;
Perfgraph.render graph ctx (width -. 205.) 5.;
(* F.epr "box=%a@." Gg.Box2.pp box;
F.epr "Painter.layout=%a@." Gg.Box2.pp *)
Painter.layout box ui page >>= fun _ ->
(* Demo.render_demo ctx mx my win_w win_h now !blowup data; *)
Gv.end_frame ctx;
Lwt.return_unit
in
while not GLFW.(windowShouldClose ~window) do
let now = GLFW.getTime () in let now = GLFW.getTime () in
let dt = now -. !t in let dt = now -. !t in
t := now; t := now;
@ -143,9 +159,7 @@ let () =
min_fps := Float.min avg !min_fps; min_fps := Float.min avg !min_fps;
max_fps := Float.max avg !max_fps); max_fps := Float.max avg !max_fps);
let _mx, _my = GLFW.getCursorPos ~window in
let win_w, win_h = GLFW.getWindowSize ~window in let win_w, win_h = GLFW.getWindowSize ~window in
Gl.viewport 0 0 win_w win_h; Gl.viewport 0 0 win_w win_h;
Gl.clear Gl.clear
(Gl.color_buffer_bit lor Gl.depth_buffer_bit (Gl.color_buffer_bit lor Gl.depth_buffer_bit
@ -154,31 +168,16 @@ let () =
Gl.blend_func Gl.src_alpha Gl.one_minus_src_alpha; Gl.blend_func Gl.src_alpha Gl.one_minus_src_alpha;
Gl.enable Gl.cull_face_enum; Gl.enable Gl.cull_face_enum;
Gl.disable Gl.depth_test; Gl.disable Gl.depth_test;
Lwt.async (fun () -> render page_root);
let width, height = (float win_w, float win_h) in
let box = Gg.(Box2.v V2.zero Size2.(v width (height -. 20.))) in
Gv.begin_frame ctx ~width ~height ~device_ratio:1.;
Perfgraph.render graph ctx (width -. 205.) 5.;
(* F.epr "box=%a@." Gg.Box2.pp box;
F.epr "Painter.layout=%a@." Gg.Box2.pp *)
Painter.layout box ui page >>= fun _ ->
(* Demo.render_demo ctx mx my win_w win_h now !blowup data; *)
Gv.end_frame ctx;
Gc.major_slice 0 |> ignore; Gc.major_slice 0 |> ignore;
GLFW.swapBuffers ~window; GLFW.swapBuffers ~window;
GLFW.pollEvents (); GLFW.pollEvents ();
Unix.sleepf Float.(max 0. (period_min -. GLFW.getTime () +. !t)); Unix.sleepf Float.(max 0. (period_min -. GLFW.getTime () +. !t))
Lwt.return_unit
in
while not GLFW.(windowShouldClose ~window) do
Lwt_main.run (render (Lwd.peek page))
done; done;
Printf.printf "MIN %.2f\n" !min_fps; Printf.printf "MIN %.2f\n" !min_fps;
Printf.printf "MAX %.2f\n%!" !max_fps Printf.printf "MAX %.2f\n%!" !max_fps;
Lwt.return_unit
(* let out_ppf = (* let out_ppf =
Format.formatter_of_out_functions Format.formatter_of_out_functions
Format. Format.
@ -199,3 +198,5 @@ let () =
(* ignore (* ignore
(Toploop.use_input out_ppf (Toploop.use_input out_ppf
(String "#use \"topfind\";;\n#list;;")); *) (String "#use \"topfind\";;\n#list;;")); *)
let () = Lwt_main.run main