mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-01 12:18:15 +00:00
Merge remote-tracking branch 'offical/master'
This commit is contained in:
@@ -117,9 +117,25 @@ assign_int :: proc(val: any, i: $T) -> bool {
|
||||
case uint: dst = uint (i)
|
||||
case uintptr: dst = uintptr(i)
|
||||
case:
|
||||
is_bit_set_different_endian_to_platform :: proc(ti: ^runtime.Type_Info) -> bool {
|
||||
if ti == nil {
|
||||
return false
|
||||
}
|
||||
t := runtime.type_info_base(ti)
|
||||
#partial switch info in t.variant {
|
||||
case runtime.Type_Info_Integer:
|
||||
switch info.endianness {
|
||||
case .Platform: return false
|
||||
case .Little: return ODIN_ENDIAN != .Little
|
||||
case .Big: return ODIN_ENDIAN != .Big
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
ti := type_info_of(v.id)
|
||||
if _, ok := ti.variant.(runtime.Type_Info_Bit_Set); ok {
|
||||
do_byte_swap := !reflect.bit_set_is_big_endian(v)
|
||||
if info, ok := ti.variant.(runtime.Type_Info_Bit_Set); ok {
|
||||
do_byte_swap := is_bit_set_different_endian_to_platform(info.underlying)
|
||||
switch ti.size * 8 {
|
||||
case 0: // no-op.
|
||||
case 8:
|
||||
|
||||
+14
-7
@@ -116,11 +116,12 @@ register_user_formatter :: proc(id: typeid, formatter: User_Formatter) -> Regist
|
||||
}
|
||||
// Creates a formatted string
|
||||
//
|
||||
// *Allocates Using Context's Allocator*
|
||||
// *Allocates Using Provided Allocator*
|
||||
//
|
||||
// Inputs:
|
||||
// - args: A variadic list of arguments to be formatted.
|
||||
// - sep: An optional separator string (default is a single space).
|
||||
// - allocator: (default: context.allocator)
|
||||
//
|
||||
// Returns: A formatted string.
|
||||
//
|
||||
@@ -132,11 +133,12 @@ aprint :: proc(args: ..any, sep := " ", allocator := context.allocator) -> strin
|
||||
}
|
||||
// Creates a formatted string with a newline character at the end
|
||||
//
|
||||
// *Allocates Using Context's Allocator*
|
||||
// *Allocates Using Provided Allocator*
|
||||
//
|
||||
// Inputs:
|
||||
// - args: A variadic list of arguments to be formatted.
|
||||
// - sep: An optional separator string (default is a single space).
|
||||
// - allocator: (default: context.allocator)
|
||||
//
|
||||
// Returns: A formatted string with a newline character at the end.
|
||||
//
|
||||
@@ -148,11 +150,12 @@ aprintln :: proc(args: ..any, sep := " ", allocator := context.allocator) -> str
|
||||
}
|
||||
// Creates a formatted string using a format string and arguments
|
||||
//
|
||||
// *Allocates Using Context's Allocator*
|
||||
// *Allocates Using Provided Allocator*
|
||||
//
|
||||
// Inputs:
|
||||
// - fmt: A format string with placeholders for the provided arguments.
|
||||
// - args: A variadic list of arguments to be formatted.
|
||||
// - allocator: (default: context.allocator)
|
||||
// - newline: Whether the string should end with a newline. (See `aprintfln`.)
|
||||
//
|
||||
// Returns: A formatted string. The returned string must be freed accordingly.
|
||||
@@ -165,11 +168,12 @@ aprintf :: proc(fmt: string, args: ..any, allocator := context.allocator, newlin
|
||||
}
|
||||
// Creates a formatted string using a format string and arguments, followed by a newline.
|
||||
//
|
||||
// *Allocates Using Context's Allocator*
|
||||
// *Allocates Using Provided Allocator*
|
||||
//
|
||||
// Inputs:
|
||||
// - fmt: A format string with placeholders for the provided arguments.
|
||||
// - args: A variadic list of arguments to be formatted.
|
||||
// - allocator: (default: context.allocator)
|
||||
//
|
||||
// Returns: A formatted string. The returned string must be freed accordingly.
|
||||
//
|
||||
@@ -359,11 +363,12 @@ panicf :: proc(fmt: string, args: ..any, loc := #caller_location) -> ! {
|
||||
|
||||
// Creates a formatted C string
|
||||
//
|
||||
// *Allocates Using Context's Allocator*
|
||||
// *Allocates Using Provided Allocator*
|
||||
//
|
||||
// Inputs:
|
||||
// - args: A variadic list of arguments to be formatted.
|
||||
// - sep: An optional separator string (default is a single space).
|
||||
// - allocator: (default: context.allocator)
|
||||
//
|
||||
// Returns: A formatted C string.
|
||||
//
|
||||
@@ -379,11 +384,12 @@ caprint :: proc(args: ..any, sep := " ", allocator := context.allocator) -> cstr
|
||||
|
||||
// Creates a formatted C string
|
||||
//
|
||||
// *Allocates Using Context's Allocator*
|
||||
// *Allocates Using Provided Allocator*
|
||||
//
|
||||
// Inputs:
|
||||
// - format: A format string with placeholders for the provided arguments
|
||||
// - args: A variadic list of arguments to be formatted
|
||||
// - allocator: (default: context.allocator)
|
||||
// - newline: Whether the string should end with a newline. (See `caprintfln`.)
|
||||
//
|
||||
// Returns: A formatted C string
|
||||
@@ -399,11 +405,12 @@ caprintf :: proc(format: string, args: ..any, allocator := context.allocator, ne
|
||||
}
|
||||
// Creates a formatted C string, followed by a newline.
|
||||
//
|
||||
// *Allocates Using Context's Allocator*
|
||||
// *Allocates Using Provided Allocator*
|
||||
//
|
||||
// Inputs:
|
||||
// - format: A format string with placeholders for the provided arguments
|
||||
// - args: A variadic list of arguments to be formatted
|
||||
// - allocator: (default: context.allocator)
|
||||
//
|
||||
// Returns: A formatted C string
|
||||
//
|
||||
|
||||
+20
-3
@@ -953,6 +953,22 @@ make_dynamic_array_len_cap :: proc(
|
||||
return runtime.make_dynamic_array_len_cap(T, len, cap, allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Create a map with no initial allocation.
|
||||
|
||||
This procedure creates a map of type `T` with no initial allocation, which will
|
||||
use the allocator specified by `allocator` as its backing allocator when it
|
||||
allocates.
|
||||
*/
|
||||
@(require_results)
|
||||
make_map :: proc(
|
||||
$T: typeid/map[$K]$E,
|
||||
allocator := context.allocator,
|
||||
loc := #caller_location,
|
||||
) -> (m: T) {
|
||||
return runtime.make_map(T, allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Allocate a map.
|
||||
|
||||
@@ -961,13 +977,13 @@ This procedure creates a map of type `T` with initial capacity specified by
|
||||
allocator.
|
||||
*/
|
||||
@(require_results)
|
||||
make_map :: proc(
|
||||
make_map_cap :: proc(
|
||||
$T: typeid/map[$K]$E,
|
||||
#any_int cap: int = 1<<runtime.MAP_MIN_LOG2_CAPACITY,
|
||||
#any_int cap: int,
|
||||
allocator := context.allocator,
|
||||
loc := #caller_location,
|
||||
) -> (m: T, err: Allocator_Error) {
|
||||
return runtime.make_map(T, cap, allocator, loc)
|
||||
return runtime.make_map_cap(T, cap, allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1060,6 +1076,7 @@ make :: proc{
|
||||
make_dynamic_array_len,
|
||||
make_dynamic_array_len_cap,
|
||||
make_map,
|
||||
make_map_cap,
|
||||
make_multi_pointer,
|
||||
make_soa_slice,
|
||||
make_soa_dynamic_array,
|
||||
|
||||
@@ -107,8 +107,9 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l
|
||||
|
||||
switch arena.kind {
|
||||
case .Growing:
|
||||
needed := mem.align_forward_uint(size, alignment)
|
||||
if arena.curr_block == nil || (safe_add(arena.curr_block.used, needed) or_else 0) > arena.curr_block.reserved {
|
||||
prev_used := 0 if arena.curr_block == nil else arena.curr_block.used
|
||||
data, err = alloc_from_memory_block(arena.curr_block, size, alignment, default_commit_size=arena.default_commit_size)
|
||||
if err == .Out_Of_Memory {
|
||||
if arena.minimum_block_size == 0 {
|
||||
arena.minimum_block_size = DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE
|
||||
arena.minimum_block_size = mem.align_forward_uint(arena.minimum_block_size, DEFAULT_PAGE_SIZE)
|
||||
@@ -124,6 +125,7 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l
|
||||
max(arena.default_commit_size, arena.minimum_block_size)
|
||||
}
|
||||
|
||||
needed := mem.align_forward_uint(size, alignment)
|
||||
needed = max(needed, arena.default_commit_size)
|
||||
block_size := max(needed, arena.minimum_block_size)
|
||||
|
||||
@@ -131,10 +133,10 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l
|
||||
new_block.prev = arena.curr_block
|
||||
arena.curr_block = new_block
|
||||
arena.total_reserved += new_block.reserved
|
||||
}
|
||||
|
||||
prev_used := arena.curr_block.used
|
||||
data, err = alloc_from_memory_block(arena.curr_block, size, alignment, default_commit_size=arena.default_commit_size)
|
||||
prev_used = 0
|
||||
data, err = alloc_from_memory_block(arena.curr_block, size, alignment, default_commit_size=arena.default_commit_size)
|
||||
}
|
||||
arena.total_used += arena.curr_block.used - prev_used
|
||||
case .Static:
|
||||
if arena.curr_block == nil {
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package mem_virtual
|
||||
|
||||
import "core:sys/posix"
|
||||
|
||||
_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
|
||||
result := posix.mmap(nil, size, {}, {.ANONYMOUS, .PRIVATE})
|
||||
if result == posix.MAP_FAILED {
|
||||
assert_contextless(posix.errno() == .ENOMEM)
|
||||
return nil, .Out_Of_Memory
|
||||
}
|
||||
|
||||
return ([^]byte)(uintptr(result))[:size], nil
|
||||
}
|
||||
|
||||
_decommit :: proc "contextless" (data: rawptr, size: uint) {
|
||||
MADV_FREE :: 5
|
||||
|
||||
posix.mprotect(data, size, {})
|
||||
posix.posix_madvise(data, size, transmute(posix.MAdvice)i32(MADV_FREE))
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package mem_virtual
|
||||
|
||||
import "core:sys/posix"
|
||||
|
||||
_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
|
||||
|
||||
PROT_MAX :: proc "contextless" (flags: posix.Prot_Flags) -> posix.Prot_Flags {
|
||||
_PROT_MAX_SHIFT :: 16
|
||||
return transmute(posix.Prot_Flags)(transmute(i32)flags << _PROT_MAX_SHIFT)
|
||||
}
|
||||
|
||||
result := posix.mmap(nil, size, PROT_MAX({.READ, .WRITE, .EXEC}), {.ANONYMOUS, .PRIVATE})
|
||||
if result == posix.MAP_FAILED {
|
||||
assert_contextless(posix.errno() == .ENOMEM)
|
||||
return nil, .Out_Of_Memory
|
||||
}
|
||||
|
||||
return ([^]byte)(uintptr(result))[:size], nil
|
||||
}
|
||||
|
||||
_decommit :: proc "contextless" (data: rawptr, size: uint) {
|
||||
MADV_FREE :: 5
|
||||
|
||||
posix.mprotect(data, size, {})
|
||||
posix.posix_madvise(data, size, transmute(posix.MAdvice)i32(MADV_FREE))
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package mem_virtual
|
||||
|
||||
import "core:sys/posix"
|
||||
|
||||
_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
|
||||
|
||||
PROT_MPROTECT :: proc "contextless" (flags: posix.Prot_Flags) -> posix.Prot_Flags {
|
||||
return transmute(posix.Prot_Flags)(transmute(i32)flags << 3)
|
||||
}
|
||||
|
||||
result := posix.mmap(nil, size, PROT_MPROTECT({.READ, .WRITE, .EXEC}), {.ANONYMOUS, .PRIVATE})
|
||||
if result == posix.MAP_FAILED {
|
||||
assert_contextless(posix.errno() == .ENOMEM)
|
||||
return nil, .Out_Of_Memory
|
||||
}
|
||||
|
||||
return ([^]byte)(uintptr(result))[:size], nil
|
||||
}
|
||||
|
||||
_decommit :: proc "contextless" (data: rawptr, size: uint) {
|
||||
MADV_FREE :: 6
|
||||
|
||||
posix.mprotect(data, size, {})
|
||||
posix.posix_madvise(data, size, transmute(posix.MAdvice)i32(MADV_FREE))
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package mem_virtual
|
||||
|
||||
import "core:sys/posix"
|
||||
|
||||
_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
|
||||
result := posix.mmap(nil, size, {}, {.ANONYMOUS, .PRIVATE})
|
||||
if result == posix.MAP_FAILED {
|
||||
assert_contextless(posix.errno() == .ENOMEM)
|
||||
return nil, .Out_Of_Memory
|
||||
}
|
||||
|
||||
return ([^]byte)(uintptr(result))[:size], nil
|
||||
}
|
||||
|
||||
_decommit :: proc "contextless" (data: rawptr, size: uint) {
|
||||
MADV_FREE :: 6
|
||||
|
||||
posix.mprotect(data, size, {})
|
||||
posix.posix_madvise(data, size, transmute(posix.MAdvice)i32(MADV_FREE))
|
||||
}
|
||||
@@ -15,7 +15,9 @@ platform_memory_alloc :: proc "contextless" (to_commit, to_reserve: uint) -> (bl
|
||||
to_commit = clamp(to_commit, size_of(Platform_Memory_Block), total_to_reserved)
|
||||
|
||||
data := reserve(total_to_reserved) or_return
|
||||
commit(raw_data(data), to_commit)
|
||||
|
||||
commit_err := commit(raw_data(data), to_commit)
|
||||
assert_contextless(commit_err == nil)
|
||||
|
||||
block = (^Platform_Memory_Block)(raw_data(data))
|
||||
block.committed = to_commit
|
||||
|
||||
@@ -4,36 +4,18 @@ package mem_virtual
|
||||
|
||||
import "core:sys/posix"
|
||||
|
||||
// Define non-posix needed flags:
|
||||
when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD {
|
||||
MADV_FREE :: 5 /* pages unneeded, discard contents */
|
||||
} else when ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD {
|
||||
MADV_FREE :: 6
|
||||
}
|
||||
|
||||
_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
|
||||
flags := posix.Map_Flags{ .ANONYMOUS, .PRIVATE }
|
||||
result := posix.mmap(nil, size, {}, flags)
|
||||
if result == posix.MAP_FAILED {
|
||||
return nil, .Out_Of_Memory
|
||||
}
|
||||
|
||||
return ([^]byte)(uintptr(result))[:size], nil
|
||||
}
|
||||
|
||||
_commit :: proc "contextless" (data: rawptr, size: uint) -> Allocator_Error {
|
||||
if posix.mprotect(data, size, { .READ, .WRITE }) != .OK {
|
||||
return .Out_Of_Memory
|
||||
#partial switch posix.errno() {
|
||||
case .EACCES, .EPERM: return .Invalid_Pointer
|
||||
case .ENOTSUP, .EINVAL: return .Invalid_Argument
|
||||
case: return .Out_Of_Memory
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
_decommit :: proc "contextless" (data: rawptr, size: uint) {
|
||||
posix.mprotect(data, size, {})
|
||||
posix.posix_madvise(data, size, transmute(posix.MAdvice)i32(MADV_FREE))
|
||||
}
|
||||
|
||||
_release :: proc "contextless" (data: rawptr, size: uint) {
|
||||
posix.munmap(data, size)
|
||||
}
|
||||
|
||||
+21
-15
@@ -1,5 +1,10 @@
|
||||
package linux
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
@(private)
|
||||
log2 :: intrinsics.constant_log2
|
||||
|
||||
|
||||
/*
|
||||
Represents an error returned by most of syscalls
|
||||
@@ -1839,22 +1844,23 @@ EPoll_Flags_Bits :: enum {
|
||||
}
|
||||
|
||||
EPoll_Event_Kind :: enum u32 {
|
||||
IN = 0x001,
|
||||
PRI = 0x002,
|
||||
OUT = 0x004,
|
||||
RDNORM = 0x040,
|
||||
RDBAND = 0x080,
|
||||
WRNORM = 0x100,
|
||||
WRBAND = 0x200,
|
||||
MSG = 0x400,
|
||||
ERR = 0x008,
|
||||
HUP = 0x010,
|
||||
RDHUP = 0x2000,
|
||||
EXCLUSIVE = 1<<28,
|
||||
WAKEUP = 1<<29,
|
||||
ONESHOT = 1<<30,
|
||||
ET = 1<<31,
|
||||
IN = log2(0x001),
|
||||
PRI = log2(0x002),
|
||||
OUT = log2(0x004),
|
||||
RDNORM = log2(0x040),
|
||||
RDBAND = log2(0x080),
|
||||
WRNORM = log2(0x100),
|
||||
WRBAND = log2(0x200),
|
||||
MSG = log2(0x400),
|
||||
ERR = log2(0x008),
|
||||
HUP = log2(0x010),
|
||||
RDHUP = log2(0x2000),
|
||||
EXCLUSIVE = log2(1<<28),
|
||||
WAKEUP = log2(1<<29),
|
||||
ONESHOT = log2(1<<30),
|
||||
ET = log2(1<<31),
|
||||
}
|
||||
EPoll_Event_Set :: bit_set[EPoll_Event_Kind; u32]
|
||||
|
||||
EPoll_Ctl_Opcode :: enum i32 {
|
||||
ADD = 1,
|
||||
|
||||
@@ -212,7 +212,7 @@ rt_sigreturn :: proc "c" () -> ! {
|
||||
/*
|
||||
Alter an action taken by a process.
|
||||
*/
|
||||
rt_sigaction :: proc "contextless" (sig: Signal, sigaction: ^Sig_Action($T), old_sigaction: ^Sig_Action) -> Errno {
|
||||
rt_sigaction :: proc "contextless" (sig: Signal, sigaction: ^Sig_Action($T), old_sigaction: ^Sig_Action($U)) -> Errno {
|
||||
// NOTE(jason): It appears that the restorer is required for i386 and amd64
|
||||
when ODIN_ARCH == .i386 || ODIN_ARCH == .amd64 {
|
||||
sigaction.flags += {.RESTORER}
|
||||
|
||||
@@ -317,5 +317,18 @@ SYS_futex_waitv :: uintptr(449)
|
||||
SYS_set_mempolicy_home_node :: uintptr(450)
|
||||
SYS_cachestat :: uintptr(451)
|
||||
SYS_fchmodat2 :: uintptr(452)
|
||||
|
||||
SYS_map_shadow_stack :: uintptr(453)
|
||||
SYS_futex_wake :: uintptr(454)
|
||||
SYS_futex_wait :: uintptr(455)
|
||||
SYS_futex_requeue :: uintptr(456)
|
||||
SYS_statmount :: uintptr(457)
|
||||
SYS_listmount :: uintptr(458)
|
||||
SYS_lsm_get_self_attr :: uintptr(459)
|
||||
SYS_lsm_set_self_attr :: uintptr(460)
|
||||
SYS_lsm_list_modules :: uintptr(461)
|
||||
SYS_mseal :: uintptr(462)
|
||||
SYS_setxattrat :: uintptr(463)
|
||||
SYS_getxattrat :: uintptr(464)
|
||||
SYS_listxattrat :: uintptr(465)
|
||||
SYS_removexattrat :: uintptr(466)
|
||||
|
||||
|
||||
@@ -1450,7 +1450,7 @@ EPoll_Data :: struct #raw_union {
|
||||
}
|
||||
|
||||
EPoll_Event :: struct #packed {
|
||||
events: EPoll_Event_Kind,
|
||||
events: EPoll_Event_Set,
|
||||
data: EPoll_Data,
|
||||
}
|
||||
|
||||
|
||||
@@ -565,7 +565,7 @@ when ODIN_OS == .Darwin {
|
||||
SS_ONSTACK :: 0x0001
|
||||
SS_DISABLE :: 0x0004
|
||||
|
||||
when ODIN_ARCH == .amd64 || ODIN_ARCH == .arm32 {
|
||||
when ODIN_ARCH == .arm64 || ODIN_ARCH == .arm32 {
|
||||
MINSIGSTKSZ :: 1024 * 4
|
||||
} else when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 {
|
||||
MINSIGSTKSZ :: 512 * 4
|
||||
|
||||
@@ -189,7 +189,7 @@ Key_Location :: enum u8 {
|
||||
KEYBOARD_MAX_KEY_SIZE :: 32
|
||||
KEYBOARD_MAX_CODE_SIZE :: 32
|
||||
|
||||
GAMEPAD_MAX_ID_SIZE :: 64
|
||||
GAMEPAD_MAX_ID_SIZE :: 96
|
||||
GAMEPAD_MAX_MAPPING_SIZE :: 64
|
||||
|
||||
GAMEPAD_MAX_BUTTONS :: 64
|
||||
@@ -239,6 +239,12 @@ Gamepad_State :: struct {
|
||||
_mapping_buf: [GAMEPAD_MAX_MAPPING_SIZE]byte `fmt:"-"`,
|
||||
}
|
||||
|
||||
Pointer_Type :: enum u8 {
|
||||
Mouse,
|
||||
Pen,
|
||||
Touch,
|
||||
}
|
||||
|
||||
Event :: struct {
|
||||
kind: Event_Kind,
|
||||
target_kind: Event_Target_Kind,
|
||||
@@ -275,6 +281,8 @@ Event :: struct {
|
||||
|
||||
repeat: bool,
|
||||
|
||||
char: rune,
|
||||
|
||||
_key_len: int `fmt:"-"`,
|
||||
_code_len: int `fmt:"-"`,
|
||||
_key_buf: [KEYBOARD_MAX_KEY_SIZE]byte `fmt:"-"`,
|
||||
@@ -295,6 +303,21 @@ Event :: struct {
|
||||
|
||||
button: i16,
|
||||
buttons: bit_set[0..<16; u16],
|
||||
|
||||
pointer: struct {
|
||||
altitude_angle: f64,
|
||||
azimuth_angle: f64,
|
||||
persistent_device_id: int,
|
||||
pointer_id: int,
|
||||
width: int,
|
||||
height: int,
|
||||
pressure: f64,
|
||||
tangential_pressure: f64,
|
||||
tilt: [2]f64,
|
||||
twist: f64,
|
||||
pointer_type: Pointer_Type,
|
||||
is_primary: bool,
|
||||
},
|
||||
},
|
||||
|
||||
gamepad: Gamepad_State,
|
||||
@@ -323,13 +346,13 @@ add_event_listener :: proc(id: string, kind: Event_Kind, user_data: rawptr, call
|
||||
return _add_event_listener(id, event_kind_string[kind], kind, user_data, callback, use_capture)
|
||||
}
|
||||
|
||||
remove_event_listener :: proc(id: string, kind: Event_Kind, user_data: rawptr, callback: proc(e: Event)) -> bool {
|
||||
remove_event_listener :: proc(id: string, kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool {
|
||||
@(default_calling_convention="contextless")
|
||||
foreign dom_lib {
|
||||
@(link_name="remove_event_listener")
|
||||
_remove_event_listener :: proc(id: string, name: string, user_data: rawptr, callback: proc "odin" (Event)) -> bool ---
|
||||
_remove_event_listener :: proc(id: string, name: string, user_data: rawptr, callback: proc "odin" (Event), use_capture: bool) -> bool ---
|
||||
}
|
||||
return _remove_event_listener(id, event_kind_string[kind], user_data, callback)
|
||||
return _remove_event_listener(id, event_kind_string[kind], user_data, callback, use_capture)
|
||||
}
|
||||
|
||||
add_window_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool {
|
||||
@@ -341,20 +364,26 @@ add_window_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback:
|
||||
return _add_window_event_listener(event_kind_string[kind], kind, user_data, callback, use_capture)
|
||||
}
|
||||
|
||||
remove_window_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event)) -> bool {
|
||||
remove_window_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool {
|
||||
@(default_calling_convention="contextless")
|
||||
foreign dom_lib {
|
||||
@(link_name="remove_window_event_listener")
|
||||
_remove_window_event_listener :: proc(name: string, user_data: rawptr, callback: proc "odin" (Event)) -> bool ---
|
||||
_remove_window_event_listener :: proc(name: string, user_data: rawptr, callback: proc "odin" (Event), use_capture: bool) -> bool ---
|
||||
}
|
||||
return _remove_window_event_listener(event_kind_string[kind], user_data, callback)
|
||||
return _remove_window_event_listener(event_kind_string[kind], user_data, callback, use_capture)
|
||||
}
|
||||
|
||||
remove_event_listener_from_event :: proc(e: Event) -> bool {
|
||||
from_use_capture_false: bool
|
||||
from_use_capture_true: bool
|
||||
if e.id == "" {
|
||||
return remove_window_event_listener(e.kind, e.user_data, e.callback)
|
||||
from_use_capture_false = remove_window_event_listener(e.kind, e.user_data, e.callback, false)
|
||||
from_use_capture_true = remove_window_event_listener(e.kind, e.user_data, e.callback, true)
|
||||
} else {
|
||||
from_use_capture_false = remove_event_listener(e.id, e.kind, e.user_data, e.callback, false)
|
||||
from_use_capture_true = remove_event_listener(e.id, e.kind, e.user_data, e.callback, true)
|
||||
}
|
||||
return remove_event_listener(e.id, e.kind, e.user_data, e.callback)
|
||||
return from_use_capture_false || from_use_capture_true
|
||||
}
|
||||
|
||||
add_custom_event_listener :: proc(id: string, name: string, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool {
|
||||
@@ -365,13 +394,13 @@ add_custom_event_listener :: proc(id: string, name: string, user_data: rawptr, c
|
||||
}
|
||||
return _add_event_listener(id, name, .Custom, user_data, callback, use_capture)
|
||||
}
|
||||
remove_custom_event_listener :: proc(id: string, name: string, user_data: rawptr, callback: proc(e: Event)) -> bool {
|
||||
remove_custom_event_listener :: proc(id: string, name: string, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool {
|
||||
@(default_calling_convention="contextless")
|
||||
foreign dom_lib {
|
||||
@(link_name="remove_event_listener")
|
||||
_remove_event_listener :: proc(id: string, name: string, user_data: rawptr, callback: proc "odin" (Event)) -> bool ---
|
||||
_remove_event_listener :: proc(id: string, name: string, user_data: rawptr, callback: proc "odin" (Event), use_capture: bool) -> bool ---
|
||||
}
|
||||
return _remove_event_listener(id, name, user_data, callback)
|
||||
return _remove_event_listener(id, name, user_data, callback, use_capture)
|
||||
}
|
||||
|
||||
get_gamepad_state :: proc "contextless" (index: int, s: ^Gamepad_State) -> bool {
|
||||
@@ -384,7 +413,14 @@ get_gamepad_state :: proc "contextless" (index: int, s: ^Gamepad_State) -> bool
|
||||
if s == nil {
|
||||
return false
|
||||
}
|
||||
return _get_gamepad_state(index, s)
|
||||
|
||||
if !_get_gamepad_state(index, s) {
|
||||
return false
|
||||
}
|
||||
|
||||
s.id = string(s._id_buf[:s._id_len])
|
||||
s.mapping = string(s._mapping_buf[:s._mapping_len])
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -415,4 +451,4 @@ do_event_callback :: proc(user_data: rawptr, callback: proc(e: Event)) {
|
||||
|
||||
callback(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,7 +263,7 @@ add_event_listener :: proc(id: string, kind: Event_Kind, user_data: rawptr, call
|
||||
panic("vendor:wasm/js not supported on non JS targets")
|
||||
}
|
||||
|
||||
remove_event_listener :: proc(id: string, kind: Event_Kind, user_data: rawptr, callback: proc(e: Event)) -> bool {
|
||||
remove_event_listener :: proc(id: string, kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool {
|
||||
panic("vendor:wasm/js not supported on non JS targets")
|
||||
}
|
||||
|
||||
@@ -271,7 +271,7 @@ add_window_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback:
|
||||
panic("vendor:wasm/js not supported on non JS targets")
|
||||
}
|
||||
|
||||
remove_window_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event)) -> bool {
|
||||
remove_window_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool {
|
||||
panic("vendor:wasm/js not supported on non JS targets")
|
||||
}
|
||||
|
||||
@@ -282,6 +282,6 @@ remove_event_listener_from_event :: proc(e: Event) -> bool {
|
||||
add_custom_event_listener :: proc(id: string, name: string, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool {
|
||||
panic("vendor:wasm/js not supported on non JS targets")
|
||||
}
|
||||
remove_custom_event_listener :: proc(id: string, name: string, user_data: rawptr, callback: proc(e: Event)) -> bool {
|
||||
remove_custom_event_listener :: proc(id: string, name: string, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool {
|
||||
panic("vendor:wasm/js not supported on non JS targets")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,4 +9,5 @@ foreign odin_env {
|
||||
abort :: proc() -> ! ---
|
||||
alert :: proc(msg: string) ---
|
||||
evaluate :: proc(str: string) ---
|
||||
}
|
||||
open :: proc(url: string, name := "", specs := "") ---
|
||||
}
|
||||
|
||||
+108
-21
@@ -17,7 +17,7 @@ class WasmMemoryInterface {
|
||||
constructor() {
|
||||
this.memory = null;
|
||||
this.exports = null;
|
||||
this.listenerMap = {};
|
||||
this.listenerMap = new Map();
|
||||
|
||||
// Size (in bytes) of the integer type, should be 4 on `js_wasm32` and 8 on `js_wasm64p32`
|
||||
this.intSize = 4;
|
||||
@@ -402,6 +402,9 @@ class WebGLInterface {
|
||||
BlendEquation: (mode) => {
|
||||
this.ctx.blendEquation(mode);
|
||||
},
|
||||
BlendEquationSeparate: (modeRGB, modeAlpha) => {
|
||||
this.ctx.blendEquationSeparate(modeRGB, modeAlpha);
|
||||
},
|
||||
BlendFunc: (sfactor, dfactor) => {
|
||||
this.ctx.blendFunc(sfactor, dfactor);
|
||||
},
|
||||
@@ -633,6 +636,13 @@ class WebGLInterface {
|
||||
GetParameter: (pname) => {
|
||||
return this.ctx.getParameter(pname);
|
||||
},
|
||||
GetParameter4i: (pname, v0, v1, v2, v3) => {
|
||||
const i4 = this.ctx.getParameter(pname);
|
||||
this.mem.storeI32(v0, i4[0]);
|
||||
this.mem.storeI32(v1, i4[1]);
|
||||
this.mem.storeI32(v2, i4[2]);
|
||||
this.mem.storeI32(v3, i4[3]);
|
||||
},
|
||||
GetProgramParameter: (program, pname) => {
|
||||
return this.ctx.getProgramParameter(this.programs[program], pname)
|
||||
},
|
||||
@@ -1393,6 +1403,10 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) {
|
||||
info.scrollTop = info.scrollHeight;
|
||||
};
|
||||
|
||||
const listener_key = (id, name, data, callback, useCapture) => {
|
||||
return `${id}-${name}-data:${data}-callback:${callback}-useCapture:${useCapture}`;
|
||||
};
|
||||
|
||||
let webglContext = new WebGLInterface(wasmMemoryInterface);
|
||||
|
||||
const env = {};
|
||||
@@ -1421,6 +1435,13 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) {
|
||||
abort: () => { Module.abort() },
|
||||
evaluate: (str_ptr, str_len) => { eval.call(null, wasmMemoryInterface.loadString(str_ptr, str_len)); },
|
||||
|
||||
open: (url_ptr, url_len, name_ptr, name_len, specs_ptr, specs_len) => {
|
||||
const url = wasmMemoryInterface.loadString(url_ptr, url_len);
|
||||
const name = wasmMemoryInterface.loadString(name_ptr, name_len);
|
||||
const specs = wasmMemoryInterface.loadString(specs_ptr, specs_len);
|
||||
window.open(url, name, specs);
|
||||
},
|
||||
|
||||
// return a bigint to be converted to i64
|
||||
time_now: () => BigInt(Date.now()),
|
||||
tick_now: () => performance.now(),
|
||||
@@ -1533,6 +1554,29 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) {
|
||||
|
||||
wmi.storeI16(off(2), e.button);
|
||||
wmi.storeU16(off(2), e.buttons);
|
||||
|
||||
if (e instanceof PointerEvent) {
|
||||
wmi.storeF64(off(8), e.altitudeAngle);
|
||||
wmi.storeF64(off(8), e.azimuthAngle);
|
||||
wmi.storeInt(off(W), e.persistentDeviceId);
|
||||
wmi.storeInt(off(W), e.pointerId);
|
||||
wmi.storeInt(off(W), e.width);
|
||||
wmi.storeInt(off(W), e.height);
|
||||
wmi.storeF64(off(8), e.pressure);
|
||||
wmi.storeF64(off(8), e.tangentialPressure);
|
||||
wmi.storeF64(off(8), e.tiltX);
|
||||
wmi.storeF64(off(8), e.tiltY);
|
||||
wmi.storeF64(off(8), e.twist);
|
||||
if (e.pointerType == "pen") {
|
||||
wmi.storeU8(off(1), 1);
|
||||
} else if (e.pointerType == "touch") {
|
||||
wmi.storeU8(off(1), 2);
|
||||
} else {
|
||||
wmi.storeU8(off(1), 0);
|
||||
}
|
||||
wmi.storeU8(off(1), !!e.isPrimary);
|
||||
}
|
||||
|
||||
} else if (e instanceof KeyboardEvent) {
|
||||
// Note: those strings are constructed
|
||||
// on the native side from buffers that
|
||||
@@ -1549,6 +1593,8 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) {
|
||||
|
||||
wmi.storeU8(off(1), !!e.repeat);
|
||||
|
||||
wmi.storeI32(off(4), e.charCode);
|
||||
|
||||
wmi.storeInt(off(W, W), e.key.length)
|
||||
wmi.storeInt(off(W, W), e.code.length)
|
||||
wmi.storeString(off(32, 1), e.key);
|
||||
@@ -1588,10 +1634,24 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) {
|
||||
}
|
||||
}
|
||||
|
||||
wmi.storeInt(off(W, W), e.gamepad.id.length)
|
||||
wmi.storeInt(off(W, W), e.gamepad.mapping.length)
|
||||
wmi.storeString(off(64, 1), e.gamepad.id);
|
||||
wmi.storeString(off(64, 1), e.gamepad.mapping);
|
||||
let idLength = e.gamepad.id.length;
|
||||
let id = e.gamepad.id;
|
||||
if (idLength > 96) {
|
||||
idLength = 96;
|
||||
id = id.slice(0, 93) + '...';
|
||||
}
|
||||
|
||||
let mappingLength = e.gamepad.mapping.length;
|
||||
let mapping = e.gamepad.mapping;
|
||||
if (mappingLength > 64) {
|
||||
mappingLength = 61;
|
||||
mapping = mapping.slice(0, 61) + '...';
|
||||
}
|
||||
|
||||
wmi.storeInt(off(W, W), idLength);
|
||||
wmi.storeInt(off(W, W), mappingLength);
|
||||
wmi.storeString(off(96, 1), id);
|
||||
wmi.storeString(off(64, 1), mapping);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1602,6 +1662,10 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) {
|
||||
if (element == undefined) {
|
||||
return false;
|
||||
}
|
||||
let key = listener_key(id, name, data, callback, !!use_capture);
|
||||
if (wasmMemoryInterface.listenerMap.has(key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let listener = (e) => {
|
||||
let event_data = {};
|
||||
@@ -1612,7 +1676,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) {
|
||||
|
||||
onEventReceived(event_data, data, callback);
|
||||
};
|
||||
wasmMemoryInterface.listenerMap[{data: data, callback: callback}] = listener;
|
||||
wasmMemoryInterface.listenerMap.set(key, listener);
|
||||
element.addEventListener(name, listener, !!use_capture);
|
||||
return true;
|
||||
},
|
||||
@@ -1620,6 +1684,11 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) {
|
||||
add_window_event_listener: (name_ptr, name_len, name_code, data, callback, use_capture) => {
|
||||
let name = wasmMemoryInterface.loadString(name_ptr, name_len);
|
||||
let element = window;
|
||||
let key = listener_key('window', name, data, callback, !!use_capture);
|
||||
if (wasmMemoryInterface.listenerMap.has(key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let listener = (e) => {
|
||||
let event_data = {};
|
||||
event_data.id_ptr = 0;
|
||||
@@ -1629,12 +1698,12 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) {
|
||||
|
||||
onEventReceived(event_data, data, callback);
|
||||
};
|
||||
wasmMemoryInterface.listenerMap[{data: data, callback: callback}] = listener;
|
||||
wasmMemoryInterface.listenerMap.set(key, listener);
|
||||
element.addEventListener(name, listener, !!use_capture);
|
||||
return true;
|
||||
},
|
||||
|
||||
remove_event_listener: (id_ptr, id_len, name_ptr, name_len, data, callback) => {
|
||||
remove_event_listener: (id_ptr, id_len, name_ptr, name_len, data, callback, use_capture) => {
|
||||
let id = wasmMemoryInterface.loadString(id_ptr, id_len);
|
||||
let name = wasmMemoryInterface.loadString(name_ptr, name_len);
|
||||
let element = getElement(id);
|
||||
@@ -1642,24 +1711,28 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let listener = wasmMemoryInterface.listenerMap[{data: data, callback: callback}];
|
||||
if (listener == undefined) {
|
||||
let key = listener_key(id, name, data, callback, !!use_capture);
|
||||
let listener = wasmMemoryInterface.listenerMap.get(key);
|
||||
if (listener === undefined) {
|
||||
return false;
|
||||
}
|
||||
element.removeEventListener(name, listener);
|
||||
wasmMemoryInterface.listenerMap.delete(key);
|
||||
|
||||
element.removeEventListener(name, listener, !!use_capture);
|
||||
return true;
|
||||
},
|
||||
remove_window_event_listener: (name_ptr, name_len, data, callback) => {
|
||||
remove_window_event_listener: (name_ptr, name_len, data, callback, use_capture) => {
|
||||
let name = wasmMemoryInterface.loadString(name_ptr, name_len);
|
||||
let element = window;
|
||||
let key = {data: data, callback: callback};
|
||||
let listener = wasmMemoryInterface.listenerMap[key];
|
||||
if (!listener) {
|
||||
|
||||
let key = listener_key('window', name, data, callback, !!use_capture);
|
||||
let listener = wasmMemoryInterface.listenerMap.get(key);
|
||||
if (listener === undefined) {
|
||||
return false;
|
||||
}
|
||||
wasmMemoryInterface.listenerMap[key] = undefined;
|
||||
wasmMemoryInterface.listenerMap.delete(key);
|
||||
|
||||
element.removeEventListener(name, listener);
|
||||
element.removeEventListener(name, listener, !!use_capture);
|
||||
return true;
|
||||
},
|
||||
|
||||
@@ -1756,10 +1829,24 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) {
|
||||
}
|
||||
}
|
||||
|
||||
wmi.storeInt(off(W, W), gamepad.id.length)
|
||||
wmi.storeInt(off(W, W), gamepad.mapping.length)
|
||||
wmi.storeString(off(64, 1), gamepad.id);
|
||||
wmi.storeString(off(64, 1), gamepad.mapping);
|
||||
let idLength = gamepad.id.length;
|
||||
let id = gamepad.id;
|
||||
if (idLength > 96) {
|
||||
idLength = 96;
|
||||
id = id.slice(0, 93) + '...';
|
||||
}
|
||||
|
||||
let mappingLength = gamepad.mapping.length;
|
||||
let mapping = gamepad.mapping;
|
||||
if (mappingLength > 64) {
|
||||
mappingLength = 61;
|
||||
mapping = mapping.slice(0, 61) + '...';
|
||||
}
|
||||
|
||||
wmi.storeInt(off(W, W), idLength);
|
||||
wmi.storeInt(off(W, W), mappingLength);
|
||||
wmi.storeString(off(96, 1), id);
|
||||
wmi.storeString(off(64, 1), mapping);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -5,13 +5,11 @@ Type representing a mononotic day number corresponding to a date.
|
||||
|
||||
Ordinal 1 = Midnight Monday, January 1, 1 A.D. (Gregorian)
|
||||
| Midnight Monday, January 3, 1 A.D. (Julian)
|
||||
|
||||
Every other ordinal counts days forwards, starting from the above date.
|
||||
*/
|
||||
Ordinal :: i64
|
||||
|
||||
/*
|
||||
*/
|
||||
EPOCH :: Ordinal(1)
|
||||
|
||||
/*
|
||||
Minimum valid value for date.
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ This procedure takes the value of an ordinal and returns the day of week for
|
||||
that ordinal.
|
||||
*/
|
||||
day_of_week :: proc "contextless" (ordinal: Ordinal) -> (day: Weekday) {
|
||||
return Weekday((ordinal - EPOCH + 1) %% 7)
|
||||
return Weekday(ordinal %% 7)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -349,8 +349,7 @@ the result is unspecified.
|
||||
unsafe_date_to_ordinal :: proc "contextless" (date: Date) -> (ordinal: Ordinal) {
|
||||
year_minus_one := date.year - 1
|
||||
|
||||
// Day before epoch
|
||||
ordinal = EPOCH - 1
|
||||
ordinal = 0
|
||||
|
||||
// Add non-leap days
|
||||
ordinal += 365 * year_minus_one
|
||||
@@ -382,17 +381,17 @@ This procedure returns the year and the day of the year of a given ordinal.
|
||||
Of the ordinal is outside of its valid range, the result is unspecified.
|
||||
*/
|
||||
unsafe_ordinal_to_year :: proc "contextless" (ordinal: Ordinal) -> (year: i64, day_ordinal: i64) {
|
||||
// Days after epoch
|
||||
d0 := ordinal - EPOCH
|
||||
// Correct for leap year cycle starting at day 1.
|
||||
d0 := ordinal - 1
|
||||
|
||||
// Number of 400-year cycles and remainder
|
||||
n400, d1 := divmod(d0, 146097)
|
||||
n400, d1 := divmod(d0, 365*400 + 100 - 3)
|
||||
|
||||
// Number of 100-year cycles and remainder
|
||||
n100, d2 := divmod(d1, 36524)
|
||||
n100, d2 := divmod(d1, 365*100 + 25 - 1)
|
||||
|
||||
// Number of 4-year cycles and remainder
|
||||
n4, d3 := divmod(d2, 1461)
|
||||
n4, d3 := divmod(d2, 365*4 + 1)
|
||||
|
||||
// Number of remaining days
|
||||
n1, d4 := divmod(d3, 365)
|
||||
|
||||
Reference in New Issue
Block a user