aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancisTheCat <90558133+FrancisTheCat@users.noreply.github.com>2024-06-14 16:34:21 +0200
committerGitHub <noreply@github.com>2024-06-14 16:34:21 +0200
commitcd5fa8523f79ce981e5047dad5b66155f493d169 (patch)
tree1a8acb79d3bf1b5fca3f0c6ac20bece15a2cbfd2
parentec7b77fc0f6ed20eecf25039c6acbe2050cef877 (diff)
parentff4787070d9673a417f549f1b9452e675c96f992 (diff)
Merge branch 'odin-lang:master' into master
-rw-r--r--.github/workflows/ci.yml29
-rw-r--r--base/runtime/core_builtin.odin10
-rw-r--r--core/crypto/rand_darwin.odin4
-rw-r--r--core/crypto/rand_linux.odin2
-rw-r--r--core/crypto/rand_windows.odin20
-rw-r--r--core/encoding/entity/entity.odin123
-rw-r--r--core/encoding/xml/tokenizer.odin43
-rw-r--r--core/encoding/xml/xml_reader.odin24
-rw-r--r--core/fmt/doc.odin1
-rw-r--r--core/fmt/example.odin57
-rw-r--r--core/fmt/fmt.odin22
-rw-r--r--core/os/os_freebsd.odin61
-rw-r--r--core/path/filepath/path_unix.odin2
-rwxr-xr-x[-rw-r--r--]core/sys/windows/kernel32.odin13
-rw-r--r--core/time/datetime/datetime.odin4
-rw-r--r--src/check_decl.cpp12
-rw-r--r--src/check_expr.cpp5
-rw-r--r--src/entity.cpp1
-rw-r--r--src/llvm_backend.cpp244
-rw-r--r--src/llvm_backend.hpp3
-rw-r--r--src/llvm_backend_general.cpp3
-rw-r--r--src/main.cpp3
-rw-r--r--tests/core/assets/XML/attribute-whitespace.xml8
-rw-r--r--tests/core/encoding/xml/test_core_xml.odin24
-rw-r--r--tests/core/fmt/test_core_fmt.odin114
-rw-r--r--tests/core/net/test_core_net.odin2
-rw-r--r--vendor/raylib/raylib.odin14
-rw-r--r--vendor/raylib/raymath.odin2
-rw-r--r--vendor/raylib/rlgl.odin555
-rw-r--r--vendor/raylib/rlgl/rlgl.odin581
30 files changed, 1155 insertions, 831 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 66c848a8a..c9c453331 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -39,6 +39,35 @@ jobs:
./odin test tests/vendor -all-packages -define:ODIN_TEST_FANCY=false
./odin test tests/benchmark -all-packages -define:ODIN_TEST_FANCY=false
(cd tests/issues; ./run.sh)
+ build_freebsd:
+ name: FreeBSD Build, Check, and Test
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Build, Check, and Test
+ timeout-minutes: 15
+ uses: vmactions/freebsd-vm@v1
+ with:
+ usesh: true
+ copyback: false
+ prepare: |
+ pkg install -y gmake git bash python3 libxml2 llvm17
+ run: |
+ # `set -e` is needed for test failures to register. https://github.com/vmactions/freebsd-vm/issues/72
+ set -e -x
+ git config --global --add safe.directory $(pwd)
+ gmake release
+ ./odin version
+ ./odin report
+ gmake -C vendor/stb/src
+ gmake -C vendor/cgltf/src
+ gmake -C vendor/miniaudio/src
+ ./odin check examples/all -vet -strict-style -target:freebsd_amd64
+ ./odin test tests/core/normal.odin -file -all-packages -define:ODIN_TEST_FANCY=false
+ ./odin test tests/core/speed.odin -file -all-packages -o:speed -define:ODIN_TEST_FANCY=false
+ ./odin test tests/vendor -all-packages -define:ODIN_TEST_FANCY=false
+ ./odin test tests/benchmark -all-packages -define:ODIN_TEST_FANCY=false
+ (cd tests/issues; ./run.sh)
ci:
strategy:
fail-fast: false
diff --git a/base/runtime/core_builtin.odin b/base/runtime/core_builtin.odin
index 00c30d3fd..a9566c831 100644
--- a/base/runtime/core_builtin.odin
+++ b/base/runtime/core_builtin.odin
@@ -383,7 +383,7 @@ clear_map :: proc "contextless" (m: ^$T/map[$K]$V) {
//
// Note: Prefer the procedure group `reserve`
@builtin
-reserve_map :: proc(m: ^$T/map[$K]$V, capacity: int, loc := #caller_location) -> Allocator_Error {
+reserve_map :: proc(m: ^$T/map[$K]$V, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {
return __dynamic_map_reserve((^Raw_Map)(m), map_info(T), uint(capacity), loc) if m != nil else nil
}
@@ -721,12 +721,12 @@ _reserve_dynamic_array :: #force_inline proc(array: ^$T/[dynamic]$E, capacity: i
}
@builtin
-reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error {
+reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {
return _reserve_dynamic_array(array, capacity, true, loc)
}
@builtin
-non_zero_reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error {
+non_zero_reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {
return _reserve_dynamic_array(array, capacity, false, loc)
}
@@ -773,12 +773,12 @@ _resize_dynamic_array :: #force_inline proc(array: ^$T/[dynamic]$E, length: int,
}
@builtin
-resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error {
+resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error {
return _resize_dynamic_array(array, length, true, loc=loc)
}
@builtin
-non_zero_resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error {
+non_zero_resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error {
return _resize_dynamic_array(array, length, false, loc=loc)
}
diff --git a/core/crypto/rand_darwin.odin b/core/crypto/rand_darwin.odin
index 5355f31c5..56acb5d22 100644
--- a/core/crypto/rand_darwin.odin
+++ b/core/crypto/rand_darwin.odin
@@ -11,7 +11,7 @@ HAS_RAND_BYTES :: true
_rand_bytes :: proc(dst: []byte) {
err := Sec.RandomCopyBytes(count=len(dst), bytes=raw_data(dst))
if err != .Success {
- msg := CF.StringCopyToOdinString(Sec.CopyErrorMessageString(err))
- panic(fmt.tprintf("crypto/rand_bytes: SecRandomCopyBytes returned non-zero result: %v %s", err, msg))
+ msg := CF.StringCopyToOdinString(Sec.CopyErrorMessageString(err))
+ fmt.panicf("crypto/rand_bytes: SecRandomCopyBytes returned non-zero result: %v %s", err, msg)
}
}
diff --git a/core/crypto/rand_linux.odin b/core/crypto/rand_linux.odin
index 43b3b3075..7e0edbb7e 100644
--- a/core/crypto/rand_linux.odin
+++ b/core/crypto/rand_linux.odin
@@ -32,7 +32,7 @@ _rand_bytes :: proc (dst: []byte) {
// All other failures are things that should NEVER happen
// unless the kernel interface changes (ie: the Linux
// developers break userland).
- panic(fmt.tprintf("crypto: getrandom failed: %v", errno))
+ fmt.panicf("crypto: getrandom failed: %v", errno)
}
l -= n_read
dst = dst[n_read:]
diff --git a/core/crypto/rand_windows.odin b/core/crypto/rand_windows.odin
index a92d376cb..9cd647cc1 100644
--- a/core/crypto/rand_windows.odin
+++ b/core/crypto/rand_windows.odin
@@ -11,16 +11,16 @@ _rand_bytes :: proc(dst: []byte) {
ret := (os.Errno)(win32.BCryptGenRandom(nil, raw_data(dst), u32(len(dst)), win32.BCRYPT_USE_SYSTEM_PREFERRED_RNG))
if ret != os.ERROR_NONE {
switch ret {
- case os.ERROR_INVALID_HANDLE:
- // The handle to the first parameter is invalid.
- // This should not happen here, since we explicitly pass nil to it
- panic("crypto: BCryptGenRandom Invalid handle for hAlgorithm")
- case os.ERROR_INVALID_PARAMETER:
- // One of the parameters was invalid
- panic("crypto: BCryptGenRandom Invalid parameter")
- case:
- // Unknown error
- panic(fmt.tprintf("crypto: BCryptGenRandom failed: %d\n", ret))
+ case os.ERROR_INVALID_HANDLE:
+ // The handle to the first parameter is invalid.
+ // This should not happen here, since we explicitly pass nil to it
+ panic("crypto: BCryptGenRandom Invalid handle for hAlgorithm")
+ case os.ERROR_INVALID_PARAMETER:
+ // One of the parameters was invalid
+ panic("crypto: BCryptGenRandom Invalid parameter")
+ case:
+ // Unknown error
+ fmt.panicf("crypto: BCryptGenRandom failed: %d\n", ret)
}
}
}
diff --git a/core/encoding/entity/entity.odin b/core/encoding/entity/entity.odin
index cee6230ef..f5208ad6f 100644
--- a/core/encoding/entity/entity.odin
+++ b/core/encoding/entity/entity.odin
@@ -56,38 +56,27 @@ CDATA_END :: "]]>"
COMMENT_START :: "<!--"
COMMENT_END :: "-->"
-/*
- Default: CDATA and comments are passed through unchanged.
-*/
+// Default: CDATA and comments are passed through unchanged.
XML_Decode_Option :: enum u8 {
- /*
- Do not decode & entities. It decodes by default.
- If given, overrides `Decode_CDATA`.
- */
+ // Do not decode & entities. It decodes by default. If given, overrides `Decode_CDATA`.
No_Entity_Decode,
- /*
- CDATA is unboxed.
- */
+ // CDATA is unboxed.
Unbox_CDATA,
- /*
- Unboxed CDATA is decoded as well.
- Ignored if `.Unbox_CDATA` is not given.
- */
+ // Unboxed CDATA is decoded as well. Ignored if `.Unbox_CDATA` is not given.
Decode_CDATA,
- /*
- Comments are stripped.
- */
+ // Comments are stripped.
Comment_Strip,
+
+ // Normalize whitespace
+ Normalize_Whitespace,
}
XML_Decode_Options :: bit_set[XML_Decode_Option; u8]
-/*
- Decode a string that may include SGML/XML/HTML entities.
- The caller has to free the result.
-*/
+// Decode a string that may include SGML/XML/HTML entities.
+// The caller has to free the result.
decode_xml :: proc(input: string, options := XML_Decode_Options{}, allocator := context.allocator) -> (decoded: string, err: Error) {
context.allocator = allocator
@@ -100,14 +89,14 @@ decode_xml :: proc(input: string, options := XML_Decode_Options{}, allocator :=
t := Tokenizer{src=input}
in_data := false
+ prev: rune = ' '
+
loop: for {
advance(&t) or_return
if t.r < 0 { break loop }
- /*
- Below here we're never inside a CDATA tag.
- At most we'll see the start of one, but that doesn't affect the logic.
- */
+ // Below here we're never inside a CDATA tag. At most we'll see the start of one,
+ // but that doesn't affect the logic.
switch t.r {
case '<':
/*
@@ -126,9 +115,7 @@ decode_xml :: proc(input: string, options := XML_Decode_Options{}, allocator :=
in_data = _handle_xml_special(&t, &builder, options) or_return
case ']':
- /*
- If we're unboxing _and_ decoding CDATA, we'll have to check for the end tag.
- */
+ // If we're unboxing _and_ decoding CDATA, we'll have to check for the end tag.
if in_data {
if t.read_offset + len(CDATA_END) < len(t.src) {
if string(t.src[t.offset:][:len(CDATA_END)]) == CDATA_END {
@@ -143,22 +130,16 @@ decode_xml :: proc(input: string, options := XML_Decode_Options{}, allocator :=
case:
if in_data && .Decode_CDATA not_in options {
- /*
- Unboxed, but undecoded.
- */
+ // Unboxed, but undecoded.
write_rune(&builder, t.r)
continue
}
if t.r == '&' {
if entity, entity_err := _extract_xml_entity(&t); entity_err != .None {
- /*
- We read to the end of the string without closing the entity.
- Pass through as-is.
- */
+ // We read to the end of the string without closing the entity. Pass through as-is.
write_string(&builder, entity)
} else {
-
if .No_Entity_Decode not_in options {
if decoded, ok := xml_decode_entity(entity); ok {
write_rune(&builder, decoded)
@@ -166,19 +147,41 @@ decode_xml :: proc(input: string, options := XML_Decode_Options{}, allocator :=
}
}
- /*
- Literal passthrough because the decode failed or we want entities not decoded.
- */
+ // Literal passthrough because the decode failed or we want entities not decoded.
write_string(&builder, "&")
write_string(&builder, entity)
write_string(&builder, ";")
}
} else {
- write_rune(&builder, t.r)
+ // Handle AV Normalization: https://www.w3.org/TR/2006/REC-xml11-20060816/#AVNormalize
+ if .Normalize_Whitespace in options {
+ switch t.r {
+ case ' ', '\r', '\n', '\t':
+ if prev != ' ' {
+ write_rune(&builder, ' ')
+ prev = ' '
+ }
+ case:
+ write_rune(&builder, t.r)
+ prev = t.r
+ }
+ } else {
+ // https://www.w3.org/TR/2006/REC-xml11-20060816/#sec-line-ends
+ switch t.r {
+ case '\n', 0x85, 0x2028:
+ write_rune(&builder, '\n')
+ case '\r': // Do nothing until next character
+ case:
+ if prev == '\r' { // Turn a single carriage return into a \n
+ write_rune(&builder, '\n')
+ }
+ write_rune(&builder, t.r)
+ }
+ prev = t.r
+ }
}
}
}
-
return strings.clone(strings.to_string(builder), allocator), err
}
@@ -253,24 +256,18 @@ xml_decode_entity :: proc(entity: string) -> (decoded: rune, ok: bool) {
return rune(val), true
case:
- /*
- Named entity.
- */
+ // Named entity.
return named_xml_entity_to_rune(entity)
}
}
-/*
- Private XML helper to extract `&<stuff>;` entity.
-*/
+// Private XML helper to extract `&<stuff>;` entity.
@(private="file")
_extract_xml_entity :: proc(t: ^Tokenizer) -> (entity: string, err: Error) {
assert(t != nil && t.r == '&')
- /*
- All of these would be in the ASCII range.
- Even if one is not, it doesn't matter. All characters we need to compare to extract are.
- */
+ // All of these would be in the ASCII range.
+ // Even if one is not, it doesn't matter. All characters we need to compare to extract are.
length := len(t.src)
found := false
@@ -292,9 +289,7 @@ _extract_xml_entity :: proc(t: ^Tokenizer) -> (entity: string, err: Error) {
return string(t.src[t.offset : t.read_offset]), .Invalid_Entity_Encoding
}
-/*
- Private XML helper for CDATA and comments.
-*/
+// Private XML helper for CDATA and comments.
@(private="file")
_handle_xml_special :: proc(t: ^Tokenizer, builder: ^strings.Builder, options: XML_Decode_Options) -> (in_data: bool, err: Error) {
assert(t != nil && t.r == '<')
@@ -304,20 +299,14 @@ _handle_xml_special :: proc(t: ^Tokenizer, builder: ^strings.Builder, options: X
t.read_offset += len(CDATA_START) - 1
if .Unbox_CDATA in options && .Decode_CDATA in options {
- /*
- We're unboxing _and_ decoding CDATA
- */
+ // We're unboxing _and_ decoding CDATA
return true, .None
}
- /*
- CDATA is passed through.
- */
+ // CDATA is passed through.
offset := t.offset
- /*
- Scan until end of CDATA.
- */
+ // Scan until end of CDATA.
for {
advance(t) or_return
if t.r < 0 { return true, .CDATA_Not_Terminated }
@@ -341,14 +330,10 @@ _handle_xml_special :: proc(t: ^Tokenizer, builder: ^strings.Builder, options: X
} else if string(t.src[t.offset:][:len(COMMENT_START)]) == COMMENT_START {
t.read_offset += len(COMMENT_START)
- /*
- Comment is passed through by default.
- */
+ // Comment is passed through by default.
offset := t.offset
- /*
- Scan until end of Comment.
- */
+ // Scan until end of Comment.
for {
advance(t) or_return
if t.r < 0 { return true, .Comment_Not_Terminated }
diff --git a/core/encoding/xml/tokenizer.odin b/core/encoding/xml/tokenizer.odin
index 0f87c366b..2d06038b7 100644
--- a/core/encoding/xml/tokenizer.odin
+++ b/core/encoding/xml/tokenizer.odin
@@ -218,9 +218,7 @@ scan_identifier :: proc(t: ^Tokenizer) -> string {
for is_valid_identifier_rune(t.ch) {
advance_rune(t)
if t.ch == ':' {
- /*
- A namespaced attr can have at most two parts, `namespace:ident`.
- */
+ // A namespaced attr can have at most two parts, `namespace:ident`.
if namespaced {
break
}
@@ -268,14 +266,10 @@ scan_comment :: proc(t: ^Tokenizer) -> (comment: string, err: Error) {
return string(t.src[offset : t.offset - 1]), .None
}
-/*
- Skip CDATA
-*/
+// Skip CDATA
skip_cdata :: proc(t: ^Tokenizer) -> (err: Error) {
if t.read_offset + len(CDATA_START) >= len(t.src) {
- /*
- Can't be the start of a CDATA tag.
- */
+ // Can't be the start of a CDATA tag.
return .None
}
@@ -290,9 +284,7 @@ skip_cdata :: proc(t: ^Tokenizer) -> (err: Error) {
return .Premature_EOF
}
- /*
- Scan until the end of a CDATA tag.
- */
+ // Scan until the end of a CDATA tag.
if t.read_offset + len(CDATA_END) < len(t.src) {
if string(t.src[t.offset:][:len(CDATA_END)]) == CDATA_END {
t.read_offset += len(CDATA_END)
@@ -319,14 +311,10 @@ scan_string :: proc(t: ^Tokenizer, offset: int, close: rune = '<', consume_close
case '<':
if peek_byte(t) == '!' {
if peek_byte(t, 1) == '[' {
- /*
- Might be the start of a CDATA tag.
- */
+ // Might be the start of a CDATA tag.
skip_cdata(t) or_return
} else if peek_byte(t, 1) == '-' && peek_byte(t, 2) == '-' {
- /*
- Comment start. Eat comment.
- */
+ // Comment start. Eat comment.
t.read_offset += 3
_ = scan_comment(t) or_return
}
@@ -342,17 +330,13 @@ scan_string :: proc(t: ^Tokenizer, offset: int, close: rune = '<', consume_close
}
if t.ch == close {
- /*
- If it's not a CDATA or comment, it's the end of this body.
- */
+ // If it's not a CDATA or comment, it's the end of this body.
break loop
}
advance_rune(t)
}
- /*
- Strip trailing whitespace.
- */
+ // Strip trailing whitespace.
lit := string(t.src[offset : t.offset])
end := len(lit)
@@ -369,11 +353,6 @@ scan_string :: proc(t: ^Tokenizer, offset: int, close: rune = '<', consume_close
if consume_close {
advance_rune(t)
}
-
- /*
- TODO: Handle decoding escape characters and unboxing CDATA.
- */
-
return lit, err
}
@@ -384,7 +363,7 @@ peek :: proc(t: ^Tokenizer) -> (token: Token) {
return token
}
-scan :: proc(t: ^Tokenizer) -> Token {
+scan :: proc(t: ^Tokenizer, multiline_string := false) -> Token {
skip_whitespace(t)
offset := t.offset
@@ -418,7 +397,7 @@ scan :: proc(t: ^Tokenizer) -> Token {
case '"', '\'':
kind = .Invalid
- lit, err = scan_string(t, t.offset, ch, true, false)
+ lit, err = scan_string(t, t.offset, ch, true, multiline_string)
if err == .None {
kind = .String
}
@@ -435,4 +414,4 @@ scan :: proc(t: ^Tokenizer) -> Token {
lit = string(t.src[offset : t.offset])
}
return Token{kind, lit, pos}
-}
+} \ No newline at end of file
diff --git a/core/encoding/xml/xml_reader.odin b/core/encoding/xml/xml_reader.odin
index 5b4b12948..b9656900f 100644
--- a/core/encoding/xml/xml_reader.odin
+++ b/core/encoding/xml/xml_reader.odin
@@ -203,9 +203,7 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha
doc.elements = make([dynamic]Element, 1024, 1024, allocator)
- // strings.intern_init(&doc.intern, allocator, allocator)
-
- err = .Unexpected_Token
+ err = .Unexpected_Token
element, parent: Element_ID
open: Token
@@ -259,8 +257,8 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha
case .Slash:
// Empty tag. Close it.
expect(t, .Gt) or_return
- parent = doc.elements[element].parent
- element = parent
+ parent = doc.elements[element].parent
+ element = parent
case:
error(t, t.offset, "Expected close tag, got: %#v\n", end_token)
@@ -276,8 +274,8 @@ parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_ha
error(t, t.offset, "Mismatched Closing Tag. Expected %v, got %v\n", doc.elements[element].ident, ident.text)
return doc, .Mismatched_Closing_Tag
}
- parent = doc.elements[element].parent
- element = parent
+ parent = doc.elements[element].parent
+ element = parent
} else if open.kind == .Exclaim {
// <!
@@ -463,8 +461,8 @@ validate_options :: proc(options: Options) -> (validated: Options, err: Error) {
return validated, .None
}
-expect :: proc(t: ^Tokenizer, kind: Token_Kind) -> (tok: Token, err: Error) {
- tok = scan(t)
+expect :: proc(t: ^Tokenizer, kind: Token_Kind, multiline_string := false) -> (tok: Token, err: Error) {
+ tok = scan(t, multiline_string=multiline_string)
if tok.kind == kind { return tok, .None }
error(t, t.offset, "Expected \"%v\", got \"%v\".", kind, tok.kind)
@@ -480,7 +478,13 @@ parse_attribute :: proc(doc: ^Document) -> (attr: Attribute, offset: int, err: E
offset = t.offset - len(key.text)
_ = expect(t, .Eq) or_return
- value := expect(t, .String) or_return
+ value := expect(t, .String, multiline_string=true) or_return
+
+ normalized, normalize_err := entity.decode_xml(value.text, {.Normalize_Whitespace}, doc.allocator)
+ if normalize_err == .None {
+ append(&doc.strings_to_free, normalized)
+ value.text = normalized
+ }
attr.key = key.text
attr.val = value.text
diff --git a/core/fmt/doc.odin b/core/fmt/doc.odin
index be666dcc4..d45e6c796 100644
--- a/core/fmt/doc.odin
+++ b/core/fmt/doc.odin
@@ -9,6 +9,7 @@ The verbs:
General:
%v the value in a default format
%#v an expanded format of %v with newlines and indentation
+ %w an Odin-syntax representation of the value
%T an Odin-syntax representation of the type of the value
%% a literal percent sign; consumes no value
{{ a literal open brace; consumes no value
diff --git a/core/fmt/example.odin b/core/fmt/example.odin
new file mode 100644
index 000000000..503e64f2b
--- /dev/null
+++ b/core/fmt/example.odin
@@ -0,0 +1,57 @@
+//+build ignore
+package custom_formatter_example
+import "core:fmt"
+import "core:io"
+
+SomeType :: struct {
+ value: int,
+}
+
+My_Custom_Base_Type :: distinct u32
+
+main :: proc() {
+ // Ensure the fmt._user_formatters map is initialized
+ fmt.set_user_formatters(new(map[typeid]fmt.User_Formatter))
+
+ // Register custom formatters for my favorite types
+ err := fmt.register_user_formatter(type_info_of(SomeType).id, SomeType_Formatter)
+ assert(err == .None)
+ err = fmt.register_user_formatter(type_info_of(My_Custom_Base_Type).id, My_Custom_Base_Formatter)
+ assert(err == .None)
+
+ // Use the custom formatters.
+ fmt.printfln("SomeType{{42}}: '%v'", SomeType{42})
+ fmt.printfln("My_Custom_Base_Type(0xdeadbeef): '%v'", My_Custom_Base_Type(0xdeadbeef))
+}
+
+SomeType_Formatter :: proc(fi: ^fmt.Info, arg: any, verb: rune) -> bool {
+ m := cast(^SomeType)arg.data
+ switch verb {
+ case 'v', 'd': // We handle `%v` and `%d`
+ fmt.fmt_int(fi, u64(m.value), true, 8 * size_of(SomeType), verb)
+ case:
+ return false
+ }
+ return true
+}
+
+My_Custom_Base_Formatter :: proc(fi: ^fmt.Info, arg: any, verb: rune) -> bool {
+ m := cast(^My_Custom_Base_Type)arg.data
+ switch verb {
+ case 'v', 'b':
+ value := u64(m^)
+ for value > 0 {
+ if value & 1 == 1 {
+ io.write_string(fi.writer, "Hellope!", &fi.n)
+ } else {
+ io.write_string(fi.writer, "Hellope?", &fi.n)
+ }
+ value >>= 1
+ }
+
+ case:
+ return false
+ }
+ return true
+}
+
diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin
index f9113a7a7..4c65dd01f 100644
--- a/core/fmt/fmt.odin
+++ b/core/fmt/fmt.odin
@@ -1726,10 +1726,12 @@ fmt_bit_set :: proc(fi: ^Info, v: any, name: string = "", verb: rune = 'v') {
et := runtime.type_info_base(info.elem)
- if name != "" {
- io.write_string(fi.writer, name, &fi.n)
- } else {
- reflect.write_type(fi.writer, type_info, &fi.n)
+ if verb != 'w' {
+ if name != "" {
+ io.write_string(fi.writer, name, &fi.n)
+ } else {
+ reflect.write_type(fi.writer, type_info, &fi.n)
+ }
}
io.write_byte(fi.writer, '{', &fi.n)
defer io.write_byte(fi.writer, '}', &fi.n)
@@ -1746,9 +1748,17 @@ fmt_bit_set :: proc(fi: ^Info, v: any, name: string = "", verb: rune = 'v') {
}
if is_enum {
+ enum_name: string
+ if ti_named, is_named := info.elem.variant.(runtime.Type_Info_Named); is_named {
+ enum_name = ti_named.name
+ }
for ev, evi in e.values {
v := u64(ev)
if v == u64(i) {
+ if verb == 'w' {
+ io.write_string(fi.writer, enum_name, &fi.n)
+ io.write_byte(fi.writer, '.', &fi.n)
+ }
io.write_string(fi.writer, e.names[evi], &fi.n)
commas += 1
continue loop
@@ -2391,7 +2401,6 @@ fmt_named :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Named)
runtime.Type_Info_Dynamic_Array,
runtime.Type_Info_Slice,
runtime.Type_Info_Struct,
- runtime.Type_Info_Union,
runtime.Type_Info_Enum,
runtime.Type_Info_Map,
runtime.Type_Info_Bit_Set,
@@ -2498,8 +2507,9 @@ fmt_matrix :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Matrix
}
} else {
// Printed in Row-Major layout to match text layout
+ row_separator := ", " if verb == 'w' else "; "
for row in 0..<info.row_count {
- if row > 0 { io.write_string(fi.writer, "; ", &fi.n) }
+ if row > 0 { io.write_string(fi.writer, row_separator, &fi.n) }
for col in 0..<info.column_count {
if col > 0 { io.write_string(fi.writer, ", ", &fi.n) }
diff --git a/core/os/os_freebsd.odin b/core/os/os_freebsd.odin
index cdd44d301..8fe179478 100644
--- a/core/os/os_freebsd.odin
+++ b/core/os/os_freebsd.odin
@@ -112,15 +112,15 @@ EOWNERDEAD: Errno : 96
O_RDONLY :: 0x00000
O_WRONLY :: 0x00001
O_RDWR :: 0x00002
-O_CREATE :: 0x00040
-O_EXCL :: 0x00080
-O_NOCTTY :: 0x00100
-O_TRUNC :: 0x00200
-O_NONBLOCK :: 0x00800
-O_APPEND :: 0x00400
-O_SYNC :: 0x01000
-O_ASYNC :: 0x02000
-O_CLOEXEC :: 0x80000
+O_NONBLOCK :: 0x00004
+O_APPEND :: 0x00008
+O_ASYNC :: 0x00040
+O_SYNC :: 0x00080
+O_CREATE :: 0x00200
+O_TRUNC :: 0x00400
+O_EXCL :: 0x00800
+O_NOCTTY :: 0x08000
+O_CLOEXEC :: 0100000
SEEK_DATA :: 3
@@ -140,6 +140,8 @@ RTLD_NOLOAD :: 0x02000
MAX_PATH :: 1024
+KINFO_FILE_SIZE :: 1392
+
args := _alloc_command_line_arguments()
Unix_File_Time :: struct {
@@ -191,6 +193,21 @@ OS_Stat :: struct {
lspare: [10]u64,
}
+KInfo_File :: struct {
+ structsize: c.int,
+ type: c.int,
+ fd: c.int,
+ ref_count: c.int,
+ flags: c.int,
+ pad0: c.int,
+ offset: i64,
+
+ // NOTE(Feoramund): This field represents a complicated union that I am
+ // avoiding implementing for now. I only need the path data below.
+ _union: [336]byte,
+
+ path: [MAX_PATH]c.char,
+}
// since FreeBSD v12
Dirent :: struct {
@@ -254,6 +271,8 @@ X_OK :: 1 // Test for execute permission
W_OK :: 2 // Test for write permission
R_OK :: 4 // Test for read permission
+F_KINFO :: 22
+
foreign libc {
@(link_name="__error") __errno_location :: proc() -> ^c.int ---
@@ -274,6 +293,7 @@ foreign libc {
@(link_name="unlink") _unix_unlink :: proc(path: cstring) -> c.int ---
@(link_name="rmdir") _unix_rmdir :: proc(path: cstring) -> c.int ---
@(link_name="mkdir") _unix_mkdir :: proc(path: cstring, mode: mode_t) -> c.int ---
+ @(link_name="fcntl") _unix_fcntl :: proc(fd: Handle, cmd: c.int, arg: uintptr) -> c.int ---
@(link_name="fdopendir") _unix_fdopendir :: proc(fd: Handle) -> Dir ---
@(link_name="closedir") _unix_closedir :: proc(dirp: Dir) -> c.int ---
@@ -365,7 +385,7 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
}
file_size :: proc(fd: Handle) -> (i64, Errno) {
- s, err := fstat(fd)
+ s, err := _fstat(fd)
if err != ERROR_NONE {
return -1, err
}
@@ -591,9 +611,26 @@ _readlink :: proc(path: string) -> (string, Errno) {
return "", Errno{}
}
-// XXX FreeBSD
absolute_path_from_handle :: proc(fd: Handle) -> (string, Errno) {
- return "", Errno(ENOSYS)
+ // NOTE(Feoramund): The situation isn't ideal, but this was the best way I
+ // could find to implement this. There are a couple outstanding bug reports
+ // regarding the desire to retrieve an absolute path from a handle, but to
+ // my knowledge, there hasn't been any work done on it.
+ //
+ // https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=198570
+ //
+ // This may be unreliable, according to a comment from 2023.
+
+ kinfo: KInfo_File
+ kinfo.structsize = KINFO_FILE_SIZE
+
+ res := _unix_fcntl(fd, F_KINFO, cast(uintptr)&kinfo)
+ if res == -1 {
+ return "", Errno(get_last_error())
+ }
+
+ path := strings.clone_from_cstring_bounded(cast(cstring)&kinfo.path[0], len(kinfo.path))
+ return path, ERROR_NONE
}
absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Errno) {
diff --git a/core/path/filepath/path_unix.odin b/core/path/filepath/path_unix.odin
index a4b27b027..b44a6a344 100644
--- a/core/path/filepath/path_unix.odin
+++ b/core/path/filepath/path_unix.odin
@@ -56,7 +56,7 @@ foreign libc {
@(link_name="free") _unix_free :: proc(ptr: rawptr) ---
}
-when ODIN_OS == .Darwin {
+when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD {
@(private)
foreign libc {
@(link_name="__error") __error :: proc() -> ^i32 ---
diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin
index 86f6b86f0..7c76381a4 100644..100755
--- a/core/sys/windows/kernel32.odin
+++ b/core/sys/windows/kernel32.odin
@@ -1156,6 +1156,19 @@ foreign kernel32 {
SetCommState :: proc(handle: HANDLE, dcb: ^DCB) -> BOOL ---
}
+COMMTIMEOUTS :: struct {
+ ReadIntervalTimeout: DWORD,
+ ReadTotalTimeoutMultiplier: DWORD,
+ ReadTotalTimeoutConstant: DWORD,
+ WriteTotalTimeoutMultiplier: DWORD,
+ WriteTotalTimeoutConstant: DWORD,
+}
+
+@(default_calling_convention="system")
+foreign kernel32 {
+ GetCommTimeouts :: proc(handle: HANDLE, timeouts: ^COMMTIMEOUTS) -> BOOL ---
+ SetCommTimeouts :: proc(handle: HANDLE, timeouts: ^COMMTIMEOUTS) -> BOOL ---
+}
LPFIBER_START_ROUTINE :: #type proc "system" (lpFiberParameter: LPVOID)
diff --git a/core/time/datetime/datetime.odin b/core/time/datetime/datetime.odin
index e15ced5a5..89fa2ce98 100644
--- a/core/time/datetime/datetime.odin
+++ b/core/time/datetime/datetime.odin
@@ -127,13 +127,13 @@ days_remaining :: proc "contextless" (date: Date) -> (days_remaining: i64, err:
return delta.days, .None
}
-last_day_of_month :: proc "contextless" (#any_int year: i64, #any_int month: i8) -> (day: i64, err: Error) {
+last_day_of_month :: proc "contextless" (#any_int year: i64, #any_int month: i8) -> (day: i8, err: Error) {
// Not using formula 2.27 from the book. This is far simpler and gives the same answer.
validate(Date{year, month, 1}) or_return
month_days := MONTH_DAYS
- day = i64(month_days[month])
+ day = month_days[month]
if month == 2 && is_leap_year(year) {
day += 1
}
diff --git a/src/check_decl.cpp b/src/check_decl.cpp
index 13b14149a..02445cbc6 100644
--- a/src/check_decl.cpp
+++ b/src/check_decl.cpp
@@ -89,6 +89,9 @@ gb_internal Type *check_init_variable(CheckerContext *ctx, Entity *e, Operand *o
return nullptr;
} else if (is_type_polymorphic(t)) {
Entity *e = entity_of_node(operand->expr);
+ if (e == nullptr) {
+ return nullptr;
+ }
if (e->state.load() != EntityState_Resolved) {
gbString str = type_to_string(t);
defer (gb_string_free(str));
@@ -1142,7 +1145,14 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
}
if (ac.link_name.len > 0) {
- e->Procedure.link_name = ac.link_name;
+ String ln = ac.link_name;
+ e->Procedure.link_name = ln;
+ if (ln == "memcpy" ||
+ ln == "memmove" ||
+ ln == "mem_copy" ||
+ ln == "mem_copy_non_overlapping") {
+ e->Procedure.is_memcpy_like = true;
+ }
}
if (ac.deferred_procedure.entity != nullptr) {
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 01cba881e..359b30276 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -2550,7 +2550,7 @@ gb_internal void check_unary_expr(CheckerContext *c, Operand *o, Token op, Ast *
error_line("\tSuggestion: Did you want to pass the iterable value to the for statement by pointer to get addressable semantics?\n");
}
- if (is_type_map(parent_type)) {
+ if (parent_type != nullptr && is_type_map(parent_type)) {
error_line("\t Prefer doing 'for key, &%.*s in ...'\n", LIT(e->token.string));
} else {
error_line("\t Prefer doing 'for &%.*s in ...'\n", LIT(e->token.string));
@@ -3564,6 +3564,9 @@ gb_internal void check_binary_matrix(CheckerContext *c, Token const &op, Operand
x->mode = Addressing_Value;
if (are_types_identical(xt, yt)) {
+ if (are_types_identical(x->type, y->type)) {
+ return;
+ }
if (!is_type_named(x->type) && is_type_named(y->type)) {
// prefer the named type
x->type = y->type;
diff --git a/src/entity.cpp b/src/entity.cpp
index 7f484e308..8f55c1faf 100644
--- a/src/entity.cpp
+++ b/src/entity.cpp
@@ -256,6 +256,7 @@ struct Entity {
bool generated_from_polymorphic : 1;
bool entry_point_only : 1;
bool has_instrumentation : 1;
+ bool is_memcpy_like : 1;
} Procedure;
struct {
Array<Entity *> entities;
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index 5dc6d94d5..04c4ce244 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -9,6 +9,11 @@
#endif
+#ifndef LLVM_IGNORE_VERIFICATION
+#define LLVM_IGNORE_VERIFICATION 0
+#endif
+
+
#include "llvm_backend.hpp"
#include "llvm_abi.cpp"
#include "llvm_backend_opt.cpp"
@@ -1125,6 +1130,53 @@ gb_internal void lb_finalize_objc_names(lbProcedure *p) {
lb_end_procedure_body(p);
}
+gb_internal void lb_verify_function(lbModule *m, lbProcedure *p, bool dump_ll=false) {
+ if (LLVM_IGNORE_VERIFICATION) {
+ return;
+ }
+
+ if (!m->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
+ char *llvm_error = nullptr;
+
+ gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %.*s\n", LIT(p->name));
+ LLVMDumpValue(p->value);
+ gb_printf_err("\n");
+ if (dump_ll) {
+ gb_printf_err("\n\n\n");
+ String filepath_ll = lb_filepath_ll_for_module(m);
+ if (LLVMPrintModuleToFile(m->mod, cast(char const *)filepath_ll.text, &llvm_error)) {
+ gb_printf_err("LLVM Error: %s\n", llvm_error);
+ }
+ }
+ LLVMVerifyFunction(p->value, LLVMPrintMessageAction);
+ exit_with_errors();
+ }
+}
+
+gb_internal WORKER_TASK_PROC(lb_llvm_module_verification_worker_proc) {
+ char *llvm_error = nullptr;
+ defer (LLVMDisposeMessage(llvm_error));
+ lbModule *m = cast(lbModule *)data;
+
+ if (LLVMVerifyModule(m->mod, LLVMReturnStatusAction, &llvm_error)) {
+ gb_printf_err("LLVM Error:\n%s\n", llvm_error);
+ if (build_context.keep_temp_files) {
+ TIME_SECTION("LLVM Print Module to File");
+ String filepath_ll = lb_filepath_ll_for_module(m);
+ if (LLVMPrintModuleToFile(m->mod, cast(char const *)filepath_ll.text, &llvm_error)) {
+ gb_printf_err("LLVM Error: %s\n", llvm_error);
+ exit_with_errors();
+ return false;
+ }
+ }
+ exit_with_errors();
+ return 1;
+ }
+ return 0;
+}
+
+
+
gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProcedure *objc_names, Array<lbGlobalVariable> &global_variables) { // Startup Runtime
Type *proc_type = alloc_type_proc(nullptr, nullptr, 0, nullptr, 0, false, ProcCC_Odin);
@@ -1227,13 +1279,7 @@ gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProc
lb_end_procedure_body(p);
- if (!main_module->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
- gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %s\n", "main");
- LLVMDumpValue(p->value);
- gb_printf_err("\n\n\n\n");
- LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
- }
-
+ lb_verify_function(main_module, p);
return p;
}
@@ -1256,31 +1302,21 @@ gb_internal lbProcedure *lb_create_cleanup_runtime(lbModule *main_module) { // C
lb_end_procedure_body(p);
- if (!main_module->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
- gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %s\n", "main");
- LLVMDumpValue(p->value);
- gb_printf_err("\n\n\n\n");
- LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
- }
-
+ lb_verify_function(main_module, p);
return p;
}
gb_internal WORKER_TASK_PROC(lb_generate_procedures_and_types_per_module) {
lbModule *m = cast(lbModule *)data;
- for (Entity *e : m->global_procedures_and_types_to_create) {
- if (e->kind == Entity_TypeName) {
- (void)lb_get_entity_name(m, e);
- lb_type(m, e->type);
- }
+ for (Entity *e : m->global_types_to_create) {
+ (void)lb_get_entity_name(m, e);
+ (void)lb_type(m, e->type);
}
- for (Entity *e : m->global_procedures_and_types_to_create) {
- if (e->kind == Entity_Procedure) {
- (void)lb_get_entity_name(m, e);
- array_add(&m->procedures_to_generate, lb_create_procedure(m, e));
- }
+ for (Entity *e : m->global_procedures_to_create) {
+ (void)lb_get_entity_name(m, e);
+ array_add(&m->procedures_to_generate, lb_create_procedure(m, e));
}
return 0;
}
@@ -1334,16 +1370,24 @@ gb_internal void lb_create_global_procedures_and_types(lbGenerator *gen, Checker
m = lb_module_of_entity(gen, e);
}
- array_add(&m->global_procedures_and_types_to_create, e);
+ if (e->kind == Entity_Procedure) {
+ array_add(&m->global_procedures_to_create, e);
+ } else if (e->kind == Entity_TypeName) {
+ array_add(&m->global_types_to_create, e);
+ }
}
- for (auto const &entry : gen->modules) {
- lbModule *m = entry.value;
- if (do_threading) {
+ if (do_threading) {
+ for (auto const &entry : gen->modules) {
+ lbModule *m = entry.value;
thread_pool_add_task(lb_generate_procedures_and_types_per_module, m);
- } else {
+ }
+ } else {
+ for (auto const &entry : gen->modules) {
+ lbModule *m = entry.value;
lb_generate_procedures_and_types_per_module(m);
}
+
}
thread_pool_wait();
@@ -2374,16 +2418,19 @@ gb_internal WORKER_TASK_PROC(lb_generate_procedures_worker_proc) {
}
gb_internal void lb_generate_procedures(lbGenerator *gen, bool do_threading) {
- for (auto const &entry : gen->modules) {
- lbModule *m = entry.value;
- if (do_threading) {
+ if (do_threading) {
+ for (auto const &entry : gen->modules) {
+ lbModule *m = entry.value;
thread_pool_add_task(lb_generate_procedures_worker_proc, m);
- } else {
+ }
+
+ thread_pool_wait();
+ } else {
+ for (auto const &entry : gen->modules) {
+ lbModule *m = entry.value;
lb_generate_procedures_worker_proc(m);
}
}
-
- thread_pool_wait();
}
gb_internal WORKER_TASK_PROC(lb_generate_missing_procedures_to_check_worker_proc) {
@@ -2397,17 +2444,20 @@ gb_internal WORKER_TASK_PROC(lb_generate_missing_procedures_to_check_worker_proc
}
gb_internal void lb_generate_missing_procedures(lbGenerator *gen, bool do_threading) {
- for (auto const &entry : gen->modules) {
- lbModule *m = entry.value;
- // NOTE(bill): procedures may be added during generation
- if (do_threading) {
+ if (do_threading) {
+ for (auto const &entry : gen->modules) {
+ lbModule *m = entry.value;
+ // NOTE(bill): procedures may be added during generation
thread_pool_add_task(lb_generate_missing_procedures_to_check_worker_proc, m);
- } else {
+ }
+ thread_pool_wait();
+ } else {
+ for (auto const &entry : gen->modules) {
+ lbModule *m = entry.value;
+ // NOTE(bill): procedures may be added during generation
lb_generate_missing_procedures_to_check_worker_proc(m);
}
}
-
- thread_pool_wait();
}
gb_internal void lb_debug_info_complete_types_and_finalize(lbGenerator *gen) {
@@ -2420,32 +2470,45 @@ gb_internal void lb_debug_info_complete_types_and_finalize(lbGenerator *gen) {
}
gb_internal void lb_llvm_function_passes(lbGenerator *gen, bool do_threading) {
- for (auto const &entry : gen->modules) {
- lbModule *m = entry.value;
- if (do_threading) {
+ if (do_threading) {
+ for (auto const &entry : gen->modules) {
+ lbModule *m = entry.value;
thread_pool_add_task(lb_llvm_function_pass_per_module, m);
- } else {
+ }
+ thread_pool_wait();
+ } else {
+ for (auto const &entry : gen->modules) {
+ lbModule *m = entry.value;
lb_llvm_function_pass_per_module(m);
}
}
- thread_pool_wait();
}
gb_internal void lb_llvm_module_passes(lbGenerator *gen, bool do_threading) {
- for (auto const &entry : gen->modules) {
- lbModule *m = entry.value;
- auto wd = gb_alloc_item(permanent_allocator(), lbLLVMModulePassWorkerData);
- wd->m = m;
- wd->target_machine = m->target_machine;
+ if (do_threading) {
+ for (auto const &entry : gen->modules) {
+ lbModule *m = entry.value;
+ auto wd = gb_alloc_item(permanent_allocator(), lbLLVMModulePassWorkerData);
+ wd->m = m;
+ wd->target_machine = m->target_machine;
- if (do_threading) {
- thread_pool_add_task(lb_llvm_module_pass_worker_proc, wd);
- } else {
+ if (do_threading) {
+ thread_pool_add_task(lb_llvm_module_pass_worker_proc, wd);
+ } else {
+ lb_llvm_module_pass_worker_proc(wd);
+ }
+ }
+ thread_pool_wait();
+ } else {
+ for (auto const &entry : gen->modules) {
+ lbModule *m = entry.value;
+ auto wd = gb_alloc_item(permanent_allocator(), lbLLVMModulePassWorkerData);
+ wd->m = m;
+ wd->target_machine = m->target_machine;
lb_llvm_module_pass_worker_proc(wd);
}
}
- thread_pool_wait();
}
gb_internal String lb_filepath_ll_for_module(lbModule *m) {
@@ -2523,40 +2586,27 @@ gb_internal String lb_filepath_obj_for_module(lbModule *m) {
return concatenate_strings(permanent_allocator(), path, ext);
}
-gb_internal WORKER_TASK_PROC(lb_llvm_module_verification_worker_proc) {
- char *llvm_error = nullptr;
- defer (LLVMDisposeMessage(llvm_error));
- lbModule *m = cast(lbModule *)data;
- if (LLVMVerifyModule(m->mod, LLVMReturnStatusAction, &llvm_error)) {
- gb_printf_err("LLVM Error:\n%s\n", llvm_error);
- if (build_context.keep_temp_files) {
- TIME_SECTION("LLVM Print Module to File");
- String filepath_ll = lb_filepath_ll_for_module(m);
- if (LLVMPrintModuleToFile(m->mod, cast(char const *)filepath_ll.text, &llvm_error)) {
- gb_printf_err("LLVM Error: %s\n", llvm_error);
- exit_with_errors();
- return false;
- }
- }
- exit_with_errors();
- return 1;
- }
- return 0;
-}
-
gb_internal bool lb_llvm_module_verification(lbGenerator *gen, bool do_threading) {
- for (auto const &entry : gen->modules) {
- lbModule *m = entry.value;
- if (do_threading) {
+ if (LLVM_IGNORE_VERIFICATION) {
+ return true;
+ }
+
+ if (do_threading) {
+ for (auto const &entry : gen->modules) {
+ lbModule *m = entry.value;
thread_pool_add_task(lb_llvm_module_verification_worker_proc, m);
- } else {
+ }
+ thread_pool_wait();
+
+ } else {
+ for (auto const &entry : gen->modules) {
+ lbModule *m = entry.value;
if (lb_llvm_module_verification_worker_proc(m)) {
return false;
}
}
}
- thread_pool_wait();
return true;
}
@@ -2777,12 +2827,7 @@ gb_internal lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *star
}
- if (!m->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
- gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %s\n", "main");
- LLVMDumpValue(p->value);
- gb_printf_err("\n\n\n\n");
- LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
- }
+ lb_verify_function(m, p);
lb_run_function_pass_manager(default_function_pass_manager, p, lbFunctionPassManager_default);
return p;
@@ -2803,28 +2848,11 @@ gb_internal void lb_generate_procedure(lbModule *m, lbProcedure *p) {
lb_end_procedure(p);
// Add Flags
- if (p->body != nullptr) {
- if (p->name == "memcpy" || p->name == "memmove" ||
- p->name == "runtime.mem_copy" || p->name == "mem_copy_non_overlapping" ||
- string_starts_with(p->name, str_lit("llvm.memcpy")) ||
- string_starts_with(p->name, str_lit("llvm.memmove"))) {
- p->flags |= lbProcedureFlag_WithoutMemcpyPass;
- }
+ if (p->entity && p->entity->kind == Entity_Procedure && p->entity->Procedure.is_memcpy_like) {
+ p->flags |= lbProcedureFlag_WithoutMemcpyPass;
}
- if (!m->debug_builder && LLVMVerifyFunction(p->value, LLVMReturnStatusAction)) {
- char *llvm_error = nullptr;
-
- gb_printf_err("LLVM CODE GEN FAILED FOR PROCEDURE: %.*s\n", LIT(p->name));
- LLVMDumpValue(p->value);
- gb_printf_err("\n\n\n\n");
- String filepath_ll = lb_filepath_ll_for_module(m);
- if (LLVMPrintModuleToFile(m->mod, cast(char const *)filepath_ll.text, &llvm_error)) {
- gb_printf_err("LLVM Error: %s\n", llvm_error);
- }
- LLVMVerifyFunction(p->value, LLVMPrintMessageAction);
- exit_with_errors();
- }
+ lb_verify_function(m, p, true);
}
diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp
index 9f7bc8843..447e93d42 100644
--- a/src/llvm_backend.hpp
+++ b/src/llvm_backend.hpp
@@ -181,7 +181,8 @@ struct lbModule {
std::atomic<u32> nested_type_name_guid;
Array<lbProcedure *> procedures_to_generate;
- Array<Entity *> global_procedures_and_types_to_create;
+ Array<Entity *> global_procedures_to_create;
+ Array<Entity *> global_types_to_create;
lbProcedure *curr_procedure;
diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp
index ea98fc60a..03d0f8b32 100644
--- a/src/llvm_backend_general.cpp
+++ b/src/llvm_backend_general.cpp
@@ -78,7 +78,8 @@ gb_internal void lb_init_module(lbModule *m, Checker *c) {
array_init(&m->procedures_to_generate, a, 0, c->info.all_procedures.count);
map_init(&m->procedure_values, c->info.all_procedures.count*2);
}
- array_init(&m->global_procedures_and_types_to_create, a, 0, 1024);
+ array_init(&m->global_procedures_to_create, a, 0, 1024);
+ array_init(&m->global_types_to_create, a, 0, 1024);
array_init(&m->missing_procedures_to_check, a, 0, 16);
map_init(&m->debug_values);
diff --git a/src/main.cpp b/src/main.cpp
index 70def5802..f4cd40fe9 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -2934,7 +2934,8 @@ int main(int arg_count, char const **arg_ptr) {
// TODO(jeroen): Remove the `init_filename` param.
// Let's put that on `build_context.build_paths[0]` instead.
if (parse_packages(parser, init_filename) != ParseFile_None) {
- return 1;
+ GB_ASSERT_MSG(any_errors(), "parse_packages failed but no error was reported.");
+ // We depend on the next conditional block to return 1, after printing errors.
}
if (any_errors()) {
diff --git a/tests/core/assets/XML/attribute-whitespace.xml b/tests/core/assets/XML/attribute-whitespace.xml
new file mode 100644
index 000000000..6381225d5
--- /dev/null
+++ b/tests/core/assets/XML/attribute-whitespace.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE foozle>
+<foozle>Barzle</foozle>
+<부끄러운:barzle>
+ <name foo:bar=" birmese
+ kittens have
+ fur ">Indeed!</name>
+</부끄러운:barzle> \ No newline at end of file
diff --git a/tests/core/encoding/xml/test_core_xml.odin b/tests/core/encoding/xml/test_core_xml.odin
index 22852d1f3..b29431e10 100644
--- a/tests/core/encoding/xml/test_core_xml.odin
+++ b/tests/core/encoding/xml/test_core_xml.odin
@@ -36,7 +36,7 @@ xml_test_utf8_normal :: proc(t: ^testing.T) {
},
expected_doctype = "恥ずべきフクロウ",
},
- crc32 = 0xe9b62f03,
+ crc32 = 0xefa55f27,
})
}
@@ -52,7 +52,7 @@ xml_test_utf8_unbox_cdata :: proc(t: ^testing.T) {
},
expected_doctype = "恥ずべきフクロウ",
},
- crc32 = 0x9c2643ed,
+ crc32 = 0x2dd27770,
})
}
@@ -128,7 +128,7 @@ xml_test_entities_unbox :: proc(t: ^testing.T) {
},
expected_doctype = "html",
},
- crc32 = 0x3b6d4a90,
+ crc32 = 0x350ca83e,
})
}
@@ -142,7 +142,21 @@ xml_test_entities_unbox_decode :: proc(t: ^testing.T) {
},
expected_doctype = "html",
},
- crc32 = 0x5be2ffdc,
+ crc32 = 0x7f58db7d,
+ })
+}
+
+@(test)
+xml_test_attribute_whitespace :: proc(t: ^testing.T) {
+ run_test(t, {
+ // Same as above.
+ // Unbox CDATA in data tag.
+ filename = "XML/attribute-whitespace.xml",
+ options = {
+ flags = {},
+ expected_doctype = "foozle",
+ },
+ crc32 = 0x8f5fd6c1,
})
}
@@ -172,7 +186,7 @@ xml_test_unicode :: proc(t: ^testing.T) {
expected_doctype = "",
},
err = .None,
- crc32 = 0x0b6100ab,
+ crc32 = 0x73070b55,
})
}
diff --git a/tests/core/fmt/test_core_fmt.odin b/tests/core/fmt/test_core_fmt.odin
index 507e0f433..49142e24d 100644
--- a/tests/core/fmt/test_core_fmt.odin
+++ b/tests/core/fmt/test_core_fmt.odin
@@ -258,6 +258,120 @@ test_pointers :: proc(t: ^testing.T) {
check(t, "0xFFFF", "%#4p", d)
}
+@(test)
+test_odin_value_export :: proc(t: ^testing.T) {
+ E :: enum u32 {
+ A, B, C,
+ }
+
+ F :: enum i16 {
+ A, B, F,
+ }
+
+ S :: struct {
+ j, k: int,
+ }
+
+ ST :: struct {
+ x: int `fmt:"-"`,
+ y: u8 `fmt:"r,0"`,
+ z: string `fmt:"s,0"`,
+ }
+
+ U :: union {
+ i8,
+ i16,
+ }
+
+ UEF :: union { E, F }
+
+ A :: [2]int
+
+ BSE :: distinct bit_set[E]
+
+ i : int = 64
+ f : f64 = 3.14
+ c : complex128 = 7+3i
+ q : quaternion256 = 1+2i+3j+4k
+ mat : matrix[2,3]f32 = {1.5, 2, 1, 0.777, 0.333, 0.8}
+ matc : #column_major matrix[2,3]f32 = {1.5, 2, 1, 0.777, 0.333, 0.8}
+ e : enum {A, B, C} = .B
+ en : E = E.C
+ ena : [2]E = {E.A, E.C}
+ s : struct { j: int, k: int } = { j = 16, k = 8 }
+ sn : S = S{ j = 24, k = 12 }
+ st : ST = { 32768, 57, "Hellope" }
+ str : string = "Hellope"
+ strc : cstring = "Hellope"
+ bsu : bit_set[0..<32; u32] = {0, 1}
+ bs : bit_set[4..<16] = {5, 7}
+ bse : bit_set[E] = { .B, .A }
+ bsE : BSE = { .A, .C }
+ arr : [3]int = {1, 2, 3}
+ ars : [3]S = {S{j = 3, k = 2}, S{j = 2, k = 1}, S{j = 1, k = 0}}
+ darr : [dynamic]u8 = { 128, 64, 32 }
+ dars : [dynamic]S = {S{j = 1, k = 2}, S{j = 3, k = 4}}
+ na : A = {7, 5}
+ may0 : Maybe(int)
+ may1 : Maybe(int) = 1
+ uz : union {i8, i16} = i8(-33)
+ u0 : U = U(nil)
+ u1 : U = i16(42)
+ uef0 : UEF = E.A
+ uefa : [3]UEF = { E.A, F.A, F.F }
+ map_ : map[string]u8 = {"foo" = 8, "bar" = 4}
+
+ bf : bit_field int {
+ a: int | 4,
+ b: int | 4,
+ e: E | 4,
+ } = {a = 1, b = 2, e = .A}
+
+ defer {
+ delete(darr)
+ delete(dars)
+ delete(map_)
+ }
+
+ check(t, "64", "%w", i)
+ check(t, "3.14", "%w", f)
+ check(t, "7+3i", "%w", c)
+ check(t, "1+2i+3j+4k", "%w", q)
+ check(t, "{1.5, 2, 1, 0.777, 0.333, 0.8}", "%w", mat)
+ check(t, "{1.5, 2, 1, 0.777, 0.333, 0.8}", "%w", matc)
+ check(t, ".B", "%w", e)
+ check(t, "E.C", "%w", en)
+ check(t, "{E.A, E.C}", "%w", ena)
+ check(t, "{j = 16, k = 8}", "%w", s)
+ check(t, "S{j = 24, k = 12}", "%w", sn)
+ check(t, `ST{y = 57, z = "Hellope"}`, "%w", st)
+ check(t, `"Hellope"`, "%w", str)
+ check(t, `"Hellope"`, "%w", strc)
+ check(t, "{0, 1}", "%w", bsu)
+ check(t, "{5, 7}", "%w", bs)
+ check(t, "{E.A, E.B}", "%w", bse)
+ check(t, "{E.A, E.C}", "%w", bsE)
+ check(t, "{1, 2, 3}", "%w", arr)
+ check(t, "{S{j = 3, k = 2}, S{j = 2, k = 1}, S{j = 1, k = 0}}", "%w", ars)
+ check(t, "{128, 64, 32}", "%w", darr)
+ check(t, "{S{j = 1, k = 2}, S{j = 3, k = 4}}", "%w", dars)
+ check(t, "{7, 5}", "%w", na)
+ check(t, "nil", "%w", may0)
+ check(t, "1", "%w", may1)
+ check(t, "-33", "%w", uz)
+ check(t, "nil", "%w", u0)
+ check(t, "42", "%w", u1)
+ check(t, "E.A", "%w", uef0)
+ check(t, "{E.A, F.A, F.F}", "%w", uefa)
+ check(t, "{a = 1, b = 2, e = E.A}", "%w", bf)
+ // Check this manually due to the non-deterministic ordering of map keys.
+ switch fmt.tprintf("%w", map_) {
+ case `{"foo"=8, "bar"=4}`: break
+ case `{"bar"=4, "foo"=8}`: break
+ case: testing.fail(t)
+ }
+}
+
@(private)
check :: proc(t: ^testing.T, exp: string, format: string, args: ..any, loc := #caller_location) {
got := fmt.tprintf(format, ..args)
diff --git a/tests/core/net/test_core_net.odin b/tests/core/net/test_core_net.odin
index 6aada88a6..f806463e9 100644
--- a/tests/core/net/test_core_net.odin
+++ b/tests/core/net/test_core_net.odin
@@ -8,7 +8,7 @@
A test suite for `core:net`
*/
-//+build !netbsd
+//+build !netbsd !freebsd !openbsd
package test_core_net
import "core:testing"
diff --git a/vendor/raylib/raylib.odin b/vendor/raylib/raylib.odin
index ebb1cdd27..3d1b74058 100644
--- a/vendor/raylib/raylib.odin
+++ b/vendor/raylib/raylib.odin
@@ -984,12 +984,14 @@ foreign lib {
LoadShader :: proc(vsFileName, fsFileName: cstring) -> Shader --- // Load shader from files and bind default locations
LoadShaderFromMemory :: proc(vsCode, fsCode: cstring) -> Shader --- // Load shader from code strings and bind default locations
IsShaderReady :: proc(shader: Shader) -> bool --- // Check if a shader is ready
- GetShaderLocation :: proc(shader: Shader, uniformName: cstring) -> ShaderLocationIndex --- // Get shader uniform location
- GetShaderLocationAttrib :: proc(shader: Shader, attribName: cstring) -> ShaderLocationIndex --- // Get shader attribute location
- SetShaderValue :: proc(shader: Shader, locIndex: ShaderLocationIndex, value: rawptr, uniformType: ShaderUniformDataType) --- // Set shader uniform value
- SetShaderValueV :: proc(shader: Shader, locIndex: ShaderLocationIndex, value: rawptr, uniformType: ShaderUniformDataType, count: c.int) --- // Set shader uniform value vector
- SetShaderValueMatrix :: proc(shader: Shader, locIndex: ShaderLocationIndex, mat: Matrix) --- // Set shader uniform value (matrix 4x4)
- SetShaderValueTexture :: proc(shader: Shader, locIndex: ShaderLocationIndex, texture: Texture2D) --- // Set shader uniform value for texture (sampler2d)
+ GetShaderLocation :: proc(shader: Shader, uniformName: cstring) -> c.int --- // Get shader uniform location
+ GetShaderLocationAttrib :: proc(shader: Shader, attribName: cstring) -> c.int --- // Get shader attribute location
+
+ // We use #any_int here so we can pass ShaderLocationIndex
+ SetShaderValue :: proc(shader: Shader, #any_int locIndex: c.int, value: rawptr, uniformType: ShaderUniformDataType) --- // Set shader uniform value
+ SetShaderValueV :: proc(shader: Shader, #any_int locIndex: c.int, value: rawptr, uniformType: ShaderUniformDataType, count: c.int) --- // Set shader uniform value vector
+ SetShaderValueMatrix :: proc(shader: Shader, #any_int locIndex: c.int, mat: Matrix) --- // Set shader uniform value (matrix 4x4)
+ SetShaderValueTexture :: proc(shader: Shader, #any_int locIndex: c.int, texture: Texture2D) --- // Set shader uniform value for texture (sampler2d)
UnloadShader :: proc(shader: Shader) --- // Unload shader from GPU memory (VRAM)
// Screen-space-related functions
diff --git a/vendor/raylib/raymath.odin b/vendor/raylib/raymath.odin
index 9682ffe4f..eef5c2fcd 100644
--- a/vendor/raylib/raymath.odin
+++ b/vendor/raylib/raymath.odin
@@ -668,7 +668,7 @@ MatrixLookAt :: proc "c" (eye, target, up: Vector3) -> Matrix {
// Get float array of matrix data
@(require_results)
MatrixToFloatV :: proc "c" (mat: Matrix) -> [16]f32 {
- return transmute([16]f32)mat
+ return transmute([16]f32)linalg.transpose(mat)
}
diff --git a/vendor/raylib/rlgl.odin b/vendor/raylib/rlgl.odin
deleted file mode 100644
index c9e8c28c2..000000000
--- a/vendor/raylib/rlgl.odin
+++ /dev/null
@@ -1,555 +0,0 @@
-/**********************************************************************************************
-*
-* rlgl v5.0 - A multi-OpenGL abstraction layer with an immediate-mode style API
-*
-* DESCRIPTION:
-* An abstraction layer for multiple OpenGL versions (1.1, 2.1, 3.3 Core, 4.3 Core, ES 2.0)
-* that provides a pseudo-OpenGL 1.1 immediate-mode style API (rlVertex, rlTranslate, rlRotate...)
-*
-* ADDITIONAL NOTES:
-* When choosing an OpenGL backend different than OpenGL 1.1, some internal buffer are
-* initialized on rlglInit() to accumulate vertex data.
-*
-* When an internal state change is required all the stored vertex data is renderer in batch,
-* additionally, rlDrawRenderBatchActive() could be called to force flushing of the batch.
-*
-* Some resources are also loaded for convenience, here the complete list:
-* - Default batch (RLGL.defaultBatch): RenderBatch system to accumulate vertex data
-* - Default texture (RLGL.defaultTextureId): 1x1 white pixel R8G8B8A8
-* - Default shader (RLGL.State.defaultShaderId, RLGL.State.defaultShaderLocs)
-*
-* Internal buffer (and resources) must be manually unloaded calling rlglClose().
-*
-* CONFIGURATION:
-* #define GRAPHICS_API_OPENGL_11
-* #define GRAPHICS_API_OPENGL_21
-* #define GRAPHICS_API_OPENGL_33
-* #define GRAPHICS_API_OPENGL_43
-* #define GRAPHICS_API_OPENGL_ES2
-* #define GRAPHICS_API_OPENGL_ES3
-* Use selected OpenGL graphics backend, should be supported by platform
-* Those preprocessor defines are only used on rlgl module, if OpenGL version is
-* required by any other module, use rlGetVersion() to check it
-*
-* #define RLGL_IMPLEMENTATION
-* Generates the implementation of the library into the included file.
-* If not defined, the library is in header only mode and can be included in other headers
-* or source files without problems. But only ONE file should hold the implementation.
-*
-* #define RLGL_RENDER_TEXTURES_HINT
-* Enable framebuffer objects (fbo) support (enabled by default)
-* Some GPUs could not support them despite the OpenGL version
-*
-* #define RLGL_SHOW_GL_DETAILS_INFO
-* Show OpenGL extensions and capabilities detailed logs on init
-*
-* #define RLGL_ENABLE_OPENGL_DEBUG_CONTEXT
-* Enable debug context (only available on OpenGL 4.3)
-*
-* rlgl capabilities could be customized just defining some internal
-* values before library inclusion (default values listed):
-*
-* #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 8192 // Default internal render batch elements limits
-* #define RL_DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering)
-* #define RL_DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture)
-* #define RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS 4 // Maximum number of textures units that can be activated on batch drawing (SetShaderValueTexture())
-*
-* #define RL_MAX_MATRIX_STACK_SIZE 32 // Maximum size of internal Matrix stack
-* #define RL_MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported
-* #define RL_CULL_DISTANCE_NEAR 0.01 // Default projection matrix near cull distance
-* #define RL_CULL_DISTANCE_FAR 1000.0 // Default projection matrix far cull distance
-*
-* When loading a shader, the following vertex attributes and uniform
-* location names are tried to be set automatically:
-*
-* #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: 0
-* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: 1
-* #define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Bound by default to shader location: 2
-* #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: 3
-* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: 4
-* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: 5
-* #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix
-* #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix
-* #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix
-* #define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix
-* #define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView))
-* #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color)
-* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0)
-* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1)
-* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2)
-*
-* DEPENDENCIES:
-* - OpenGL libraries (depending on platform and OpenGL version selected)
-* - GLAD OpenGL extensions loading library (only for OpenGL 3.3 Core, 4.3 Core)
-*
-*
-* LICENSE: zlib/libpng
-*
-* Copyright (c) 2014-2023 Ramon Santamaria (@raysan5)
-*
-* This software is provided "as-is", without any express or implied warranty. In no event
-* will the authors be held liable for any damages arising from the use of this software.
-*
-* Permission is granted to anyone to use this software for any purpose, including commercial
-* applications, and to alter it and redistribute it freely, subject to the following restrictions:
-*
-* 1. The origin of this software must not be misrepresented; you must not claim that you
-* wrote the original software. If you use this software in a product, an acknowledgment
-* in the product documentation would be appreciated but is not required.
-*
-* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
-* as being the original software.
-*
-* 3. This notice may not be removed or altered from any source distribution.
-*
-**********************************************************************************************/
-
-
-package raylib
-
-import "core:c"
-
-RLGL_VERSION :: "4.5"
-
-when ODIN_OS == .Windows {
- foreign import lib {
- "windows/raylib.lib",
- "system:Winmm.lib",
- "system:Gdi32.lib",
- "system:User32.lib",
- "system:Shell32.lib",
- }
-} else when ODIN_OS == .Linux {
- foreign import lib "linux/libraylib.a"
-} else when ODIN_OS == .Darwin {
- foreign import lib {
- "macos-arm64/libraylib.a" when ODIN_ARCH == .arm64 else "macos/libraylib.a",
- "system:Cocoa.framework",
- "system:OpenGL.framework",
- "system:IOKit.framework",
- }
-} else {
- foreign import lib "system:raylib"
-}
-
-RL_GRAPHICS_API_OPENGL_11 :: false
-RL_GRAPHICS_API_OPENGL_21 :: true
-RL_GRAPHICS_API_OPENGL_33 :: RL_GRAPHICS_API_OPENGL_21 // default currently
-RL_GRAPHICS_API_OPENGL_ES2 :: false
-RL_GRAPHICS_API_OPENGL_43 :: false
-RL_GRAPHICS_API_OPENGL_ES3 :: false
-
-when RL_GRAPHICS_API_OPENGL_ES3 {
- RL_GRAPHICS_API_OPENGL_ES2 :: true
-}
-
-when !RL_GRAPHICS_API_OPENGL_ES2 {
- // This is the maximum amount of elements (quads) per batch
- // NOTE: Be careful with text, every letter maps to a quad
- RL_DEFAULT_BATCH_BUFFER_ELEMENTS :: 8192
-} else {
- // We reduce memory sizes for embedded systems (RPI and HTML5)
- // NOTE: On HTML5 (emscripten) this is allocated on heap,
- // by default it's only 16MB!...just take care...
- RL_DEFAULT_BATCH_BUFFER_ELEMENTS :: 2048
-}
-
-RL_DEFAULT_BATCH_BUFFERS :: 1 // Default number of batch buffers (multi-buffering)
-RL_DEFAULT_BATCH_DRAWCALLS :: 256 // Default number of batch draw calls (by state changes: mode, texture)
-RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS :: 4 // Maximum number of additional textures that can be activated on batch drawing (SetShaderValueTexture())
-
-// Internal Matrix stack
-RL_MAX_MATRIX_STACK_SIZE :: 32 // Maximum size of Matrix stack
-
-// Shader limits
-RL_MAX_SHADER_LOCATIONS :: 32 // Maximum number of shader locations supported
-
-// Projection matrix culling
-RL_CULL_DISTANCE_NEAR :: 0.01 // Default near cull distance
-RL_CULL_DISTANCE_FAR :: 1000.0 // Default far cull distance
-
-// Texture parameters (equivalent to OpenGL defines)
-RL_TEXTURE_WRAP_S :: 0x2802 // GL_TEXTURE_WRAP_S
-RL_TEXTURE_WRAP_T :: 0x2803 // GL_TEXTURE_WRAP_T
-RL_TEXTURE_MAG_FILTER :: 0x2800 // GL_TEXTURE_MAG_FILTER
-RL_TEXTURE_MIN_FILTER :: 0x2801 // GL_TEXTURE_MIN_FILTER
-
-RL_TEXTURE_FILTER_NEAREST :: 0x2600 // GL_NEAREST
-RL_TEXTURE_FILTER_LINEAR :: 0x2601 // GL_LINEAR
-RL_TEXTURE_FILTER_MIP_NEAREST :: 0x2700 // GL_NEAREST_MIPMAP_NEAREST
-RL_TEXTURE_FILTER_NEAREST_MIP_LINEAR :: 0x2702 // GL_NEAREST_MIPMAP_LINEAR
-RL_TEXTURE_FILTER_LINEAR_MIP_NEAREST :: 0x2701 // GL_LINEAR_MIPMAP_NEAREST
-RL_TEXTURE_FILTER_MIP_LINEAR :: 0x2703 // GL_LINEAR_MIPMAP_LINEAR
-RL_TEXTURE_FILTER_ANISOTROPIC :: 0x3000 // Anisotropic filter (custom identifier)
-
-RL_TEXTURE_WRAP_REPEAT :: 0x2901 // GL_REPEAT
-RL_TEXTURE_WRAP_CLAMP :: 0x812F // GL_CLAMP_TO_EDGE
-RL_TEXTURE_WRAP_MIRROR_REPEAT :: 0x8370 // GL_MIRRORED_REPEAT
-RL_TEXTURE_WRAP_MIRROR_CLAMP :: 0x8742 // GL_MIRROR_CLAMP_EXT
-
-// Matrix modes (equivalent to OpenGL)
-RL_MODELVIEW :: 0x1700 // GL_MODELVIEW
-RL_PROJECTION :: 0x1701 // GL_PROJECTION
-RL_TEXTURE :: 0x1702 // GL_TEXTURE
-
-// Primitive assembly draw modes
-RL_LINES :: 0x0001 // GL_LINES
-RL_TRIANGLES :: 0x0004 // GL_TRIANGLES
-RL_QUADS :: 0x0007 // GL_QUADS
-
-// GL equivalent data types
-RL_UNSIGNED_BYTE :: 0x1401 // GL_UNSIGNED_BYTE
-RL_FLOAT :: 0x1406 // GL_FLOAT
-
-// Buffer usage hint
-RL_STREAM_DRAW :: 0x88E0 // GL_STREAM_DRAW
-RL_STREAM_READ :: 0x88E1 // GL_STREAM_READ
-RL_STREAM_COPY :: 0x88E2 // GL_STREAM_COPY
-RL_STATIC_DRAW :: 0x88E4 // GL_STATIC_DRAW
-RL_STATIC_READ :: 0x88E5 // GL_STATIC_READ
-RL_STATIC_COPY :: 0x88E6 // GL_STATIC_COPY
-RL_DYNAMIC_DRAW :: 0x88E8 // GL_DYNAMIC_DRAW
-RL_DYNAMIC_READ :: 0x88E9 // GL_DYNAMIC_READ
-RL_DYNAMIC_COPY :: 0x88EA // GL_DYNAMIC_COPY
-
-// GL Shader type
-RL_FRAGMENT_SHADER :: 0x8B30 // GL_FRAGMENT_SHADER
-RL_VERTEX_SHADER :: 0x8B31 // GL_VERTEX_SHADER
-RL_COMPUTE_SHADER :: 0x91B9 // GL_COMPUTE_SHADER
-
-// GL blending factors
-RL_ZERO :: 0 // GL_ZERO
-RL_ONE :: 1 // GL_ONE
-RL_SRC_COLOR :: 0x0300 // GL_SRC_COLOR
-RL_ONE_MINUS_SRC_COLOR :: 0x0301 // GL_ONE_MINUS_SRC_COLOR
-RL_SRC_ALPHA :: 0x0302 // GL_SRC_ALPHA
-RL_ONE_MINUS_SRC_ALPHA :: 0x0303 // GL_ONE_MINUS_SRC_ALPHA
-RL_DST_ALPHA :: 0x0304 // GL_DST_ALPHA
-RL_ONE_MINUS_DST_ALPHA :: 0x0305 // GL_ONE_MINUS_DST_ALPHA
-RL_DST_COLOR :: 0x0306 // GL_DST_COLOR
-RL_ONE_MINUS_DST_COLOR :: 0x0307 // GL_ONE_MINUS_DST_COLOR
-RL_SRC_ALPHA_SATURATE :: 0x0308 // GL_SRC_ALPHA_SATURATE
-RL_CONSTANT_COLOR :: 0x8001 // GL_CONSTANT_COLOR
-RL_ONE_MINUS_CONSTANT_COLOR :: 0x8002 // GL_ONE_MINUS_CONSTANT_COLOR
-RL_CONSTANT_ALPHA :: 0x8003 // GL_CONSTANT_ALPHA
-RL_ONE_MINUS_CONSTANT_ALPHA :: 0x8004 // GL_ONE_MINUS_CONSTANT_ALPHA
-
-// GL blending functions/equations
-RL_FUNC_ADD :: 0x8006 // GL_FUNC_ADD
-RL_MIN :: 0x8007 // GL_MIN
-RL_MAX :: 0x8008 // GL_MAX
-RL_FUNC_SUBTRACT :: 0x800A // GL_FUNC_SUBTRACT
-RL_FUNC_REVERSE_SUBTRACT :: 0x800B // GL_FUNC_REVERSE_SUBTRACT
-RL_BLEND_EQUATION :: 0x8009 // GL_BLEND_EQUATION
-RL_BLEND_EQUATION_RGB :: 0x8009 // GL_BLEND_EQUATION_RGB // (Same as BLEND_EQUATION)
-RL_BLEND_EQUATION_ALPHA :: 0x883D // GL_BLEND_EQUATION_ALPHA
-RL_BLEND_DST_RGB :: 0x80C8 // GL_BLEND_DST_RGB
-RL_BLEND_SRC_RGB :: 0x80C9 // GL_BLEND_SRC_RGB
-RL_BLEND_DST_ALPHA :: 0x80CA // GL_BLEND_DST_ALPHA
-RL_BLEND_SRC_ALPHA :: 0x80CB // GL_BLEND_SRC_ALPHA
-RL_BLEND_COLOR :: 0x8005 // GL_BLEND_COLOR
-
-
-//----------------------------------------------------------------------------------
-// Types and Structures Definition
-//----------------------------------------------------------------------------------
-
-
-VertexBufferIndexType :: c.ushort when RL_GRAPHICS_API_OPENGL_ES2 else c.uint
-
-// Dynamic vertex buffers (position + texcoords + colors + indices arrays)
-VertexBuffer :: struct {
- elementCount: c.int, // Number of elements in the buffer (QUADS)
-
- vertices: [^]f32, // Vertex position (XYZ - 3 components per vertex) (shader-location = 0)
- texcoords: [^]f32, // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
- colors: [^]u8, // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
- indices: [^]VertexBufferIndexType, // Vertex indices (in case vertex data comes indexed) (6 indices per quad)
- vaoId: c.uint, // OpenGL Vertex Array Object id
- vboId: [4]c.uint, // OpenGL Vertex Buffer Objects id (4 types of vertex data)
-}
-
-// Draw call type
-// NOTE: Only texture changes register a new draw, other state-change-related elements are not
-// used at this moment (vaoId, shaderId, matrices), raylib just forces a batch draw call if any
-// of those state-change happens (this is done in core module)
-DrawCall :: struct {
- mode: c.int, // Drawing mode: LINES, TRIANGLES, QUADS
- vertexCount: c.int, // Number of vertex of the draw
- vertexAlignment: c.int, // Number of vertex required for index alignment (LINES, TRIANGLES)
- textureId: c.uint, // Texture id to be used on the draw -> Use to create new draw call if changes
-}
-
-// RenderBatch type
-RenderBatch :: struct {
- bufferCount: c.int, // Number of vertex buffers (multi-buffering support)
- currentBuffer: c.int, // Current buffer tracking in case of multi-buffering
- vertexBuffer: [^]VertexBuffer, // Dynamic buffer(s) for vertex data
-
- draws: [^]DrawCall, // Draw calls array, depends on textureId
- drawCounter: c.int, // Draw calls counter
- currentDepth: f32, // Current depth value for next draw
-}
-
-
-// OpenGL version
-GlVersion :: enum c.int {
- OPENGL_11 = 1, // OpenGL 1.1
- OPENGL_21, // OpenGL 2.1 (GLSL 120)
- OPENGL_33, // OpenGL 3.3 (GLSL 330)
- OPENGL_43, // OpenGL 4.3 (using GLSL 330)
- OPENGL_ES_20, // OpenGL ES 2.0 (GLSL 100)
- OPENGL_ES_30, // OpenGL ES 3.0 (GLSL 300 es)
-}
-
-
-// Shader attribute data types
-ShaderAttributeDataType :: enum c.int {
- FLOAT = 0, // Shader attribute type: float
- VEC2, // Shader attribute type: vec2 (2 float)
- VEC3, // Shader attribute type: vec3 (3 float)
- VEC4, // Shader attribute type: vec4 (4 float)
-}
-
-// Framebuffer attachment type
-// NOTE: By default up to 8 color channels defined, but it can be more
-FramebufferAttachType :: enum c.int {
- COLOR_CHANNEL0 = 0, // Framebuffer attachment type: color 0
- COLOR_CHANNEL1 = 1, // Framebuffer attachment type: color 1
- COLOR_CHANNEL2 = 2, // Framebuffer attachment type: color 2
- COLOR_CHANNEL3 = 3, // Framebuffer attachment type: color 3
- COLOR_CHANNEL4 = 4, // Framebuffer attachment type: color 4
- COLOR_CHANNEL5 = 5, // Framebuffer attachment type: color 5
- COLOR_CHANNEL6 = 6, // Framebuffer attachment type: color 6
- COLOR_CHANNEL7 = 7, // Framebuffer attachment type: color 7
- DEPTH = 100, // Framebuffer attachment type: depth
- STENCIL = 200, // Framebuffer attachment type: stencil
-}
-
-// Framebuffer texture attachment type
-FramebufferAttachTextureType :: enum c.int {
- CUBEMAP_POSITIVE_X = 0, // Framebuffer texture attachment type: cubemap, +X side
- CUBEMAP_NEGATIVE_X = 1, // Framebuffer texture attachment type: cubemap, -X side
- CUBEMAP_POSITIVE_Y = 2, // Framebuffer texture attachment type: cubemap, +Y side
- CUBEMAP_NEGATIVE_Y = 3, // Framebuffer texture attachment type: cubemap, -Y side
- CUBEMAP_POSITIVE_Z = 4, // Framebuffer texture attachment type: cubemap, +Z side
- CUBEMAP_NEGATIVE_Z = 5, // Framebuffer texture attachment type: cubemap, -Z side
- TEXTURE2D = 100, // Framebuffer texture attachment type: texture2d
- RENDERBUFFER = 200, // Framebuffer texture attachment type: renderbuffer
-}
-
-CullMode :: enum c.int {
- FRONT = 0,
- BACK,
-}
-
-@(default_calling_convention="c")
-foreign lib {
- //------------------------------------------------------------------------------------
- // Functions Declaration - Matrix operations
- //------------------------------------------------------------------------------------
- rlMatrixMode :: proc(mode: c.int) --- // Choose the current matrix to be transformed
- rlPushMatrix :: proc() --- // Push the current matrix to stack
- rlPopMatrix :: proc() --- // Pop lattest inserted matrix from stack
- rlLoadIdentity :: proc() --- // Reset current matrix to identity matrix
- rlTranslatef :: proc(x, y, z: f32) --- // Multiply the current matrix by a translation matrix
- rlRotatef :: proc(angleDeg: f32, x, y, z: f32) --- // Multiply the current matrix by a rotation matrix
- rlScalef :: proc(x, y, z: f32) --- // Multiply the current matrix by a scaling matrix
- rlMultMatrixf :: proc(matf: [^]f32) --- // Multiply the current matrix by another matrix
- rlFrustum :: proc(left, right, bottom, top, znear, zfar: f64) ---
- rlOrtho :: proc(left, right, bottom, top, znear, zfar: f64) ---
- rlViewport :: proc(x, y, width, height: c.int) --- // Set the viewport area
-
- //------------------------------------------------------------------------------------
- // Functions Declaration - Vertex level operations
- //------------------------------------------------------------------------------------
- rlBegin :: proc(mode: c.int) --- // Initialize drawing mode (how to organize vertex)
- rlEnd :: proc() --- // Finish vertex providing
- rlVertex2i :: proc(x, y: c.int) --- // Define one vertex (position) - 2 int
- rlVertex2f :: proc(x, y: f32) --- // Define one vertex (position) - 2 f32
- rlVertex3f :: proc(x, y, z: f32) --- // Define one vertex (position) - 3 f32
- rlTexCoord2f :: proc(x, y: f32) --- // Define one vertex (texture coordinate) - 2 f32
- rlNormal3f :: proc(x, y, z: f32) --- // Define one vertex (normal) - 3 f32
- rlColor4ub :: proc(r, g, b, a: u8) --- // Define one vertex (color) - 4 byte
- rlColor3f :: proc(x, y, z: f32) --- // Define one vertex (color) - 3 f32
- rlColor4f :: proc(x, y, z, w: f32) --- // Define one vertex (color) - 4 f32
-
- //------------------------------------------------------------------------------------
- // Functions Declaration - OpenGL style functions (common to 1.1, 3.3+, ES2)
- // NOTE: This functions are used to completely abstract raylib code from OpenGL layer,
- // some of them are direct wrappers over OpenGL calls, some others are custom
- //------------------------------------------------------------------------------------
-
- // Vertex buffers state
- rlEnableVertexArray :: proc(vaoId: c.uint) -> bool --- // Enable vertex array (VAO, if supported)
- rlDisableVertexArray :: proc() --- // Disable vertex array (VAO, if supported)
- rlEnableVertexBuffer :: proc(id: c.uint) --- // Enable vertex buffer (VBO)
- rlDisableVertexBuffer :: proc() --- // Disable vertex buffer (VBO)
- rlEnableVertexBufferElement :: proc(id: c.uint) --- // Enable vertex buffer element (VBO element)
- rlDisableVertexBufferElement :: proc() --- // Disable vertex buffer element (VBO element)
- rlEnableVertexAttribute :: proc(index: c.uint) --- // Enable vertex attribute index
- rlDisableVertexAttribute :: proc(index: c.uint) --- // Disable vertex attribute index
- when RL_GRAPHICS_API_OPENGL_11 {
- rlEnableStatePointer :: proc(vertexAttribType: c.int, buffer: rawptr) ---
- rlDisableStatePointer :: proc(vertexAttribType: c.int) ---
- }
-
- // Textures state
- rlActiveTextureSlot :: proc(slot: c.int) --- // Select and active a texture slot
- rlEnableTexture :: proc(id: c.uint) --- // Enable texture
- rlDisableTexture :: proc() --- // Disable texture
- rlEnableTextureCubemap :: proc(id: c.uint) --- // Enable texture cubemap
- rlDisableTextureCubemap :: proc() --- // Disable texture cubemap
- rlTextureParameters :: proc(id: c.uint, param: c.int, value: c.int) --- // Set texture parameters (filter, wrap)
- rlCubemapParameters :: proc(id: i32, param: c.int, value: c.int) --- // Set cubemap parameters (filter, wrap)
-
- // Shader state
- rlEnableShader :: proc(id: c.uint) --- // Enable shader program
- rlDisableShader :: proc() --- // Disable shader program
-
- // Framebuffer state
- rlEnableFramebuffer :: proc(id: c.uint) --- // Enable render texture (fbo)
- rlDisableFramebuffer :: proc() --- // Disable render texture (fbo), return to default framebuffer
- rlActiveDrawBuffers :: proc(count: c.int) --- // Activate multiple draw color buffers
- rlBlitFramebuffer :: proc(srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight, bufferMask: c.int) --- // Blit active framebuffer to main framebuffer
-
- // General render state
- rlDisableColorBlend :: proc() --- // Disable color blending
- rlEnableDepthTest :: proc() --- // Enable depth test
- rlDisableDepthTest :: proc() --- // Disable depth test
- rlEnableDepthMask :: proc() --- // Enable depth write
- rlDisableDepthMask :: proc() --- // Disable depth write
- rlEnableBackfaceCulling :: proc() --- // Enable backface culling
- rlDisableBackfaceCulling :: proc() --- // Disable backface culling
- rlSetCullFace :: proc(mode: CullMode) --- // Set face culling mode
- rlEnableScissorTest :: proc() --- // Enable scissor test
- rlDisableScissorTest :: proc() --- // Disable scissor test
- rlScissor :: proc(x, y, width, height: c.int) --- // Scissor test
- rlEnableWireMode :: proc() --- // Enable wire mode
- rlEnablePointMode :: proc() --- // Enable point mode
- rlDisableWireMode :: proc() --- // Disable wire and point modes
- rlSetLineWidth :: proc(width: f32) --- // Set the line drawing width
- rlGetLineWidth :: proc() -> f32 --- // Get the line drawing width
- rlEnableSmoothLines :: proc() --- // Enable line aliasing
- rlDisableSmoothLines :: proc() --- // Disable line aliasing
- rlEnableStereoRender :: proc() --- // Enable stereo rendering
- rlDisableStereoRender :: proc() --- // Disable stereo rendering
- rlIsStereoRenderEnabled :: proc() -> bool --- // Check if stereo render is enabled
-
-
- rlClearColor :: proc(r, g, b, a: u8) --- // Clear color buffer with color
- rlClearScreenBuffers :: proc() --- // Clear used screen buffers (color and depth)
- rlCheckErrors :: proc() --- // Check and log OpenGL error codes
- rlSetBlendMode :: proc(mode: c.int) --- // Set blending mode
- rlSetBlendFactors :: proc(glSrcFactor, glDstFactor, glEquation: c.int) --- // Set blending mode factor and equation (using OpenGL factors)
- rlSetBlendFactorsSeparate :: proc(glSrcRGB, glDstRGB, glSrcAlpha, glDstAlpha, glEqRGB, glEqAlpha: c.int) --- // Set blending mode factors and equations separately (using OpenGL factors)
-
- //------------------------------------------------------------------------------------
- // Functions Declaration - rlgl functionality
- //------------------------------------------------------------------------------------
- // rlgl initialization functions
- rlglInit :: proc(width, height: c.int) --- // Initialize rlgl (buffers, shaders, textures, states)
- rlglClose :: proc() --- // De-initialize rlgl (buffers, shaders, textures)
- rlLoadExtensions :: proc(loader: rawptr) --- // Load OpenGL extensions (loader function required)
- rlGetVersion :: proc() -> GlVersion --- // Get current OpenGL version
- rlSetFramebufferWidth :: proc(width: c.int) --- // Set current framebuffer width
- rlGetFramebufferWidth :: proc() -> c.int --- // Get default framebuffer width
- rlSetFramebufferHeight :: proc(height: c.int) --- // Set current framebuffer height
- rlGetFramebufferHeight :: proc() -> c.int --- // Get default framebuffer height
-
-
- rlGetTextureIdDefault :: proc() -> c.uint --- // Get default texture id
- rlGetShaderIdDefault :: proc() -> c.uint --- // Get default shader id
- rlGetShaderLocsDefault :: proc() -> [^]c.int --- // Get default shader locations
-
- // Render batch management
- // NOTE: rlgl provides a default render batch to behave like OpenGL 1.1 immediate mode
- // but this render batch API is exposed in case of custom batches are required
- rlLoadRenderBatch :: proc(numBuffers, bufferElements: c.int) -> RenderBatch --- // Load a render batch system
- rlUnloadRenderBatch :: proc(batch: RenderBatch) --- // Unload render batch system
- rlDrawRenderBatch :: proc(batch: ^RenderBatch) --- // Draw render batch data (Update->Draw->Reset)
- rlSetRenderBatchActive :: proc(batch: ^RenderBatch) --- // Set the active render batch for rlgl (NULL for default internal)
- rlDrawRenderBatchActive :: proc() --- // Update and draw internal render batch
- rlCheckRenderBatchLimit :: proc(vCount: c.int) -> c.int --- // Check internal buffer overflow for a given number of vertex
-
- rlSetTexture :: proc(id: c.uint) --- // Set current texture for render batch and check buffers limits
-
- //------------------------------------------------------------------------------------------------------------------------
-
- // Vertex buffers management
- rlLoadVertexArray :: proc() -> c.uint --- // Load vertex array (vao) if supported
- rlLoadVertexBuffer :: proc(buffer: rawptr, size: c.int, is_dynamic: bool) -> c.uint --- // Load a vertex buffer attribute
- rlLoadVertexBufferElement :: proc(buffer: rawptr, size: c.int, is_dynamic: bool) -> c.uint --- // Load a new attributes element buffer
- rlUpdateVertexBuffer :: proc(bufferId: c.uint, data: rawptr, dataSize: c.int, offset: c.int) --- // Update GPU buffer with new data
- rlUpdateVertexBufferElements :: proc(id: c.uint, data: rawptr, dataSize: c.int, offset: c.int) --- // Update vertex buffer elements with new data
- rlUnloadVertexArray :: proc(vaoId: c.uint) ---
- rlUnloadVertexBuffer :: proc(vboId: c.uint) ---
- rlSetVertexAttribute :: proc(index: c.uint, compSize: c.int, type: c.int, normalized: bool, stride: c.int, pointer: rawptr) ---
- rlSetVertexAttributeDivisor :: proc(index: c.uint, divisor: c.int) ---
- rlSetVertexAttributeDefault :: proc(locIndex: c.int, value: rawptr, attribType: c.int, count: c.int) --- // Set vertex attribute default value
- rlDrawVertexArray :: proc(offset: c.int, count: c.int) ---
- rlDrawVertexArrayElements :: proc(offset: c.int, count: c.int, buffer: rawptr) ---
- rlDrawVertexArrayInstanced :: proc(offset: c.int, count: c.int, instances: c.int) ---
- rlDrawVertexArrayElementsInstanced :: proc(offset: c.int, count: c.int, buffer: rawptr, instances: c.int) ---
-
- // Textures management
- rlLoadTexture :: proc(data: rawptr, width, height: c.int, format: c.int, mipmapCount: c.int) -> c.uint --- // Load texture in GPU
- rlLoadTextureDepth :: proc(width, height: c.int, useRenderBuffer: bool) -> c.uint --- // Load depth texture/renderbuffer (to be attached to fbo)
- rlLoadTextureCubemap :: proc(data: rawptr, size: c.int, format: c.int) -> c.uint --- // Load texture cubemap
- rlUpdateTexture :: proc(id: c.uint, offsetX, offsetY: c.int, width, height: c.int, format: c.int, data: rawptr) --- // Update GPU texture with new data
- rlGetGlTextureFormats :: proc(format: c.int, glInternalFormat, glFormat, glType: ^c.uint) --- // Get OpenGL internal formats
- rlGetPixelFormatName :: proc(format: c.uint) -> cstring --- // Get name string for pixel format
- rlUnloadTexture :: proc(id: c.uint) --- // Unload texture from GPU memory
- rlGenTextureMipmaps :: proc(id: c.uint, width, height: c.int, format: c.int, mipmaps: ^c.int) --- // Generate mipmap data for selected texture
- rlReadTexturePixels :: proc(id: c.uint, width, height: c.int, format: c.int) -> rawptr --- // Read texture pixel data
- rlReadScreenPixels :: proc(width, height: c.int) -> [^]byte --- // Read screen pixel data (color buffer)
-
- // Framebuffer management (fbo)
- rlLoadFramebuffer :: proc(width, height: c.int) -> c.uint --- // Load an empty framebuffer
- rlFramebufferAttach :: proc(fboId, texId: c.uint, attachType: c.int, texType: c.int, mipLevel: c.int) --- // Attach texture/renderbuffer to a framebuffer
- rlFramebufferComplete :: proc(id: c.uint) -> bool --- // Verify framebuffer is complete
- rlUnloadFramebuffer :: proc(id: c.uint) --- // Delete framebuffer from GPU
-
- // Shaders management
- rlLoadShaderCode :: proc(vsCode, fsCode: cstring) -> c.uint --- // Load shader from code strings
- rlCompileShader :: proc(shaderCode: cstring, type: c.int) -> c.uint --- // Compile custom shader and return shader id (type: RL_VERTEX_SHADER, RL_FRAGMENT_SHADER, RL_COMPUTE_SHADER)
- rlLoadShaderProgram :: proc(vShaderId, fShaderId: c.uint) -> c.uint --- // Load custom shader program
- rlUnloadShaderProgram :: proc(id: c.uint) --- // Unload shader program
- rlGetLocationUniform :: proc(shaderId: c.uint, uniformName: cstring) -> c.int --- // Get shader location uniform
- rlGetLocationAttrib :: proc(shaderId: c.uint, attribName: cstring) -> c.int --- // Get shader location attribute
- rlSetUniform :: proc(locIndex: c.int, value: rawptr, uniformType: c.int, count: c.int) --- // Set shader value uniform
- rlSetUniformMatrix :: proc(locIndex: c.int, mat: Matrix) --- // Set shader value matrix
- rlSetUniformSampler :: proc(locIndex: c.int, textureId: c.uint) --- // Set shader value sampler
- rlSetShader :: proc(id: c.uint, locs: [^]c.int) --- // Set shader currently active (id and locations)
-
- // Compute shader management
- rlLoadComputeShaderProgram :: proc(shaderId: c.uint) -> c.uint --- // Load compute shader program
- rlComputeShaderDispatch :: proc(groupX, groupY, groupZ: c.uint) --- // Dispatch compute shader (equivalent to *draw* for graphics pipeline)
-
- // Shader buffer storage object management (ssbo)
- rlLoadShaderBuffer :: proc(size: c.uint, data: rawptr, usageHint: c.int) -> c.uint --- // Load shader storage buffer object (SSBO)
- rlUnloadShaderBuffer :: proc(ssboId: c.uint) --- // Unload shader storage buffer object (SSBO)
- rlUpdateShaderBuffer :: proc(id: c.uint, data: rawptr, dataSize: c.uint, offset: c.uint) --- // Update SSBO buffer data
- rlBindShaderBuffer :: proc(id: c.uint, index: c.uint) --- // Bind SSBO buffer
- rlReadShaderBuffer :: proc(id: c.uint, dest: rawptr, count: c.uint, offset: c.uint) --- // Read SSBO buffer data (GPU->CPU)
- rlCopyShaderBuffer :: proc(destId, srcId: c.uint, destOffset, srcOffset: c.uint, count: c.uint) --- // Copy SSBO data between buffers
- rlGetShaderBufferSize :: proc(id: c.uint) -> c.uint --- // Get SSBO buffer size
-
- // Buffer management
- rlBindImageTexture :: proc(id: c.uint, index: c.uint, format: c.int, readonly: bool) --- // Bind image texture
-
- // Matrix state management
- rlGetMatrixModelview :: proc() -> Matrix --- // Get internal modelview matrix
- rlGetMatrixProjection :: proc() -> Matrix --- // Get internal projection matrix
- rlGetMatrixTransform :: proc() -> Matrix --- // Get internal accumulated transform matrix
- rlGetMatrixProjectionStereo :: proc(eye: c.int) -> Matrix --- // Get internal projection matrix for stereo render (selected eye)
- rlGetMatrixViewOffsetStereo :: proc(eye: c.int) -> Matrix --- // Get internal view offset matrix for stereo render (selected eye)
- rlSetMatrixProjection :: proc(proj: Matrix) --- // Set a custom projection matrix (replaces internal projection matrix)
- rlSetMatrixModelview :: proc(view: Matrix) --- // Set a custom modelview matrix (replaces internal modelview matrix)
- rlSetMatrixProjectionStereo :: proc(right, left: Matrix) --- // Set eyes projection matrices for stereo rendering
- rlSetMatrixViewOffsetStereo :: proc(right, left: Matrix) --- // Set eyes view offsets matrices for stereo rendering
-
- // Quick and dirty cube/quad buffers load->draw->unload
- rlLoadDrawCube :: proc() --- // Load and draw a cube
- rlLoadDrawQuad :: proc() --- // Load and draw a quad
-}
diff --git a/vendor/raylib/rlgl/rlgl.odin b/vendor/raylib/rlgl/rlgl.odin
new file mode 100644
index 000000000..cef31c238
--- /dev/null
+++ b/vendor/raylib/rlgl/rlgl.odin
@@ -0,0 +1,581 @@
+/**********************************************************************************************
+*
+* rlgl v5.0 - A multi-OpenGL abstraction layer with an immediate-mode style API
+*
+* DESCRIPTION:
+* An abstraction layer for multiple OpenGL versions (1.1, 2.1, 3.3 Core, 4.3 Core, ES 2.0)
+* that provides a pseudo-OpenGL 1.1 immediate-mode style API (rlVertex, rlTranslate, rlRotate...)
+*
+* ADDITIONAL NOTES:
+* When choosing an OpenGL backend different than OpenGL 1.1, some internal buffer are
+* initialized on rlglInit() to accumulate vertex data.
+*
+* When an internal state change is required all the stored vertex data is renderer in batch,
+* additionally, rlDrawRenderBatchActive() could be called to force flushing of the batch.
+*
+* Some resources are also loaded for convenience, here the complete list:
+* - Default batch (RLGL.defaultBatch): RenderBatch system to accumulate vertex data
+* - Default texture (RLGL.defaultTextureId): 1x1 white pixel R8G8B8A8
+* - Default shader (RLGL.State.defaultShaderId, RLGL.State.defaultShaderLocs)
+*
+* Internal buffer (and resources) must be manually unloaded calling rlglClose().
+*
+* CONFIGURATION:
+* #define GRAPHICS_API_OPENGL_11
+* #define GRAPHICS_API_OPENGL_21
+* #define GRAPHICS_API_OPENGL_33
+* #define GRAPHICS_API_OPENGL_43
+* #define GRAPHICS_API_OPENGL_ES2
+* #define GRAPHICS_API_OPENGL_ES3
+* Use selected OpenGL graphics backend, should be supported by platform
+* Those preprocessor defines are only used on rlgl module, if OpenGL version is
+* required by any other module, use rlGetVersion() to check it
+*
+* #define RLGL_IMPLEMENTATION
+* Generates the implementation of the library into the included file.
+* If not defined, the library is in header only mode and can be included in other headers
+* or source files without problems. But only ONE file should hold the implementation.
+*
+* #define RLGL_RENDER_TEXTURES_HINT
+* Enable framebuffer objects (fbo) support (enabled by default)
+* Some GPUs could not support them despite the OpenGL version
+*
+* #define RLGL_SHOW_GL_DETAILS_INFO
+* Show OpenGL extensions and capabilities detailed logs on init
+*
+* #define RLGL_ENABLE_OPENGL_DEBUG_CONTEXT
+* Enable debug context (only available on OpenGL 4.3)
+*
+* rlgl capabilities could be customized just defining some internal
+* values before library inclusion (default values listed):
+*
+* #define RL_DEFAULT_BATCH_BUFFER_ELEMENTS 8192 // Default internal render batch elements limits
+* #define RL_DEFAULT_BATCH_BUFFERS 1 // Default number of batch buffers (multi-buffering)
+* #define RL_DEFAULT_BATCH_DRAWCALLS 256 // Default number of batch draw calls (by state changes: mode, texture)
+* #define RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS 4 // Maximum number of textures units that can be activated on batch drawing (SetShaderValueTexture())
+*
+* #define RL_MAX_MATRIX_STACK_SIZE 32 // Maximum size of internal Matrix stack
+* #define RL_MAX_SHADER_LOCATIONS 32 // Maximum number of shader locations supported
+* #define RL_CULL_DISTANCE_NEAR 0.01 // Default projection matrix near cull distance
+* #define RL_CULL_DISTANCE_FAR 1000.0 // Default projection matrix far cull distance
+*
+* When loading a shader, the following vertex attributes and uniform
+* location names are tried to be set automatically:
+*
+* #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: 0
+* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: 1
+* #define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Bound by default to shader location: 2
+* #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: 3
+* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: 4
+* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: 5
+* #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix
+* #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix
+* #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix
+* #define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix
+* #define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView))
+* #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color)
+* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0)
+* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1)
+* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2)
+*
+* DEPENDENCIES:
+* - OpenGL libraries (depending on platform and OpenGL version selected)
+* - GLAD OpenGL extensions loading library (only for OpenGL 3.3 Core, 4.3 Core)
+*
+*
+* LICENSE: zlib/libpng
+*
+* Copyright (c) 2014-2023 Ramon Santamaria (@raysan5)
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+
+package rlgl
+
+import "core:c"
+import rl "../."
+
+VERSION :: "5.0"
+
+RAYLIB_SHARED :: #config(RAYLIB_SHARED, false)
+
+// Note: We pull in the full raylib library. If you want a truly stand-alone rlgl, then:
+// - Compile a separate rlgl library and use that in the foreign import blocks below.
+// - Remove the `import rl "../."` line
+// - Copy the code from raylib.odin for any types we alias from that package (see PixelFormat etc)
+
+when ODIN_OS == .Windows {
+ @(extra_linker_flags="/NODEFAULTLIB:" + ("msvcrt" when RAYLIB_SHARED else "libcmt"))
+ foreign import lib {
+ "../windows/raylibdll.lib" when RAYLIB_SHARED else "../windows/raylib.lib" ,
+ "system:Winmm.lib",
+ "system:Gdi32.lib",
+ "system:User32.lib",
+ "system:Shell32.lib",
+ }
+} else when ODIN_OS == .Linux {
+ foreign import lib {
+ // Note(bumbread): I'm not sure why in `linux/` folder there are
+ // multiple copies of raylib.so, but since these bindings are for
+ // particular version of the library, I better specify it. Ideally,
+ // though, it's best specified in terms of major (.so.4)
+ "../linux/libraylib.so.500" when RAYLIB_SHARED else "../linux/libraylib.a",
+ "system:dl",
+ "system:pthread",
+ }
+} else when ODIN_OS == .Darwin {
+ foreign import lib {
+ "../macos" +
+ ("-arm64" when ODIN_ARCH == .arm64 else "") +
+ "/libraylib" + (".500.dylib" when RAYLIB_SHARED else ".a"),
+ "system:Cocoa.framework",
+ "system:OpenGL.framework",
+ "system:IOKit.framework",
+ }
+} else {
+ foreign import lib "system:raylib"
+}
+
+GRAPHICS_API_OPENGL_11 :: false
+GRAPHICS_API_OPENGL_21 :: true
+GRAPHICS_API_OPENGL_33 :: GRAPHICS_API_OPENGL_21 // default currently
+GRAPHICS_API_OPENGL_ES2 :: false
+GRAPHICS_API_OPENGL_43 :: false
+GRAPHICS_API_OPENGL_ES3 :: false
+
+when GRAPHICS_API_OPENGL_ES3 {
+ GRAPHICS_API_OPENGL_ES2 :: true
+}
+
+when !GRAPHICS_API_OPENGL_ES2 {
+ // This is the maximum amount of elements (quads) per batch
+ // NOTE: Be careful with text, every letter maps to a quad
+ DEFAULT_BATCH_BUFFER_ELEMENTS :: 8192
+} else {
+ // We reduce memory sizes for embedded systems (RPI and HTML5)
+ // NOTE: On HTML5 (emscripten) this is allocated on heap,
+ // by default it's only 16MB!...just take care...
+ DEFAULT_BATCH_BUFFER_ELEMENTS :: 2048
+}
+
+DEFAULT_BATCH_BUFFERS :: 1 // Default number of batch buffers (multi-buffering)
+DEFAULT_BATCH_DRAWCALLS :: 256 // Default number of batch draw calls (by state changes: mode, texture)
+DEFAULT_BATCH_MAX_TEXTURE_UNITS :: 4 // Maximum number of additional textures that can be activated on batch drawing (SetShaderValueTexture())
+
+// Internal Matrix stack
+MAX_MATRIX_STACK_SIZE :: 32 // Maximum size of Matrix stack
+
+// Shader limits
+MAX_SHADER_LOCATIONS :: 32 // Maximum number of shader locations supported
+
+// Projection matrix culling
+CULL_DISTANCE_NEAR :: 0.01 // Default near cull distance
+CULL_DISTANCE_FAR :: 1000.0 // Default far cull distance
+
+// Texture parameters (equivalent to OpenGL defines)
+TEXTURE_WRAP_S :: 0x2802 // GL_TEXTURE_WRAP_S
+TEXTURE_WRAP_T :: 0x2803 // GL_TEXTURE_WRAP_T
+TEXTURE_MAG_FILTER :: 0x2800 // GL_TEXTURE_MAG_FILTER
+TEXTURE_MIN_FILTER :: 0x2801 // GL_TEXTURE_MIN_FILTER
+
+TEXTURE_FILTER_NEAREST :: 0x2600 // GL_NEAREST
+TEXTURE_FILTER_LINEAR :: 0x2601 // GL_LINEAR
+TEXTURE_FILTER_MIP_NEAREST :: 0x2700 // GL_NEAREST_MIPMAP_NEAREST
+TEXTURE_FILTER_NEAREST_MIP_LINEAR :: 0x2702 // GL_NEAREST_MIPMAP_LINEAR
+TEXTURE_FILTER_LINEAR_MIP_NEAREST :: 0x2701 // GL_LINEAR_MIPMAP_NEAREST
+TEXTURE_FILTER_MIP_LINEAR :: 0x2703 // GL_LINEAR_MIPMAP_LINEAR
+TEXTURE_FILTER_ANISOTROPIC :: 0x3000 // Anisotropic filter (custom identifier)
+
+TEXTURE_WRAP_REPEAT :: 0x2901 // GL_REPEAT
+TEXTURE_WRAP_CLAMP :: 0x812F // GL_CLAMP_TO_EDGE
+TEXTURE_WRAP_MIRROR_REPEAT :: 0x8370 // GL_MIRRORED_REPEAT
+TEXTURE_WRAP_MIRROR_CLAMP :: 0x8742 // GL_MIRROR_CLAMP_EXT
+
+// Matrix modes (equivalent to OpenGL)
+MODELVIEW :: 0x1700 // GL_MODELVIEW
+PROJECTION :: 0x1701 // GL_PROJECTION
+TEXTURE :: 0x1702 // GL_TEXTURE
+
+// Primitive assembly draw modes
+LINES :: 0x0001 // GL_LINES
+TRIANGLES :: 0x0004 // GL_TRIANGLES
+QUADS :: 0x0007 // GL_QUADS
+
+// GL equivalent data types
+UNSIGNED_BYTE :: 0x1401 // GL_UNSIGNED_BYTE
+FLOAT :: 0x1406 // GL_FLOAT
+
+// Buffer usage hint
+STREAM_DRAW :: 0x88E0 // GL_STREAM_DRAW
+STREAM_READ :: 0x88E1 // GL_STREAM_READ
+STREAM_COPY :: 0x88E2 // GL_STREAM_COPY
+STATIC_DRAW :: 0x88E4 // GL_STATIC_DRAW
+STATIC_READ :: 0x88E5 // GL_STATIC_READ
+STATIC_COPY :: 0x88E6 // GL_STATIC_COPY
+DYNAMIC_DRAW :: 0x88E8 // GL_DYNAMIC_DRAW
+DYNAMIC_READ :: 0x88E9 // GL_DYNAMIC_READ
+DYNAMIC_COPY :: 0x88EA // GL_DYNAMIC_COPY
+
+// GL Shader type
+FRAGMENT_SHADER :: 0x8B30 // GL_FRAGMENT_SHADER
+VERTEX_SHADER :: 0x8B31 // GL_VERTEX_SHADER
+COMPUTE_SHADER :: 0x91B9 // GL_COMPUTE_SHADER
+
+// GL blending factors
+ZERO :: 0 // GL_ZERO
+ONE :: 1 // GL_ONE
+SRC_COLOR :: 0x0300 // GL_SRC_COLOR
+ONE_MINUS_SRC_COLOR :: 0x0301 // GL_ONE_MINUS_SRC_COLOR
+SRC_ALPHA :: 0x0302 // GL_SRC_ALPHA
+ONE_MINUS_SRC_ALPHA :: 0x0303 // GL_ONE_MINUS_SRC_ALPHA
+DST_ALPHA :: 0x0304 // GL_DST_ALPHA
+ONE_MINUS_DST_ALPHA :: 0x0305 // GL_ONE_MINUS_DST_ALPHA
+DST_COLOR :: 0x0306 // GL_DST_COLOR
+ONE_MINUS_DST_COLOR :: 0x0307 // GL_ONE_MINUS_DST_COLOR
+SRC_ALPHA_SATURATE :: 0x0308 // GL_SRC_ALPHA_SATURATE
+CONSTANT_COLOR :: 0x8001 // GL_CONSTANT_COLOR
+ONE_MINUS_CONSTANT_COLOR :: 0x8002 // GL_ONE_MINUS_CONSTANT_COLOR
+CONSTANT_ALPHA :: 0x8003 // GL_CONSTANT_ALPHA
+ONE_MINUS_CONSTANT_ALPHA :: 0x8004 // GL_ONE_MINUS_CONSTANT_ALPHA
+
+// GL blending functions/equations
+FUNC_ADD :: 0x8006 // GL_FUNC_ADD
+MIN :: 0x8007 // GL_MIN
+MAX :: 0x8008 // GL_MAX
+FUNC_SUBTRACT :: 0x800A // GL_FUNC_SUBTRACT
+FUNC_REVERSE_SUBTRACT :: 0x800B // GL_FUNC_REVERSE_SUBTRACT
+BLEND_EQUATION :: 0x8009 // GL_BLEND_EQUATION
+BLEND_EQUATION_RGB :: 0x8009 // GL_BLEND_EQUATION_RGB // (Same as BLEND_EQUATION)
+BLEND_EQUATION_ALPHA :: 0x883D // GL_BLEND_EQUATION_ALPHA
+BLEND_DST_RGB :: 0x80C8 // GL_BLEND_DST_RGB
+BLEND_SRC_RGB :: 0x80C9 // GL_BLEND_SRC_RGB
+BLEND_DST_ALPHA :: 0x80CA // GL_BLEND_DST_ALPHA
+BLEND_SRC_ALPHA :: 0x80CB // GL_BLEND_SRC_ALPHA
+BLEND_COLOR :: 0x8005 // GL_BLEND_COLOR
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+
+
+VertexBufferIndexType :: c.ushort when GRAPHICS_API_OPENGL_ES2 else c.uint
+
+// Dynamic vertex buffers (position + texcoords + colors + indices arrays)
+VertexBuffer :: struct {
+ elementCount: c.int, // Number of elements in the buffer (QUADS)
+
+ vertices: [^]f32, // Vertex position (XYZ - 3 components per vertex) (shader-location = 0)
+ texcoords: [^]f32, // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
+ colors: [^]u8, // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
+ indices: [^]VertexBufferIndexType, // Vertex indices (in case vertex data comes indexed) (6 indices per quad)
+ vaoId: c.uint, // OpenGL Vertex Array Object id
+ vboId: [4]c.uint, // OpenGL Vertex Buffer Objects id (4 types of vertex data)
+}
+
+// Draw call type
+// NOTE: Only texture changes register a new draw, other state-change-related elements are not
+// used at this moment (vaoId, shaderId, matrices), raylib just forces a batch draw call if any
+// of those state-change happens (this is done in core module)
+DrawCall :: struct {
+ mode: c.int, // Drawing mode: LINES, TRIANGLES, QUADS
+ vertexCount: c.int, // Number of vertex of the draw
+ vertexAlignment: c.int, // Number of vertex required for index alignment (LINES, TRIANGLES)
+ textureId: c.uint, // Texture id to be used on the draw -> Use to create new draw call if changes
+}
+
+// RenderBatch type
+RenderBatch :: struct {
+ bufferCount: c.int, // Number of vertex buffers (multi-buffering support)
+ currentBuffer: c.int, // Current buffer tracking in case of multi-buffering
+ vertexBuffer: [^]VertexBuffer, // Dynamic buffer(s) for vertex data
+
+ draws: [^]DrawCall, // Draw calls array, depends on textureId
+ drawCounter: c.int, // Draw calls counter
+ currentDepth: f32, // Current depth value for next draw
+}
+
+// OpenGL version
+GlVersion :: enum c.int {
+ OPENGL_11 = 1, // OpenGL 1.1
+ OPENGL_21, // OpenGL 2.1 (GLSL 120)
+ OPENGL_33, // OpenGL 3.3 (GLSL 330)
+ OPENGL_43, // OpenGL 4.3 (using GLSL 330)
+ OPENGL_ES_20, // OpenGL ES 2.0 (GLSL 100)
+ OPENGL_ES_30, // OpenGL ES 3.0 (GLSL 300 es)
+}
+
+PixelFormat :: rl.PixelFormat
+TextureFilter :: rl.TextureFilter
+BlendMode :: rl.BlendMode
+ShaderLocationIndex :: rl.ShaderLocationIndex
+ShaderUniformDataType :: rl.ShaderUniformDataType
+
+// Shader attribute data types
+ShaderAttributeDataType :: enum c.int {
+ FLOAT = 0, // Shader attribute type: float
+ VEC2, // Shader attribute type: vec2 (2 float)
+ VEC3, // Shader attribute type: vec3 (3 float)
+ VEC4, // Shader attribute type: vec4 (4 float)
+}
+
+// Framebuffer attachment type
+// NOTE: By default up to 8 color channels defined, but it can be more
+FramebufferAttachType :: enum c.int {
+ COLOR_CHANNEL0 = 0, // Framebuffer attachment type: color 0
+ COLOR_CHANNEL1 = 1, // Framebuffer attachment type: color 1
+ COLOR_CHANNEL2 = 2, // Framebuffer attachment type: color 2
+ COLOR_CHANNEL3 = 3, // Framebuffer attachment type: color 3
+ COLOR_CHANNEL4 = 4, // Framebuffer attachment type: color 4
+ COLOR_CHANNEL5 = 5, // Framebuffer attachment type: color 5
+ COLOR_CHANNEL6 = 6, // Framebuffer attachment type: color 6
+ COLOR_CHANNEL7 = 7, // Framebuffer attachment type: color 7
+ DEPTH = 100, // Framebuffer attachment type: depth
+ STENCIL = 200, // Framebuffer attachment type: stencil
+}
+
+// Framebuffer texture attachment type
+FramebufferAttachTextureType :: enum c.int {
+ CUBEMAP_POSITIVE_X = 0, // Framebuffer texture attachment type: cubemap, +X side
+ CUBEMAP_NEGATIVE_X = 1, // Framebuffer texture attachment type: cubemap, -X side
+ CUBEMAP_POSITIVE_Y = 2, // Framebuffer texture attachment type: cubemap, +Y side
+ CUBEMAP_NEGATIVE_Y = 3, // Framebuffer texture attachment type: cubemap, -Y side
+ CUBEMAP_POSITIVE_Z = 4, // Framebuffer texture attachment type: cubemap, +Z side
+ CUBEMAP_NEGATIVE_Z = 5, // Framebuffer texture attachment type: cubemap, -Z side
+ TEXTURE2D = 100, // Framebuffer texture attachment type: texture2d
+ RENDERBUFFER = 200, // Framebuffer texture attachment type: renderbuffer
+}
+
+CullMode :: enum c.int {
+ FRONT = 0,
+ BACK,
+}
+
+Matrix :: rl.Matrix
+
+@(default_calling_convention="c", link_prefix="rl")
+foreign lib {
+ //------------------------------------------------------------------------------------
+ // Functions Declaration - Matrix operations
+ //------------------------------------------------------------------------------------
+ MatrixMode :: proc(mode: c.int) --- // Choose the current matrix to be transformed
+ PushMatrix :: proc() --- // Push the current matrix to stack
+ PopMatrix :: proc() --- // Pop lattest inserted matrix from stack
+ LoadIdentity :: proc() --- // Reset current matrix to identity matrix
+ Translatef :: proc(x, y, z: f32) --- // Multiply the current matrix by a translation matrix
+ Rotatef :: proc(angleDeg: f32, x, y, z: f32) --- // Multiply the current matrix by a rotation matrix
+ Scalef :: proc(x, y, z: f32) --- // Multiply the current matrix by a scaling matrix
+ MultMatrixf :: proc(matf: [^]f32) --- // Multiply the current matrix by another matrix
+ Frustum :: proc(left, right, bottom, top, znear, zfar: f64) ---
+ Ortho :: proc(left, right, bottom, top, znear, zfar: f64) ---
+ Viewport :: proc(x, y, width, height: c.int) --- // Set the viewport area
+
+ //------------------------------------------------------------------------------------
+ // Functions Declaration - Vertex level operations
+ //------------------------------------------------------------------------------------
+ Begin :: proc(mode: c.int) --- // Initialize drawing mode (how to organize vertex)
+ End :: proc() --- // Finish vertex providing
+ Vertex2i :: proc(x, y: c.int) --- // Define one vertex (position) - 2 int
+ Vertex2f :: proc(x, y: f32) --- // Define one vertex (position) - 2 f32
+ Vertex3f :: proc(x, y, z: f32) --- // Define one vertex (position) - 3 f32
+ TexCoord2f :: proc(x, y: f32) --- // Define one vertex (texture coordinate) - 2 f32
+ Normal3f :: proc(x, y, z: f32) --- // Define one vertex (normal) - 3 f32
+ Color4ub :: proc(r, g, b, a: u8) --- // Define one vertex (color) - 4 byte
+ Color3f :: proc(x, y, z: f32) --- // Define one vertex (color) - 3 f32
+ Color4f :: proc(x, y, z, w: f32) --- // Define one vertex (color) - 4 f32
+
+ //------------------------------------------------------------------------------------
+ // Functions Declaration - OpenGL style functions (common to 1.1, 3.3+, ES2)
+ // NOTE: This functions are used to completely abstract raylib code from OpenGL layer,
+ // some of them are direct wrappers over OpenGL calls, some others are custom
+ //------------------------------------------------------------------------------------
+
+ // Vertex buffers state
+ EnableVertexArray :: proc(vaoId: c.uint) -> bool --- // Enable vertex array (VAO, if supported)
+ DisableVertexArray :: proc() --- // Disable vertex array (VAO, if supported)
+ EnableVertexBuffer :: proc(id: c.uint) --- // Enable vertex buffer (VBO)
+ DisableVertexBuffer :: proc() --- // Disable vertex buffer (VBO)
+ EnableVertexBufferElement :: proc(id: c.uint) --- // Enable vertex buffer element (VBO element)
+ DisableVertexBufferElement :: proc() --- // Disable vertex buffer element (VBO element)
+ EnableVertexAttribute :: proc(index: c.uint) --- // Enable vertex attribute index
+ DisableVertexAttribute :: proc(index: c.uint) --- // Disable vertex attribute index
+ when GRAPHICS_API_OPENGL_11 {
+ EnableStatePointer :: proc(vertexAttribType: c.int, buffer: rawptr) ---
+ DisableStatePointer :: proc(vertexAttribType: c.int) ---
+ }
+
+ // Textures state
+ ActiveTextureSlot :: proc(slot: c.int) --- // Select and active a texture slot
+ EnableTexture :: proc(id: c.uint) --- // Enable texture
+ DisableTexture :: proc() --- // Disable texture
+ EnableTextureCubemap :: proc(id: c.uint) --- // Enable texture cubemap
+ DisableTextureCubemap :: proc() --- // Disable texture cubemap
+ TextureParameters :: proc(id: c.uint, param: c.int, value: c.int) --- // Set texture parameters (filter, wrap)
+ CubemapParameters :: proc(id: i32, param: c.int, value: c.int) --- // Set cubemap parameters (filter, wrap)
+
+ // Shader state
+ EnableShader :: proc(id: c.uint) --- // Enable shader program
+ DisableShader :: proc() --- // Disable shader program
+
+ // Framebuffer state
+ EnableFramebuffer :: proc(id: c.uint) --- // Enable render texture (fbo)
+ DisableFramebuffer :: proc() --- // Disable render texture (fbo), return to default framebuffer
+ ActiveDrawBuffers :: proc(count: c.int) --- // Activate multiple draw color buffers
+ BlitFramebuffer :: proc(srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight, bufferMask: c.int) --- // Blit active framebuffer to main framebuffer
+
+ // General render state
+ DisableColorBlend :: proc() --- // Disable color blending
+ EnableDepthTest :: proc() --- // Enable depth test
+ DisableDepthTest :: proc() --- // Disable depth test
+ EnableDepthMask :: proc() --- // Enable depth write
+ DisableDepthMask :: proc() --- // Disable depth write
+ EnableBackfaceCulling :: proc() --- // Enable backface culling
+ DisableBackfaceCulling :: proc() --- // Disable backface culling
+ SetCullFace :: proc(mode: CullMode) --- // Set face culling mode
+ EnableScissorTest :: proc() --- // Enable scissor test
+ DisableScissorTest :: proc() --- // Disable scissor test
+ Scissor :: proc(x, y, width, height: c.int) --- // Scissor test
+ EnableWireMode :: proc() --- // Enable wire mode
+ EnablePointMode :: proc() --- // Enable point mode
+ DisableWireMode :: proc() --- // Disable wire and point modes
+ SetLineWidth :: proc(width: f32) --- // Set the line drawing width
+ GetLineWidth :: proc() -> f32 --- // Get the line drawing width
+ EnableSmoothLines :: proc() --- // Enable line aliasing
+ DisableSmoothLines :: proc() --- // Disable line aliasing
+ EnableStereoRender :: proc() --- // Enable stereo rendering
+ DisableStereoRender :: proc() --- // Disable stereo rendering
+ IsStereoRenderEnabled :: proc() -> bool --- // Check if stereo render is enabled
+
+
+ ClearColor :: proc(r, g, b, a: u8) --- // Clear color buffer with color
+ ClearScreenBuffers :: proc() --- // Clear used screen buffers (color and depth)
+ CheckErrors :: proc() --- // Check and log OpenGL error codes
+ SetBlendMode :: proc(mode: c.int) --- // Set blending mode
+ SetBlendFactors :: proc(glSrcFactor, glDstFactor, glEquation: c.int) --- // Set blending mode factor and equation (using OpenGL factors)
+ SetBlendFactorsSeparate :: proc(glSrcRGB, glDstRGB, glSrcAlpha, glDstAlpha, glEqRGB, glEqAlpha: c.int) --- // Set blending mode factors and equations separately (using OpenGL factors)
+
+ //------------------------------------------------------------------------------------
+ // Functions Declaration - rlgl functionality
+ //------------------------------------------------------------------------------------
+ // rlgl initialization functions
+ @(link_prefix="rlgl")
+ Init :: proc(width, height: c.int) --- // Initialize rlgl (buffers, shaders, textures, states)
+ @(link_prefix="rlgl")
+ Close :: proc() --- // De-initialize rlgl (buffers, shaders, textures)
+ LoadExtensions :: proc(loader: rawptr) --- // Load OpenGL extensions (loader function required)
+ GetVersion :: proc() -> GlVersion --- // Get current OpenGL version
+ SetFramebufferWidth :: proc(width: c.int) --- // Set current framebuffer width
+ GetFramebufferWidth :: proc() -> c.int --- // Get default framebuffer width
+ SetFramebufferHeight :: proc(height: c.int) --- // Set current framebuffer height
+ GetFramebufferHeight :: proc() -> c.int --- // Get default framebuffer height
+
+
+ GetTextureIdDefault :: proc() -> c.uint --- // Get default texture id
+ GetShaderIdDefault :: proc() -> c.uint --- // Get default shader id
+ GetShaderLocsDefault :: proc() -> [^]c.int --- // Get default shader locations
+
+ // Render batch management
+ // NOTE: rlgl provides a default render batch to behave like OpenGL 1.1 immediate mode
+ // but this render batch API is exposed in case of custom batches are required
+ LoadRenderBatch :: proc(numBuffers, bufferElements: c.int) -> RenderBatch --- // Load a render batch system
+ UnloadRenderBatch :: proc(batch: RenderBatch) --- // Unload render batch system
+ DrawRenderBatch :: proc(batch: ^RenderBatch) --- // Draw render batch data (Update->Draw->Reset)
+ SetRenderBatchActive :: proc(batch: ^RenderBatch) --- // Set the active render batch for rlgl (NULL for default internal)
+ DrawRenderBatchActive :: proc() --- // Update and draw internal render batch
+ CheckRenderBatchLimit :: proc(vCount: c.int) -> c.int --- // Check internal buffer overflow for a given number of vertex
+
+ SetTexture :: proc(id: c.uint) --- // Set current texture for render batch and check buffers limits
+
+ //------------------------------------------------------------------------------------------------------------------------
+
+ // Vertex buffers management
+ LoadVertexArray :: proc() -> c.uint --- // Load vertex array (vao) if supported
+ LoadVertexBuffer :: proc(buffer: rawptr, size: c.int, is_dynamic: bool) -> c.uint --- // Load a vertex buffer attribute
+ LoadVertexBufferElement :: proc(buffer: rawptr, size: c.int, is_dynamic: bool) -> c.uint --- // Load a new attributes element buffer
+ UpdateVertexBuffer :: proc(bufferId: c.uint, data: rawptr, dataSize: c.int, offset: c.int) --- // Update GPU buffer with new data
+ UpdateVertexBufferElements :: proc(id: c.uint, data: rawptr, dataSize: c.int, offset: c.int) --- // Update vertex buffer elements with new data
+ UnloadVertexArray :: proc(vaoId: c.uint) ---
+ UnloadVertexBuffer :: proc(vboId: c.uint) ---
+ SetVertexAttribute :: proc(index: c.uint, compSize: c.int, type: c.int, normalized: bool, stride: c.int, pointer: rawptr) ---
+ SetVertexAttributeDivisor :: proc(index: c.uint, divisor: c.int) ---
+ SetVertexAttributeDefault :: proc(locIndex: c.int, value: rawptr, attribType: c.int, count: c.int) --- // Set vertex attribute default value
+ DrawVertexArray :: proc(offset: c.int, count: c.int) ---
+ DrawVertexArrayElements :: proc(offset: c.int, count: c.int, buffer: rawptr) ---
+ DrawVertexArrayInstanced :: proc(offset: c.int, count: c.int, instances: c.int) ---
+ DrawVertexArrayElementsInstanced :: proc(offset: c.int, count: c.int, buffer: rawptr, instances: c.int) ---
+
+ // Textures management
+ LoadTexture :: proc(data: rawptr, width, height: c.int, format: c.int, mipmapCount: c.int) -> c.uint --- // Load texture in GPU
+ LoadTextureDepth :: proc(width, height: c.int, useRenderBuffer: bool) -> c.uint --- // Load depth texture/renderbuffer (to be attached to fbo)
+ LoadTextureCubemap :: proc(data: rawptr, size: c.int, format: c.int) -> c.uint --- // Load texture cubemap
+ UpdateTexture :: proc(id: c.uint, offsetX, offsetY: c.int, width, height: c.int, format: c.int, data: rawptr) --- // Update GPU texture with new data
+ GetGlTextureFormats :: proc(format: c.int, glInternalFormat, glFormat, glType: ^c.uint) --- // Get OpenGL internal formats
+ GetPixelFormatName :: proc(format: c.uint) -> cstring --- // Get name string for pixel format
+ UnloadTexture :: proc(id: c.uint) --- // Unload texture from GPU memory
+ GenTextureMipmaps :: proc(id: c.uint, width, height: c.int, format: c.int, mipmaps: ^c.int) --- // Generate mipmap data for selected texture
+ ReadTexturePixels :: proc(id: c.uint, width, height: c.int, format: c.int) -> rawptr --- // Read texture pixel data
+ ReadScreenPixels :: proc(width, height: c.int) -> [^]byte --- // Read screen pixel data (color buffer)
+
+ // Framebuffer management (fbo)
+ LoadFramebuffer :: proc(width, height: c.int) -> c.uint --- // Load an empty framebuffer
+ FramebufferAttach :: proc(fboId, texId: c.uint, attachType: c.int, texType: c.int, mipLevel: c.int) --- // Attach texture/renderbuffer to a framebuffer
+ FramebufferComplete :: proc(id: c.uint) -> bool --- // Verify framebuffer is complete
+ UnloadFramebuffer :: proc(id: c.uint) --- // Delete framebuffer from GPU
+
+ // Shaders management
+ LoadShaderCode :: proc(vsCode, fsCode: cstring) -> c.uint --- // Load shader from code strings
+ CompileShader :: proc(shaderCode: cstring, type: c.int) -> c.uint --- // Compile custom shader and return shader id (type: VERTEX_SHADER, FRAGMENT_SHADER, COMPUTE_SHADER)
+ LoadShaderProgram :: proc(vShaderId, fShaderId: c.uint) -> c.uint --- // Load custom shader program
+ UnloadShaderProgram :: proc(id: c.uint) --- // Unload shader program
+ GetLocationUniform :: proc(shaderId: c.uint, uniformName: cstring) -> c.int --- // Get shader location uniform
+ GetLocationAttrib :: proc(shaderId: c.uint, attribName: cstring) -> c.int --- // Get shader location attribute
+ SetUniform :: proc(locIndex: c.int, value: rawptr, uniformType: c.int, count: c.int) --- // Set shader value uniform
+ SetUniformMatrix :: proc(locIndex: c.int, mat: Matrix) --- // Set shader value matrix
+ SetUniformSampler :: proc(locIndex: c.int, textureId: c.uint) --- // Set shader value sampler
+ SetShader :: proc(id: c.uint, locs: [^]c.int) --- // Set shader currently active (id and locations)
+
+ // Compute shader management
+ LoadComputeShaderProgram :: proc(shaderId: c.uint) -> c.uint --- // Load compute shader program
+ ComputeShaderDispatch :: proc(groupX, groupY, groupZ: c.uint) --- // Dispatch compute shader (equivalent to *draw* for graphics pipeline)
+
+ // Shader buffer storage object management (ssbo)
+ LoadShaderBuffer :: proc(size: c.uint, data: rawptr, usageHint: c.int) -> c.uint --- // Load shader storage buffer object (SSBO)
+ UnloadShaderBuffer :: proc(ssboId: c.uint) --- // Unload shader storage buffer object (SSBO)
+ UpdateShaderBuffer :: proc(id: c.uint, data: rawptr, dataSize: c.uint, offset: c.uint) --- // Update SSBO buffer data
+ BindShaderBuffer :: proc(id: c.uint, index: c.uint) --- // Bind SSBO buffer
+ ReadShaderBuffer :: proc(id: c.uint, dest: rawptr, count: c.uint, offset: c.uint) --- // Read SSBO buffer data (GPU->CPU)
+ CopyShaderBuffer :: proc(destId, srcId: c.uint, destOffset, srcOffset: c.uint, count: c.uint) --- // Copy SSBO data between buffers
+ GetShaderBufferSize :: proc(id: c.uint) -> c.uint --- // Get SSBO buffer size
+
+ // Buffer management
+ BindImageTexture :: proc(id: c.uint, index: c.uint, format: c.int, readonly: bool) --- // Bind image texture
+
+ // Matrix state management
+ GetMatrixModelview :: proc() -> Matrix --- // Get internal modelview matrix
+ GetMatrixProjection :: proc() -> Matrix --- // Get internal projection matrix
+ GetMatrixTransform :: proc() -> Matrix --- // Get internal accumulated transform matrix
+ GetMatrixProjectionStereo :: proc(eye: c.int) -> Matrix --- // Get internal projection matrix for stereo render (selected eye)
+ GetMatrixViewOffsetStereo :: proc(eye: c.int) -> Matrix --- // Get internal view offset matrix for stereo render (selected eye)
+ SetMatrixProjection :: proc(proj: Matrix) --- // Set a custom projection matrix (replaces internal projection matrix)
+ SetMatrixModelview :: proc(view: Matrix) --- // Set a custom modelview matrix (replaces internal modelview matrix)
+ SetMatrixProjectionStereo :: proc(right, left: Matrix) --- // Set eyes projection matrices for stereo rendering
+ SetMatrixViewOffsetStereo :: proc(right, left: Matrix) --- // Set eyes view offsets matrices for stereo rendering
+
+ // Quick and dirty cube/quad buffers load->draw->unload
+ LoadDrawCube :: proc() --- // Load and draw a cube
+ LoadDrawQuad :: proc() --- // Load and draw a quad
+}