Image noise/OCaml/Xlib
< Image noise | OCaml
By default this program displays the noise with double buffering.
The command-line options -single
selects the single buffering.
Launch this program as a script with:
ocaml -I +Xlib Xlib.cma unix.cma noise_fps_x.ml ocaml -I +Xlib Xlib.cma unix.cma noise_fps_x.ml -single
<lang ocaml>open Xlib
type buffering = Single | Double
let best_buffering = Double let default_buffering = Single
let num_frames = 1000
(* choose the buffering kind *) let buffering =
match Sys.argv with | [| _; "-db" |] -> Double | [| _; "-best" |] -> best_buffering | [| _; "-single" |] -> Single | [| _; "-default" |] -> default_buffering | _ -> best_buffering
(* report the buffering chosen *) let () =
print_endline ( match buffering with | Double -> "double buffering" | Single -> "single buffering")
let () =
let width = 320 and height = 240 in let dpy = xOpenDisplay "" in
(* initialisation of the standard variables *) let screen = xDefaultScreen dpy in let root = xDefaultRootWindow dpy and visual = xDefaultVisual dpy screen and depth = xDefaultDepth dpy screen and black = xBlackPixel dpy screen and white = xWhitePixel dpy screen in
(* set foreground and background in the graphics context *) let gcvalues = new_xGCValues() in xGCValues_set_foreground gcvalues black; xGCValues_set_background gcvalues white; let gc = xCreateGC dpy root [GCForeground;GCBackground] gcvalues in
(* creation of the double buffer *) let db = xCreatePixmap dpy root width height depth in (* without these lines previous images from memory will appear *) xSetForeground dpy gc white; xFillRectangle dpy db gc 0 0 width height; xSetForeground dpy gc black;
(* window attributes *) let xswa = new_win_attr() in
(* the events we want *) xswa.set_event_mask [ExposureMask;PointerMotionMask;KeyPressMask];
(* border and background colors *) xswa.set_background_pixel white; xswa.set_border_pixel black;
let win = xCreateWindow dpy root 100 100 width height 2 depth InputOutput visual [CWEventMask;CWBorderPixel;CWBackPixel] xswa.attr in
(* show the window on screen *) xMapRaised dpy win;
(* connect the close button of the window handle *) let wm_delete_window = xInternAtom dpy "WM_DELETE_WINDOW" true in xSetWMProtocols dpy win wm_delete_window 1;
let t0 = Unix.gettimeofday() in let event = new_xEvent() in
for i = 1 to num_frames do if xPending dpy > 0 then begin (* handle events *) xNextEvent dpy event; match xEventType event with | Expose -> (* remove all the Expose events from the event stack *) while (xCheckTypedEvent dpy Expose event) do () done; xCopyArea dpy db win gc 0 0 width height 0 0; (* force refresh the screen *) xFlush dpy;
| KeyPress -> (* exit on any key press *) xCloseDisplay dpy; exit 0;
| ClientMessage -> (* delete window event *) let xclient = to_xClientMessageEvent event in let atom = xEvent_xclient_data xclient in if atom = wm_delete_window then exit 0
| _ -> () end;
begin match buffering with | Double -> (* animation with the double buffer *) xSetForeground dpy gc white; xFillRectangle dpy db gc 0 0 width height; xSetForeground dpy gc black;
let points = Array.init (width * height / 2) (fun _ -> { pnt_x = Random.int width; pnt_y = Random.int height }) in xDrawPoints dpy db gc points CoordModeOrigin;
xCopyArea dpy db win gc 0 0 width height 0 0; (* force refresh the screen *) xFlush dpy; | Single -> (* animation without double buffer *) xClearWindow dpy win;
let points = Array.init (width * height / 2) (fun _ -> { pnt_x = Random.int width; pnt_y = Random.int height }) in
xDrawPoints dpy win gc points CoordModeOrigin; end done;
(* tell what was the FPS for num_frames frames *) let t_end = Unix.gettimeofday() in let fps = (float num_frames) /. (t_end -. t0) in print_string ">> fps:"; print_float fps; print_newline()</lang>
You can also compile this program to native-code with the following command:
- $ ocamlopt -I +Xlib Xlib.cmxa unix.cmxa noise_fps_x.ml -o noise_fps_x.opt
and then execute the result with:
- $ ./noise_fps_x.opt