| 1 |
type buffer_raw;; |
|---|
| 2 |
type buffer = (buffer_raw * int * int);; |
|---|
| 3 |
|
|---|
| 4 |
external create_raw : int -> int -> buffer_raw = "c_FB_new_buffer";; |
|---|
| 5 |
external free_raw : buffer_raw -> unit = "c_FB_free_buffer";; |
|---|
| 6 |
external fill_raw : buffer_raw -> int -> int -> (int -> float) -> unit = |
|---|
| 7 |
"c_FB_fill_buffer";; |
|---|
| 8 |
external fill_from_raw : buffer_raw -> int -> buffer_raw -> int -> int -> unit = |
|---|
| 9 |
"c_FB_fill_buffer_from_buffer";; |
|---|
| 10 |
external add_raw : buffer_raw -> buffer_raw -> int -> buffer_raw = |
|---|
| 11 |
"c_FB_add_buffers";; |
|---|
| 12 |
external mult_raw : buffer_raw -> buffer_raw -> int -> buffer_raw = |
|---|
| 13 |
"c_FB_mult_buffers";; |
|---|
| 14 |
external at_raw : buffer_raw -> int -> float = "c_FB_at";; |
|---|
| 15 |
external short_at_raw : buffer_raw -> int -> int = "c_FB_short_at";; |
|---|
| 16 |
external split_raw : buffer_raw -> buffer_raw array -> int -> unit = |
|---|
| 17 |
"c_FB_split_into_channels";; |
|---|
| 18 |
external merge_raw : buffer_raw array -> buffer_raw -> int -> unit = |
|---|
| 19 |
"c_FB_merge_channels";; |
|---|
| 20 |
external blit_raw : buffer_raw -> int -> buffer_raw -> int -> int -> unit = |
|---|
| 21 |
"c_FB_blit";; |
|---|
| 22 |
external transparency_raw : buffer_raw -> buffer_raw -> buffer_raw -> int -> |
|---|
| 23 |
buffer_raw = "c_FB_transparency";; |
|---|
| 24 |
external average_raw : buffer_raw array -> int -> buffer_raw = "c_FB_average";; |
|---|
| 25 |
|
|---|
| 26 |
exception ChannelsMismatch;; |
|---|
| 27 |
exception BlitOutOfBounds;; |
|---|
| 28 |
|
|---|
| 29 |
let create l c = (create_raw l c, l, c);; |
|---|
| 30 |
let free (b,l,c) = free_raw b;; |
|---|
| 31 |
let fill (b,l,c) f = fill_raw b l c f;; |
|---|
| 32 |
let fill_from_buffer (b,l,c) (bf,lf,cf) o = |
|---|
| 33 |
if c != cf then raise ChannelsMismatch; |
|---|
| 34 |
fill_from_raw b (l*c) bf (lf*cf) (o*c);; |
|---|
| 35 |
let add (b1,l1,c1) (b2,l2,c2) = |
|---|
| 36 |
if c1 != c2 then raise ChannelsMismatch; |
|---|
| 37 |
let l = min l1 l2 in (add_raw b1 b2 (l*c1), l, c1);; |
|---|
| 38 |
let mult (b1,l1,c1) (b2,l2,c2) = |
|---|
| 39 |
if c1 != c2 then raise ChannelsMismatch; |
|---|
| 40 |
let l = min l1 l2 in (mult_raw b1 b2 (l*c1), l, c1);; |
|---|
| 41 |
let at (b,l,c) p = at_raw b p;; |
|---|
| 42 |
let short_at (b,l,c) p = short_at_raw b p;; |
|---|
| 43 |
let split (b,l,c) = |
|---|
| 44 |
let raw_arr = Array.init c (fun i -> create_raw l 1) in |
|---|
| 45 |
split_raw b raw_arr l; |
|---|
| 46 |
Array.init c (fun i -> (raw_arr.(i), l, 1));; |
|---|
| 47 |
let merge arr = |
|---|
| 48 |
let raw_arr = Array.init (Array.length arr) |
|---|
| 49 |
(fun i -> (match arr.(i) with | (b,_,_) -> b)) in |
|---|
| 50 |
let len = (match arr.(0) with | (_,l,_) -> l) in |
|---|
| 51 |
let out_arr = create_raw len (Array.length arr) in |
|---|
| 52 |
merge_raw raw_arr out_arr len; |
|---|
| 53 |
(out_arr, len, (Array.length arr));; |
|---|
| 54 |
let blit (bs, ls, cs) spos (bd, ld, cd) dpos len = |
|---|
| 55 |
if cs != cd then raise ChannelsMismatch; |
|---|
| 56 |
if spos < 0 then raise BlitOutOfBounds; |
|---|
| 57 |
if dpos < 0 then raise BlitOutOfBounds; |
|---|
| 58 |
if (spos + len) > ls then raise BlitOutOfBounds; |
|---|
| 59 |
if (dpos + len) > ld then raise BlitOutOfBounds; |
|---|
| 60 |
blit_raw bs (spos * cs) bd (dpos * cd) (len * cd);; |
|---|
| 61 |
let transparency (b1,l1,c1) (b2,l2,c2) (bt,lt,ct) = |
|---|
| 62 |
if c1 != c2 then raise ChannelsMismatch; |
|---|
| 63 |
if c1 != ct then raise ChannelsMismatch; |
|---|
| 64 |
let len = min (min l1 l2) lt in |
|---|
| 65 |
(transparency_raw b1 b2 bt (len * c1), len, c1);; |
|---|
| 66 |
let average arr = |
|---|
| 67 |
let raw_arr = Array.init (Array.length arr) |
|---|
| 68 |
(fun i -> (match arr.(i) with | (b,_,_) -> b)) in |
|---|
| 69 |
let (len,chans) = (match arr.(0) with | (_,l,c) -> (l,c)) in |
|---|
| 70 |
(average_raw raw_arr (len * chans), len, chans);; |
|---|
| 71 |
let length (b,l,c) = l;; |
|---|
| 72 |
let size (b,l,c) = l * c;; |
|---|
| 73 |
|
|---|
| 74 |
let fun_cache = ref [];; |
|---|
| 75 |
let create_with_caching func period length channels offset = |
|---|
| 76 |
let b = create length channels in |
|---|
| 77 |
( |
|---|
| 78 |
try |
|---|
| 79 |
let r = List.assoc (func, channels) (!fun_cache) in |
|---|
| 80 |
fill_from_buffer b r offset |
|---|
| 81 |
with Not_found -> |
|---|
| 82 |
( |
|---|
| 83 |
let cache = create period channels in |
|---|
| 84 |
fill cache func; |
|---|
| 85 |
fill_from_buffer b cache offset; |
|---|
| 86 |
fun_cache := ((func, channels), cache)::(!fun_cache) |
|---|
| 87 |
) |
|---|
| 88 |
); |
|---|
| 89 |
b;; |
|---|