/
tsdl.ml
4677 lines (3842 loc) · 152 KB
/
tsdl.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
(*---------------------------------------------------------------------------
Copyright (c) 2013 Daniel C. Bünzli. All rights reserved.
Distributed under the BSD3 license, see license at the end of the file.
%%NAME%% release %%VERSION%%
---------------------------------------------------------------------------*)
let unsafe_get = Array.unsafe_get
open Ctypes
open Foreign
module Sdl = struct
(* Enum cases and #ifdef'd constants, see support/ in the distribution *)
open Tsdl_consts
(* Formatting with continuation. *)
let kpp k fmt =
let k fmt = k (Format.flush_str_formatter ()) in
Format.kfprintf k Format.str_formatter fmt
(* Invalid_argument strings *)
let str = Printf.sprintf
let err_index i = str "invalid index: %d" i
let err_length_mul l mul = str "invalid length: %d not a multiple of %d" l mul
let err_drop_file = "null file name (drop_file_free already called ?)"
let err_read_field = "cannot read field"
let err_bigarray_pitch pitch ba_el_size =
"invalid bigarray kind: pitch (%d bytes) not a multiple of bigarray element \
byte size (%d)"
let err_bigarray_data len ba_el_size =
"invalid bigarray kind: data (%d bytes) not a multiple of bigarray element \
byte size (%d)"
(* ctypes views *)
let write_never _ = assert false
let bool =
view ~read:((<>)0) ~write:(fun b -> compare b false) int;;
let int_as_uint8_t =
view ~read:Unsigned.UInt8.to_int ~write:Unsigned.UInt8.of_int uint8_t
let int_as_uint16_t =
view ~read:Unsigned.UInt16.to_int ~write:Unsigned.UInt16.of_int uint16_t
let int_as_uint32_t =
view ~read:Unsigned.UInt32.to_int ~write:Unsigned.UInt32.of_int uint32_t
let int_as_int32_t =
view ~read:Signed.Int32.to_int ~write:Signed.Int32.of_int int32_t
let int32_as_uint32_t =
view ~read:Unsigned.UInt32.to_int32 ~write:Unsigned.UInt32.of_int32 uint32_t
let string_as_char_array n = (* FIXME: drop this if ctypes proposes better *)
let n_array = array n char in
let read a =
let len = Array.length a in
let b = Buffer.create len in
try
for i = 0 to len - 1 do
let c = Array.get a i in
if c = '\000' then raise Exit else Buffer.add_char b c
done;
Buffer.contents b
with Exit -> Buffer.contents b
in
let write s =
let a = Array.make char n in
let len = min (Array.length a) (String.length s) in
for i = 0 to len - 1 do Array.set a i (s.[i]) done;
a
in
view ~read ~write n_array
let get_error =
foreign "SDL_GetError" (void @-> returning string)
let error () = `Error (get_error ())
let zero_to_ok =
let read = function 0 -> `Ok () | err -> error () in
view ~read ~write:write_never int
let one_to_ok =
let read = function 1 -> `Ok () | err -> error () in
view ~read ~write:write_never int
let bool_to_ok =
let read = function 0 -> `Ok false | 1 -> `Ok true | _ -> error () in
view ~read ~write:write_never int
let nat_to_ok =
let read = function n when n < 0 -> error () | n -> `Ok n in
view ~read ~write:write_never int
let some_to_ok t =
let read = function Some v -> `Ok v | None -> error () in
view ~read ~write:write_never t
let sdl_free = foreign "SDL_free" (ptr void @-> returning void)
(* Since we never let SDL redefine our main make sure this is always
called. *)
let () =
let set_main_ready = foreign "SDL_SetMainReady" (void @-> returning void) in
set_main_ready ()
(* SDL results *)
type 'a result = [ `Ok of 'a | `Error of string ]
(* Integer types and maps *)
type uint8 = int
type uint16 = int
type int16 = int
type uint32 = int32
type uint64 = int64
module Int = struct type t = int let compare : int -> int -> int = compare end
module Imap = Map.Make(Int)
(* Bigarrays *)
type ('a, 'b) bigarray = ('a, 'b, Bigarray.c_layout) Bigarray.Array1.t
let ba_create k len = Bigarray.Array1.create k Bigarray.c_layout len
let ba_kind_byte_size : ('a, 'b) Bigarray.kind -> int = fun k ->
let open Bigarray in
(* FIXME: see http://caml.inria.fr/mantis/view.php?id=6263 *)
match Obj.magic k with
| k when k = char || k = int8_signed || k = int8_unsigned -> 1
| k when k = int16_signed || k = int16_unsigned -> 2
| k when k = int32 || k = float32 -> 4
| k when k = float64 || k = int64 || k = complex32 -> 8
| k when k = complex64 -> 16
| k when k = int || k = nativeint -> Sys.word_size / 8
| k -> assert false
let access_ptr_typ_of_ba_kind : ('a, 'b) Bigarray.kind -> 'a ptr typ = fun k ->
let open Bigarray in
(* FIXME: use typ_of_bigarray_kind when ctypes support it. *)
match Obj.magic k with
| k when k = float32 -> Obj.magic (ptr Ctypes.float)
| k when k = float64 -> Obj.magic (ptr Ctypes.double)
| k when k = complex32 -> Obj.magic (ptr Ctypes.complex32)
| k when k = complex64 -> Obj.magic (ptr Ctypes.complex64)
| k when k = int8_signed -> Obj.magic (ptr Ctypes.int8_t)
| k when k = int8_unsigned -> Obj.magic (ptr Ctypes.uint8_t)
| k when k = int16_signed -> Obj.magic (ptr Ctypes.int16_t)
| k when k = int16_unsigned -> Obj.magic (ptr Ctypes.uint16_t)
| k when k = int -> Obj.magic (ptr Ctypes.camlint)
| k when k = int32 -> Obj.magic (ptr Ctypes.int32_t)
| k when k = int64 -> Obj.magic (ptr Ctypes.int64_t)
| k when k = nativeint -> Obj.magic (ptr Ctypes.nativeint)
| k when k = char -> Obj.magic (ptr Ctypes.char)
| _ -> assert false
let ba_byte_size ba =
let el_size = ba_kind_byte_size (Bigarray.Array1.kind ba) in
el_size * Bigarray.Array1.dim ba
(* Basics *)
(* Initialization and shutdown *)
module Init = struct
type t = Unsigned.uint32
let i = Unsigned.UInt32.of_int
let ( + ) = Unsigned.UInt32.logor
let test f m = Unsigned.UInt32.(compare (logand f m) zero <> 0)
let eq f f' = Unsigned.UInt32.(compare f f' = 0)
let timer = i sdl_init_timer
let audio = i sdl_init_audio
let video = i sdl_init_video
let joystick = i sdl_init_joystick
let haptic = i sdl_init_haptic
let gamecontroller = i sdl_init_gamecontroller
let events = i sdl_init_events
let everything = i sdl_init_everything
let noparachute = i sdl_init_noparachute
end
let init =
foreign "SDL_Init" (uint32_t @-> returning zero_to_ok)
let init_sub_system =
foreign "SDL_InitSubSystem" (uint32_t @-> returning zero_to_ok)
let quit =
foreign "SDL_Quit" (void @-> returning void)
let quit_sub_system =
foreign "SDL_QuitSubSystem" (uint32_t @-> returning void)
let was_init =
foreign "SDL_WasInit" (uint32_t @-> returning uint32_t)
let was_init = function
| None -> was_init (Unsigned.UInt32.of_int 0)
| Some m -> was_init m
(* Hints *)
module Hint = struct
type t = string
let framebuffer_acceleration = sdl_hint_framebuffer_acceleration
let idle_timer_disabled = sdl_hint_idle_timer_disabled
let orientations = sdl_hint_orientations
let render_driver = sdl_hint_render_driver
let render_opengl_shaders = sdl_hint_render_opengl_shaders
let render_scale_quality = sdl_hint_render_scale_quality
let render_vsync = sdl_hint_render_vsync
type priority = int
let default = sdl_hint_default
let normal = sdl_hint_normal
let override = sdl_hint_override
end
let clear_hints =
foreign "SDL_ClearHints" (void @-> returning void)
let get_hint =
foreign "SDL_GetHint" (string @-> returning string_opt)
let set_hint =
foreign "SDL_SetHint" (string @-> string @-> returning bool)
let set_hint_with_priority =
foreign "SDL_SetHintWithPriority"
(string @-> string @-> int @-> returning bool)
(* Errors *)
let clear_error =
foreign "SDL_ClearError" (void @-> returning void)
let set_error =
foreign "SDL_SetError" (string @-> returning int)
let set_error fmt =
kpp (fun s -> ignore (set_error s)) fmt
(* Log *)
module Log = struct
type category = int
let category_application = sdl_log_category_application
let category_error = sdl_log_category_error
let category_system = sdl_log_category_system
let category_audio = sdl_log_category_audio
let category_video = sdl_log_category_video
let category_render = sdl_log_category_render
let category_input = sdl_log_category_input
let category_custom = sdl_log_category_custom
type priority = int
let priority_compare : int -> int -> int = Pervasives.compare
let priority_verbose = sdl_log_priority_verbose
let priority_debug = sdl_log_priority_debug
let priority_info = sdl_log_priority_info
let priority_warn = sdl_log_priority_warn
let priority_error = sdl_log_priority_error
let priority_critical = sdl_log_priority_critical
end
let log_fun_t = (int @-> string @-> string @-> returning void)
let log =
foreign "SDL_Log" (string @-> string @-> returning void)
let log fmt =
kpp (fun s -> ignore (log "%s" s)) fmt
let log_critical =
foreign "SDL_LogCritical" log_fun_t
let log_critical c fmt =
kpp (fun s -> ignore (log_critical c "%s" s)) fmt
let log_debug =
foreign "SDL_LogDebug" log_fun_t
let log_debug c fmt =
kpp (fun s -> ignore (log_debug c "%s" s)) fmt
let log_error =
foreign "SDL_LogError" log_fun_t
let log_error c fmt =
kpp (fun s -> ignore (log_error c "%s" s)) fmt
let log_info =
foreign "SDL_LogInfo" log_fun_t
let log_info c fmt =
kpp (fun s -> ignore (log_info c "%s" s)) fmt
let log_verbose =
foreign "SDL_LogVerbose" log_fun_t
let log_verbose c fmt =
kpp (fun s -> ignore (log_verbose c "%s" s)) fmt
let log_warn =
foreign "SDL_LogWarn" log_fun_t
let log_warn c fmt =
kpp (fun s -> ignore (log_warn c "%s" s)) fmt
let log_get_priority =
foreign "SDL_LogGetPriority" (int @-> returning int)
let log_message =
foreign "SDL_LogMessage"
(int @-> int @-> string @-> string @-> returning void)
let log_message c p fmt =
kpp (fun s -> ignore (log_message c p "%s" s)) fmt
let log_reset_priorities =
foreign "SDL_LogResetPriorities" (void @-> returning void)
let log_set_all_priority =
foreign "SDL_LogSetAllPriority" (int @-> returning void)
let log_set_priority =
foreign "SDL_LogSetPriority" (int @-> int @-> returning void)
(* Version *)
let version = structure "SDL_version"
let version_major = field version "major" uint8_t
let version_minor = field version "minor" uint8_t
let version_patch = field version "patch" uint8_t
let () = seal version
let get_version =
foreign "SDL_GetVersion" (ptr version @-> returning void)
let get_version () =
let get v f = Unsigned.UInt8.to_int (getf v f) in
let v = make version in
get_version (addr v);
(get v version_major), (get v version_minor), (get v version_patch)
let get_revision =
foreign "SDL_GetRevision" (void @-> returning string)
let get_revision_number =
foreign "SDL_GetRevisionNumber" (void @-> returning int)
(* IO absraction *)
type _rw_ops
let rw_ops_struct : _rw_ops structure typ = structure "SDL_RWops"
let rw_ops : _rw_ops structure ptr typ = ptr rw_ops_struct
let rw_ops_opt : _rw_ops structure ptr option typ = ptr_opt rw_ops_struct
let rw_ops_size = field rw_ops_struct "size"
(funptr (rw_ops @-> returning int64_t))
let rw_ops_seek = field rw_ops_struct "seek"
(funptr (rw_ops @-> int64_t @-> int @-> returning int64_t))
let rw_ops_read = field rw_ops_struct "read"
(funptr (rw_ops @-> ptr void @-> size_t @-> size_t @-> returning size_t))
let rw_ops_write = field rw_ops_struct "write"
(funptr (rw_ops @-> ptr void @-> size_t @-> size_t @-> returning size_t))
let rw_ops_close = field rw_ops_struct "close"
(funptr (rw_ops @-> returning int))
let _ = field rw_ops_struct "type" uint32_t
(* ... #ifdef'd union follows, we don't care we don't use Ctypes.make *)
let () = seal rw_ops_struct
type rw_ops = _rw_ops structure ptr
let rw_from_file =
foreign "SDL_RWFromFile"
(string @-> string @-> returning (some_to_ok rw_ops_opt))
let rw_close ops =
let close = getf (!@ ops) rw_ops_close in
if close ops = 0 then `Ok () else (error ())
(* File system paths *)
let get_base_path =
foreign "SDL_GetBasePath" (void @-> returning (ptr char))
let get_base_path () =
let p = get_base_path () in
let path = coerce (ptr char) (some_to_ok string_opt) p in
sdl_free (coerce (ptr char) (ptr void) p);
path
let get_pref_path =
foreign "SDL_GetPrefPath" (string @-> string @-> returning (ptr char))
let get_pref_path ~org ~app =
let p = get_pref_path org app in
let path = coerce (ptr char) (some_to_ok string_opt) p in
sdl_free (coerce (ptr char) (ptr void) p);
path
(* Video *)
type window = unit ptr
let window : window typ = ptr void
let window_opt : window option typ = ptr_opt void
(* Colors *)
type _color
type color = _color structure
let color : color typ = structure "SDL_Color"
let color_r = field color "r" uint8_t
let color_g = field color "g" uint8_t
let color_b = field color "b" uint8_t
let color_a = field color "a" uint8_t
let () = seal color
module Color = struct
let create ~r ~g ~b ~a =
let c = make color in
setf c color_r (Unsigned.UInt8.of_int r);
setf c color_g (Unsigned.UInt8.of_int g);
setf c color_b (Unsigned.UInt8.of_int b);
setf c color_a (Unsigned.UInt8.of_int a);
c
let r c = Unsigned.UInt8.to_int (getf c color_r)
let g c = Unsigned.UInt8.to_int (getf c color_g)
let b c = Unsigned.UInt8.to_int (getf c color_b)
let a c = Unsigned.UInt8.to_int (getf c color_a)
end
(* Points *)
type _point
type point = _point structure
let point : point typ = structure "SDL_Point"
let point_x = field point "x" int
let point_y = field point "y" int
let () = seal point
module Point = struct
let create ~x ~y =
let p = make point in
setf p point_x x;
setf p point_y y;
p
let x p = getf p point_x
let y p = getf p point_y
let opt_addr = function
| None -> coerce (ptr void) (ptr point) null
| Some v -> addr v
end
(* Rectangle *)
type _rect
type rect = _rect structure
let rect : rect typ = structure "SDL_Rect"
let rect_x = field rect "x" int
let rect_y = field rect "y" int
let rect_w = field rect "w" int
let rect_h = field rect "h" int
let () = seal rect
module Rect = struct
let create ~x ~y ~w ~h =
let r = make rect in
setf r rect_x x;
setf r rect_y y;
setf r rect_w w;
setf r rect_h h;
r
let x r = getf r rect_x
let y r = getf r rect_y
let w r = getf r rect_w
let h r = getf r rect_h
let opt_addr = function
| None -> coerce (ptr void) (ptr rect) null
| Some v -> addr v
end
let enclose_points =
foreign "SDL_EnclosePoints"
(ptr void @-> int @-> ptr rect @-> ptr rect @-> returning bool)
let enclose_points_ba ?clip ps =
let len = Bigarray.Array1.dim ps in
if len mod 2 <> 0 then invalid_arg (err_length_mul len 2) else
let count = len / 2 in
let ps = to_voidp (bigarray_start array1 ps) in
let res = make rect in
if enclose_points ps count (Rect.opt_addr clip) (addr res)
then Some res
else None
let enclose_points ?clip ps =
let count = List.length ps in
let ps = to_voidp (Array.start (Array.of_list point ps)) in
let res = make rect in
if enclose_points ps count (Rect.opt_addr clip) (addr res)
then Some res
else None
let has_intersection =
foreign "SDL_HasIntersection"
(ptr rect @-> ptr rect @-> returning bool)
let has_intersection a b =
has_intersection (addr a) (addr b)
let intersect_rect =
foreign "SDL_IntersectRect"
(ptr rect @-> ptr rect @-> ptr rect @-> returning bool)
let intersect_rect a b =
let res = make rect in
if intersect_rect (addr a) (addr b) (addr res) then Some res else None
let intersect_rect_and_line =
foreign "SDL_IntersectRectAndLine"
(ptr rect @-> ptr int @-> ptr int @-> ptr int @-> ptr int @->
returning bool)
let intersect_rect_and_line r x1 y1 x2 y2 =
let alloc v = allocate int v in
let x1, y1 = alloc x1, alloc y1 in
let x2, y2 = alloc x2, alloc y2 in
if intersect_rect_and_line (addr r) x1 y1 x2 y2
then Some ((!@x1, !@y1), (!@x2, !@y2))
else None
let rect_empty r =
(* symbol doesn't exist: SDL_FORCE_INLINE directive
foreign "SDL_RectEmpty" (ptr rect @-> returning bool) *)
Rect.w r <= 0 || Rect.h r <= 0
let rect_equals a b =
(* symbol doesn't exist: SDL_FORCE_INLINE directive
foreign "SDL_RectEquals" (ptr rect @-> ptr rect @-> returning bool) *)
(Rect.x a = Rect.x b) && (Rect.y a = Rect.y b) &&
(Rect.w a = Rect.w b) && (Rect.h a = Rect.h b)
let union_rect =
foreign "SDL_UnionRect"
(ptr rect @-> ptr rect @-> ptr rect @-> returning void)
let union_rect a b =
let res = make rect in
union_rect (addr a) (addr b) (addr res);
res
(* Palettes *)
type _palette
type palette_struct = _palette structure
let palette_struct : palette_struct typ = structure "SDL_Palette"
let palette_ncolors = field palette_struct "ncolors" int
let palette_colors = field palette_struct "colors" (ptr color)
let _ = field palette_struct "version" uint32_t
let _ = field palette_struct "refcount" int
let () = seal palette_struct
type palette = palette_struct ptr
let palette : palette typ = ptr palette_struct
let palette_opt : palette option typ = ptr_opt palette_struct
let alloc_palette =
foreign "SDL_AllocPalette"
(int @-> returning (some_to_ok palette_opt))
let free_palette =
foreign "SDL_FreePalette" (palette @-> returning void)
let get_palette_ncolors p =
getf (!@ p) palette_ncolors
let get_palette_colors p =
let ps = !@ p in
Array.to_list
(Array.from_ptr (getf ps palette_colors) (getf ps palette_ncolors))
let get_palette_colors_ba p =
let ps = !@ p in
(* FIXME: ctypes should have an Array.copy function *)
let n = getf ps palette_ncolors in
let ba = Bigarray.(Array1.create int8_unsigned c_layout (n * 4)) in
let ba_ptr =
Array.from_ptr (coerce (ptr int) (ptr color) (bigarray_start array1 ba)) n
in
let ca = Array.from_ptr (getf ps palette_colors) n in
for i = 0 to n - 1 do Array.set ba_ptr i (Array.get ca i) done;
ba
let set_palette_colors =
foreign "SDL_SetPaletteColors"
(palette @-> ptr void @-> int @-> int @-> returning zero_to_ok)
let set_palette_colors_ba p cs ~fst =
let len = Bigarray.Array1.dim cs in
if len mod 4 <> 0 then invalid_arg (err_length_mul len 4) else
let count = len / 4 in
let cs = to_voidp (bigarray_start array1 cs) in
set_palette_colors p cs fst count
let set_palette_colors p cs ~fst =
let count = List.length cs in
let a = Array.of_list color cs in
set_palette_colors p (to_voidp (Array.start a)) fst count
(* Pixel formats *)
type gamma_ramp = (int, Bigarray.int16_unsigned_elt) bigarray
let calculate_gamma_ramp =
foreign "SDL_CalculateGammaRamp"
(float @-> ptr void @-> returning void)
let calculate_gamma_ramp g =
let ba = Bigarray.(Array1.create int16_unsigned c_layout 256) in
calculate_gamma_ramp g (to_voidp (bigarray_start array1 ba));
ba
module Blend = struct
type mode = int
let mode_none = sdl_blendmode_none
let mode_blend = sdl_blendmode_blend
let mode_add = sdl_blendmode_add
let mode_mod = sdl_blendmode_mod
end
module Pixel = struct
type format_enum = Unsigned.UInt32.t
let i = Unsigned.UInt32.of_int32
let to_uint32 = Unsigned.UInt32.to_int32
let eq f f' = Unsigned.UInt32.(compare f f' = 0)
let format_unknown = i sdl_pixelformat_unknown
let format_index1lsb = i sdl_pixelformat_index1lsb
let format_index1msb = i sdl_pixelformat_index1msb
let format_index4lsb = i sdl_pixelformat_index4lsb
let format_index4msb = i sdl_pixelformat_index4msb
let format_index8 = i sdl_pixelformat_index8
let format_rgb332 = i sdl_pixelformat_rgb332
let format_rgb444 = i sdl_pixelformat_rgb444
let format_rgb555 = i sdl_pixelformat_rgb555
let format_bgr555 = i sdl_pixelformat_bgr555
let format_argb4444 = i sdl_pixelformat_argb4444
let format_rgba4444 = i sdl_pixelformat_rgba4444
let format_abgr4444 = i sdl_pixelformat_abgr4444
let format_bgra4444 = i sdl_pixelformat_bgra4444
let format_argb1555 = i sdl_pixelformat_argb1555
let format_rgba5551 = i sdl_pixelformat_rgba5551
let format_abgr1555 = i sdl_pixelformat_abgr1555
let format_bgra5551 = i sdl_pixelformat_bgra5551
let format_rgb565 = i sdl_pixelformat_rgb565
let format_bgr565 = i sdl_pixelformat_bgr565
let format_rgb24 = i sdl_pixelformat_rgb24
let format_bgr24 = i sdl_pixelformat_bgr24
let format_rgb888 = i sdl_pixelformat_rgb888
let format_rgbx8888 = i sdl_pixelformat_rgbx8888
let format_bgr888 = i sdl_pixelformat_bgr888
let format_bgrx8888 = i sdl_pixelformat_bgrx8888
let format_argb8888 = i sdl_pixelformat_argb8888
let format_rgba8888 = i sdl_pixelformat_rgba8888
let format_abgr8888 = i sdl_pixelformat_abgr8888
let format_bgra8888 = i sdl_pixelformat_bgra8888
let format_argb2101010 = i sdl_pixelformat_argb2101010
let format_yv12 = i sdl_pixelformat_yv12
let format_iyuv = i sdl_pixelformat_iyuv
let format_yuy2 = i sdl_pixelformat_yuy2
let format_uyvy = i sdl_pixelformat_uyvy
let format_yvyu = i sdl_pixelformat_yvyu
end
(* Note. Giving direct access to the palette field of SDL_PixelFormat
is problematic. We can't ensure the pointer won't become invalid at
a certain point. *)
type _pixel_format
type pixel_format_struct = _pixel_format structure
let pixel_format_struct : pixel_format_struct typ = structure "SDL_PixelFormat"
let pf_format = field pixel_format_struct "format" uint32_t
let pf_palette = field pixel_format_struct "palette" palette
let pf_bits_per_pixel = field pixel_format_struct "BitsPerPixel" uint8_t
let pf_bytes_per_pixel = field pixel_format_struct "BytesPerPixel" uint8_t
let _ = field pixel_format_struct "padding" uint16_t
let _ = field pixel_format_struct "Rmask" uint32_t
let _ = field pixel_format_struct "Gmask" uint32_t
let _ = field pixel_format_struct "Bmask" uint32_t
let _ = field pixel_format_struct "Amask" uint32_t
let _ = field pixel_format_struct "Rloss" uint8_t
let _ = field pixel_format_struct "Gloss" uint8_t
let _ = field pixel_format_struct "Bloss" uint8_t
let _ = field pixel_format_struct "Aloss" uint8_t
let _ = field pixel_format_struct "Rshift" uint8_t
let _ = field pixel_format_struct "Gshift" uint8_t
let _ = field pixel_format_struct "Bshift" uint8_t
let _ = field pixel_format_struct "Ashift" uint8_t
let _ = field pixel_format_struct "refcount" int
let _ = field pixel_format_struct "next" (ptr pixel_format_struct)
let () = seal pixel_format_struct
type pixel_format = pixel_format_struct ptr
let pixel_format : pixel_format typ = ptr pixel_format_struct
let pixel_format_opt : pixel_format option typ = ptr_opt pixel_format_struct
let alloc_format =
foreign "SDL_AllocFormat"
(uint32_t @-> returning (some_to_ok pixel_format_opt))
let free_format =
foreign "SDL_FreeFormat" (pixel_format @-> returning void)
let get_pixel_format_name =
foreign "SDL_GetPixelFormatName" (uint32_t @-> returning string)
let get_pixel_format_format pf =
getf (!@ pf) pf_format
let get_pixel_format_bits_pp pf =
Unsigned.UInt8.to_int (getf (!@ pf) pf_bits_per_pixel)
let get_pixel_format_bytes_pp pf =
Unsigned.UInt8.to_int (getf (!@ pf) pf_bytes_per_pixel)
let get_rgb =
foreign "SDL_GetRGB"
(int32_as_uint32_t @-> pixel_format @-> ptr uint8_t @->
ptr uint8_t @-> ptr uint8_t @-> returning void)
let get_rgb pf p =
let alloc () = allocate uint8_t Unsigned.UInt8.zero in
let to_int = Unsigned.UInt8.to_int in
let r, g, b = alloc (), alloc (), alloc () in
get_rgb p pf r g b;
to_int (!@ r), to_int (!@ g), to_int (!@ b)
let get_rgba =
foreign "SDL_GetRGBA"
(int32_as_uint32_t @-> pixel_format @-> ptr uint8_t @->
ptr uint8_t @-> ptr uint8_t @-> ptr uint8_t @-> returning void)
let get_rgba pf p =
let alloc () = allocate uint8_t Unsigned.UInt8.zero in
let to_int = Unsigned.UInt8.to_int in
let r, g, b, a = alloc (), alloc (), alloc (), alloc () in
get_rgba p pf r g b a;
to_int (!@ r), to_int (!@ g), to_int (!@ b), to_int (!@ a)
let map_rgb =
foreign "SDL_MapRGB"
(pixel_format @-> int_as_uint8_t @-> int_as_uint8_t @-> int_as_uint8_t @->
returning int32_as_uint32_t)
let map_rgba =
foreign "SDL_MapRGBA"
(pixel_format @-> int_as_uint8_t @-> int_as_uint8_t @-> int_as_uint8_t @->
int_as_uint8_t @-> returning int32_as_uint32_t)
let masks_to_pixel_format_enum =
foreign "SDL_MasksToPixelFormatEnum"
(int @-> int32_as_uint32_t @-> int32_as_uint32_t @-> int32_as_uint32_t @->
int32_as_uint32_t @-> returning uint32_t)
let pixel_format_enum_to_masks =
foreign "SDL_PixelFormatEnumToMasks"
(uint32_t @-> ptr int @->
ptr uint32_t @-> ptr uint32_t @-> ptr uint32_t @-> ptr uint32_t @->
returning bool)
let pixel_format_enum_to_masks pf =
let ui () = allocate uint32_t (Unsigned.UInt32.of_int 0) in
let get iptr = Unsigned.UInt32.to_int32 (!@ iptr) in
let bpp = allocate int 0 in
let rm, gm, bm, am = ui (), ui (), ui (), ui () in
if not (pixel_format_enum_to_masks pf bpp rm gm bm am) then error () else
`Ok (!@ bpp, get rm, get gm, get bm, get am)
let set_pixel_format_palette =
foreign "SDL_SetPixelFormatPalette"
(pixel_format @-> palette @-> returning zero_to_ok)
(* Surface *)
type _surface
type surface_struct = _surface structure
let surface_struct : surface_struct typ = structure "SDL_Surface"
let _ = field surface_struct "flags" uint32_t
let surface_format = field surface_struct "format" pixel_format
let surface_w = field surface_struct "w" int
let surface_h = field surface_struct "h" int
let surface_pitch = field surface_struct "pitch" int
let surface_pixels = field surface_struct "pixels" (ptr void)
let _ = field surface_struct "userdata" (ptr void)
let _ = field surface_struct "locked" int
let _ = field surface_struct "lock_data" (ptr void)
let _ = field surface_struct "clip_rect" rect
let _ = field surface_struct "map" (ptr void)
let _ = field surface_struct "refcount" int
let () = seal surface_struct
type surface = surface_struct ptr
let surface : surface typ = ptr surface_struct
let surface_opt : surface option typ = ptr_opt surface_struct
let blit_scaled =
(* SDL_BlitScaled is #ifdef'd to SDL_UpperBlitScaled *)
foreign "SDL_UpperBlitScaled"
(surface @-> ptr rect @-> surface @-> ptr rect @-> returning zero_to_ok)
let blit_scaled ~src sr ~dst dr =
blit_scaled src (addr sr) dst (Rect.opt_addr dr)
let blit_surface =
(* SDL_BlitSurface is #ifdef'd to SDL_UpperBlit *)
foreign "SDL_UpperBlit"
(surface @-> ptr rect @-> surface @-> ptr rect @-> returning zero_to_ok)
let blit_surface ~src sr ~dst dr =
blit_surface src (addr sr) dst (addr dr)
let convert_pixels =
foreign "SDL_ConvertPixels"
(int @-> int @-> uint32_t @-> ptr void @-> int @-> uint32_t @->
ptr void @-> int @-> returning zero_to_ok)
let convert_pixels ~w ~h ~src sp spitch ~dst dp dpitch =
(* FIXME: we could try check bounds. *)
let spitch = ba_kind_byte_size (Bigarray.Array1.kind sp) * spitch in
let dpitch = ba_kind_byte_size (Bigarray.Array1.kind dp) * dpitch in
let sp = to_voidp (bigarray_start array1 sp) in
let dp = to_voidp (bigarray_start array1 dp) in
convert_pixels w h src sp spitch dst dp dpitch
let convert_surface =
foreign "SDL_ConvertSurface"
(surface @-> pixel_format @-> uint32_t @->
returning (some_to_ok surface_opt))
let convert_surface s pf =
convert_surface s pf Unsigned.UInt32.zero
let convert_surface_format =
foreign "SDL_ConvertSurfaceFormat"
(surface @-> uint32_t @-> uint32_t @-> returning (some_to_ok surface_opt))
let convert_surface_format s pf =
convert_surface_format s pf Unsigned.UInt32.zero
let create_rgb_surface =
foreign "SDL_CreateRGBSurface"
(uint32_t @-> int @-> int @-> int @-> int32_as_uint32_t @->
int32_as_uint32_t @-> int32_as_uint32_t @-> int32_as_uint32_t @->
returning (some_to_ok surface_opt))
let create_rgb_surface ~w ~h ~depth rmask gmask bmask amask =
create_rgb_surface Unsigned.UInt32.zero w h depth rmask gmask bmask amask
let create_rgb_surface_from =
foreign "SDL_CreateRGBSurfaceFrom"
(ptr void @-> int @-> int @-> int @-> int @-> int32_as_uint32_t @->
int32_as_uint32_t @-> int32_as_uint32_t @-> int32_as_uint32_t @->
returning (some_to_ok surface_opt))
let create_rgb_surface_from p ~w ~h ~depth ~pitch rmask gmask bmask amask =
(* FIXME: we could try check bounds. *)
let pitch = ba_kind_byte_size (Bigarray.Array1.kind p) * pitch in
let p = to_voidp (bigarray_start array1 p) in
create_rgb_surface_from p w h depth pitch rmask gmask bmask amask
let fill_rect =
foreign "SDL_FillRect"
(surface @-> ptr rect @-> int32_as_uint32_t @-> returning zero_to_ok)
let fill_rect s r c =
fill_rect s (Rect.opt_addr r) c
let fill_rects =
foreign "SDL_FillRects"
(surface @-> ptr void @-> int @-> int32_as_uint32_t @->
returning zero_to_ok)
let fill_rects_ba s rs col =
let len = Bigarray.Array1.dim rs in
if len mod 4 <> 0 then invalid_arg (err_length_mul len 4) else
let count = len / 4 in
let rs = to_voidp (bigarray_start array1 rs) in
fill_rects s rs count col
let fill_rects s rs col =
let count = List.length rs in
let a = Array.of_list rect rs in
fill_rects s (to_voidp (Array.start a)) count col
let free_surface =
foreign "SDL_FreeSurface" (surface @-> returning void)
let get_clip_rect =
foreign "SDL_GetClipRect" (surface @-> ptr rect @-> returning void)
let get_clip_rect s =
let r = make rect in
(get_clip_rect s (addr r); r)
let get_color_key =
foreign "SDL_GetColorKey"
(surface @-> ptr uint32_t @-> returning zero_to_ok)
let get_color_key s =
let key = allocate uint32_t Unsigned.UInt32.zero in
match get_color_key s key with
| `Ok () -> `Ok (Unsigned.UInt32.to_int32 (!@ key)) | `Error _ as e -> e
let get_surface_alpha_mod =
foreign "SDL_GetSurfaceAlphaMod"
(surface @-> ptr uint8_t @-> returning zero_to_ok)
let get_surface_alpha_mod s =
let alpha = allocate uint8_t Unsigned.UInt8.zero in
match get_surface_alpha_mod s alpha with
| `Ok () -> `Ok (Unsigned.UInt8.to_int (!@ alpha)) | `Error _ as e -> e
let get_surface_blend_mode =
foreign "SDL_GetSurfaceBlendMode"
(surface @-> ptr int @-> returning zero_to_ok)
let get_surface_blend_mode s =
let mode = allocate int 0 in
match get_surface_blend_mode s mode with
`Ok () -> `Ok (!@ mode) | `Error _ as e -> e
let get_surface_color_mod =
foreign "SDL_GetSurfaceColorMod"
(surface @-> ptr uint8_t @-> ptr uint8_t @-> ptr uint8_t @->
returning zero_to_ok)
let get_surface_color_mod s =
let alloc () = allocate uint8_t Unsigned.UInt8.zero in
let get v = Unsigned.UInt8.to_int (!@ v) in
let r, g, b = alloc (), alloc (), alloc () in
match get_surface_color_mod s r g b with
| `Ok () -> `Ok (get r, get g, get b) | `Error _ as e -> e
let get_surface_format_enum s =
(* We don't give direct access to the format field. This prevents
memory ownership problems. *)
get_pixel_format_format (getf (!@ s) surface_format)
let get_surface_pitch s =
getf (!@ s) surface_pitch
let get_surface_pixels s kind =
let pitch = get_surface_pitch s in
let kind_size = ba_kind_byte_size kind in
if pitch mod kind_size <> 0
then invalid_arg (err_bigarray_pitch pitch kind_size)
else
let h = getf (!@ s) surface_h in
let ba_size = (pitch * h) / kind_size in
let pixels = getf (!@ s) surface_pixels in
let pixels = coerce (ptr void) (access_ptr_typ_of_ba_kind kind) pixels in
bigarray_of_ptr array1 ba_size kind pixels
let get_surface_size s =
getf (!@ s) surface_w, getf (!@ s) surface_h
let load_bmp_rw =
foreign "SDL_LoadBMP_RW"
(rw_ops @-> bool @-> returning (some_to_ok surface_opt))
let load_bmp_rw rw ~close =
load_bmp_rw rw close
let load_bmp file =
(* SDL_LoadBMP is cpp based *)
match rw_from_file file "rb" with
| `Error _ as e -> e
| `Ok rw -> load_bmp_rw rw ~close:true
let lock_surface =
foreign "SDL_LockSurface" (surface @-> returning zero_to_ok)
let lower_blit =
foreign "SDL_LowerBlit"